1 // Copyright 2019 Google LLC. 2 #ifndef LineBreaker_DEFINED 3 #define LineBreaker_DEFINED 4 5 #include <functional> // std::function 6 #include <queue> 7 #include "include/core/SkSpan.h" 8 #include "modules/skparagraph/include/TextStyle.h" 9 #include "modules/skparagraph/src/ParagraphImpl.h" 10 #include "modules/skparagraph/src/Run.h" 11 12 namespace skia { 13 namespace textlayout { 14 15 class ParagraphImpl; 16 class OneLineShaper : public SkShaper::RunHandler { 17 public: OneLineShaper(ParagraphImpl * paragraph)18 explicit OneLineShaper(ParagraphImpl* paragraph) 19 : fParagraph(paragraph) 20 , fHeight(0.0f) 21 , fUseHalfLeading(false) 22 , fBaselineShift(0.0f) 23 , fAdvance(SkPoint::Make(0.0f, 0.0f)) 24 , fUnresolvedGlyphs(0) 25 , fUniqueRunId(paragraph->fRuns.size()){ } 26 27 bool shape(); 28 unresolvedGlyphs()29 size_t unresolvedGlyphs() { return fUnresolvedGlyphs; } 30 31 private: 32 33 struct RunBlock { RunBlockRunBlock34 RunBlock() : fRun(nullptr) { } 35 36 // First unresolved block RunBlockRunBlock37 explicit RunBlock(TextRange text) : fRun(nullptr), fText(text) { } 38 RunBlockRunBlock39 RunBlock(std::shared_ptr<Run> run, TextRange text, GlyphRange glyphs, size_t score) 40 : fRun(std::move(run)) 41 , fText(text) 42 , fGlyphs(glyphs) { } 43 44 // Entire run comes as one block fully resolved RunBlockRunBlock45 explicit RunBlock(std::shared_ptr<Run> run) 46 : fRun(std::move(run)) 47 , fText(fRun->fTextRange) 48 , fGlyphs(GlyphRange(0, fRun->size())) { } 49 50 std::shared_ptr<Run> fRun; 51 TextRange fText; 52 GlyphRange fGlyphs; isFullyResolvedRunBlock53 bool isFullyResolved() { return fRun != nullptr && fGlyphs.width() == fRun->size(); } 54 }; 55 56 using ShapeVisitor = 57 std::function<SkScalar(TextRange textRange, SkSpan<Block>, SkScalar&, TextIndex, uint8_t)>; 58 bool iterateThroughShapingRegions(const ShapeVisitor& shape); 59 60 using ShapeSingleFontVisitor = 61 std::function<void(Block, SkTArray<SkShaper::Feature>)>; 62 void iterateThroughFontStyles( 63 TextRange textRange, SkSpan<Block> styleSpan, const ShapeSingleFontVisitor& visitor); 64 65 enum Resolved { 66 Nothing, 67 Something, 68 Everything 69 }; 70 71 #ifndef USE_SKIA_TXT 72 using TypefaceVisitor = std::function<Resolved(sk_sp<SkTypeface> typeface)>; 73 #else 74 using TypefaceVisitor = std::function<Resolved(std::shared_ptr<RSTypeface> typeface)>; 75 #endif 76 void matchResolvedFonts(const TextStyle& textStyle, const TypefaceVisitor& visitor); 77 78 #ifdef OHOS_SUPPORT 79 bool isUnresolvedCombineGlyphRange(std::shared_ptr<Run> run, size_t glyphStart, size_t glyphEnd, 80 size_t charStart) const; 81 void splitUnresolvedBlockAndStageResolvedSubBlock( 82 std::deque<RunBlock>& stagedUnresolvedBlocks, const RunBlock& unresolvedBlock); 83 void shapeUnresolvedTextSeparatelyFromUnresolvedBlock(const TextStyle& textStyle, const TypefaceVisitor& visitor); 84 #endif 85 86 #ifdef SK_DEBUG 87 void printState(); 88 #endif 89 void finish(const Block& block, SkScalar height, SkScalar& advanceX); 90 beginLine()91 void beginLine() override {} runInfo(const RunInfo &)92 void runInfo(const RunInfo&) override {} commitRunInfo()93 void commitRunInfo() override {} commitLine()94 void commitLine() override {} 95 runBuffer(const RunInfo & info)96 Buffer runBuffer(const RunInfo& info) override { 97 fCurrentRun = std::make_shared<Run>(fParagraph, 98 info, 99 fCurrentText.start, 100 fHeight, 101 fUseHalfLeading, 102 fBaselineShift, 103 ++fUniqueRunId, 104 fAdvance.fX); 105 return fCurrentRun->newRunBuffer(); 106 } 107 108 void commitRunBuffer(const RunInfo&) override; 109 110 #ifdef OHOS_SUPPORT 111 void adjustRange(GlyphRange& glyphs, TextRange& textRange); 112 #endif 113 TextRange clusteredText(GlyphRange& glyphs); clusterIndex(GlyphIndex glyph)114 ClusterIndex clusterIndex(GlyphIndex glyph) { 115 return fCurrentText.start + fCurrentRun->fClusterIndexes[glyph]; 116 } 117 void addFullyResolved(); 118 void addUnresolvedWithRun(GlyphRange glyphRange); 119 void sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock); 120 ClusterRange normalizeTextRange(GlyphRange glyphRange); 121 void fillGaps(size_t); 122 BlockRange generateBlockRange(const Block& block, const TextRange& textRange); 123 124 ParagraphImpl* fParagraph; 125 TextRange fCurrentText; 126 SkScalar fHeight; 127 bool fUseHalfLeading; 128 SkScalar fBaselineShift; 129 SkVector fAdvance; 130 size_t fUnresolvedGlyphs; 131 size_t fUniqueRunId; 132 133 // TODO: Something that is not thead-safe since we don't need it 134 std::shared_ptr<Run> fCurrentRun; 135 std::deque<RunBlock> fUnresolvedBlocks; 136 std::vector<RunBlock> fResolvedBlocks; 137 138 // Keeping all resolved typefaces 139 struct FontKey { 140 FontKeyFontKey141 FontKey() {} 142 143 #ifndef USE_SKIA_TXT FontKeyFontKey144 FontKey(SkUnichar unicode, SkFontStyle fontStyle, SkString locale) 145 : fUnicode(unicode), fFontStyle(fontStyle), fLocale(locale) { } 146 #else FontKeyFontKey147 FontKey(SkUnichar unicode, RSFontStyle fontStyle, SkString locale) 148 : fUnicode(unicode), fFontStyle(fontStyle), fLocale(locale) { } 149 #endif 150 151 SkUnichar fUnicode; 152 #ifndef USE_SKIA_TXT 153 SkFontStyle fFontStyle; 154 #else 155 RSFontStyle fFontStyle; 156 #endif 157 SkString fLocale; 158 159 bool operator==(const FontKey& other) const; 160 161 struct Hasher { 162 uint32_t operator()(const FontKey& key) const; 163 }; 164 }; 165 166 #ifndef USE_SKIA_TXT 167 SkTHashMap<FontKey, sk_sp<SkTypeface>, FontKey::Hasher> fFallbackFonts; 168 #else 169 std::unordered_map<FontKey, std::shared_ptr<RSTypeface>, FontKey::Hasher> fFallbackFonts; 170 #endif 171 }; 172 173 } // namespace textlayout 174 } // namespace skia 175 #endif 176