• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC.
2 #ifndef ParagraphImpl_DEFINED
3 #define ParagraphImpl_DEFINED
4 
5 #include "include/core/SkFont.h"
6 #include "include/core/SkPaint.h"
7 #include "include/core/SkPicture.h"
8 #include "include/core/SkPoint.h"
9 #include "include/core/SkRect.h"
10 #include "include/core/SkRefCnt.h"
11 #include "include/core/SkScalar.h"
12 #include "include/core/SkSpan.h"
13 #include "include/core/SkString.h"
14 #include "include/core/SkTypes.h"
15 #include "include/private/SkBitmaskEnum.h"
16 #include "include/private/SkOnce.h"
17 #include "include/private/SkTArray.h"
18 #include "include/private/SkTemplates.h"
19 #include "modules/skparagraph/include/DartTypes.h"
20 #include "modules/skparagraph/include/FontCollection.h"
21 #include "modules/skparagraph/include/Paragraph.h"
22 #include "modules/skparagraph/include/ParagraphCache.h"
23 #include "modules/skparagraph/include/ParagraphStyle.h"
24 #include "modules/skparagraph/include/TextLineBase.h"
25 #include "modules/skparagraph/include/TextShadow.h"
26 #include "modules/skparagraph/include/TextStyle.h"
27 #include "modules/skparagraph/src/Run.h"
28 #include "modules/skparagraph/src/TextLine.h"
29 #include "modules/skunicode/include/SkUnicode.h"
30 #include "include/private/SkTHash.h"
31 
32 #include <memory>
33 #include <string>
34 #include <vector>
35 
36 class SkCanvas;
37 
38 namespace skia {
39 namespace textlayout {
40 
41 class LineMetrics;
42 class TextLine;
43 
44 template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
45     return a.size() == b.size() && a.begin() == b.begin();
46 }
47 
48 template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) {
49     return a.begin() >= b.begin() && a.end() <= b.end();
50 }
51 
52 template <typename TStyle>
53 struct StyleBlock {
StyleBlockStyleBlock54     StyleBlock() : fRange(EMPTY_RANGE), fStyle() { }
StyleBlockStyleBlock55     StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {}
StyleBlockStyleBlock56     StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {}
addStyleBlock57     void add(TextRange tail) {
58         SkASSERT(fRange.end == tail.start);
59         fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
60     }
61     TextRange fRange;
62     TStyle fStyle;
63 };
64 
65 struct ResolvedFontDescriptor {
66 
67 #ifndef USE_SKIA_TXT
ResolvedFontDescriptorResolvedFontDescriptor68     ResolvedFontDescriptor(TextIndex index, SkFont font)
69         : fFont(font), fTextStart(index) { }
70     SkFont fFont;
71 #else
72     ResolvedFontDescriptor(TextIndex index, RSFont font)
73         : fFont(font), fTextStart(index) { }
74     RSFont fFont;
75 #endif
76     TextIndex fTextStart;
77 };
78 
79 enum InternalState {
80   kUnknown = 0,
81   kIndexed = 1,     // Text is indexed
82   kShaped = 2,      // Text is shaped
83   kLineBroken = 5,
84   kFormatted = 6,
85   kDrawn = 7
86 };
87 
88 /*
89 struct BidiRegion {
90     BidiRegion(size_t start, size_t end, uint8_t dir)
91         : text(start, end), direction(dir) { }
92     TextRange text;
93     uint8_t direction;
94 };
95 */
96 class ParagraphImpl final : public Paragraph {
97 
98 public:
99 
100     ParagraphImpl() = default;
101 
102     ParagraphImpl(const SkString& text,
103                   ParagraphStyle style,
104                   SkTArray<Block, true> blocks,
105                   SkTArray<Placeholder, true> placeholders,
106                   sk_sp<FontCollection> fonts,
107                   std::shared_ptr<SkUnicode> unicode);
108 
109     ParagraphImpl(const std::u16string& utf16text,
110                   ParagraphStyle style,
111                   SkTArray<Block, true> blocks,
112                   SkTArray<Placeholder, true> placeholders,
113                   sk_sp<FontCollection> fonts,
114                   std::shared_ptr<SkUnicode> unicode);
115 
116     ~ParagraphImpl() override;
117 
118     void layout(SkScalar width) override;
119     void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
120     void paint(ParagraphPainter* canvas, SkScalar x, SkScalar y) override;
121     void paint(ParagraphPainter* canvas, RSPath* path, SkScalar hOffset, SkScalar vOffset) override;
122     std::vector<TextBox> getRectsForRange(unsigned start,
123                                           unsigned end,
124                                           RectHeightStyle rectHeightStyle,
125                                           RectWidthStyle rectWidthStyle) override;
126     std::vector<TextBox> getRectsForPlaceholders() override;
127     void getLineMetrics(std::vector<LineMetrics>&) override;
128     PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
129     SkRange<size_t> getWordBoundary(unsigned offset) override;
130 
getApplyRoundingHack()131     bool getApplyRoundingHack() const { return false; }
132 
lineNumber()133     size_t lineNumber() override { return fLineNumber; }
134 
135     TextLine& addLine(SkVector offset, SkVector advance,
136                       TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines,
137                       ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces,
138                       InternalLineMetrics sizes);
139 
text()140     SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); }
141     std::vector<SkUnichar> convertUtf8ToUnicode(const SkString& utf8);
unicodeText()142     const std::vector<SkUnichar>& unicodeText() const { return fUnicodeText; }
getUnicodeIndex(TextIndex index)143     size_t getUnicodeIndex(TextIndex index) const {
144         if (index >= fUnicodeIndexForUTF8Index.size()) {
145             return fUnicodeIndexForUTF8Index.empty() ? 0 : fUnicodeIndexForUTF8Index.back() + 1;
146         }
147         return fUnicodeIndexForUTF8Index[index];
148     }
state()149     InternalState state() const { return fState; }
runs()150     SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
styles()151     SkSpan<Block> styles() {
152         return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
153     }
placeholders()154     SkSpan<Placeholder> placeholders() {
155         return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size());
156     }
lines()157     SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
paragraphStyle()158     const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
clusters()159     SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
fontCollection()160     sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
161     void formatLines(SkScalar maxWidth);
162     void ensureUTF16Mapping();
163     SkTArray<TextIndex> countSurroundingGraphemes(TextRange textRange) const;
164     TextIndex findNextGraphemeBoundary(TextIndex utf8) const;
165     TextIndex findPreviousGraphemeBoundary(TextIndex utf8) const;
166     TextIndex findNextGlyphClusterBoundary(TextIndex utf8) const;
167     TextIndex findPreviousGlyphClusterBoundary(TextIndex utf8) const;
getUTF16Index(TextIndex index)168     size_t getUTF16Index(TextIndex index) const {
169         return fUTF16IndexForUTF8Index[index];
170     }
171 
strutEnabled()172     bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
strutForceHeight()173     bool strutForceHeight() const {
174         return paragraphStyle().getStrutStyle().getForceStrutHeight();
175     }
strutHeightOverride()176     bool strutHeightOverride() const {
177         return paragraphStyle().getStrutStyle().getHeightOverride();
178     }
strutMetrics()179     InternalLineMetrics strutMetrics() const { return fStrutMetrics; }
180 
181     SkString getEllipsis() const;
182     WordBreakType getWordBreakType() const;
183     LineBreakStrategy getLineBreakStrategy() const;
184 
185     SkSpan<const char> text(TextRange textRange);
186     SkSpan<Cluster> clusters(ClusterRange clusterRange);
187     Cluster& cluster(ClusterIndex clusterIndex);
clusterIndex(TextIndex textIndex)188     ClusterIndex clusterIndex(TextIndex textIndex) {
189         auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex];
190         SkASSERT(clusterIndex != EMPTY_INDEX);
191         return clusterIndex;
192     }
run(RunIndex runIndex)193     Run& run(RunIndex runIndex) {
194         SkASSERT(runIndex < SkToSizeT(fRuns.size()));
195         return fRuns[runIndex];
196     }
197 
198     Run& runByCluster(ClusterIndex clusterIndex);
199     SkSpan<Block> blocks(BlockRange blockRange);
200     Block& block(BlockIndex blockIndex);
resolvedFonts()201     SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; }
202 
markDirty()203     void markDirty() override {
204         if (fState > kIndexed) {
205             fState = kIndexed;
206         }
207     }
208 
209     int32_t unresolvedGlyphs() override;
210     std::unordered_set<SkUnichar> unresolvedCodepoints() override;
211     void addUnresolvedCodepoints(TextRange textRange);
212 
213     void setState(InternalState state);
getPicture()214     sk_sp<SkPicture> getPicture() { return fPicture; }
215 
widthWithTrailingSpaces()216     SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; }
getMaxWidth()217     SkScalar getMaxWidth() { return fOldMaxWidth; }
218 
219     void resetContext();
220     void resolveStrut();
221 
222     bool computeCodeUnitProperties();
223     void applySpacingAndBuildClusterTable();
224     void buildClusterTable();
225     bool shapeTextIntoEndlessLine();
226     void positionShapedTextIntoLine(SkScalar maxWidth);
227     void breakShapedTextIntoLines(SkScalar maxWidth);
228 
229     void updateTextAlign(TextAlign textAlign) override;
230     void updateFontSize(size_t from, size_t to, SkScalar fontSize) override;
231     void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override;
232     void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override;
233 #ifdef OHOS_SUPPORT
234     std::vector<ParagraphPainter::PaintID> updateColor(size_t from, size_t to, SkColor color) override;
235 #endif
236 
237     void visit(const Visitor&) override;
238 
239     void setIndents(const std::vector<SkScalar>& indents) override;
240     int getLineNumberAt(TextIndex codeUnitIndex) const override;
241     bool getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const override;
242     TextRange getActualTextRange(int lineNumber, bool includeSpaces) const override;
243     bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) override;
244     bool getClosestGlyphClusterAt(SkScalar dx,
245                                   SkScalar dy,
246                                   GlyphClusterInfo* glyphInfo) override;
247 #ifndef USE_SKIA_TXT
248     SkFont getFontAt(TextIndex codeUnitIndex) const override;
249 #else
250     RSFont getFontAt(TextIndex codeUnitIndex) const override;
251 #endif
252     std::vector<FontInfo> getFonts() const override;
253 
getEmptyMetrics()254     InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; }
getStrutMetrics()255     InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; }
256 
257     BlockRange findAllBlocks(TextRange textRange);
258 
resetShifts()259     void resetShifts() {
260         for (auto& run : fRuns) {
261             run.resetJustificationShifts();
262         }
263     }
264 
resetAutoSpacing()265     void resetAutoSpacing() {
266         for (auto& run : fRuns) {
267             run.resetAutoSpacing();
268         }
269     }
270 
271     void scanTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end);
272     bool middleEllipsisDeal();
codeUnitHasProperty(size_t index,SkUnicode::CodeUnitFlags property)273     bool codeUnitHasProperty(size_t index, SkUnicode::CodeUnitFlags property) const {
274         return (fCodeUnitProperties[index] & property) == property;
275     }
276 
getUnicode()277     SkUnicode* getUnicode() { return fUnicode.get(); }
278 
279     SkScalar detectIndents(size_t index) override;
280 
getTextSplitRatio()281     SkScalar getTextSplitRatio() const override { return fParagraphStyle.getTextSplitRatio(); }
282 
283 #ifndef USE_SKIA_TXT
284     SkFontMetrics measureText() override;
285 #else
286     RSFontMetrics measureText() override;
287 #endif
288 
getEllipsisState()289     bool &getEllipsisState() { return isMiddleEllipsis; }
290 
291 #ifndef USE_SKIA_TXT
292     bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber,
293         std::vector<SkFontMetrics>& fontMetrics) override;
294 #else
295     bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber,
296         std::vector<RSFontMetrics>& fontMetrics) override;
297 #endif
298 
299     std::vector<std::unique_ptr<TextLineBase>> GetTextLines() override;
300     std::unique_ptr<Paragraph> CloneSelf() override;
301 
hash()302     uint32_t& hash() {
303         return hash_;
304     }
305 
306 private:
307     friend class ParagraphBuilder;
308     friend class ParagraphCacheKey;
309     friend class ParagraphCacheValue;
310     friend class ParagraphCache;
311 
312     friend class TextWrapper;
313     friend class OneLineShaper;
314 
315     void computeEmptyMetrics();
316     void middleEllipsisAddText(size_t charStart,
317                                size_t charEnd,
318                                SkScalar& allTextWidth,
319                                SkScalar width,
320                                bool isLeftToRight);
321     SkScalar resetEllipsisWidth(SkScalar ellipsisWidth, size_t& lastRunIndex, const size_t textIndex);
322     void scanRTLTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end);
323     void scanLTRTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end);
324     void prepareForMiddleEllipsis(SkScalar rawWidth);
325     bool shapeForMiddleEllipsis(SkScalar rawWidth);
326     TextRange resetRangeWithDeletedRange(const TextRange& sourceRange,
327         const TextRange& deletedRange, const size_t& ellSize);
328     void resetTextStyleRange(const TextRange& deletedRange);
329     void resetPlaceholderRange(const TextRange& deletedRange);
setSize(SkScalar height,SkScalar width,SkScalar longestLine)330     void setSize(SkScalar height, SkScalar width, SkScalar longestLine) {
331         fHeight = height;
332         fWidth = width;
333         fLongestLine = longestLine;
334     }
getSize(SkScalar & height,SkScalar & width,SkScalar & longestLine)335     void getSize(SkScalar& height, SkScalar& width, SkScalar& longestLine) {
336         height = fHeight;
337         width = fWidth;
338         longestLine = fLongestLine;
339     }
setIntrinsicSize(SkScalar maxIntrinsicWidth,SkScalar minIntrinsicWidth,SkScalar alphabeticBaseline,SkScalar ideographicBaseline,bool exceededMaxLines)340     void setIntrinsicSize(SkScalar maxIntrinsicWidth, SkScalar minIntrinsicWidth, SkScalar alphabeticBaseline,
341                           SkScalar ideographicBaseline, bool exceededMaxLines) {
342         fMaxIntrinsicWidth = maxIntrinsicWidth;
343         fMinIntrinsicWidth = minIntrinsicWidth;
344         fAlphabeticBaseline = alphabeticBaseline;
345         fIdeographicBaseline = ideographicBaseline;
346         fExceededMaxLines = exceededMaxLines;
347     }
getIntrinsicSize(SkScalar & maxIntrinsicWidth,SkScalar & minIntrinsicWidth,SkScalar & alphabeticBaseline,SkScalar & ideographicBaseline,bool & exceededMaxLines)348     void getIntrinsicSize(SkScalar& maxIntrinsicWidth, SkScalar& minIntrinsicWidth, SkScalar& alphabeticBaseline,
349                           SkScalar& ideographicBaseline, bool& exceededMaxLines) {
350         maxIntrinsicWidth = fMaxIntrinsicWidth;
351         minIntrinsicWidth = fMinIntrinsicWidth;
352         alphabeticBaseline = fAlphabeticBaseline ;
353         ideographicBaseline = fIdeographicBaseline;
354         exceededMaxLines = fExceededMaxLines;
355     }
356 
357 #ifdef OHOS_SUPPORT
358     ParagraphPainter::PaintID updateTextStyleColorAndForeground(TextStyle& TextStyle, SkColor color);
359     TextBox getEmptyTextRect(RectHeightStyle rectHeightStyle) const;
360 #endif
361 
362     // Input
363     SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
364     SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
365     SkTArray<StyleBlock<SkPaint>> fBackgroundStyles;
366     SkTArray<StyleBlock<SkPaint>> fForegroundStyles;
367     SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles;
368     SkTArray<StyleBlock<Decoration>> fDecorationStyles;
369     SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff
370     SkTArray<Placeholder, true> fPlaceholders;
371     SkString fText;
372     std::vector<SkUnichar> fUnicodeText;
373 
374     // Internal structures
375     InternalState fState;
376     SkTArray<Run, false> fRuns;         // kShaped
377     SkTArray<Cluster, true> fClusters;  // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
378     SkTArray<SkUnicode::CodeUnitFlags, true> fCodeUnitProperties;
379     SkTArray<size_t, true> fClustersIndexFromCodeUnit;
380     std::vector<size_t> fWords;
381     std::vector<SkScalar> fIndents;
382     std::vector<TextCutRecord> rtlTextSize;
383     std::vector<TextCutRecord> ltrTextSize;
384     std::vector<SkUnicode::BidiRegion> fBidiRegions;
385     // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate)
386     // They are filled lazily whenever they need and cached
387     SkTArray<TextIndex, true> fUTF8IndexForUTF16Index;
388     SkTArray<size_t, true> fUTF16IndexForUTF8Index;
389     SkTArray<size_t, true> fUnicodeIndexForUTF8Index;
390     SkOnce fillUTF16MappingOnce;
391     size_t fUnresolvedGlyphs;
392     bool isMiddleEllipsis;
393     std::unordered_set<SkUnichar> fUnresolvedCodepoints;
394 
395     SkTArray<TextLine, false> fLines;   // kFormatted   (cached: width, max lines, ellipsis, text align)
396     sk_sp<SkPicture> fPicture;          // kRecorded    (cached: text styles)
397 
398     SkTArray<ResolvedFontDescriptor> fFontSwitches;
399 
400     InternalLineMetrics fEmptyMetrics;
401     InternalLineMetrics fStrutMetrics;
402 
403     SkScalar fOldWidth;
404     SkScalar fOldHeight;
405     SkScalar fMaxWidthWithTrailingSpaces;
406     SkScalar fOldMaxWidth;
407     SkScalar allTextWidth;
408     std::shared_ptr<SkUnicode> fUnicode;
409     bool fHasLineBreaks;
410     bool fHasWhitespacesInside;
411     TextIndex fTrailingSpaces;
412     SkScalar fLayoutRawWidth {0};
413 
414     size_t fLineNumber;
415     uint32_t hash_{0u};
416 };
417 }  // namespace textlayout
418 }  // namespace skia
419 
420 
421 #endif  // ParagraphImpl_DEFINED
422