From ecd4aa14397ed081a521d8412557724e52f277f3 Mon Sep 17 00:00:00 2001 From: Young Hahn Date: Fri, 10 Jun 2016 23:05:15 -0400 Subject: [PATCH] text-pitch-alignment (#5288) * First pass at port of https://github.com/mapbox/mapbox-gl-js/pull/2668 * RotationAlignmentType => AlignmentType * Handle undefined default value for text-pitch-alignment and implement inheritance for this value from text-rotation-alignment * Update dependencies * Move handling fo undefined default value out of camelize functions --- include/mbgl/style/layers/symbol_layer.hpp | 11 ++++--- include/mbgl/style/types.hpp | 3 +- package.json | 6 ++-- scripts/generate-style-code.js | 10 +++++-- src/mbgl/geometry/icon_buffer.cpp | 3 +- src/mbgl/geometry/icon_buffer.hpp | 2 +- src/mbgl/geometry/text_buffer.cpp | 3 +- src/mbgl/geometry/text_buffer.hpp | 2 +- src/mbgl/renderer/painter.hpp | 3 +- src/mbgl/renderer/painter_symbol.cpp | 30 ++++++++++++------- src/mbgl/renderer/symbol_bucket.cpp | 21 +++++++------ src/mbgl/shader/icon_shader.hpp | 2 +- src/mbgl/shader/sdf_shader.hpp | 6 +++- src/mbgl/style/layers/symbol_layer.cpp | 15 +++++++--- src/mbgl/style/layers/symbol_layer_impl.cpp | 9 ++++-- .../style/layers/symbol_layer_properties.cpp | 2 ++ .../style/layers/symbol_layer_properties.hpp | 5 ++-- src/mbgl/style/property_evaluator.cpp | 4 +-- src/mbgl/style/property_parsing.cpp | 10 +++---- src/mbgl/style/property_parsing.hpp | 2 +- src/mbgl/text/quads.cpp | 16 +++++----- src/mbgl/text/quads.hpp | 7 +++-- 22 files changed, 107 insertions(+), 65 deletions(-) diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index 3806310c956..676d90d5b93 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -47,8 +47,8 @@ class SymbolLayer : public Layer { PropertyValue getIconOptional() const; void setIconOptional(PropertyValue); - PropertyValue getIconRotationAlignment() const; - void setIconRotationAlignment(PropertyValue); + PropertyValue getIconRotationAlignment() const; + void setIconRotationAlignment(PropertyValue); PropertyValue getIconSize() const; void setIconSize(PropertyValue); @@ -68,8 +68,11 @@ class SymbolLayer : public Layer { PropertyValue> getIconOffset() const; void setIconOffset(PropertyValue>); - PropertyValue getTextRotationAlignment() const; - void setTextRotationAlignment(PropertyValue); + PropertyValue getTextPitchAlignment() const; + void setTextPitchAlignment(PropertyValue); + + PropertyValue getTextRotationAlignment() const; + void setTextRotationAlignment(PropertyValue); PropertyValue getTextField() const; void setTextField(PropertyValue); diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp index 27b524a800f..3be7b5d9c70 100644 --- a/include/mbgl/style/types.hpp +++ b/include/mbgl/style/types.hpp @@ -58,9 +58,10 @@ enum class SymbolPlacementType : bool { Line, }; -enum class RotationAlignmentType : bool { +enum class AlignmentType : uint8_t { Map, Viewport, + Undefined, }; enum class TextJustifyType : uint8_t { diff --git a/package.json b/package.json index 20865b60506..acfd3e11122 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "csscolorparser": "^1.0.2", "ejs": "^2.4.1", "express": "^4.11.1", - "mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#f0b94dcc5f782958e9aade61d592a207d8a46e0f", - "mapbox-gl-style-spec": "^8.5.1", - "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#3e27bc27ea050952481ef1f9a655538590eccb26", + "mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#30caf388dbddd02cfc4f967ffc94c1338c30fbf8", + "mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#2461efc3d883f2f2e56a6c6b2bfd7d54bbfe9f86", + "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#5587d796c99145991ea2a7b749a8782b7a0cb483", "node-gyp": "^3.3.1", "request": "^2.72.0", "tape": "^4.5.1" diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js index 63795984467..1796cda2123 100644 --- a/scripts/generate-style-code.js +++ b/scripts/generate-style-code.js @@ -21,8 +21,8 @@ global.propertyType = function (property) { if (/-translate-anchor$/.test(property.name)) { return 'TranslateAnchorType'; } - if (/-rotation-alignment$/.test(property.name)) { - return 'RotationAlignmentType'; + if (/-(rotation|pitch)-alignment$/.test(property.name)) { + return 'AlignmentType'; } switch (property.type) { case 'boolean': @@ -57,7 +57,11 @@ global.defaultValue = function (property) { case 'string': return JSON.stringify(property.default || ""); case 'enum': - return `${propertyType(property)}::${camelize(property.default)}`; + if (property.default === undefined) { + return `${propertyType(property)}::Undefined`; + } else { + return `${propertyType(property)}::${camelize(property.default)}`; + } case 'color': return `{{ ${parseCSSColor(property.default).join(', ')} }}` case 'array': diff --git a/src/mbgl/geometry/icon_buffer.cpp b/src/mbgl/geometry/icon_buffer.cpp index 101132ddbc9..51a4aa69fdb 100644 --- a/src/mbgl/geometry/icon_buffer.cpp +++ b/src/mbgl/geometry/icon_buffer.cpp @@ -6,7 +6,7 @@ namespace mbgl { -size_t IconVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, int16_t tx, int16_t ty, float minzoom, float maxzoom, float labelminzoom) { +size_t IconVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, int16_t tx, int16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle) { const size_t idx = index(); void *data = addElement(); @@ -21,6 +21,7 @@ size_t IconVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, int16_t t ubytes[8] /* tex */ = tx / 4; ubytes[9] /* tex */ = ty / 4; ubytes[10] /* labelminzoom */ = labelminzoom * 10; + ubytes[11] /* labelangle */ = labelangle; // a_data2 ubytes[12] /* minzoom */ = minzoom * 10; // 1/10 zoom levels: z16 == 160. diff --git a/src/mbgl/geometry/icon_buffer.hpp b/src/mbgl/geometry/icon_buffer.hpp index 01166862657..3a1d57ccd72 100644 --- a/src/mbgl/geometry/icon_buffer.hpp +++ b/src/mbgl/geometry/icon_buffer.hpp @@ -10,7 +10,7 @@ namespace mbgl { 16 > { public: - size_t add(int16_t x, int16_t y, float ox, float oy, int16_t tx, int16_t ty, float minzoom, float maxzoom, float labelminzoom); + size_t add(int16_t x, int16_t y, float ox, float oy, int16_t tx, int16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle); }; diff --git a/src/mbgl/geometry/text_buffer.cpp b/src/mbgl/geometry/text_buffer.cpp index 1aa65146a43..382e87324d3 100644 --- a/src/mbgl/geometry/text_buffer.cpp +++ b/src/mbgl/geometry/text_buffer.cpp @@ -6,7 +6,7 @@ namespace mbgl { -size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom) { +size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle) { const size_t idx = index(); void *data = addElement(); @@ -21,6 +21,7 @@ size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t ubytes[8] /* tex */ = tx / 4; ubytes[9] /* tex */ = ty / 4; ubytes[10] /* labelminzoom */ = labelminzoom * 10; + ubytes[11] /* labelangle */ = labelangle; // a_data2 ubytes[12] /* minzoom */ = minzoom * 10; // 1/10 zoom levels: z16 == 160. diff --git a/src/mbgl/geometry/text_buffer.hpp b/src/mbgl/geometry/text_buffer.hpp index 8d7859fde29..c6b632c67ec 100644 --- a/src/mbgl/geometry/text_buffer.hpp +++ b/src/mbgl/geometry/text_buffer.hpp @@ -13,7 +13,7 @@ class TextVertexBuffer : public Buffer < public: typedef int16_t vertex_type; - size_t add(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom); + size_t add(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle); }; diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 25627a8d7a3..65573b65947 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -140,7 +140,8 @@ class Painter : private util::noncopyable { void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&), // Layout - style::RotationAlignmentType rotationAlignment, + style::AlignmentType rotationAlignment, + style::AlignmentType pitchAlignment, float layoutSize, // Paint diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index 3c453242ae7..d4d580e78da 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -24,7 +24,8 @@ void Painter::renderSDF(SymbolBucket &bucket, void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&), // Layout - RotationAlignmentType rotationAlignment, + AlignmentType rotationAlignment, + AlignmentType pitchAlignment, float layoutSize, // Paint @@ -45,10 +46,11 @@ void Painter::renderSDF(SymbolBucket &bucket, float scale = fontScale; std::array exScale = extrudeScale; - bool alignedWithMap = rotationAlignment == RotationAlignmentType::Map; + bool rotateWithMap = rotationAlignment == AlignmentType::Map; + bool pitchWithMap = pitchAlignment == AlignmentType::Map; float gammaScale = 1.0f; - if (alignedWithMap) { + if (pitchWithMap) { scale *= tileID.pixelsToTileUnits(1, state.getZoom()); exScale.fill(scale); gammaScale /= std::cos(state.getPitch()); @@ -60,8 +62,12 @@ void Painter::renderSDF(SymbolBucket &bucket, sdfShader.u_matrix = vtxMatrix; sdfShader.u_extrude_scale = exScale; sdfShader.u_texsize = texsize; - sdfShader.u_skewed = alignedWithMap; + sdfShader.u_rotate_with_map = rotateWithMap; + sdfShader.u_pitch_with_map = pitchWithMap; sdfShader.u_texture = 0; + sdfShader.u_pitch = state.getPitch() * util::DEG2RAD; + sdfShader.u_bearing = -1.0f * state.getAngle(); + sdfShader.u_aspect_ratio = (state.getWidth() * 1.0f) / (state.getHeight() * 1.0f); // adjust min/max zooms for variable font sies float zoomAdjust = std::log(fontSize / layoutSize) / std::log(2); @@ -135,7 +141,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, } if (bucket.hasIconData()) { - if (layout.iconRotationAlignment == RotationAlignmentType::Map) { + if (layout.iconRotationAlignment == AlignmentType::Map) { config.depthFunc.reset(); config.depthTest = GL_TRUE; } else { @@ -145,7 +151,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, bool sdf = bucket.sdfIcons; const float angleOffset = - layout.iconRotationAlignment == RotationAlignmentType::Map + layout.iconRotationAlignment == AlignmentType::Map ? state.getAngle() : 0; @@ -154,7 +160,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, SpriteAtlas* activeSpriteAtlas = layer.impl->spriteAtlas; const bool iconScaled = fontScale != 1 || frame.pixelRatio != activeSpriteAtlas->getPixelRatio() || bucket.iconsNeedLinear; - const bool iconTransformed = layout.iconRotationAlignment == RotationAlignmentType::Map || angleOffset != 0 || state.getPitch() != 0; + const bool iconTransformed = layout.iconRotationAlignment == AlignmentType::Map || angleOffset != 0 || state.getPitch() != 0; config.activeTexture = GL_TEXTURE0; activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed, store); @@ -167,6 +173,9 @@ void Painter::renderSymbol(SymbolBucket& bucket, *sdfIconShader, &SymbolBucket::drawIcons, layout.iconRotationAlignment, + // icon-pitch-alignment is not yet implemented + // and we simply inherit the rotation alignment + layout.iconRotationAlignment, layout.iconSize, paint.iconOpacity, paint.iconColor, @@ -182,7 +191,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, float scale = fontScale; std::array exScale = extrudeScale; - const bool alignedWithMap = layout.iconRotationAlignment == RotationAlignmentType::Map; + const bool alignedWithMap = layout.iconRotationAlignment == AlignmentType::Map; if (alignedWithMap) { scale *= tileID.pixelsToTileUnits(1, state.getZoom()); exScale.fill(scale); @@ -194,7 +203,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, iconShader->u_matrix = vtxMatrix; iconShader->u_extrude_scale = exScale; iconShader->u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }}; - iconShader->u_skewed = alignedWithMap; + iconShader->u_rotate_with_map = alignedWithMap; iconShader->u_texture = 0; // adjust min/max zooms for variable font sies @@ -212,7 +221,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, } if (bucket.hasTextData()) { - if (layout.textRotationAlignment == RotationAlignmentType::Map) { + if (layout.textRotationAlignment == AlignmentType::Map) { config.depthFunc.reset(); config.depthTest = GL_TRUE; } else { @@ -230,6 +239,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, *sdfGlyphShader, &SymbolBucket::drawGlyphs, layout.textRotationAlignment, + layout.textPitchAlignment, layout.textSize, paint.textOpacity, paint.textColor, diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index f4e55432c13..fb312661a7b 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -314,10 +314,10 @@ void SymbolBucket::addFeature(const GeometryCollection &lines, const float iconPadding = layout.iconPadding * tilePixelRatio; const float textMaxAngle = layout.textMaxAngle * util::DEG2RAD; const bool textAlongLine = - layout.textRotationAlignment == RotationAlignmentType::Map && + layout.textRotationAlignment == AlignmentType::Map && layout.symbolPlacement == SymbolPlacementType::Line; const bool iconAlongLine = - layout.iconRotationAlignment == RotationAlignmentType::Map && + layout.iconRotationAlignment == AlignmentType::Map && layout.symbolPlacement == SymbolPlacementType::Line; const bool mayOverlap = layout.textAllowOverlap || layout.iconAllowOverlap || layout.textIgnorePlacement || layout.iconIgnorePlacement; @@ -394,10 +394,10 @@ void SymbolBucket::placeFeatures(CollisionTile& collisionTile) { // create the bufers used for rendering. const bool textAlongLine = - layout.textRotationAlignment == RotationAlignmentType::Map && + layout.textRotationAlignment == AlignmentType::Map && layout.symbolPlacement == SymbolPlacementType::Line; const bool iconAlongLine = - layout.iconRotationAlignment == RotationAlignmentType::Map && + layout.iconRotationAlignment == AlignmentType::Map && layout.symbolPlacement == SymbolPlacementType::Line; const bool mayOverlap = layout.textAllowOverlap || layout.iconAllowOverlap || @@ -495,7 +495,7 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float const auto &anchorPoint = symbol.anchorPoint; // drop upside down versions of glyphs - const float a = std::fmod(symbol.angle + placementAngle + M_PI, M_PI * 2); + const float a = std::fmod(symbol.anchorAngle + placementAngle + M_PI, M_PI * 2); if (keepUpright && alongLine && (a <= M_PI / 2 || a > M_PI * 3 / 2)) continue; @@ -521,15 +521,18 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float auto &triangleGroup = *buffer.groups.back(); GLsizei triangleIndex = triangleGroup.vertex_length; + // Encode angle of glyph + uint8_t glyphAngle = std::round((symbol.glyphAngle / (M_PI * 2)) * 256); + // coordinates (2 triangles) buffer.vertices.add(anchorPoint.x, anchorPoint.y, tl.x, tl.y, tex.x, tex.y, minZoom, - maxZoom, placementZoom); + maxZoom, placementZoom, glyphAngle); buffer.vertices.add(anchorPoint.x, anchorPoint.y, tr.x, tr.y, tex.x + tex.w, tex.y, - minZoom, maxZoom, placementZoom); + minZoom, maxZoom, placementZoom, glyphAngle); buffer.vertices.add(anchorPoint.x, anchorPoint.y, bl.x, bl.y, tex.x, tex.y + tex.h, - minZoom, maxZoom, placementZoom); + minZoom, maxZoom, placementZoom, glyphAngle); buffer.vertices.add(anchorPoint.x, anchorPoint.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h, - minZoom, maxZoom, placementZoom); + minZoom, maxZoom, placementZoom, glyphAngle); // add the two triangles, referencing the four coordinates we just inserted. buffer.triangles.add(triangleIndex + 0, triangleIndex + 1, triangleIndex + 2); diff --git a/src/mbgl/shader/icon_shader.hpp b/src/mbgl/shader/icon_shader.hpp index b8cfcabb10b..ed1861d1bbd 100644 --- a/src/mbgl/shader/icon_shader.hpp +++ b/src/mbgl/shader/icon_shader.hpp @@ -16,7 +16,7 @@ class IconShader : public Shader { Uniform u_zoom = {"u_zoom", *this}; Uniform u_opacity = {"u_opacity", *this}; Uniform> u_texsize = {"u_texsize", *this}; - Uniform u_skewed = {"u_skewed", *this}; + Uniform u_rotate_with_map = {"u_rotate_with_map", *this}; Uniform u_texture = {"u_texture", *this}; Uniform u_fadetexture = {"u_fadetexture", *this}; diff --git a/src/mbgl/shader/sdf_shader.hpp b/src/mbgl/shader/sdf_shader.hpp index f067c30aeb2..6889288c284 100644 --- a/src/mbgl/shader/sdf_shader.hpp +++ b/src/mbgl/shader/sdf_shader.hpp @@ -17,7 +17,11 @@ class SDFShader : public Shader { Uniform u_buffer = {"u_buffer", *this}; Uniform u_gamma = {"u_gamma", *this}; Uniform u_zoom = {"u_zoom", *this}; - Uniform u_skewed = {"u_skewed", *this}; + Uniform u_pitch = {"u_pitch", *this}; + Uniform u_bearing = {"u_bearing", *this}; + Uniform u_aspect_ratio = {"u_aspect_ratio", *this}; + Uniform u_rotate_with_map = {"u_rotate_with_map",*this}; + Uniform u_pitch_with_map = {"u_pitch_with_map",*this}; Uniform u_texture = {"u_texture", *this}; Uniform u_fadetexture = {"u_fadetexture", *this}; diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp index d7d6a02acee..282873b5016 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -92,11 +92,11 @@ PropertyValue SymbolLayer::getIconOptional() const { void SymbolLayer::setIconOptional(PropertyValue value) { impl->layout.iconOptional.set(value); } -PropertyValue SymbolLayer::getIconRotationAlignment() const { +PropertyValue SymbolLayer::getIconRotationAlignment() const { return impl->layout.iconRotationAlignment.get(); } -void SymbolLayer::setIconRotationAlignment(PropertyValue value) { +void SymbolLayer::setIconRotationAlignment(PropertyValue value) { impl->layout.iconRotationAlignment.set(value); } PropertyValue SymbolLayer::getIconSize() const { @@ -141,11 +141,18 @@ PropertyValue> SymbolLayer::getIconOffset() const { void SymbolLayer::setIconOffset(PropertyValue> value) { impl->layout.iconOffset.set(value); } -PropertyValue SymbolLayer::getTextRotationAlignment() const { +PropertyValue SymbolLayer::getTextPitchAlignment() const { + return impl->layout.textPitchAlignment.get(); +} + +void SymbolLayer::setTextPitchAlignment(PropertyValue value) { + impl->layout.textPitchAlignment.set(value); +} +PropertyValue SymbolLayer::getTextRotationAlignment() const { return impl->layout.textRotationAlignment.get(); } -void SymbolLayer::setTextRotationAlignment(PropertyValue value) { +void SymbolLayer::setTextRotationAlignment(PropertyValue value) { impl->layout.textRotationAlignment.set(value); } PropertyValue SymbolLayer::getTextField() const { diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp index a4dc264ed2f..34438285c5c 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.cpp +++ b/src/mbgl/style/layers/symbol_layer_impl.cpp @@ -45,8 +45,13 @@ std::unique_ptr SymbolLayer::Impl::createBucket(BucketParameters& parame CalculationParameters p(parameters.tileID.overscaledZ); bucket->layout.symbolPlacement.calculate(p); if (bucket->layout.symbolPlacement.value == SymbolPlacementType::Line) { - bucket->layout.iconRotationAlignment.value = RotationAlignmentType::Map; - bucket->layout.textRotationAlignment.value = RotationAlignmentType::Map; + bucket->layout.iconRotationAlignment.value = AlignmentType::Map; + bucket->layout.textRotationAlignment.value = AlignmentType::Map; + }; + + // If unspecified `text-pitch-alignment` inherits `text-rotation-alignment` + if (bucket->layout.textPitchAlignment.value == AlignmentType::Undefined) { + bucket->layout.textPitchAlignment.value = bucket->layout.textRotationAlignment.value; }; bucket->layout.recalculate(p); diff --git a/src/mbgl/style/layers/symbol_layer_properties.cpp b/src/mbgl/style/layers/symbol_layer_properties.cpp index ce16ae2e50b..5c6f65112dd 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.cpp +++ b/src/mbgl/style/layers/symbol_layer_properties.cpp @@ -19,6 +19,7 @@ void SymbolLayoutProperties::parse(const JSValue& value) { iconPadding.parse("icon-padding", value); iconKeepUpright.parse("icon-keep-upright", value); iconOffset.parse("icon-offset", value); + textPitchAlignment.parse("text-pitch-alignment", value); textRotationAlignment.parse("text-rotation-alignment", value); textField.parse("text-field", value); textFont.parse("text-font", value); @@ -53,6 +54,7 @@ void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters iconPadding.calculate(parameters); iconKeepUpright.calculate(parameters); iconOffset.calculate(parameters); + textPitchAlignment.calculate(parameters); textRotationAlignment.calculate(parameters); textField.calculate(parameters); textFont.calculate(parameters); diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp index 38455b5cac6..e938a09c56a 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.hpp +++ b/src/mbgl/style/layers/symbol_layer_properties.hpp @@ -23,14 +23,15 @@ class SymbolLayoutProperties { LayoutProperty iconAllowOverlap { false }; LayoutProperty iconIgnorePlacement { false }; LayoutProperty iconOptional { false }; - LayoutProperty iconRotationAlignment { RotationAlignmentType::Viewport }; + LayoutProperty iconRotationAlignment { AlignmentType::Viewport }; LayoutProperty iconSize { 1 }; LayoutProperty iconImage { "" }; LayoutProperty iconRotate { 0 }; LayoutProperty iconPadding { 2 }; LayoutProperty iconKeepUpright { false }; LayoutProperty> iconOffset { {{ 0, 0 }} }; - LayoutProperty textRotationAlignment { RotationAlignmentType::Viewport }; + LayoutProperty textPitchAlignment { AlignmentType::Undefined }; + LayoutProperty textRotationAlignment { AlignmentType::Viewport }; LayoutProperty textField { "" }; LayoutProperty> textFont { { "Open Sans Regular", "Arial Unicode MS Regular" } }; LayoutProperty textSize { 16 }; diff --git a/src/mbgl/style/property_evaluator.cpp b/src/mbgl/style/property_evaluator.cpp index d2e633c7822..ce132e0b5b5 100644 --- a/src/mbgl/style/property_evaluator.cpp +++ b/src/mbgl/style/property_evaluator.cpp @@ -29,7 +29,7 @@ template <> inline SymbolPlacementType defaultStopsValue() { return {}; }; template <> inline TextAnchorType defaultStopsValue() { return {}; }; template <> inline TextJustifyType defaultStopsValue() { return {}; }; template <> inline TextTransformType defaultStopsValue() { return {}; }; -template <> inline RotationAlignmentType defaultStopsValue() { return {}; }; +template <> inline AlignmentType defaultStopsValue() { return {}; }; template T PropertyEvaluator::operator()(const Function& fn) const { @@ -97,7 +97,7 @@ template class PropertyEvaluator; template class PropertyEvaluator; template class PropertyEvaluator; template class PropertyEvaluator; -template class PropertyEvaluator; +template class PropertyEvaluator; template Faded CrossFadedPropertyEvaluator::operator()(const Undefined&) const { diff --git a/src/mbgl/style/property_parsing.cpp b/src/mbgl/style/property_parsing.cpp index 9f60ddf3b63..ecfa85595d6 100644 --- a/src/mbgl/style/property_parsing.cpp +++ b/src/mbgl/style/property_parsing.cpp @@ -188,19 +188,19 @@ optional parseConstant(const char* name, c return { TextTransformTypeClass({ value.GetString(), value.GetStringLength() }) }; } -MBGL_DEFINE_ENUM_CLASS(RotationAlignmentTypeClass, RotationAlignmentType, { - { RotationAlignmentType::Map, "map" }, - { RotationAlignmentType::Viewport, "viewport" }, +MBGL_DEFINE_ENUM_CLASS(AlignmentTypeClass, AlignmentType, { + { AlignmentType::Map, "map" }, + { AlignmentType::Viewport, "viewport" }, }); template <> -optional parseConstant(const char* name, const JSValue& value) { +optional parseConstant(const char* name, const JSValue& value) { if (!value.IsString()) { Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); return {}; } - return { RotationAlignmentTypeClass({ value.GetString(), value.GetStringLength() }) }; + return { AlignmentTypeClass({ value.GetString(), value.GetStringLength() }) }; } template <> diff --git a/src/mbgl/style/property_parsing.hpp b/src/mbgl/style/property_parsing.hpp index bb894c24078..d2d283fe179 100644 --- a/src/mbgl/style/property_parsing.hpp +++ b/src/mbgl/style/property_parsing.hpp @@ -32,7 +32,7 @@ template <> optional parseConstant(const char*, const JSVal template <> optional parseConstant(const char*, const JSValue&); template <> optional parseConstant(const char*, const JSValue&); template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); +template <> optional parseConstant(const char*, const JSValue&); template <> optional> parseConstant(const char*, const JSValue&); template <> optional> parseConstant(const char*, const JSValue&); template <> optional> parseConstant(const char*, const JSValue&); diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index ce320791c34..eadfe5c1fd0 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -57,7 +57,7 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon, } SymbolQuads quads; - quads.emplace_back(tl, tr, bl, br, image.pos, 0, anchor.point, globalMinScale, std::numeric_limits::infinity()); + quads.emplace_back(tl, tr, bl, br, image.pos, 0, 0, anchor.point, globalMinScale, std::numeric_limits::infinity()); return quads; } @@ -102,8 +102,6 @@ void getSegmentGlyphs(std::back_insert_iterator glyphs, Anchor & float angle = std::atan2(end.y - newAnchorPoint.y, end.x - newAnchorPoint.x); if (!forward) angle += M_PI; - if (upsideDown) - angle += M_PI; glyphs = GlyphInstance{ /* anchor */ newAnchorPoint, @@ -188,12 +186,11 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, Point tr = otr; Point bl = obl; Point br = obr; - const float angle = instance.angle + textRotate; - if (angle) { + if (textRotate) { // Compute the transformation matrix. - float angle_sin = std::sin(angle); - float angle_cos = std::cos(angle); + float angle_sin = std::sin(textRotate); + float angle_cos = std::cos(textRotate); std::array matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}}; tl = util::matrixMultiply(matrix, tl); @@ -205,8 +202,9 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText, // Prevent label from extending past the end of the line const float glyphMinScale = std::max(instance.minScale, anchor.scale); - const float glyphAngle = std::fmod((anchor.angle + textRotate + instance.offset + 2 * M_PI), (2 * M_PI)); - quads.emplace_back(tl, tr, bl, br, rect, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale); + const float anchorAngle = std::fmod((anchor.angle + textRotate + instance.offset + 2 * M_PI), (2 * M_PI)); + const float glyphAngle = std::fmod((instance.angle + textRotate + instance.offset + 2 * M_PI), (2 * M_PI)); + quads.emplace_back(tl, tr, bl, br, rect, anchorAngle, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale); } diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp index 0627647f4c0..e78fe308e24 100644 --- a/src/mbgl/text/quads.hpp +++ b/src/mbgl/text/quads.hpp @@ -17,21 +17,22 @@ class SymbolLayoutProperties; struct SymbolQuad { explicit SymbolQuad(const Point &tl_, const Point &tr_, const Point &bl_, const Point &br_, - const Rect &tex_, float angle_, const Point &anchorPoint_, + const Rect &tex_, float anchorAngle_, float glyphAngle_, const Point &anchorPoint_, float minScale_, float maxScale_) : tl(tl_), tr(tr_), bl(bl_), br(br_), tex(tex_), - angle(angle_), + anchorAngle(anchorAngle_), + glyphAngle(glyphAngle_), anchorPoint(anchorPoint_), minScale(minScale_), maxScale(maxScale_) {} Point tl, tr, bl, br; Rect tex; - float angle; + float anchorAngle, glyphAngle; Point anchorPoint; float minScale, maxScale; };