diff options
author | Chris Loer <chris.loer@gmail.com> | 2018-10-02 17:03:50 -0700 |
---|---|---|
committer | Chris Loer <chris.loer@mapbox.com> | 2018-10-15 13:15:46 -0700 |
commit | ce76bde13d0f4381ee861f81daf636defaff0bc5 (patch) | |
tree | e37d93d14fc64620069bac5488bae871af2fa431 /src/mbgl/layout/symbol_layout.cpp | |
parent | bc718257748f1ad87658e85f8c31b574afca57a9 (diff) | |
download | qtlocation-mapboxgl-ce76bde13d0f4381ee861f81daf636defaff0bc5.tar.gz |
[core] Initial implementation of 'format' expression
Diffstat (limited to 'src/mbgl/layout/symbol_layout.cpp')
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 80 |
1 files changed, 42 insertions, 38 deletions
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 74abd74f01..f4a55a1f91 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -108,28 +108,40 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, ft.index = i; if (hasText) { - std::string u8string = layout.evaluate<TextField>(zoom, ft); - + auto formatted = layout.evaluate<TextField>(zoom, ft); auto textTransform = layout.evaluate<TextTransform>(zoom, ft); - if (textTransform == TextTransformType::Uppercase) { - u8string = platform::uppercase(u8string); - } else if (textTransform == TextTransformType::Lowercase) { - u8string = platform::lowercase(u8string); + FontStack baseFontStack = layout.evaluate<TextFont>(zoom, ft); + FontStackHash baseFontStackHash = FontStackHasher()(baseFontStack); + + ft.formattedText = TaggedString(); + for (std::size_t j = 0; j < formatted.sections.size(); j++) { + const auto& section = formatted.sections[j]; + std::string u8string = section.text; + if (textTransform == TextTransformType::Uppercase) { + u8string = platform::uppercase(u8string); + } else if (textTransform == TextTransformType::Lowercase) { + u8string = platform::lowercase(u8string); + } + + ft.formattedText->addSection(applyArabicShaping(util::utf8_to_utf16::convert(u8string)), + section.fontScale ? *section.fontScale : 1.0, + section.fontStack ? FontStackHasher()(*section.fontStack) : baseFontStackHash); + } - ft.text = applyArabicShaping(util::utf8_to_utf16::convert(u8string)); + const bool canVerticalizeText = layout.get<TextRotationAlignment>() == AlignmentType::Map && layout.get<SymbolPlacement>() != SymbolPlacementType::Point - && util::i18n::allowsVerticalWritingMode(*ft.text); - - FontStack fontStack = layout.evaluate<TextFont>(zoom, ft); - GlyphIDs& dependencies = glyphDependencies[fontStack]; - + && util::i18n::allowsVerticalWritingMode(ft.formattedText->rawText()); + // Loop through all characters of this text and collect unique codepoints. - for (char16_t chr : *ft.text) { - dependencies.insert(chr); + for (std::size_t j = 0; j < ft.formattedText->length(); j++) { + const auto& sectionFontStack = formatted.sections[ft.formattedText->getSectionIndex(j)].fontStack; + GlyphIDs& dependencies = glyphDependencies[sectionFontStack ? *sectionFontStack : baseFontStack]; + char16_t codePoint = ft.formattedText->getCharCodeAt(j); + dependencies.insert(codePoint); if (canVerticalizeText) { - if (char16_t verticalChr = util::i18n::verticalizePunctuation(chr)) { + if (char16_t verticalChr = util::i18n::verticalizePunctuation(codePoint)) { dependencies.insert(verticalChr); } } @@ -141,7 +153,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, imageDependencies.emplace(*ft.icon, ImageType::Icon); } - if (ft.text || ft.icon) { + if (ft.formattedText || ft.icon) { features.push_back(std::move(ft)); } } @@ -168,44 +180,35 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions auto& feature = *it; if (feature.geometry.empty()) continue; - FontStack fontStack = layout.evaluate<TextFont>(zoom, feature); - - auto glyphMapIt = glyphMap.find(fontStack); - const Glyphs& glyphs = glyphMapIt != glyphMap.end() - ? glyphMapIt->second : Glyphs(); - - auto glyphPositionsIt = glyphPositions.find(fontStack); - const GlyphPositionMap& glyphPositionMap = glyphPositionsIt != glyphPositions.end() - ? glyphPositionsIt->second : GlyphPositionMap(); - std::pair<Shaping, Shaping> shapedTextOrientations; optional<PositionedIcon> shapedIcon; // if feature has text, shape the text - if (feature.text) { - auto applyShaping = [&] (const std::u16string& text, WritingModeType writingMode) { + if (feature.formattedText) { + auto applyShaping = [&] (const TaggedString& formattedText, WritingModeType writingMode) { const float oneEm = 24.0f; const Shaping result = getShaping( - /* string */ text, + /* string */ formattedText, /* maxWidth: ems */ layout.get<SymbolPlacement>() == SymbolPlacementType::Point ? layout.evaluate<TextMaxWidth>(zoom, feature) * oneEm : 0, /* lineHeight: ems */ layout.get<TextLineHeight>() * oneEm, /* anchor */ layout.evaluate<TextAnchor>(zoom, feature), /* justify */ layout.evaluate<TextJustify>(zoom, feature), - /* spacing: ems */ util::i18n::allowsLetterSpacing(*feature.text) ? layout.evaluate<TextLetterSpacing>(zoom, feature) * oneEm : 0.0f, + /* spacing: ems */ util::i18n::allowsLetterSpacing(feature.formattedText->rawText()) ? layout.evaluate<TextLetterSpacing>(zoom, feature) * 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); + /* glyphs */ glyphMap); return result; }; - shapedTextOrientations.first = applyShaping(*feature.text, WritingModeType::Horizontal); + shapedTextOrientations.first = applyShaping(*feature.formattedText, WritingModeType::Horizontal); - if (util::i18n::allowsVerticalWritingMode(*feature.text) && textAlongLine) { - shapedTextOrientations.second = applyShaping(util::i18n::verticalizePunctuation(*feature.text), WritingModeType::Vertical); + if (util::i18n::allowsVerticalWritingMode(feature.formattedText->rawText()) && textAlongLine) { + feature.formattedText->verticalizePunctuation(); + shapedTextOrientations.second = applyShaping(*feature.formattedText, WritingModeType::Vertical); } } @@ -231,7 +234,7 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions // if either shapedText or icon position is present, add the feature if (shapedTextOrientations.first || shapedIcon) { - addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, glyphPositionMap); + addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, glyphPositions); } feature.geometry.clear(); @@ -244,7 +247,7 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, const SymbolFeature& feature, const std::pair<Shaping, Shaping>& shapedTextOrientations, optional<PositionedIcon> shapedIcon, - const GlyphPositionMap& glyphPositionMap) { + const GlyphPositions& glyphPositions) { const float minScale = 0.5f; const float glyphSize = 24.0f; @@ -287,7 +290,8 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, layout.evaluate(zoom, feature), layoutTextSize, textBoxScale, textPadding, textPlacement, textOffset, iconBoxScale, iconPadding, iconOffset, - glyphPositionMap, indexedFeature, layoutFeatureIndex, feature.index, feature.text.value_or(std::u16string()), overscaling); + glyphPositions, indexedFeature, layoutFeatureIndex, feature.index, + feature.formattedText ? feature.formattedText->rawText() : std::u16string(), overscaling); } }; @@ -308,7 +312,7 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, overscaling); for (auto& anchor : anchors) { - if (!feature.text || !anchorIsTooClose(*feature.text, textRepeatDistance, anchor)) { + if (!feature.formattedText || !anchorIsTooClose(feature.formattedText->rawText(), textRepeatDistance, anchor)) { addSymbolInstance(line, anchor); } } |