• 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 #ifndef OHOS_SUPPORT
80 enum InternalState {
81   kUnknown = 0,
82   kIndexed = 1,     // Text is indexed
83   kShaped = 2,      // Text is shaped
84   kLineBroken = 5,
85   kFormatted = 6,
86   kDrawn = 7
87 };
88 #endif
89 
90 /*
91 struct BidiRegion {
92     BidiRegion(size_t start, size_t end, uint8_t dir)
93         : text(start, end), direction(dir) { }
94     TextRange text;
95     uint8_t direction;
96 };
97 */
98 class ParagraphImpl final : public Paragraph {
99 
100 public:
101 
102     ParagraphImpl() = default;
103 
104     ParagraphImpl(const SkString& text,
105                   ParagraphStyle style,
106                   SkTArray<Block, true> blocks,
107                   SkTArray<Placeholder, true> placeholders,
108                   sk_sp<FontCollection> fonts,
109                   std::shared_ptr<SkUnicode> unicode);
110 
111     ParagraphImpl(const std::u16string& utf16text,
112                   ParagraphStyle style,
113                   SkTArray<Block, true> blocks,
114                   SkTArray<Placeholder, true> placeholders,
115                   sk_sp<FontCollection> fonts,
116                   std::shared_ptr<SkUnicode> unicode);
117 
118     ~ParagraphImpl() override;
119 
120     void layout(SkScalar width) override;
121     void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
122     void paint(ParagraphPainter* canvas, SkScalar x, SkScalar y) override;
123     void paint(ParagraphPainter* canvas, RSPath* path, SkScalar hOffset, SkScalar vOffset) override;
124     std::vector<TextBox> getRectsForRange(unsigned start,
125                                           unsigned end,
126                                           RectHeightStyle rectHeightStyle,
127                                           RectWidthStyle rectWidthStyle) override;
128     std::vector<TextBox> getRectsForPlaceholders() override;
129     void getLineMetrics(std::vector<LineMetrics>&) override;
130     PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
131     SkRange<size_t> getWordBoundary(unsigned offset) override;
132 
getApplyRoundingHack()133     bool getApplyRoundingHack() const { return false; }
134 
lineNumber()135     size_t lineNumber() override { return fLineNumber; }
136 
137 #ifdef OHOS_SUPPORT
138     TextRange getEllipsisTextRange() override;
isRunCombinated()139     bool isRunCombinated() const override { return fRuns.size() < fTextStyles.size(); }
140     std::string GetDumpInfo() const override;
141 #endif
142 
143     TextLine& addLine(SkVector offset, SkVector advance,
144                       TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines,
145                       ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces,
146                       InternalLineMetrics sizes);
147 
text()148     SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); }
149 #ifdef OHOS_SUPPORT
150     std::vector<SkUnichar> convertUtf8ToUnicode(const SkString& utf8);
151     std::unique_ptr<Paragraph> createCroppedCopy(
152             size_t startIndex, size_t count = std::numeric_limits<size_t>::max()) override;
153     void initUnicodeText() override;
unicodeText()154     const std::vector<SkUnichar>& unicodeText() const override { return fUnicodeText; }
getUnicodeIndex(TextIndex index)155     size_t getUnicodeIndex(TextIndex index) const override {
156         if (index >= fUnicodeIndexForUTF8Index.size()) {
157             return fUnicodeIndexForUTF8Index.empty() ? 0 : fUnicodeIndexForUTF8Index.back() + 1;
158         }
159         return fUnicodeIndexForUTF8Index[index];
160     }
161 #else
unicodeText()162     const std::vector<SkUnichar>& unicodeText() const { return fUnicodeText; }
getUnicodeIndex(TextIndex index)163     size_t getUnicodeIndex(TextIndex index) const {
164         if (index >= fUnicodeIndexForUTF8Index.size()) {
165             return fUnicodeIndexForUTF8Index.empty() ? 0 : fUnicodeIndexForUTF8Index.back() + 1;
166         }
167         return fUnicodeIndexForUTF8Index[index];
168     }
169 #endif
state()170     InternalState state() const { return fState; }
runs()171     SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
styles()172     SkSpan<Block> styles() {
173         return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
174     }
placeholders()175     SkSpan<Placeholder> placeholders() {
176         return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size());
177     }
lines()178     SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
paragraphStyle()179     const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
clusters()180     SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
fontCollection()181     sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
182     void formatLines(SkScalar maxWidth);
183     void ensureUTF16Mapping();
184     SkTArray<TextIndex> countSurroundingGraphemes(TextRange textRange) const;
185     TextIndex findNextGraphemeBoundary(TextIndex utf8) const;
186     TextIndex findPreviousGraphemeBoundary(TextIndex utf8) const;
187     TextIndex findNextGlyphClusterBoundary(TextIndex utf8) const;
188     TextIndex findPreviousGlyphClusterBoundary(TextIndex utf8) const;
getUTF16Index(TextIndex index)189     size_t getUTF16Index(TextIndex index) const {
190         return fUTF16IndexForUTF8Index[index];
191     }
192 
193 #ifdef OHOS_SUPPORT
getUTF16IndexWithOverflowCheck(TextIndex index)194     size_t getUTF16IndexWithOverflowCheck(TextIndex index) const {
195         if (index >= fUTF16IndexForUTF8Index.size()) {
196             // This branch is entered only if the index of the ellipsis exceeds the size of the fUTF16IndexForUTF8Index
197             return fUTF16IndexForUTF8Index.back();
198         }
199         return fUTF16IndexForUTF8Index[index];
200     }
getText()201     const SkString& getText() const { return fText; }
202 #endif
203 
strutEnabled()204     bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
strutForceHeight()205     bool strutForceHeight() const {
206         return paragraphStyle().getStrutStyle().getForceStrutHeight();
207     }
strutHeightOverride()208     bool strutHeightOverride() const {
209         return paragraphStyle().getStrutStyle().getHeightOverride();
210     }
strutMetrics()211     InternalLineMetrics strutMetrics() const { return fStrutMetrics; }
212 
213     SkString getEllipsis() const;
214     WordBreakType getWordBreakType() const;
215     LineBreakStrategy getLineBreakStrategy() const;
216 
217     SkSpan<const char> text(TextRange textRange);
218     SkSpan<Cluster> clusters(ClusterRange clusterRange);
219     Cluster& cluster(ClusterIndex clusterIndex);
clusterIndex(TextIndex textIndex)220     ClusterIndex clusterIndex(TextIndex textIndex) {
221         auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex];
222         SkASSERT(clusterIndex != EMPTY_INDEX);
223         return clusterIndex;
224     }
run(RunIndex runIndex)225     Run& run(RunIndex runIndex) {
226         SkASSERT(runIndex < SkToSizeT(fRuns.size()));
227         return fRuns[runIndex];
228     }
229 
230     Run& runByCluster(ClusterIndex clusterIndex);
231     SkSpan<Block> blocks(BlockRange blockRange);
232     Block& block(BlockIndex blockIndex);
resolvedFonts()233     SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; }
234 
markDirty()235     void markDirty() override {
236         if (fState > kIndexed) {
237             fState = kIndexed;
238         }
239     }
240 
241     int32_t unresolvedGlyphs() override;
242     std::unordered_set<SkUnichar> unresolvedCodepoints() override;
243     void addUnresolvedCodepoints(TextRange textRange);
244 
245 #ifdef OHOS_SUPPORT
246     void setState(InternalState state) override;
getState()247     InternalState getState() const override { return state(); }
248     std::vector<TextBlobRecordInfo> getTextBlobRecordInfo() override;
hasSkipTextBlobDrawing()249     bool hasSkipTextBlobDrawing() const override { return fSkipTextBlobDrawing; }
setSkipTextBlobDrawing(bool state)250     void setSkipTextBlobDrawing(bool state) override { fSkipTextBlobDrawing = state; }
251     bool canPaintAllText() const override;
252 #else
253     void setState(InternalState state);
254 #endif
255 
getPicture()256     sk_sp<SkPicture> getPicture() { return fPicture; }
257 
widthWithTrailingSpaces()258     SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; }
259 
260     void resetContext();
261     void resolveStrut();
262 
263     bool computeCodeUnitProperties();
264     void applySpacingAndBuildClusterTable();
265     void buildClusterTable();
266     bool shapeTextIntoEndlessLine();
267     void positionShapedTextIntoLine(SkScalar maxWidth);
268     void breakShapedTextIntoLines(SkScalar maxWidth);
269 
270     void updateTextAlign(TextAlign textAlign) override;
271     void updateFontSize(size_t from, size_t to, SkScalar fontSize) override;
272     void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override;
273     void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override;
274 #ifdef OHOS_SUPPORT
275     std::vector<ParagraphPainter::PaintID> updateColor(size_t from, size_t to, SkColor color,
276         UtfEncodeType encodeType) override;
277     SkIRect generatePaintRegion(SkScalar x, SkScalar y) override;
exportTextStyles()278     SkTArray<Block, true>& exportTextStyles() override { return fTextStyles; }
279     bool preCalculateSingleRunAutoSpaceWidth(SkScalar floorWidth);
280     bool isAutoSpaceEnabled() const;
281     SkScalar clusterUsingAutoSpaceWidth(const Cluster& cluster) const;
282     void updateSplitRunClusterInfo(const Run& run, bool isSplitRun);
283     void refreshLines();
284     bool isTailOfLineNeedSplit(const Run& lineLastRun, size_t lineEnd, bool hasGenerated);
285     void generateSplitPoint(
286         std::vector<SplitPoint>& splitPoints, const Run& run, ClusterRange lineRange, size_t lineIndex);
287     void generateSplitPoints(std::vector<SplitPoint>& splitPoints);
288     void generateRunsBySplitPoints(std::vector<SplitPoint>& splitPoints, SkTArray<Run, false>& runs);
289     void splitRuns();
290 #endif
291 
292     void visit(const Visitor&) override;
293 
294     void setIndents(const std::vector<SkScalar>& indents) override;
295     int getLineNumberAt(TextIndex codeUnitIndex) const override;
296     bool getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const override;
297     TextRange getActualTextRange(int lineNumber, bool includeSpaces) const override;
298     bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) override;
299     bool getClosestGlyphClusterAt(SkScalar dx,
300                                   SkScalar dy,
301                                   GlyphClusterInfo* glyphInfo) override;
302 #ifndef USE_SKIA_TXT
303     SkFont getFontAt(TextIndex codeUnitIndex) const override;
304 #else
305     RSFont getFontAt(TextIndex codeUnitIndex) const override;
306 #endif
307     std::vector<FontInfo> getFonts() const override;
308 
getEmptyMetrics()309     InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; }
getStrutMetrics()310     InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; }
311 
312     BlockRange findAllBlocks(TextRange textRange);
313 
resetShifts()314     void resetShifts() {
315         for (auto& run : fRuns) {
316             run.resetJustificationShifts();
317         }
318     }
319 
resetAutoSpacing()320     void resetAutoSpacing() {
321         for (auto& run : fRuns) {
322             run.resetAutoSpacing();
323         }
324     }
325 
codeUnitHasProperty(size_t index,SkUnicode::CodeUnitFlags property)326     bool codeUnitHasProperty(size_t index, SkUnicode::CodeUnitFlags property) const {
327         return (fCodeUnitProperties[index] & property) == property;
328     }
329 
getUnicode()330     SkUnicode* getUnicode() { return fUnicode.get(); }
331 
332     SkScalar detectIndents(size_t index) override;
333 
getTextSplitRatio()334     SkScalar getTextSplitRatio() const override { return fParagraphStyle.getTextSplitRatio(); }
335 
336 #ifndef USE_SKIA_TXT
337     SkFontMetrics measureText() override;
338 #else
339     RSFontMetrics measureText() override;
340 #endif
341 
342 #ifdef OHOS_SUPPORT
343     bool needCreateMiddleEllipsis();
344     Placeholder* getPlaceholderByIndex(size_t placeholderIndex);
345     bool IsPlaceholderAlignedFollowParagraph(size_t placeholderIndex);
346     bool setPlaceholderAlignment(size_t placeholderIndex, PlaceholderAlignment alignment);
347     Block& getBlockByRun(const Run& run);
348 #endif
349 #ifndef USE_SKIA_TXT
350     bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber,
351         std::vector<SkFontMetrics>& fontMetrics) override;
352 #else
353     bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber,
354         std::vector<RSFontMetrics>& fontMetrics) override;
355 #endif
356 
357     std::vector<std::unique_ptr<TextLineBase>> GetTextLines() override;
358     std::unique_ptr<Paragraph> CloneSelf() override;
359 
hash()360     uint32_t& hash() {
361         return hash_;
362     }
363 
364 #ifdef OHOS_SUPPORT
GetMaxLines()365     size_t GetMaxLines() const override { return fParagraphStyle.getMaxLines(); }
setLastAutoSpacingFlag(Cluster::AutoSpacingFlag flag)366     void setLastAutoSpacingFlag(Cluster::AutoSpacingFlag flag) { fLastAutoSpacingFlag = flag; }
getLastAutoSpacingFlag()367     const Cluster::AutoSpacingFlag& getLastAutoSpacingFlag() const { return fLastAutoSpacingFlag; }
368 #endif
369 
370 private:
371     friend class ParagraphBuilder;
372     friend class ParagraphCacheKey;
373     friend class ParagraphCacheValue;
374     friend class ParagraphCache;
375 #ifdef OHOS_SUPPORT
376     friend struct TextWrapScorer;
377 #endif
378     friend class TextWrapper;
379     friend class OneLineShaper;
380     void computeEmptyMetrics();
381 
382     TextRange resetRangeWithDeletedRange(const TextRange& sourceRange,
383         const TextRange& deletedRange, const size_t& ellSize);
384     void resetTextStyleRange(const TextRange& deletedRange);
385     void resetPlaceholderRange(const TextRange& deletedRange);
setSize(SkScalar height,SkScalar width,SkScalar longestLine)386     void setSize(SkScalar height, SkScalar width, SkScalar longestLine) {
387         fHeight = height;
388         fWidth = width;
389         fLongestLine = longestLine;
390     }
getSize(SkScalar & height,SkScalar & width,SkScalar & longestLine)391     void getSize(SkScalar& height, SkScalar& width, SkScalar& longestLine) {
392         height = fHeight;
393         width = fWidth;
394         longestLine = fLongestLine;
395     }
setIntrinsicSize(SkScalar maxIntrinsicWidth,SkScalar minIntrinsicWidth,SkScalar alphabeticBaseline,SkScalar ideographicBaseline,bool exceededMaxLines)396     void setIntrinsicSize(SkScalar maxIntrinsicWidth, SkScalar minIntrinsicWidth, SkScalar alphabeticBaseline,
397                           SkScalar ideographicBaseline, bool exceededMaxLines) {
398         fMaxIntrinsicWidth = maxIntrinsicWidth;
399         fMinIntrinsicWidth = minIntrinsicWidth;
400         fAlphabeticBaseline = alphabeticBaseline;
401         fIdeographicBaseline = ideographicBaseline;
402         fExceededMaxLines = exceededMaxLines;
403     }
getIntrinsicSize(SkScalar & maxIntrinsicWidth,SkScalar & minIntrinsicWidth,SkScalar & alphabeticBaseline,SkScalar & ideographicBaseline,bool & exceededMaxLines)404     void getIntrinsicSize(SkScalar& maxIntrinsicWidth, SkScalar& minIntrinsicWidth, SkScalar& alphabeticBaseline,
405                           SkScalar& ideographicBaseline, bool& exceededMaxLines) {
406         maxIntrinsicWidth = fMaxIntrinsicWidth;
407         minIntrinsicWidth = fMinIntrinsicWidth;
408         alphabeticBaseline = fAlphabeticBaseline ;
409         ideographicBaseline = fIdeographicBaseline;
410         exceededMaxLines = fExceededMaxLines;
411     }
412 
413 #ifdef OHOS_SUPPORT
414     ParagraphPainter::PaintID updateTextStyleColorAndForeground(TextStyle& TextStyle, SkColor color);
415     TextBox getEmptyTextRect(RectHeightStyle rectHeightStyle) const;
416     size_t prefixByteCountUntilChar(size_t index);
417     void copyProperties(const ParagraphImpl& source);
418     std::string_view GetState() const;
419 #endif
420 
421     // Input
422     SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
423     SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
424     SkTArray<StyleBlock<SkPaint>> fBackgroundStyles;
425     SkTArray<StyleBlock<SkPaint>> fForegroundStyles;
426     SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles;
427     SkTArray<StyleBlock<Decoration>> fDecorationStyles;
428     SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff
429     SkTArray<Placeholder, true> fPlaceholders;
430     SkString fText;
431     std::vector<SkUnichar> fUnicodeText;
432 
433     // Internal structures
434     InternalState fState;
435     SkTArray<Run, false> fRuns;         // kShaped
436     SkTArray<Cluster, true> fClusters;  // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
437     SkTArray<SkUnicode::CodeUnitFlags, true> fCodeUnitProperties;
438     SkTArray<size_t, true> fClustersIndexFromCodeUnit;
439     std::vector<size_t> fWords;
440     std::vector<SkScalar> fIndents;
441     std::vector<SkUnicode::BidiRegion> fBidiRegions;
442     // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate)
443     // They are filled lazily whenever they need and cached
444     SkTArray<TextIndex, true> fUTF8IndexForUTF16Index;
445     SkTArray<size_t, true> fUTF16IndexForUTF8Index;
446     SkTArray<size_t, true> fUnicodeIndexForUTF8Index;
447     SkOnce fillUTF16MappingOnce;
448     size_t fUnresolvedGlyphs;
449     std::unordered_set<SkUnichar> fUnresolvedCodepoints;
450 
451     SkTArray<TextLine, false> fLines;   // kFormatted   (cached: width, max lines, ellipsis, text align)
452     sk_sp<SkPicture> fPicture;          // kRecorded    (cached: text styles)
453 
454     SkTArray<ResolvedFontDescriptor> fFontSwitches;
455 
456     InternalLineMetrics fEmptyMetrics;
457     InternalLineMetrics fStrutMetrics;
458 
459     SkScalar fOldWidth;
460     SkScalar fOldHeight;
461     SkScalar fMaxWidthWithTrailingSpaces;
462     std::shared_ptr<SkUnicode> fUnicode;
463     bool fHasLineBreaks;
464     bool fHasWhitespacesInside;
465     TextIndex fTrailingSpaces;
466     SkScalar fLayoutRawWidth {0};
467 
468     size_t fLineNumber { 0 };
469     uint32_t hash_{0u};
470 
471 #ifdef OHOS_SUPPORT
472     TextRange fEllipsisRange{EMPTY_RANGE};
473     std::optional<SkRect> fPaintRegion;
474     // just for building cluster table, record the last built unicode autospacing flag;
475     Cluster::AutoSpacingFlag fLastAutoSpacingFlag;
476     bool fSkipTextBlobDrawing{false};
477 #endif
478 };
479 }  // namespace textlayout
480 }  // namespace skia
481 
482 
483 #endif  // ParagraphImpl_DEFINED
484