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 , fAdvance(SkPoint::Make(0.0f, 0.0f)) 23 , fUnresolvedGlyphs(0) 24 , fUniqueRunId(paragraph->fRuns.size()){ } 25 26 bool shape(); 27 unresolvedGlyphs()28 size_t unresolvedGlyphs() { return fUnresolvedGlyphs; } 29 30 private: 31 32 struct RunBlock { RunBlockRunBlock33 RunBlock() : fRun(nullptr) { } 34 35 // First unresolved block RunBlockRunBlock36 explicit RunBlock(TextRange text) : fRun(nullptr), fText(text) { } 37 RunBlockRunBlock38 RunBlock(std::shared_ptr<Run> run, TextRange text, GlyphRange glyphs, size_t score) 39 : fRun(std::move(run)) 40 , fText(text) 41 , fGlyphs(glyphs) { } 42 43 // Entire run comes as one block fully resolved RunBlockRunBlock44 explicit RunBlock(std::shared_ptr<Run> run) 45 : fRun(std::move(run)) 46 , fText(fRun->fTextRange) 47 , fGlyphs(GlyphRange(0, fRun->size())) { } 48 49 std::shared_ptr<Run> fRun; 50 TextRange fText; 51 GlyphRange fGlyphs; isFullyResolvedRunBlock52 bool isFullyResolved() { return fRun != nullptr && fGlyphs.width() == fRun->size(); } 53 }; 54 55 using ShapeVisitor = 56 std::function<SkScalar(TextRange textRange, SkSpan<Block>, SkScalar&, TextIndex, uint8_t)>; 57 bool iterateThroughShapingRegions(const ShapeVisitor& shape); 58 59 using ShapeSingleFontVisitor = std::function<void(Block, SkTArray<SkShaper::Feature>)>; 60 void iterateThroughFontStyles(TextRange textRange, SkSpan<Block> styleSpan, const ShapeSingleFontVisitor& visitor); 61 62 enum Resolved { 63 Nothing, 64 Something, 65 Everything 66 }; 67 68 using TypefaceVisitor = std::function<Resolved(sk_sp<SkTypeface> typeface)>; 69 void matchResolvedFonts(const TextStyle& textStyle, const TypefaceVisitor& visitor); 70 #ifdef SK_DEBUG 71 void printState(); 72 #endif 73 void finish(const Block& block, SkScalar height, SkScalar& advanceX); 74 beginLine()75 void beginLine() override {} runInfo(const RunInfo &)76 void runInfo(const RunInfo&) override {} commitRunInfo()77 void commitRunInfo() override {} commitLine()78 void commitLine() override {} 79 runBuffer(const RunInfo & info)80 Buffer runBuffer(const RunInfo& info) override { 81 fCurrentRun = std::make_shared<Run>(fParagraph, 82 info, 83 fCurrentText.start, 84 fHeight, 85 fUseHalfLeading, 86 ++fUniqueRunId, 87 fAdvance.fX); 88 return fCurrentRun->newRunBuffer(); 89 } 90 91 void commitRunBuffer(const RunInfo&) override; 92 93 TextRange clusteredText(GlyphRange& glyphs); clusterIndex(GlyphIndex glyph)94 ClusterIndex clusterIndex(GlyphIndex glyph) { 95 return fCurrentText.start + fCurrentRun->fClusterIndexes[glyph]; 96 } 97 void addFullyResolved(); 98 void addUnresolvedWithRun(GlyphRange glyphRange); 99 void sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock); 100 ClusterRange normalizeTextRange(GlyphRange glyphRange); 101 void fillGaps(size_t); 102 103 ParagraphImpl* fParagraph; 104 TextRange fCurrentText; 105 SkScalar fHeight; 106 bool fUseHalfLeading; 107 SkVector fAdvance; 108 size_t fUnresolvedGlyphs; 109 size_t fUniqueRunId; 110 111 // TODO: Something that is not thead-safe since we don't need it 112 std::shared_ptr<Run> fCurrentRun; 113 std::deque<RunBlock> fUnresolvedBlocks; 114 std::vector<RunBlock> fResolvedBlocks; 115 116 // Keeping all resolved typefaces 117 struct FontKey { 118 FontKeyFontKey119 FontKey() {} 120 FontKeyFontKey121 FontKey(SkUnichar unicode, SkFontStyle fontStyle, SkString locale) 122 : fUnicode(unicode), fFontStyle(fontStyle), fLocale(locale) { } 123 SkUnichar fUnicode; 124 SkFontStyle fFontStyle; 125 SkString fLocale; 126 127 bool operator==(const FontKey& other) const; 128 129 struct Hasher { 130 size_t operator()(const FontKey& key) const; 131 }; 132 }; 133 SkTHashMap<FontKey, sk_sp<SkTypeface>, FontKey::Hasher> fFallbackFonts; 134 }; 135 136 } // namespace textlayout 137 } // namespace skia 138 #endif 139