Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit 199ea2a

Browse files
authored
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
1 parent a020e53 commit 199ea2a

16 files changed

+384
-10
lines changed

include/mbgl/style/layers/symbol_layer.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ class SymbolLayer : public Layer {
5353
PropertyValue<float> getIconSize() const;
5454
void setIconSize(PropertyValue<float>);
5555

56+
PropertyValue<IconTextFitType> getIconTextFit() const;
57+
void setIconTextFit(PropertyValue<IconTextFitType>);
58+
59+
PropertyValue<std::array<float, 4>> getIconTextFitPadding() const;
60+
void setIconTextFitPadding(PropertyValue<std::array<float, 4>>);
61+
5662
PropertyValue<std::string> getIconImage() const;
5763
void setIconImage(PropertyValue<std::string>);
5864

include/mbgl/style/types.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,12 @@ enum class TextTransformType : uint8_t {
8080
Lowercase,
8181
};
8282

83+
enum class IconTextFitType : uint8_t {
84+
None,
85+
Both,
86+
Width,
87+
Height
88+
};
89+
8390
} // namespace style
8491
} // namespace mbgl

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
"ejs": "^2.4.1",
2323
"express": "^4.11.1",
2424
"mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#59e998295d548f208ee3ec10cdd21ff2630e2079",
25-
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#2461efc3d883f2f2e56a6c6b2bfd7d54bbfe9f86",
26-
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#3d06b422b1aa81aec71b4c67128f3d947205d6af",
25+
"mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#194fc55b6a7dd54c1e2cf2dd9048fbb5e836716d",
26+
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#146a348f1768ce13e153fce3b32bbed469aa5fe4",
2727
"node-gyp": "^3.3.1",
2828
"request": "^2.72.0",
2929
"tape": "^4.5.1"

platform/node/src/node_style.hpp

+8
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ struct ValueConverter<std::array<float, 2>> {
7878
}
7979
};
8080

81+
template <>
82+
struct ValueConverter<std::array<float, 4>> {
83+
mbgl::optional<mbgl::style::PropertyValue<std::array<float, 4>>> operator()(const v8::Local<v8::Value>& value) const {
84+
(void)value;
85+
return {};
86+
}
87+
};
88+
8189
template <>
8290
struct ValueConverter<std::vector<float>> {
8391
mbgl::optional<mbgl::style::PropertyValue<std::vector<float>>> operator()(const v8::Local<v8::Value>& value) const {

platform/node/src/node_style_properties.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@ inline PropertySetters makeLayoutPropertySetters() {
2727
result["icon-optional"] = makePropertySetter(&SymbolLayer::setIconOptional);
2828
result["icon-rotation-alignment"] = makePropertySetter(&SymbolLayer::setIconRotationAlignment);
2929
result["icon-size"] = makePropertySetter(&SymbolLayer::setIconSize);
30+
result["icon-text-fit"] = makePropertySetter(&SymbolLayer::setIconTextFit);
31+
result["icon-text-fit-padding"] = makePropertySetter(&SymbolLayer::setIconTextFitPadding);
3032
result["icon-image"] = makePropertySetter(&SymbolLayer::setIconImage);
3133
result["icon-rotate"] = makePropertySetter(&SymbolLayer::setIconRotate);
3234
result["icon-padding"] = makePropertySetter(&SymbolLayer::setIconPadding);
3335
result["icon-keep-upright"] = makePropertySetter(&SymbolLayer::setIconKeepUpright);
3436
result["icon-offset"] = makePropertySetter(&SymbolLayer::setIconOffset);
37+
result["text-pitch-alignment"] = makePropertySetter(&SymbolLayer::setTextPitchAlignment);
3538
result["text-rotation-alignment"] = makePropertySetter(&SymbolLayer::setTextRotationAlignment);
3639
result["text-field"] = makePropertySetter(&SymbolLayer::setTextField);
3740
result["text-font"] = makePropertySetter(&SymbolLayer::setTextFont);

src/mbgl/renderer/symbol_bucket.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
5151

5252
// Create the quad used for rendering the icon.
5353
iconQuads(addToBuffers && shapedIcon ?
54-
getIconQuads(anchor, shapedIcon, line, layout, iconAlongLine) :
54+
getIconQuads(anchor, shapedIcon, line, layout, iconAlongLine, shapedText) :
5555
SymbolQuads()),
5656

5757
// Create the collision features that will be used to check whether this symbol instance can be placed

src/mbgl/style/layers/symbol_layer.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,20 @@ PropertyValue<float> SymbolLayer::getIconSize() const {
106106
void SymbolLayer::setIconSize(PropertyValue<float> value) {
107107
impl->layout.iconSize.set(value);
108108
}
109+
PropertyValue<IconTextFitType> SymbolLayer::getIconTextFit() const {
110+
return impl->layout.iconTextFit.get();
111+
}
112+
113+
void SymbolLayer::setIconTextFit(PropertyValue<IconTextFitType> value) {
114+
impl->layout.iconTextFit.set(value);
115+
}
116+
PropertyValue<std::array<float, 4>> SymbolLayer::getIconTextFitPadding() const {
117+
return impl->layout.iconTextFitPadding.get();
118+
}
119+
120+
void SymbolLayer::setIconTextFitPadding(PropertyValue<std::array<float, 4>> value) {
121+
impl->layout.iconTextFitPadding.set(value);
122+
}
109123
PropertyValue<std::string> SymbolLayer::getIconImage() const {
110124
return impl->layout.iconImage.get();
111125
}

src/mbgl/style/layers/symbol_layer_properties.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ void SymbolLayoutProperties::parse(const JSValue& value) {
1414
iconOptional.parse("icon-optional", value);
1515
iconRotationAlignment.parse("icon-rotation-alignment", value);
1616
iconSize.parse("icon-size", value);
17+
iconTextFit.parse("icon-text-fit", value);
18+
iconTextFitPadding.parse("icon-text-fit-padding", value);
1719
iconImage.parse("icon-image", value);
1820
iconRotate.parse("icon-rotate", value);
1921
iconPadding.parse("icon-padding", value);
@@ -49,6 +51,8 @@ void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters
4951
iconOptional.calculate(parameters);
5052
iconRotationAlignment.calculate(parameters);
5153
iconSize.calculate(parameters);
54+
iconTextFit.calculate(parameters);
55+
iconTextFitPadding.calculate(parameters);
5256
iconImage.calculate(parameters);
5357
iconRotate.calculate(parameters);
5458
iconPadding.calculate(parameters);

src/mbgl/style/layers/symbol_layer_properties.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class SymbolLayoutProperties {
2525
LayoutProperty<bool> iconOptional { false };
2626
LayoutProperty<AlignmentType> iconRotationAlignment { AlignmentType::Viewport };
2727
LayoutProperty<float> iconSize { 1 };
28+
LayoutProperty<IconTextFitType> iconTextFit { IconTextFitType::None };
29+
LayoutProperty<std::array<float, 4>> iconTextFitPadding { {{ 0, 0, 0, 0 }} };
2830
LayoutProperty<std::string> iconImage { "" };
2931
LayoutProperty<float> iconRotate { 0 };
3032
LayoutProperty<float> iconPadding { 2 };

src/mbgl/style/property_evaluator.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ template <> inline Color defaultStopsValue() { return { 0, 0, 0, 1 }; }
1919
template <> inline std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; }
2020
template <> inline std::vector<std::string> defaultStopsValue() { return {{}}; }
2121
template <> inline std::array<float, 2> defaultStopsValue() { return {{ 0, 0 }}; }
22+
template <> inline std::array<float, 4> defaultStopsValue() { return {{ 0, 0, 0, 0 }}; }
2223

2324
template <> inline std::string defaultStopsValue() { return {}; }
2425
template <> inline TranslateAnchorType defaultStopsValue() { return {}; }
@@ -30,6 +31,7 @@ template <> inline TextAnchorType defaultStopsValue() { return {}; }
3031
template <> inline TextJustifyType defaultStopsValue() { return {}; }
3132
template <> inline TextTransformType defaultStopsValue() { return {}; }
3233
template <> inline AlignmentType defaultStopsValue() { return {}; }
34+
template <> inline IconTextFitType defaultStopsValue() { return {}; };
3335

3436
template <typename T>
3537
T PropertyEvaluator<T>::operator()(const Function<T>& fn) const {
@@ -87,6 +89,7 @@ template class PropertyEvaluator<Color>;
8789
template class PropertyEvaluator<std::vector<float>>;
8890
template class PropertyEvaluator<std::vector<std::string>>;
8991
template class PropertyEvaluator<std::array<float, 2>>;
92+
template class PropertyEvaluator<std::array<float, 4>>;
9093

9194
template class PropertyEvaluator<std::string>;
9295
template class PropertyEvaluator<TranslateAnchorType>;
@@ -98,6 +101,7 @@ template class PropertyEvaluator<TextAnchorType>;
98101
template class PropertyEvaluator<TextJustifyType>;
99102
template class PropertyEvaluator<TextTransformType>;
100103
template class PropertyEvaluator<AlignmentType>;
104+
template class PropertyEvaluator<IconTextFitType>;
101105

102106
template <typename T>
103107
Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const Undefined&) const {

src/mbgl/style/property_parsing.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,25 @@ optional<std::array<float, 2>> parseConstant(const char* name, const JSValue& va
7070
}
7171
}
7272

73+
template <>
74+
optional<std::array<float, 4>> parseConstant(const char* name, const JSValue& value) {
75+
if (value.IsArray() && value.Size() == 4 &&
76+
value[rapidjson::SizeType(0)].IsNumber() &&
77+
value[rapidjson::SizeType(1)].IsNumber() &&
78+
value[rapidjson::SizeType(2)].IsNumber() &&
79+
value[rapidjson::SizeType(3)].IsNumber()) {
80+
81+
float first = value[rapidjson::SizeType(0)].GetDouble();
82+
float second = value[rapidjson::SizeType(1)].GetDouble();
83+
float third = value[rapidjson::SizeType(2)].GetDouble();
84+
float fourth = value[rapidjson::SizeType(3)].GetDouble();
85+
return { {{ first, second, third, fourth }} };
86+
} else {
87+
Log::Warning(Event::ParseStyle, "value of '%s' must be an array of four numbers", name);
88+
return {};
89+
}
90+
}
91+
7392
template <>
7493
optional<std::vector<float>> parseConstant(const char* name, const JSValue& value) {
7594
if (!value.IsArray()) {

src/mbgl/style/types.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,11 @@ MBGL_DEFINE_ENUM(AlignmentType, {
7777
{ AlignmentType::Undefined, "undefined" },
7878
});
7979

80+
MBGL_DEFINE_ENUM(IconTextFitType, {
81+
{ IconTextFitType::None, "none" },
82+
{ IconTextFitType::Both, "both" },
83+
{ IconTextFitType::Width, "width" },
84+
{ IconTextFitType::Height, "height" },
85+
});
86+
8087
} // namespace mbgl

src/mbgl/text/quads.cpp

+38-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const float globalMinScale = 0.5f; // underscale by 1 zoom level
1515

1616
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
1717
const GeometryCoordinates& line, const SymbolLayoutProperties& layout,
18-
const bool alongLine) {
18+
const bool alongLine, const Shaping& shapedText) {
1919

2020
auto image = *(shapedIcon.image);
2121

@@ -24,11 +24,43 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
2424
auto right = left + image.pos.w / image.relativePixelRatio;
2525
auto top = shapedIcon.top - border;
2626
auto bottom = top + image.pos.h / image.relativePixelRatio;
27-
Point<float> tl{left, top};
28-
Point<float> tr{right, top};
29-
Point<float> br{right, bottom};
30-
Point<float> bl{left, bottom};
31-
27+
Point<float> tl;
28+
Point<float> tr;
29+
Point<float> br;
30+
Point<float> bl;
31+
32+
if (layout.iconTextFit != IconTextFitType::None && shapedText) {
33+
auto iconWidth = right - left;
34+
auto iconHeight = bottom - top;
35+
auto size = layout.textSize / 24.0f;
36+
auto textLeft = shapedText.left * size;
37+
auto textRight = shapedText.right * size;
38+
auto textTop = shapedText.top * size;
39+
auto textBottom = shapedText.bottom * size;
40+
auto textWidth = textRight - textLeft;
41+
auto textHeight = textBottom - textTop;;
42+
auto padT = layout.iconTextFitPadding.value[0];
43+
auto padR = layout.iconTextFitPadding.value[1];
44+
auto padB = layout.iconTextFitPadding.value[2];
45+
auto padL = layout.iconTextFitPadding.value[3];
46+
auto offsetY = layout.iconTextFit == IconTextFitType::Width ? (textHeight - iconHeight) * 0.5 : 0;
47+
auto offsetX = layout.iconTextFit == IconTextFitType::Height ? (textWidth - iconWidth) * 0.5 : 0;
48+
auto width = layout.iconTextFit == IconTextFitType::Width || layout.iconTextFit == IconTextFitType::Both ? textWidth : iconWidth;
49+
auto height = layout.iconTextFit == IconTextFitType::Height || layout.iconTextFit == IconTextFitType::Both ? textHeight : iconHeight;
50+
left = textLeft + offsetX - padL;
51+
top = textTop + offsetY - padT;
52+
right = textLeft + offsetX + padR + width;
53+
bottom = textTop + offsetY + padB + height;
54+
tl = {left, top};
55+
tr = {right, top};
56+
br = {right, bottom};
57+
bl = {left, bottom};
58+
} else {
59+
tl = {left, top};
60+
tr = {right, top};
61+
br = {right, bottom};
62+
bl = {left, bottom};
63+
}
3264

3365
float angle = layout.iconRotate * util::DEG2RAD;
3466
if (alongLine) {

src/mbgl/text/quads.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ typedef std::vector<SymbolQuad> SymbolQuads;
4040

4141
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
4242
const GeometryCoordinates& line, const style::SymbolLayoutProperties&,
43-
const bool alongLine);
43+
const bool alongLine, const Shaping& shapedText);
4444

4545
SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText,
4646
const float boxScale, const GeometryCoordinates& line, const style::SymbolLayoutProperties&,

test/test.gypi

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
'math/minmax.cpp',
5757
'math/clamp.cpp',
5858

59+
'text/quads.cpp',
60+
5961
'tile/geometry_tile_data.cpp',
6062
'tile/tile_id.cpp',
6163

0 commit comments

Comments
 (0)