diff options
Diffstat (limited to 'src/mbgl/layout/symbol_layout.cpp')
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 121 |
1 files changed, 66 insertions, 55 deletions
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 2accac281b..adc7eaaed8 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -1,12 +1,12 @@ #include <mbgl/layout/symbol_layout.hpp> #include <mbgl/layout/merge_lines.hpp> #include <mbgl/layout/clip_lines.hpp> -#include <mbgl/renderer/symbol_bucket.hpp> +#include <mbgl/renderer/buckets/symbol_bucket.hpp> #include <mbgl/style/filter_evaluator.hpp> #include <mbgl/renderer/bucket_parameters.hpp> -#include <mbgl/renderer/render_symbol_layer.hpp> +#include <mbgl/renderer/layers/render_symbol_layer.hpp> +#include <mbgl/renderer/image_atlas.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> -#include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/text/get_anchors.hpp> #include <mbgl/text/collision_tile.hpp> #include <mbgl/text/shaping.hpp> @@ -40,21 +40,22 @@ static bool has(const style::SymbolLayoutProperties::PossiblyEvaluated& layout) SymbolLayout::SymbolLayout(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers, - const GeometryTileLayer& sourceLayer, - IconDependencies& iconDependencies, + std::unique_ptr<GeometryTileLayer> sourceLayer_, + ImageDependencies& imageDependencies, GlyphDependencies& glyphDependencies) - : sourceLayerName(sourceLayer.getName()), + : sourceLayer(std::move(sourceLayer_)), bucketName(layers.at(0)->getID()), overscaling(parameters.tileID.overscaleFactor()), zoom(parameters.tileID.overscaledZ), mode(parameters.mode), + pixelRatio(parameters.pixelRatio), tileSize(util::tileSize * overscaling), tilePixelRatio(float(util::EXTENT) / tileSize), - textSize(layers.at(0)->as<RenderSymbolLayer>()->impl->layout.unevaluated.get<TextSize>()), - iconSize(layers.at(0)->as<RenderSymbolLayer>()->impl->layout.unevaluated.get<IconSize>()) + textSize(layers.at(0)->as<RenderSymbolLayer>()->impl().layout.get<TextSize>()), + iconSize(layers.at(0)->as<RenderSymbolLayer>()->impl().layout.get<IconSize>()) { - const SymbolLayer::Impl& leader = *layers.at(0)->as<RenderSymbolLayer>()->impl; + const SymbolLayer::Impl& leader = layers.at(0)->as<RenderSymbolLayer>()->impl(); layout = leader.layout.evaluate(PropertyEvaluationParameters(zoom)); @@ -94,9 +95,9 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, } // Determine glyph dependencies - const size_t featureCount = sourceLayer.featureCount(); + const size_t featureCount = sourceLayer->featureCount(); for (size_t i = 0; i < featureCount; ++i) { - auto feature = sourceLayer.getFeature(i); + auto feature = sourceLayer->getFeature(i); if (!leader.filter(feature->getType(), feature->getID(), [&] (const auto& key) { return feature->getValue(key); })) continue; @@ -136,12 +137,17 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, } ft.text = applyArabicShaping(util::utf8_to_utf16::convert(u8string)); + const bool canVerticalizeText = layout.get<TextRotationAlignment>() == AlignmentType::Map + && layout.get<SymbolPlacement>() == SymbolPlacementType::Line + && util::i18n::allowsVerticalWritingMode(*ft.text); // Loop through all characters of this text and collect unique codepoints. for (char16_t chr : *ft.text) { glyphDependencies[layout.get<TextFont>()].insert(chr); - if (char16_t verticalChr = util::i18n::verticalizePunctuation(chr)) { - glyphDependencies[layout.get<TextFont>()].insert(verticalChr); + if (canVerticalizeText) { + if (char16_t verticalChr = util::i18n::verticalizePunctuation(chr)) { + glyphDependencies[layout.get<TextFont>()].insert(verticalChr); + } } } } @@ -152,7 +158,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, icon = util::replaceTokens(icon, getValue); } ft.icon = icon; - iconDependencies.insert(*ft.icon); + imageDependencies.insert(*ft.icon); } if (ft.text || ft.icon) { @@ -169,7 +175,8 @@ bool SymbolLayout::hasSymbolInstances() const { return !symbolInstances.empty(); } -void SymbolLayout::prepare(const GlyphPositionMap& glyphs, const IconMap& icons) { +void SymbolLayout::prepare(const GlyphMap& glyphMap, const GlyphPositions& glyphPositions, + const ImageMap& imageMap, const ImagePositions& imagePositions) { float horizontalAlign = 0.5; float verticalAlign = 0.5; @@ -211,61 +218,65 @@ void SymbolLayout::prepare(const GlyphPositionMap& glyphs, const IconMap& icons) layout.get<TextJustify>() == TextJustifyType::Left ? 0 : 0.5; - const bool textAlongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map && layout.get<SymbolPlacement>() == SymbolPlacementType::Line; + auto glyphMapIt = glyphMap.find(layout.get<TextFont>()); + const Glyphs& glyphs = glyphMapIt != glyphMap.end() + ? glyphMapIt->second : Glyphs(); + + auto glyphPositionsIt = glyphPositions.find(layout.get<TextFont>()); + const GlyphPositionMap& glyphPositionMap = glyphPositionsIt != glyphPositions.end() + ? glyphPositionsIt->second : GlyphPositionMap(); + for (auto it = features.begin(); it != features.end(); ++it) { auto& feature = *it; if (feature.geometry.empty()) continue; std::pair<Shaping, Shaping> shapedTextOrientations; optional<PositionedIcon> shapedIcon; - GlyphPositions face; // if feature has text, shape the text if (feature.text) { - auto glyphPositions = glyphs.find(layout.get<TextFont>()); - if (glyphPositions != glyphs.end()) { // If there are no glyphs available for this feature, skip shaping - auto applyShaping = [&] (const std::u16string& text, WritingModeType writingMode) { - const float oneEm = 24.0f; - const Shaping result = getShaping( - /* string */ text, - /* maxWidth: ems */ layout.get<SymbolPlacement>() != SymbolPlacementType::Line ? - layout.get<TextMaxWidth>() * oneEm : 0, - /* lineHeight: ems */ layout.get<TextLineHeight>() * oneEm, - /* horizontalAlign */ horizontalAlign, - /* verticalAlign */ verticalAlign, - /* justify */ justify, - /* spacing: ems */ util::i18n::allowsLetterSpacing(*feature.text) ? layout.get<TextLetterSpacing>() * oneEm : 0.0f, - /* translate */ Point<float>(layout.evaluate<TextOffset>(zoom, feature)[0] * oneEm, layout.evaluate<TextOffset>(zoom, feature)[1] * oneEm), - /* verticalHeight */ oneEm, - /* writingMode */ writingMode, - /* bidirectional algorithm object */ bidi, - /* glyphs */ glyphPositions->second); - - return result; - }; - - shapedTextOrientations.first = applyShaping(*feature.text, WritingModeType::Horizontal); - - if (util::i18n::allowsVerticalWritingMode(*feature.text) && textAlongLine) { - shapedTextOrientations.second = applyShaping(util::i18n::verticalizePunctuation(*feature.text), WritingModeType::Vertical); - } + auto applyShaping = [&] (const std::u16string& text, WritingModeType writingMode) { + const float oneEm = 24.0f; + const Shaping result = getShaping( + /* string */ text, + /* maxWidth: ems */ layout.get<SymbolPlacement>() != SymbolPlacementType::Line ? + layout.get<TextMaxWidth>() * oneEm : 0, + /* lineHeight: ems */ layout.get<TextLineHeight>() * oneEm, + /* horizontalAlign */ horizontalAlign, + /* verticalAlign */ verticalAlign, + /* justify */ justify, + /* spacing: ems */ util::i18n::allowsLetterSpacing(*feature.text) ? layout.get<TextLetterSpacing>() * oneEm : 0.0f, + /* translate */ Point<float>(layout.evaluate<TextOffset>(zoom, feature)[0] * oneEm, layout.evaluate<TextOffset>(zoom, feature)[1] * oneEm), + /* verticalHeight */ oneEm, + /* writingMode */ writingMode, + /* bidirectional algorithm object */ bidi, + /* glyphs */ glyphs); + + return result; + }; + + shapedTextOrientations.first = applyShaping(*feature.text, WritingModeType::Horizontal); + + if (util::i18n::allowsVerticalWritingMode(*feature.text) && textAlongLine) { + shapedTextOrientations.second = applyShaping(util::i18n::verticalizePunctuation(*feature.text), WritingModeType::Vertical); } } // if feature has icon, get sprite atlas position if (feature.icon) { - auto image = icons.find(*feature.icon); - if (image != icons.end()) { - shapedIcon = PositionedIcon::shapeIcon(image->second, + auto image = imageMap.find(*feature.icon); + if (image != imageMap.end()) { + shapedIcon = PositionedIcon::shapeIcon( + imagePositions.at(*feature.icon), layout.evaluate<IconOffset>(zoom, feature), layout.evaluate<IconRotate>(zoom, feature) * util::DEG2RAD); - if (image->second.sdf) { + if (image->second->sdf) { sdfIcons = true; } - if (image->second.relativePixelRatio != 1.0f) { + if (image->second->pixelRatio != pixelRatio) { iconsNeedLinear = true; } else if (layout.get<IconRotate>().constantOr(1) != 0) { iconsNeedLinear = true; @@ -275,8 +286,7 @@ void SymbolLayout::prepare(const GlyphPositionMap& glyphs, const IconMap& icons) // if either shapedText or icon position is present, add the feature if (shapedTextOrientations.first || shapedIcon) { - auto glyphPositionsIt = glyphs.find(layout.get<TextFont>()); - addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, glyphPositionsIt == glyphs.end() ? GlyphPositions() : glyphPositionsIt->second); + addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, glyphPositionMap); } feature.geometry.clear(); @@ -289,7 +299,7 @@ void SymbolLayout::addFeature(const std::size_t index, const SymbolFeature& feature, const std::pair<Shaping, Shaping>& shapedTextOrientations, optional<PositionedIcon> shapedIcon, - const GlyphPositions& glyphs) { + const GlyphPositionMap& glyphPositionMap) { const float minScale = 0.5f; const float glyphSize = 24.0f; @@ -318,8 +328,9 @@ void SymbolLayout::addFeature(const std::size_t index, ? SymbolPlacementType::Point : layout.get<SymbolPlacement>(); const float textRepeatDistance = symbolSpacing / 2; - IndexedSubfeature indexedFeature = {feature.index, sourceLayerName, bucketName, symbolInstances.size()}; - + IndexedSubfeature indexedFeature = { feature.index, sourceLayer->getName(), bucketName, + symbolInstances.size() }; + auto addSymbolInstance = [&] (const GeometryCoordinates& line, Anchor& anchor) { // https://github.com/mapbox/vector-tile-spec/tree/master/2.1#41-layers // +-------------------+ Symbols with anchors located on tile edges @@ -346,7 +357,7 @@ void SymbolLayout::addFeature(const std::size_t index, addToBuffers, symbolInstances.size(), textBoxScale, textPadding, textPlacement, iconBoxScale, iconPadding, iconPlacement, - glyphs, indexedFeature, index); + glyphPositionMap, indexedFeature, index); }; const auto& type = feature.getType(); |