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

Commit

Permalink
Support for icon-text-fit, icon-text-fit-padding (#5334)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
yhahn authored Jun 15, 2016
1 parent a020e53 commit 199ea2a
Show file tree
Hide file tree
Showing 16 changed files with 384 additions and 10 deletions.
6 changes: 6 additions & 0 deletions include/mbgl/style/layers/symbol_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ class SymbolLayer : public Layer {
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>);

Expand Down
7 changes: 7 additions & 0 deletions include/mbgl/style/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,12 @@ enum class TextTransformType : uint8_t {
Lowercase,
};

enum class IconTextFitType : uint8_t {
None,
Both,
Width,
Height
};

} // namespace style
} // namespace mbgl
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 8 additions & 0 deletions platform/node/src/node_style.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,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 {
Expand Down
3 changes: 3 additions & 0 deletions platform/node/src/node_style_properties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/renderer/symbol_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions src/mbgl/style/layers/symbol_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
4 changes: 4 additions & 0 deletions src/mbgl/style/layers/symbol_layer_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/style/layers/symbol_layer_properties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class SymbolLayoutProperties {
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 };
Expand Down
4 changes: 4 additions & 0 deletions src/mbgl/style/property_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}; }
Expand All @@ -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 {
Expand Down Expand Up @@ -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>;
Expand All @@ -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 {
Expand Down
19 changes: 19 additions & 0 deletions src/mbgl/style/property_parsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,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()) {
Expand Down
7 changes: 7 additions & 0 deletions src/mbgl/style/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
44 changes: 38 additions & 6 deletions src/mbgl/text/quads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/text/quads.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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&,
Expand Down
2 changes: 2 additions & 0 deletions test/test.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
'math/minmax.cpp',
'math/clamp.cpp',

'text/quads.cpp',

'tile/geometry_tile_data.cpp',
'tile/tile_id.cpp',

Expand Down
Loading

0 comments on commit 199ea2a

Please sign in to comment.