1 // Copyright 2019 Google LLC. 2 #ifndef LineBreaker_DEFINED 3 #define LineBreaker_DEFINED 4 5 #include <functional> // std::function 6 #include <queue> 7 #include "modules/skparagraph/include/TextStyle.h" 8 #include "modules/skparagraph/src/ParagraphImpl.h" 9 #include "modules/skparagraph/src/Run.h" 10 #include "src/core/SkSpan.h" 11 12 namespace skia { 13 namespace textlayout { 14 15 typedef size_t GlyphIndex; 16 typedef SkRange<GlyphIndex> GlyphRange; 17 18 class ParagraphImpl; 19 class OneLineShaper : public SkShaper::RunHandler { 20 public: OneLineShaper(ParagraphImpl * paragraph)21 explicit OneLineShaper(ParagraphImpl* paragraph) 22 : fParagraph(paragraph) 23 , fHeight(0.0f) 24 , fAdvance(SkPoint::Make(0.0f, 0.0f)) 25 , fUnresolvedGlyphs(0) { } 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(run->fTextRange) 48 , fGlyphs(GlyphRange(0, run->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 = std::function<void(Block, SkTArray<SkShaper::Feature>)>; 61 void iterateThroughFontStyles(TextRange textRange, SkSpan<Block> styleSpan, const ShapeSingleFontVisitor& visitor); 62 63 using TypefaceVisitor = std::function<bool(sk_sp<SkTypeface> typeface)>; 64 void matchResolvedFonts(const TextStyle& textStyle, const TypefaceVisitor& visitor); 65 #ifdef SK_DEBUG 66 void printState(); 67 #endif 68 void dropUnresolved(); 69 void finish(TextRange text, SkScalar height, SkScalar& advanceX); 70 beginLine()71 void beginLine() override {} runInfo(const RunInfo &)72 void runInfo(const RunInfo&) override {} commitRunInfo()73 void commitRunInfo() override {} commitLine()74 void commitLine() override {} 75 runBuffer(const RunInfo & info)76 Buffer runBuffer(const RunInfo& info) override { 77 auto index = fUnresolvedBlocks.size() + fResolvedBlocks.size(); 78 fCurrentRun = std::make_shared<Run>(fParagraph, 79 info, 80 fCurrentText.start, 81 fHeight, 82 index, 83 fAdvance.fX); 84 return fCurrentRun->newRunBuffer(); 85 } 86 87 void commitRunBuffer(const RunInfo&) override; 88 89 TextRange clusteredText(GlyphRange glyphs); clusterIndex(GlyphIndex glyph)90 ClusterIndex clusterIndex(GlyphIndex glyph) { 91 return fCurrentText.start + fCurrentRun->fClusterIndexes[glyph]; 92 } 93 void addFullyResolved(); 94 void addUnresolvedWithRun(GlyphRange glyphRange); 95 void sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock); 96 ClusterRange normalizeTextRange(GlyphRange glyphRange); 97 void increment(TextIndex& index); 98 void fillGaps(size_t); 99 100 ParagraphImpl* fParagraph; 101 TextRange fCurrentText; 102 SkScalar fHeight; 103 SkVector fAdvance; 104 size_t fUnresolvedGlyphs; 105 106 // TODO: Something that is not thead-safe since we don't need it 107 std::shared_ptr<Run> fCurrentRun; 108 std::queue<RunBlock> fUnresolvedBlocks; 109 std::vector<RunBlock> fResolvedBlocks; 110 }; 111 112 } 113 } 114 #endif 115