From 3bfdb110646f33953fe7c44a6f4db7cdbb540d6a Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 4 Mar 2019 09:21:39 +0200 Subject: [core] Assign formatted section index to quads --- platform/default/src/mbgl/text/bidi.cpp | 2 +- platform/qt/src/bidi.cpp | 2 +- src/mbgl/text/bidi.hpp | 2 +- src/mbgl/text/glyph.hpp | 8 +++++--- src/mbgl/text/quads.cpp | 2 +- src/mbgl/text/quads.hpp | 7 +++++-- src/mbgl/text/shaping.cpp | 7 ++++--- src/mbgl/text/tagged_string.cpp | 24 ++++++++++++++++++++---- src/mbgl/text/tagged_string.hpp | 25 ++++++++++++++++++------- test/text/bidi.test.cpp | 10 +++++----- test/text/tagged_string.test.cpp | 10 +++++----- test/util/merge_lines.test.cpp | 2 +- 12 files changed, 67 insertions(+), 34 deletions(-) diff --git a/platform/default/src/mbgl/text/bidi.cpp b/platform/default/src/mbgl/text/bidi.cpp index 32a3dc23ef..8e30017f5f 100644 --- a/platform/default/src/mbgl/text/bidi.cpp +++ b/platform/default/src/mbgl/text/bidi.cpp @@ -148,7 +148,7 @@ std::vector BiDi::processStyledText(const StyledText& input, std::se // Each time we see a change in style, render a reversed chunk // of everything since the last change std::size_t styleRunStart = logicalEnd; - uint8_t currentStyleIndex = styleIndices.at(styleRunStart - 1); + std::size_t currentStyleIndex = styleIndices.at(styleRunStart - 1); for (std::size_t i = logicalEnd - 1; i >= logicalStart; i--) { if (currentStyleIndex != styleIndices.at(i) || i == logicalStart) { std::size_t styleRunEnd = i == logicalStart ? i : i + 1; diff --git a/platform/qt/src/bidi.cpp b/platform/qt/src/bidi.cpp index 6b680a9769..a99398959a 100644 --- a/platform/qt/src/bidi.cpp +++ b/platform/qt/src/bidi.cpp @@ -41,7 +41,7 @@ std::vector BiDi::processStyledText(const StyledText& input, std::se for (std::size_t lineBreakPoint : lineBreakPoints) { transformedLines.emplace_back( input.first.substr(start, lineBreakPoint - start), - std::vector(input.second.begin() + start, input.second.begin() + lineBreakPoint)); + std::vector(input.second.begin() + start, input.second.begin() + lineBreakPoint)); start = lineBreakPoint; } diff --git a/src/mbgl/text/bidi.hpp b/src/mbgl/text/bidi.hpp index 5ce2887db8..8680e6f7e5 100644 --- a/src/mbgl/text/bidi.hpp +++ b/src/mbgl/text/bidi.hpp @@ -18,7 +18,7 @@ std::u16string applyArabicShaping(const std::u16string&); // the styling options to use for rendering that code point // The data structure is intended to accomodate the reordering/interleaving // of formatting that can happen when BiDi rearranges inputs -using StyledText = std::pair>; +using StyledText = std::pair>; class BiDi : private util::noncopyable { public: diff --git a/src/mbgl/text/glyph.hpp b/src/mbgl/text/glyph.hpp index 034784dc24..c97b242c10 100644 --- a/src/mbgl/text/glyph.hpp +++ b/src/mbgl/text/glyph.hpp @@ -19,7 +19,7 @@ namespace mbgl { using GlyphID = char16_t; using GlyphIDs = std::set; - + // Note: this only works for the BMP GlyphRange getGlyphRange(GlyphID glyph); @@ -59,8 +59,8 @@ using GlyphMap = std::map; class PositionedGlyph { public: - explicit PositionedGlyph(GlyphID glyph_, float x_, float y_, bool vertical_, FontStackHash font_, float scale_) - : glyph(glyph_), x(x_), y(y_), vertical(vertical_), font(font_), scale(scale_) + explicit PositionedGlyph(GlyphID glyph_, float x_, float y_, bool vertical_, FontStackHash font_, float scale_, std::size_t sectionIndex_ = 0) + : glyph(glyph_), x(x_), y(y_), vertical(vertical_), font(font_), scale(scale_), sectionIndex(sectionIndex_) {} GlyphID glyph = 0; @@ -70,6 +70,8 @@ public: FontStackHash font = 0; float scale = 0.0; + // Maps positioned glyph to TaggedString section + std::size_t sectionIndex; }; enum class WritingModeType : uint8_t; diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index 9d582f14d6..ec0045caad 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -172,7 +172,7 @@ SymbolQuads getGlyphQuads(const Shaping& shapedText, br = util::matrixMultiply(matrix, br); } - quads.emplace_back(tl, tr, bl, br, rect, shapedText.writingMode, glyphOffset); + quads.emplace_back(tl, tr, bl, br, rect, shapedText.writingMode, glyphOffset, positionedGlyph.sectionIndex); } return quads; diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp index 44a35a5014..f41a4fec66 100644 --- a/src/mbgl/text/quads.hpp +++ b/src/mbgl/text/quads.hpp @@ -20,14 +20,16 @@ public: Point br_, Rect tex_, WritingModeType writingMode_, - Point glyphOffset_) + Point glyphOffset_, + size_t sectionIndex_ = 0) : tl(std::move(tl_)), tr(std::move(tr_)), bl(std::move(bl_)), br(std::move(br_)), tex(std::move(tex_)), writingMode(writingMode_), - glyphOffset(glyphOffset_) {} + glyphOffset(glyphOffset_), + sectionIndex(sectionIndex_){} Point tl; Point tr; @@ -36,6 +38,7 @@ public: Rect tex; WritingModeType writingMode; Point glyphOffset; + size_t sectionIndex; }; using SymbolQuads = std::vector; diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp index 3a6335955b..02dbf146e1 100644 --- a/src/mbgl/text/shaping.cpp +++ b/src/mbgl/text/shaping.cpp @@ -299,7 +299,8 @@ void shapeLines(Shaping& shaping, std::size_t lineStartIndex = shaping.positionedGlyphs.size(); for (std::size_t i = 0; i < line.length(); i++) { - const SectionOptions& section = line.getSection(i); + const std::size_t sectionIndex = line.getSectionIndex(i); + const SectionOptions& section = line.sectionAt(sectionIndex); char16_t codePoint = line.getCharCodeAt(i); auto glyphs = glyphMap.find(section.fontStackHash); if (glyphs == glyphMap.end()) { @@ -318,10 +319,10 @@ void shapeLines(Shaping& shaping, const Glyph& glyph = **it->second; if (writingMode == WritingModeType::Horizontal || !util::i18n::hasUprightVerticalOrientation(codePoint)) { - shaping.positionedGlyphs.emplace_back(codePoint, x, y + baselineOffset, false, section.fontStackHash, section.scale); + shaping.positionedGlyphs.emplace_back(codePoint, x, y + baselineOffset, false, section.fontStackHash, section.scale, sectionIndex); x += glyph.metrics.advance * section.scale + spacing; } else { - shaping.positionedGlyphs.emplace_back(codePoint, x, baselineOffset, true, section.fontStackHash, section.scale); + shaping.positionedGlyphs.emplace_back(codePoint, x, baselineOffset, true, section.fontStackHash, section.scale, sectionIndex); x += verticalHeight * section.scale + spacing; } } diff --git a/src/mbgl/text/tagged_string.cpp b/src/mbgl/text/tagged_string.cpp index 851e011c4f..3755ad3a28 100644 --- a/src/mbgl/text/tagged_string.cpp +++ b/src/mbgl/text/tagged_string.cpp @@ -1,11 +1,12 @@ #include +#include #include namespace mbgl { -void TaggedString::addSection(const std::u16string& sectionText, double scale, FontStackHash fontStack) { +void TaggedString::addSection(const std::u16string& sectionText, double scale, FontStack fontStack, const optional& id) { styledText.first += sectionText; - sections.emplace_back(scale, fontStack); + sections.emplace_back(scale, fontStack, id); styledText.second.resize(styledText.first.size(), sections.size() - 1); } @@ -19,14 +20,14 @@ void TaggedString::trim() { std::size_t trailingWhitespace = styledText.first.find_last_not_of(u" \t\n\v\f\r") + 1; styledText.first = styledText.first.substr(beginningWhitespace, trailingWhitespace - beginningWhitespace); - styledText.second = std::vector(styledText.second.begin() + beginningWhitespace, styledText.second.begin() + trailingWhitespace); + styledText.second = std::vector(styledText.second.begin() + beginningWhitespace, styledText.second.begin() + trailingWhitespace); } } double TaggedString::getMaxScale() const { double maxScale = 0.0; for (std::size_t i = 0; i < styledText.first.length(); i++) { - maxScale = std::max(maxScale, getSection(i).scale); + maxScale = util::max(maxScale, getSection(i).scale); } return maxScale; } @@ -36,4 +37,19 @@ void TaggedString::verticalizePunctuation() { styledText.first = util::i18n::verticalizePunctuation(styledText.first); } +bool TaggedString::hasMultipleUniqueSections() const noexcept { + if (sections.size() < 2) { + return false; + } + + const auto& id = sections.at(0).id; + for (std::size_t i = 1; i < sections.size(); ++i) { + if (id != sections.at(i).id) { + return true; + } + } + + return false; +} + } // namespace mbgl diff --git a/src/mbgl/text/tagged_string.hpp b/src/mbgl/text/tagged_string.hpp index 476c2225f0..c40c253753 100644 --- a/src/mbgl/text/tagged_string.hpp +++ b/src/mbgl/text/tagged_string.hpp @@ -1,17 +1,22 @@ #pragma once -#include #include +#include +#include namespace mbgl { +using style::expression::FormattedSectionID; + struct SectionOptions { - SectionOptions(double scale_, FontStackHash fontStackHash_) - : scale(scale_), fontStackHash(fontStackHash_) + SectionOptions(double scale_, FontStack fontStack_, const optional& id_ = {}) + : scale(scale_), fontStackHash(FontStackHasher()(fontStack_)), fontStack(std::move(fontStack_)), id(std::move(id_)) {} double scale; FontStackHash fontStackHash; + FontStack fontStack; + optional id; }; /** @@ -34,7 +39,7 @@ struct TaggedString { TaggedString(std::u16string text_, SectionOptions options) : styledText(std::move(text_), - std::vector(text_.size(), 0)) { + std::vector(text_.size(), 0)) { sections.push_back(std::move(options)); } @@ -71,7 +76,11 @@ struct TaggedString { return styledText; } - void addSection(const std::u16string& text, double scale, FontStackHash fontStack); + void addSection(const std::u16string& text, + double scale, + FontStack fontStack, + const optional& id = {}); + const SectionOptions& sectionAt(std::size_t index) const { return sections.at(index); } @@ -80,7 +89,7 @@ struct TaggedString { return sections; } - uint8_t getSectionIndex(std::size_t characterIndex) const { + std::size_t getSectionIndex(std::size_t characterIndex) const { return styledText.second.at(characterIndex); } @@ -88,7 +97,9 @@ struct TaggedString { void trim(); void verticalizePunctuation(); - + + bool hasMultipleUniqueSections() const noexcept; + private: StyledText styledText; std::vector sections; diff --git a/test/text/bidi.test.cpp b/test/text/bidi.test.cpp index 7c0eb82884..a3a2ac12a8 100644 --- a/test/text/bidi.test.cpp +++ b/test/text/bidi.test.cpp @@ -61,27 +61,27 @@ TEST(BiDi, StyledText) { std::vector expected; StyledText input( applyArabicShaping(u"مكتبة الإسكندرية‎‎ Maktabat al-Iskandarīyah"), - std::vector{ 0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,4,5,5,5,5,6,6,6,6,6,6,6,6,6,6,7,7,7 } + std::vector{ 0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,4,5,5,5,5,6,6,6,6,6,6,6,6,6,6,7,7,7 } ); expected.emplace_back(StyledText( u"ﺔﺒﺘﻜﻣ", - std::vector{ 0,0,0,0,0 } + std::vector{ 0,0,0,0,0 } )); EXPECT_EQ(expected.rbegin()->first.size(), expected.rbegin()->second.size()); expected.emplace_back(StyledText( u" ‎‎ﺔﻳﺭﺪﻨﻜﺳﻹﺍ ", - std::vector{ 2,2,2,2,2,2,2,1,1,1,1,1,1 } + std::vector{ 2,2,2,2,2,2,2,1,1,1,1,1,1 } )); EXPECT_EQ(expected.rbegin()->first.size(), expected.rbegin()->second.size()); expected.emplace_back(StyledText( u"Maktabat al-", - std::vector{ 2,3,3,3,3,3,4,5,5,5,5,6 } + std::vector{ 2,3,3,3,3,3,4,5,5,5,5,6 } )); EXPECT_EQ(expected.rbegin()->first.size(), expected.rbegin()->second.size()); expected.emplace_back(StyledText( u"Iskandarīyah", - std::vector{ 6,6,6,6,6,6,6,6,6,7,7,7 } + std::vector{ 6,6,6,6,6,6,6,6,6,7,7,7 } )); EXPECT_EQ(expected.rbegin()->first.size(), expected.rbegin()->second.size()); diff --git a/test/text/tagged_string.test.cpp b/test/text/tagged_string.test.cpp index de74126db8..d3a2176eba 100644 --- a/test/text/tagged_string.test.cpp +++ b/test/text/tagged_string.test.cpp @@ -7,22 +7,22 @@ using namespace mbgl; using namespace std::literals; TEST(TaggedString, Trim) { - TaggedString basic(u" \t\ntrim that and not this \n\t", SectionOptions(1.0f, 0)); + TaggedString basic(u" \t\ntrim that and not this \n\t", SectionOptions(1.0f, {})); basic.trim(); EXPECT_EQ(basic.rawText(), u"trim that and not this"); TaggedString twoSections; - twoSections.addSection(u" \t\ntrim that", 1.5f, 1); - twoSections.addSection(u" and not this \n\t", 0.5f, 2); + twoSections.addSection(u" \t\ntrim that", 1.5f, {}); + twoSections.addSection(u" and not this \n\t", 0.5f, {}); twoSections.trim(); EXPECT_EQ(twoSections.rawText(), u"trim that and not this"); - TaggedString empty(u"\n\t\v \r \t\n", SectionOptions(1.0f, 0)); + TaggedString empty(u"\n\t\v \r \t\n", SectionOptions(1.0f, {})); empty.trim(); EXPECT_EQ(empty.rawText(), u""); - TaggedString noTrim(u"no trim!", SectionOptions(1.0f, 0)); + TaggedString noTrim(u"no trim!", SectionOptions(1.0f, {})); noTrim.trim(); EXPECT_EQ(noTrim.rawText(), u"no trim!"); } diff --git a/test/util/merge_lines.test.cpp b/test/util/merge_lines.test.cpp index f76a1ea72a..1d4b0d230e 100644 --- a/test/util/merge_lines.test.cpp +++ b/test/util/merge_lines.test.cpp @@ -25,7 +25,7 @@ public: SymbolFeature(std::make_unique(std::move(id_), type_, std::move(geometry_), std::move(properties_))) { if (text_) { - formattedText = TaggedString(*text_, SectionOptions(1.0, 0)); + formattedText = TaggedString(*text_, SectionOptions(1.0, {})); } icon = std::move(icon_); index = index_; -- cgit v1.2.1