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