summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoung Hahn <young@mapbox.com>2016-06-15 17:13:31 -0400
committerGitHub <noreply@github.com>2016-06-15 17:13:31 -0400
commit199ea2a82a74cf2f7b63078e2dd4b8274c061851 (patch)
tree5d56478a020a911745d793b8ac5d7f236730c621
parenta020e535cac36d69a8939fb7956260d2217c65b4 (diff)
downloadqtlocation-mapboxgl-199ea2a82a74cf2f7b63078e2dd4b8274c061851.tar.gz
Support for icon-text-fit, icon-text-fit-padding (#5334)
* Add support for icon-text-fit * Port unit tests for getIconQuads() from js => cpp * Add support for padding in all 4 directions. * Update all hashes post-merge
-rw-r--r--include/mbgl/style/layers/symbol_layer.hpp6
-rw-r--r--include/mbgl/style/types.hpp7
-rw-r--r--package.json4
-rw-r--r--platform/node/src/node_style.hpp8
-rw-r--r--platform/node/src/node_style_properties.hpp3
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp2
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp14
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.cpp4
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp2
-rw-r--r--src/mbgl/style/property_evaluator.cpp4
-rw-r--r--src/mbgl/style/property_parsing.cpp19
-rw-r--r--src/mbgl/style/types.cpp7
-rw-r--r--src/mbgl/text/quads.cpp44
-rw-r--r--src/mbgl/text/quads.hpp2
-rw-r--r--test/test.gypi2
-rw-r--r--test/text/quads.cpp266
16 files changed, 384 insertions, 10 deletions
diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp
index 676d90d5b9..7d98a5ef6b 100644
--- a/include/mbgl/style/layers/symbol_layer.hpp
+++ b/include/mbgl/style/layers/symbol_layer.hpp
@@ -53,6 +53,12 @@ public:
PropertyValue<float> getIconSize() const;
void setIconSize(PropertyValue<float>);
+ PropertyValue<IconTextFitType> getIconTextFit() const;
+ void setIconTextFit(PropertyValue<IconTextFitType>);
+
+ PropertyValue<std::array<float, 4>> getIconTextFitPadding() const;
+ void setIconTextFitPadding(PropertyValue<std::array<float, 4>>);
+
PropertyValue<std::string> getIconImage() const;
void setIconImage(PropertyValue<std::string>);
diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp
index 46c0cb3c39..28ebda9fb9 100644
--- a/include/mbgl/style/types.hpp
+++ b/include/mbgl/style/types.hpp
@@ -80,5 +80,12 @@ enum class TextTransformType : uint8_t {
Lowercase,
};
+enum class IconTextFitType : uint8_t {
+ None,
+ Both,
+ Width,
+ Height
+};
+
} // namespace style
} // namespace mbgl
diff --git a/package.json b/package.json
index 1b0da8c4df..fcf5ee9bc4 100644
--- a/package.json
+++ b/package.json
@@ -22,8 +22,8 @@
"ejs": "^2.4.1",
"express": "^4.11.1",
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#59e998295d548f208ee3ec10cdd21ff2630e2079",
- "mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#2461efc3d883f2f2e56a6c6b2bfd7d54bbfe9f86",
- "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#3d06b422b1aa81aec71b4c67128f3d947205d6af",
+ "mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#194fc55b6a7dd54c1e2cf2dd9048fbb5e836716d",
+ "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#146a348f1768ce13e153fce3b32bbed469aa5fe4",
"node-gyp": "^3.3.1",
"request": "^2.72.0",
"tape": "^4.5.1"
diff --git a/platform/node/src/node_style.hpp b/platform/node/src/node_style.hpp
index 34b8b96a99..a987c0d262 100644
--- a/platform/node/src/node_style.hpp
+++ b/platform/node/src/node_style.hpp
@@ -79,6 +79,14 @@ struct ValueConverter<std::array<float, 2>> {
};
template <>
+struct ValueConverter<std::array<float, 4>> {
+ mbgl::optional<mbgl::style::PropertyValue<std::array<float, 4>>> operator()(const v8::Local<v8::Value>& value) const {
+ (void)value;
+ return {};
+ }
+};
+
+template <>
struct ValueConverter<std::vector<float>> {
mbgl::optional<mbgl::style::PropertyValue<std::vector<float>>> operator()(const v8::Local<v8::Value>& value) const {
(void)value;
diff --git a/platform/node/src/node_style_properties.hpp b/platform/node/src/node_style_properties.hpp
index 4702918ae1..88142f8e1f 100644
--- a/platform/node/src/node_style_properties.hpp
+++ b/platform/node/src/node_style_properties.hpp
@@ -27,11 +27,14 @@ inline PropertySetters makeLayoutPropertySetters() {
result["icon-optional"] = makePropertySetter(&SymbolLayer::setIconOptional);
result["icon-rotation-alignment"] = makePropertySetter(&SymbolLayer::setIconRotationAlignment);
result["icon-size"] = makePropertySetter(&SymbolLayer::setIconSize);
+ result["icon-text-fit"] = makePropertySetter(&SymbolLayer::setIconTextFit);
+ result["icon-text-fit-padding"] = makePropertySetter(&SymbolLayer::setIconTextFitPadding);
result["icon-image"] = makePropertySetter(&SymbolLayer::setIconImage);
result["icon-rotate"] = makePropertySetter(&SymbolLayer::setIconRotate);
result["icon-padding"] = makePropertySetter(&SymbolLayer::setIconPadding);
result["icon-keep-upright"] = makePropertySetter(&SymbolLayer::setIconKeepUpright);
result["icon-offset"] = makePropertySetter(&SymbolLayer::setIconOffset);
+ result["text-pitch-alignment"] = makePropertySetter(&SymbolLayer::setTextPitchAlignment);
result["text-rotation-alignment"] = makePropertySetter(&SymbolLayer::setTextRotationAlignment);
result["text-field"] = makePropertySetter(&SymbolLayer::setTextField);
result["text-font"] = makePropertySetter(&SymbolLayer::setTextFont);
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index 60624fa59e..e34aedb47e 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -51,7 +51,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
// Create the quad used for rendering the icon.
iconQuads(addToBuffers && shapedIcon ?
- getIconQuads(anchor, shapedIcon, line, layout, iconAlongLine) :
+ getIconQuads(anchor, shapedIcon, line, layout, iconAlongLine, shapedText) :
SymbolQuads()),
// Create the collision features that will be used to check whether this symbol instance can be placed
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index 282873b501..38a898deca 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -106,6 +106,20 @@ PropertyValue<float> SymbolLayer::getIconSize() const {
void SymbolLayer::setIconSize(PropertyValue<float> value) {
impl->layout.iconSize.set(value);
}
+PropertyValue<IconTextFitType> SymbolLayer::getIconTextFit() const {
+ return impl->layout.iconTextFit.get();
+}
+
+void SymbolLayer::setIconTextFit(PropertyValue<IconTextFitType> value) {
+ impl->layout.iconTextFit.set(value);
+}
+PropertyValue<std::array<float, 4>> SymbolLayer::getIconTextFitPadding() const {
+ return impl->layout.iconTextFitPadding.get();
+}
+
+void SymbolLayer::setIconTextFitPadding(PropertyValue<std::array<float, 4>> value) {
+ impl->layout.iconTextFitPadding.set(value);
+}
PropertyValue<std::string> SymbolLayer::getIconImage() const {
return impl->layout.iconImage.get();
}
diff --git a/src/mbgl/style/layers/symbol_layer_properties.cpp b/src/mbgl/style/layers/symbol_layer_properties.cpp
index 5c6f65112d..d77d10700c 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.cpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.cpp
@@ -14,6 +14,8 @@ void SymbolLayoutProperties::parse(const JSValue& value) {
iconOptional.parse("icon-optional", value);
iconRotationAlignment.parse("icon-rotation-alignment", value);
iconSize.parse("icon-size", value);
+ iconTextFit.parse("icon-text-fit", value);
+ iconTextFitPadding.parse("icon-text-fit-padding", value);
iconImage.parse("icon-image", value);
iconRotate.parse("icon-rotate", value);
iconPadding.parse("icon-padding", value);
@@ -49,6 +51,8 @@ void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters
iconOptional.calculate(parameters);
iconRotationAlignment.calculate(parameters);
iconSize.calculate(parameters);
+ iconTextFit.calculate(parameters);
+ iconTextFitPadding.calculate(parameters);
iconImage.calculate(parameters);
iconRotate.calculate(parameters);
iconPadding.calculate(parameters);
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index 772445f051..1882c03fef 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -25,6 +25,8 @@ public:
LayoutProperty<bool> iconOptional { false };
LayoutProperty<AlignmentType> iconRotationAlignment { AlignmentType::Viewport };
LayoutProperty<float> iconSize { 1 };
+ LayoutProperty<IconTextFitType> iconTextFit { IconTextFitType::None };
+ LayoutProperty<std::array<float, 4>> iconTextFitPadding { {{ 0, 0, 0, 0 }} };
LayoutProperty<std::string> iconImage { "" };
LayoutProperty<float> iconRotate { 0 };
LayoutProperty<float> iconPadding { 2 };
diff --git a/src/mbgl/style/property_evaluator.cpp b/src/mbgl/style/property_evaluator.cpp
index 7b91b9e500..3394d69e41 100644
--- a/src/mbgl/style/property_evaluator.cpp
+++ b/src/mbgl/style/property_evaluator.cpp
@@ -19,6 +19,7 @@ template <> inline Color defaultStopsValue() { return { 0, 0, 0, 1 }; }
template <> inline std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; }
template <> inline std::vector<std::string> defaultStopsValue() { return {{}}; }
template <> inline std::array<float, 2> defaultStopsValue() { return {{ 0, 0 }}; }
+template <> inline std::array<float, 4> defaultStopsValue() { return {{ 0, 0, 0, 0 }}; }
template <> inline std::string defaultStopsValue() { return {}; }
template <> inline TranslateAnchorType defaultStopsValue() { return {}; }
@@ -30,6 +31,7 @@ template <> inline TextAnchorType defaultStopsValue() { return {}; }
template <> inline TextJustifyType defaultStopsValue() { return {}; }
template <> inline TextTransformType defaultStopsValue() { return {}; }
template <> inline AlignmentType defaultStopsValue() { return {}; }
+template <> inline IconTextFitType defaultStopsValue() { return {}; };
template <typename T>
T PropertyEvaluator<T>::operator()(const Function<T>& fn) const {
@@ -87,6 +89,7 @@ template class PropertyEvaluator<Color>;
template class PropertyEvaluator<std::vector<float>>;
template class PropertyEvaluator<std::vector<std::string>>;
template class PropertyEvaluator<std::array<float, 2>>;
+template class PropertyEvaluator<std::array<float, 4>>;
template class PropertyEvaluator<std::string>;
template class PropertyEvaluator<TranslateAnchorType>;
@@ -98,6 +101,7 @@ template class PropertyEvaluator<TextAnchorType>;
template class PropertyEvaluator<TextJustifyType>;
template class PropertyEvaluator<TextTransformType>;
template class PropertyEvaluator<AlignmentType>;
+template class PropertyEvaluator<IconTextFitType>;
template <typename T>
Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const Undefined&) const {
diff --git a/src/mbgl/style/property_parsing.cpp b/src/mbgl/style/property_parsing.cpp
index f5e0cca993..2b08ba8788 100644
--- a/src/mbgl/style/property_parsing.cpp
+++ b/src/mbgl/style/property_parsing.cpp
@@ -71,6 +71,25 @@ optional<std::array<float, 2>> parseConstant(const char* name, const JSValue& va
}
template <>
+optional<std::array<float, 4>> parseConstant(const char* name, const JSValue& value) {
+ if (value.IsArray() && value.Size() == 4 &&
+ value[rapidjson::SizeType(0)].IsNumber() &&
+ value[rapidjson::SizeType(1)].IsNumber() &&
+ value[rapidjson::SizeType(2)].IsNumber() &&
+ value[rapidjson::SizeType(3)].IsNumber()) {
+
+ float first = value[rapidjson::SizeType(0)].GetDouble();
+ float second = value[rapidjson::SizeType(1)].GetDouble();
+ float third = value[rapidjson::SizeType(2)].GetDouble();
+ float fourth = value[rapidjson::SizeType(3)].GetDouble();
+ return { {{ first, second, third, fourth }} };
+ } else {
+ Log::Warning(Event::ParseStyle, "value of '%s' must be an array of four numbers", name);
+ return {};
+ }
+}
+
+template <>
optional<std::vector<float>> parseConstant(const char* name, const JSValue& value) {
if (!value.IsArray()) {
Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers", name);
diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp
index d292d2d5b4..25a1753870 100644
--- a/src/mbgl/style/types.cpp
+++ b/src/mbgl/style/types.cpp
@@ -77,4 +77,11 @@ MBGL_DEFINE_ENUM(AlignmentType, {
{ AlignmentType::Undefined, "undefined" },
});
+MBGL_DEFINE_ENUM(IconTextFitType, {
+ { IconTextFitType::None, "none" },
+ { IconTextFitType::Both, "both" },
+ { IconTextFitType::Width, "width" },
+ { IconTextFitType::Height, "height" },
+});
+
} // namespace mbgl
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index a46b329d1a..727b86f610 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -15,7 +15,7 @@ const float globalMinScale = 0.5f; // underscale by 1 zoom level
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
const GeometryCoordinates& line, const SymbolLayoutProperties& layout,
- const bool alongLine) {
+ const bool alongLine, const Shaping& shapedText) {
auto image = *(shapedIcon.image);
@@ -24,11 +24,43 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
auto right = left + image.pos.w / image.relativePixelRatio;
auto top = shapedIcon.top - border;
auto bottom = top + image.pos.h / image.relativePixelRatio;
- Point<float> tl{left, top};
- Point<float> tr{right, top};
- Point<float> br{right, bottom};
- Point<float> bl{left, bottom};
-
+ Point<float> tl;
+ Point<float> tr;
+ Point<float> br;
+ Point<float> bl;
+
+ if (layout.iconTextFit != IconTextFitType::None && shapedText) {
+ auto iconWidth = right - left;
+ auto iconHeight = bottom - top;
+ auto size = layout.textSize / 24.0f;
+ auto textLeft = shapedText.left * size;
+ auto textRight = shapedText.right * size;
+ auto textTop = shapedText.top * size;
+ auto textBottom = shapedText.bottom * size;
+ auto textWidth = textRight - textLeft;
+ auto textHeight = textBottom - textTop;;
+ auto padT = layout.iconTextFitPadding.value[0];
+ auto padR = layout.iconTextFitPadding.value[1];
+ auto padB = layout.iconTextFitPadding.value[2];
+ auto padL = layout.iconTextFitPadding.value[3];
+ auto offsetY = layout.iconTextFit == IconTextFitType::Width ? (textHeight - iconHeight) * 0.5 : 0;
+ auto offsetX = layout.iconTextFit == IconTextFitType::Height ? (textWidth - iconWidth) * 0.5 : 0;
+ auto width = layout.iconTextFit == IconTextFitType::Width || layout.iconTextFit == IconTextFitType::Both ? textWidth : iconWidth;
+ auto height = layout.iconTextFit == IconTextFitType::Height || layout.iconTextFit == IconTextFitType::Both ? textHeight : iconHeight;
+ left = textLeft + offsetX - padL;
+ top = textTop + offsetY - padT;
+ right = textLeft + offsetX + padR + width;
+ bottom = textTop + offsetY + padB + height;
+ tl = {left, top};
+ tr = {right, top};
+ br = {right, bottom};
+ bl = {left, bottom};
+ } else {
+ tl = {left, top};
+ tr = {right, top};
+ br = {right, bottom};
+ bl = {left, bottom};
+ }
float angle = layout.iconRotate * util::DEG2RAD;
if (alongLine) {
diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp
index 0ea5129238..dd64af682a 100644
--- a/src/mbgl/text/quads.hpp
+++ b/src/mbgl/text/quads.hpp
@@ -40,7 +40,7 @@ typedef std::vector<SymbolQuad> SymbolQuads;
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
const GeometryCoordinates& line, const style::SymbolLayoutProperties&,
- const bool alongLine);
+ const bool alongLine, const Shaping& shapedText);
SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText,
const float boxScale, const GeometryCoordinates& line, const style::SymbolLayoutProperties&,
diff --git a/test/test.gypi b/test/test.gypi
index da605b6fd8..e72718d865 100644
--- a/test/test.gypi
+++ b/test/test.gypi
@@ -56,6 +56,8 @@
'math/minmax.cpp',
'math/clamp.cpp',
+ 'text/quads.cpp',
+
'tile/geometry_tile_data.cpp',
'tile/tile_id.cpp',
diff --git a/test/text/quads.cpp b/test/text/quads.cpp
new file mode 100644
index 0000000000..6fdd769fc3
--- /dev/null
+++ b/test/text/quads.cpp
@@ -0,0 +1,266 @@
+#include <mbgl/geometry/anchor.hpp>
+#include <mbgl/sprite/sprite_atlas.hpp>
+#include <mbgl/test/util.hpp>
+#include <mbgl/text/quads.hpp>
+#include <mbgl/text/shaping.hpp>
+#include <mbgl/text/glyph.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
+
+using namespace mbgl;
+using namespace mbgl::style;
+
+TEST(getIconQuads, normal) {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ Anchor anchor(2.0, 3.0, 0.0, 0.5f, 0);
+ SpriteAtlasElement image = {
+ Rect<uint16_t>( 0, 0, 15, 11 ),
+ std::shared_ptr<const SpriteImage>(),
+ 1.0f
+ };
+ PositionedIcon shapedIcon(image, -5.0, 6.0, -7.0, 8.0);
+ GeometryCoordinates line;
+ Shaping shapedText;
+
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads.size(), 1u);
+ ASSERT_EQ(quads[0].anchorPoint.x, 2);
+ ASSERT_EQ(quads[0].anchorPoint.y, 3);
+ ASSERT_EQ(quads[0].tl.x, -8);
+ ASSERT_EQ(quads[0].tl.y, -6);
+ ASSERT_EQ(quads[0].tr.x, 7);
+ ASSERT_EQ(quads[0].tr.y, -6);
+ ASSERT_EQ(quads[0].bl.x, -8);
+ ASSERT_EQ(quads[0].bl.y, 5);
+ ASSERT_EQ(quads[0].br.x, 7);
+ ASSERT_EQ(quads[0].br.y, 5);
+ ASSERT_EQ(quads[0].anchorAngle, 0.0f);
+ ASSERT_EQ(quads[0].glyphAngle, 0.0f);
+ ASSERT_EQ(quads[0].minScale, 0.5f);
+}
+
+TEST(getIconQuads, style) {
+ Anchor anchor(0.0, 0.0, 0.0, 0.5f, 0);
+ SpriteAtlasElement image = {
+ Rect<uint16_t>( 0, 0, 20, 20 ),
+ std::shared_ptr<const SpriteImage>(),
+ 1.0f
+ };
+ PositionedIcon shapedIcon(image, -10.0, 10.0, -10.0, 10.0);
+ GeometryCoordinates line;
+ Shaping shapedText;
+ shapedText.top = -10.0f;
+ shapedText.bottom = 30.0f;
+ shapedText.left = -60.0f;
+ shapedText.right = 20.0f;
+ shapedText.positionedGlyphs.emplace_back(PositionedGlyph(32, 0.0f, 0.0f));
+
+ // none
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads.size(), 1u);
+ ASSERT_EQ(quads[0].anchorPoint.x, 0);
+ ASSERT_EQ(quads[0].anchorPoint.y, 0);
+ ASSERT_EQ(quads[0].tl.x, -11);
+ ASSERT_EQ(quads[0].tl.y, -11);
+ ASSERT_EQ(quads[0].tr.x, 9);
+ ASSERT_EQ(quads[0].tr.y, -11);
+ ASSERT_EQ(quads[0].bl.x, -11);
+ ASSERT_EQ(quads[0].bl.y, 9);
+ ASSERT_EQ(quads[0].br.x, 9);
+ ASSERT_EQ(quads[0].br.y, 9);
+ ASSERT_EQ(quads[0].anchorAngle, 0.0f);
+ ASSERT_EQ(quads[0].glyphAngle, 0.0f);
+ ASSERT_EQ(quads[0].minScale, 0.5f);
+ }
+
+ // width
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(24.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Width);
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -60);
+ ASSERT_EQ(quads[0].tl.y, 0);
+ ASSERT_EQ(quads[0].tr.x, 20);
+ ASSERT_EQ(quads[0].tr.y, 0);
+ ASSERT_EQ(quads[0].bl.x, -60);
+ ASSERT_EQ(quads[0].bl.y, 20);
+ ASSERT_EQ(quads[0].br.x, 20);
+ ASSERT_EQ(quads[0].br.y, 20);
+ }
+
+ // width x textSize
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(12.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Width);
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -30);
+ ASSERT_EQ(quads[0].tl.y, -5);
+ ASSERT_EQ(quads[0].tr.x, 10);
+ ASSERT_EQ(quads[0].tr.y, -5);
+ ASSERT_EQ(quads[0].bl.x, -30);
+ ASSERT_EQ(quads[0].bl.y, 15);
+ ASSERT_EQ(quads[0].br.x, 10);
+ ASSERT_EQ(quads[0].br.y, 15);
+ }
+
+ // width x textSize + padding
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(12.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Width);
+ layer->impl->layout.iconTextFitPadding.value[0] = 5.0f;
+ layer->impl->layout.iconTextFitPadding.value[1] = 10.0f;
+ layer->impl->layout.iconTextFitPadding.value[2] = 5.0f;
+ layer->impl->layout.iconTextFitPadding.value[3] = 10.0f;
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -40);
+ ASSERT_EQ(quads[0].tl.y, -10);
+ ASSERT_EQ(quads[0].tr.x, 20);
+ ASSERT_EQ(quads[0].tr.y, -10);
+ ASSERT_EQ(quads[0].bl.x, -40);
+ ASSERT_EQ(quads[0].bl.y, 20);
+ ASSERT_EQ(quads[0].br.x, 20);
+ ASSERT_EQ(quads[0].br.y, 20);
+ }
+
+ // height
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(24.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Height);
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -30);
+ ASSERT_EQ(quads[0].tl.y, -10);
+ ASSERT_EQ(quads[0].tr.x, -10);
+ ASSERT_EQ(quads[0].tr.y, -10);
+ ASSERT_EQ(quads[0].bl.x, -30);
+ ASSERT_EQ(quads[0].bl.y, 30);
+ ASSERT_EQ(quads[0].br.x, -10);
+ ASSERT_EQ(quads[0].br.y, 30);
+ }
+
+ // height x textSize
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(12.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Height);
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -20);
+ ASSERT_EQ(quads[0].tl.y, -5);
+ ASSERT_EQ(quads[0].tr.x, 0);
+ ASSERT_EQ(quads[0].tr.y, -5);
+ ASSERT_EQ(quads[0].bl.x, -20);
+ ASSERT_EQ(quads[0].bl.y, 15);
+ ASSERT_EQ(quads[0].br.x, 0);
+ ASSERT_EQ(quads[0].br.y, 15);
+ }
+
+ // height x textSize + padding
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(12.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Height);
+ layer->impl->layout.iconTextFitPadding.value[0] = 5.0f;
+ layer->impl->layout.iconTextFitPadding.value[1] = 10.0f;
+ layer->impl->layout.iconTextFitPadding.value[2] = 5.0f;
+ layer->impl->layout.iconTextFitPadding.value[3] = 10.0f;
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -30);
+ ASSERT_EQ(quads[0].tl.y, -10);
+ ASSERT_EQ(quads[0].tr.x, 10);
+ ASSERT_EQ(quads[0].tr.y, -10);
+ ASSERT_EQ(quads[0].bl.x, -30);
+ ASSERT_EQ(quads[0].bl.y, 20);
+ ASSERT_EQ(quads[0].br.x, 10);
+ ASSERT_EQ(quads[0].br.y, 20);
+ }
+
+ // both
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(24.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Both);
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -60);
+ ASSERT_EQ(quads[0].tl.y, -10);
+ ASSERT_EQ(quads[0].tr.x, 20);
+ ASSERT_EQ(quads[0].tr.y, -10);
+ ASSERT_EQ(quads[0].bl.x, -60);
+ ASSERT_EQ(quads[0].bl.y, 30);
+ ASSERT_EQ(quads[0].br.x, 20);
+ ASSERT_EQ(quads[0].br.y, 30);
+ }
+
+ // both x textSize
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(12.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Both);
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -30);
+ ASSERT_EQ(quads[0].tl.y, -5);
+ ASSERT_EQ(quads[0].tr.x, 10);
+ ASSERT_EQ(quads[0].tr.y, -5);
+ ASSERT_EQ(quads[0].bl.x, -30);
+ ASSERT_EQ(quads[0].bl.y, 15);
+ ASSERT_EQ(quads[0].br.x, 10);
+ ASSERT_EQ(quads[0].br.y, 15);
+ }
+
+ // both x textSize + padding
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(12.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Both);
+ layer->impl->layout.iconTextFitPadding.value[0] = 5.0f;
+ layer->impl->layout.iconTextFitPadding.value[1] = 10.0f;
+ layer->impl->layout.iconTextFitPadding.value[2] = 5.0f;
+ layer->impl->layout.iconTextFitPadding.value[3] = 10.0f;
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -40);
+ ASSERT_EQ(quads[0].tl.y, -10);
+ ASSERT_EQ(quads[0].tr.x, 20);
+ ASSERT_EQ(quads[0].tr.y, -10);
+ ASSERT_EQ(quads[0].bl.x, -40);
+ ASSERT_EQ(quads[0].bl.y, 20);
+ ASSERT_EQ(quads[0].br.x, 20);
+ ASSERT_EQ(quads[0].br.y, 20);
+ }
+
+ // both x textSize + padding t/r/b/l
+ {
+ auto layer = std::make_unique<SymbolLayer>("symbol");
+ layer->impl->layout.textSize = LayoutProperty<float>(12.0f);
+ layer->impl->layout.iconTextFit = LayoutProperty<IconTextFitType>(IconTextFitType::Both);
+ layer->impl->layout.iconTextFitPadding.value[0] = 0.0f;
+ layer->impl->layout.iconTextFitPadding.value[1] = 5.0f;
+ layer->impl->layout.iconTextFitPadding.value[2] = 10.0f;
+ layer->impl->layout.iconTextFitPadding.value[3] = 15.0f;
+ SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText);
+
+ ASSERT_EQ(quads[0].tl.x, -45);
+ ASSERT_EQ(quads[0].tl.y, -5);
+ ASSERT_EQ(quads[0].tr.x, 15);
+ ASSERT_EQ(quads[0].tr.y, -5);
+ ASSERT_EQ(quads[0].bl.x, -45);
+ ASSERT_EQ(quads[0].bl.y, 25);
+ ASSERT_EQ(quads[0].br.x, 15);
+ ASSERT_EQ(quads[0].br.y, 25);
+ }
+}
+