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