• 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 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