• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     /**
32      * This method is based on definition of https://unicode.org/reports/tr51/#def_emoji_sequence
33      * It determines if the string begins with an emoji sequence and,
34      * if so, return the first codepoint, moving 'begin' pointer to the next once.
35      * Otherwise it does not move the pointer and returns -1.
36      */
37     static SkUnichar getEmojiSequenceStart(SkUnicode* unicode, const char** begin, const char* end);
38 
39 private:
40 
41     struct RunBlock {
RunBlockRunBlock42         RunBlock() : fRun(nullptr) { }
43 
44         // First unresolved block
RunBlockRunBlock45         explicit RunBlock(TextRange text) : fRun(nullptr), fText(text) { }
46 
RunBlockRunBlock47         RunBlock(std::shared_ptr<Run> run, TextRange text, GlyphRange glyphs, size_t score)
48             : fRun(std::move(run))
49             , fText(text)
50             , fGlyphs(glyphs) { }
51 
52         // Entire run comes as one block fully resolved
RunBlockRunBlock53         explicit RunBlock(std::shared_ptr<Run> run)
54             : fRun(std::move(run))
55             , fText(fRun->fTextRange)
56             , fGlyphs(GlyphRange(0, fRun->size())) { }
57 
58         std::shared_ptr<Run> fRun;
59         TextRange fText;
60         GlyphRange fGlyphs;
isFullyResolvedRunBlock61         bool isFullyResolved() { return fRun != nullptr && fGlyphs.width() == fRun->size(); }
62     };
63 
64     using ShapeVisitor =
65             std::function<SkScalar(TextRange textRange, SkSpan<Block>, SkScalar&, TextIndex, uint8_t)>;
66     bool iterateThroughShapingRegions(const ShapeVisitor& shape);
67 
68     using ShapeSingleFontVisitor =
69             std::function<void(Block, skia_private::TArray<SkShaper::Feature>)>;
70     void iterateThroughFontStyles(
71             TextRange textRange, SkSpan<Block> styleSpan, const ShapeSingleFontVisitor& visitor);
72 
73     enum Resolved {
74         Nothing,
75         Something,
76         Everything
77     };
78 
79 #ifdef ENABLE_TEXT_ENHANCE
80     using TypefaceVisitor = std::function<Resolved(std::shared_ptr<RSTypeface> typeface)>;
81 #else
82     using TypefaceVisitor = std::function<Resolved(sk_sp<SkTypeface> typeface)>;
83 #endif
84     void matchResolvedFonts(const TextStyle& textStyle, const TypefaceVisitor& visitor);
85 
86 #ifdef ENABLE_TEXT_ENHANCE
87     bool isUnresolvedCombineGlyphRange(std::shared_ptr<Run> run, size_t glyphStart, size_t glyphEnd,
88         size_t charStart) const;
89     void splitUnresolvedBlockAndStageResolvedSubBlock(
90         std::deque<RunBlock>& stagedUnresolvedBlocks, const RunBlock& unresolvedBlock);
91     void shapeUnresolvedTextSeparatelyFromUnresolvedBlock(const TextStyle& textStyle, const TypefaceVisitor& visitor);
92     void matchResolvedFontsFindTypeface(const TextStyle& textStyle, std::shared_ptr<RSTypeface>& typeface,
93         SkUnichar& unicode);
94     void matchResolvedFontsByUnicode(const TextStyle& textStyle, const TypefaceVisitor& visitor,
95         std::vector<RunBlock>& hopelessBlocks);
96 #endif
97 
98 #ifdef SK_DEBUG
99     void printState();
100 #endif
101     void finish(const Block& block, SkScalar height, SkScalar& advanceX);
102 
beginLine()103     void beginLine() override {}
runInfo(const RunInfo &)104     void runInfo(const RunInfo&) override {}
commitRunInfo()105     void commitRunInfo() override {}
commitLine()106     void commitLine() override {}
107 
runBuffer(const RunInfo & info)108     Buffer runBuffer(const RunInfo& info) override {
109         fCurrentRun = std::make_shared<Run>(fParagraph,
110                                            info,
111                                            fCurrentText.start,
112                                            fHeight,
113                                            fUseHalfLeading,
114                                            fBaselineShift,
115                                            ++fUniqueRunId,
116                                            fAdvance.fX);
117         return fCurrentRun->newRunBuffer();
118     }
119 
120     void commitRunBuffer(const RunInfo&) override;
121 
122 #ifdef ENABLE_TEXT_ENHANCE
123     void adjustRange(GlyphRange& glyphs, TextRange& textRange);
124 #endif
125     TextRange clusteredText(GlyphRange& glyphs);
clusterIndex(GlyphIndex glyph)126     ClusterIndex clusterIndex(GlyphIndex glyph) {
127         return fCurrentText.start + fCurrentRun->fClusterIndexes[glyph];
128     }
129     void addFullyResolved();
130     void addUnresolvedWithRun(GlyphRange glyphRange);
131     void sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock);
132     ClusterRange normalizeTextRange(GlyphRange glyphRange);
133     void fillGaps(size_t);
134 #ifdef ENABLE_TEXT_ENHANCE
135 	BlockRange generateBlockRange(const Block& block, const TextRange& textRange);
136 #endif
137 
138     ParagraphImpl* fParagraph;
139     TextRange fCurrentText;
140     SkScalar fHeight;
141     bool fUseHalfLeading;
142     SkScalar fBaselineShift;
143     SkVector fAdvance;
144     size_t fUnresolvedGlyphs;
145     size_t fUniqueRunId;
146 
147     // TODO: Something that is not thead-safe since we don't need it
148     std::shared_ptr<Run> fCurrentRun;
149     std::deque<RunBlock> fUnresolvedBlocks;
150     std::vector<RunBlock> fResolvedBlocks;
151 
152     // Keeping all resolved typefaces
153     struct FontKey {
154 
FontKeyFontKey155         FontKey() {}
156 
157 #ifdef ENABLE_TEXT_ENHANCE
FontKeyFontKey158         FontKey(SkUnichar unicode, RSFontStyle fontStyle, SkString locale)
159             : fUnicode(unicode), fFontStyle(fontStyle), fLocale(locale) { }
160 #else
FontKeyFontKey161         FontKey(SkUnichar unicode, SkFontStyle fontStyle, SkString locale)
162             : fUnicode(unicode), fFontStyle(fontStyle), fLocale(std::move(locale)) { }
163 #endif
164         SkUnichar fUnicode;
165 #ifdef ENABLE_TEXT_ENHANCE
166         RSFontStyle fFontStyle;
167 #else
168         SkFontStyle fFontStyle;
169 #endif
170         SkString fLocale;
171 
172         bool operator==(const FontKey& other) const;
173 
174         struct Hasher {
175             uint32_t operator()(const FontKey& key) const;
176         };
177     };
178 
179 #ifdef ENABLE_TEXT_ENHANCE
180     std::unordered_map<FontKey, std::shared_ptr<RSTypeface>, FontKey::Hasher> fFallbackFonts;
181 #else
182     skia_private::THashMap<FontKey, sk_sp<SkTypeface>, FontKey::Hasher> fFallbackFonts;
183 #endif
184 };
185 
186 }  // namespace textlayout
187 }  // namespace skia
188 #endif
189