• 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/TextShadow.h"
25 #include "modules/skparagraph/include/TextStyle.h"
26 #include "modules/skparagraph/src/Run.h"
27 #include "modules/skparagraph/src/TextLine.h"
28 #include "modules/skunicode/include/SkUnicode.h"
29 #include "include/private/SkTHash.h"
30 #include <hilog/log.h>
31 
32 #include <memory>
33 #include <string>
34 #include <vector>
35 
36 class SkCanvas;
37 
38 namespace skia {
39 namespace textlayout {
40 #define LOGD(fmt, ...) \
41     ::OHOS::HiviewDFX::HiLog::Debug(::OHOS::HiviewDFX::HiLogLabel \
42         { LOG_CORE, 0xD001402, "2DGraphics" }, "%{public}s: " fmt, __func__, ##__VA_ARGS__)
43 
44 class LineMetrics;
45 class TextLine;
46 
47 template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
48     return a.size() == b.size() && a.begin() == b.begin();
49 }
50 
51 template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) {
52     return a.begin() >= b.begin() && a.end() <= b.end();
53 }
54 
55 template <typename TStyle>
56 struct StyleBlock {
StyleBlockStyleBlock57     StyleBlock() : fRange(EMPTY_RANGE), fStyle() { }
StyleBlockStyleBlock58     StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {}
StyleBlockStyleBlock59     StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {}
addStyleBlock60     void add(TextRange tail) {
61         SkASSERT(fRange.end == tail.start);
62         fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
63     }
64     TextRange fRange;
65     TStyle fStyle;
66 };
67 
68 struct ResolvedFontDescriptor {
69 
ResolvedFontDescriptorResolvedFontDescriptor70     ResolvedFontDescriptor(TextIndex index, SkFont font)
71         : fFont(font), fTextStart(index) { }
72     SkFont fFont;
73     TextIndex fTextStart;
74 };
75 
76 enum InternalState {
77   kUnknown = 0,
78   kIndexed = 1,     // Text is indexed
79   kShaped = 2,      // Text is shaped
80   kLineBroken = 5,
81   kFormatted = 6,
82   kDrawn = 7
83 };
84 
85 /*
86 struct BidiRegion {
87     BidiRegion(size_t start, size_t end, uint8_t dir)
88         : text(start, end), direction(dir) { }
89     TextRange text;
90     uint8_t direction;
91 };
92 */
93 class ParagraphImpl final : public Paragraph {
94 
95 public:
96 
97     ParagraphImpl(const SkString& text,
98                   ParagraphStyle style,
99                   SkTArray<Block, true> blocks,
100                   SkTArray<Placeholder, true> placeholders,
101                   sk_sp<FontCollection> fonts,
102                   std::shared_ptr<SkUnicode> unicode);
103 
104     ParagraphImpl(const std::u16string& utf16text,
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() override;
112 
113     void layout(SkScalar width) override;
114     void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override;
115     void paint(ParagraphPainter* canvas, SkScalar x, SkScalar y) override;
116     std::vector<TextBox> getRectsForRange(unsigned start,
117                                           unsigned end,
118                                           RectHeightStyle rectHeightStyle,
119                                           RectWidthStyle rectWidthStyle) override;
120     std::vector<TextBox> getRectsForPlaceholders() override;
121     void getLineMetrics(std::vector<LineMetrics>&) override;
122     PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override;
123     SkRange<size_t> getWordBoundary(unsigned offset) override;
124 
getApplyRoundingHack()125     bool getApplyRoundingHack() const { return false; }
126 
lineNumber()127     size_t lineNumber() override { return fLineNumber; }
128 
129     TextLine& addLine(SkVector offset, SkVector advance,
130                       TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines,
131                       ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces,
132                       InternalLineMetrics sizes);
133 
text()134     SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); }
state()135     InternalState state() const { return fState; }
runs()136     SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); }
styles()137     SkSpan<Block> styles() {
138         return SkSpan<Block>(fTextStyles.data(), fTextStyles.size());
139     }
placeholders()140     SkSpan<Placeholder> placeholders() {
141         return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size());
142     }
lines()143     SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); }
paragraphStyle()144     const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
clusters()145     SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
fontCollection()146     sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
147     void formatLines(SkScalar maxWidth);
148     void ensureUTF16Mapping();
149     SkTArray<TextIndex> countSurroundingGraphemes(TextRange textRange) const;
150     TextIndex findNextGraphemeBoundary(TextIndex utf8) const;
151     TextIndex findPreviousGraphemeBoundary(TextIndex utf8) const;
152     TextIndex findNextGlyphClusterBoundary(TextIndex utf8) const;
153     TextIndex findPreviousGlyphClusterBoundary(TextIndex utf8) const;
getUTF16Index(TextIndex index)154     size_t getUTF16Index(TextIndex index) const {
155         return fUTF16IndexForUTF8Index[index];
156     }
157 
strutEnabled()158     bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
strutForceHeight()159     bool strutForceHeight() const {
160         return paragraphStyle().getStrutStyle().getForceStrutHeight();
161     }
strutHeightOverride()162     bool strutHeightOverride() const {
163         return paragraphStyle().getStrutStyle().getHeightOverride();
164     }
strutMetrics()165     InternalLineMetrics strutMetrics() const { return fStrutMetrics; }
166 
167     SkString getEllipsis() const;
168     WordBreakType getWordBreakType() const;
169 
170     SkSpan<const char> text(TextRange textRange);
171     SkSpan<Cluster> clusters(ClusterRange clusterRange);
172     Cluster& cluster(ClusterIndex clusterIndex);
clusterIndex(TextIndex textIndex)173     ClusterIndex clusterIndex(TextIndex textIndex) {
174         auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex];
175         SkASSERT(clusterIndex != EMPTY_INDEX);
176         return clusterIndex;
177     }
run(RunIndex runIndex)178     Run& run(RunIndex runIndex) {
179         SkASSERT(runIndex < SkToSizeT(fRuns.size()));
180         return fRuns[runIndex];
181     }
182 
183     Run& runByCluster(ClusterIndex clusterIndex);
184     SkSpan<Block> blocks(BlockRange blockRange);
185     Block& block(BlockIndex blockIndex);
resolvedFonts()186     SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; }
187 
markDirty()188     void markDirty() override {
189         if (fState > kIndexed) {
190             fState = kIndexed;
191         }
192     }
193 
194     int32_t unresolvedGlyphs() override;
195     std::unordered_set<SkUnichar> unresolvedCodepoints() override;
196     void addUnresolvedCodepoints(TextRange textRange);
197 
198     void setState(InternalState state);
getPicture()199     sk_sp<SkPicture> getPicture() { return fPicture; }
200 
widthWithTrailingSpaces()201     SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; }
getMaxWidth()202     SkScalar getMaxWidth() { return fOldMaxWidth; }
203 
204     void resetContext();
205     void resolveStrut();
206 
207     bool computeCodeUnitProperties();
208     void applySpacingAndBuildClusterTable();
209     void buildClusterTable();
210     bool shapeTextIntoEndlessLine();
211     void breakShapedTextIntoLines(SkScalar maxWidth);
212 
213     void updateTextAlign(TextAlign textAlign) override;
214     void updateFontSize(size_t from, size_t to, SkScalar fontSize) override;
215     void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override;
216     void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override;
217 
218     void visit(const Visitor&) override;
219 
220     void setIndents(const std::vector<SkScalar>& indents) override;
221     int getLineNumberAt(TextIndex codeUnitIndex) const override;
222     bool getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const override;
223     TextRange getActualTextRange(int lineNumber, bool includeSpaces) const override;
224     bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) override;
225     bool getClosestGlyphClusterAt(SkScalar dx,
226                                   SkScalar dy,
227                                   GlyphClusterInfo* glyphInfo) override;
228     SkFont getFontAt(TextIndex codeUnitIndex) const override;
229     std::vector<FontInfo> getFonts() const override;
230 
getEmptyMetrics()231     InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; }
getStrutMetrics()232     InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; }
233 
234     BlockRange findAllBlocks(TextRange textRange);
235 
resetShifts()236     void resetShifts() {
237         for (auto& run : fRuns) {
238             run.resetJustificationShifts();
239         }
240     }
241 
242     void scanTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end);
243     void middleEllipsisDeal();
codeUnitHasProperty(size_t index,SkUnicode::CodeUnitFlags property)244     bool codeUnitHasProperty(size_t index, SkUnicode::CodeUnitFlags property) const {
245         return (fCodeUnitProperties[index] & property) == property;
246     }
247 
getUnicode()248     SkUnicode* getUnicode() { return fUnicode.get(); }
249 
250     SkScalar detectIndents(size_t index);
251 
getTextSplitRatio()252     SkScalar getTextSplitRatio() const override { return fParagraphStyle.getTextSplitRatio(); }
253 
254     SkFontMetrics measureText() override;
255 
getEllipsisState()256     bool &getEllipsisState() { return isMiddleEllipsis; }
257 private:
258     friend class ParagraphBuilder;
259     friend class ParagraphCacheKey;
260     friend class ParagraphCacheValue;
261     friend class ParagraphCache;
262 
263     friend class TextWrapper;
264     friend class OneLineShaper;
265 
266     void computeEmptyMetrics();
267     void middleEllipsisAddText(size_t charStart,
268                                size_t charEnd,
269                                SkScalar& allTextWidth,
270                                SkScalar width,
271                                bool isLeftToRight);
272     void setRunTimeEllipsisWidthForMiddleEllipsis();
273     void scanRTLTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end);
274     void scanLTRTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end);
275 
276     // Input
277     SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
278     SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
279     SkTArray<StyleBlock<SkPaint>> fBackgroundStyles;
280     SkTArray<StyleBlock<SkPaint>> fForegroundStyles;
281     SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles;
282     SkTArray<StyleBlock<Decoration>> fDecorationStyles;
283     SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff
284     SkTArray<Placeholder, true> fPlaceholders;
285     SkString fText;
286 
287     // Internal structures
288     InternalState fState;
289     SkTArray<Run, false> fRuns;         // kShaped
290     SkTArray<Cluster, true> fClusters;  // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
291     SkTArray<SkUnicode::CodeUnitFlags, true> fCodeUnitProperties;
292     SkTArray<size_t, true> fClustersIndexFromCodeUnit;
293     std::vector<size_t> fWords;
294     std::vector<SkScalar> fIndents;
295     std::vector<TextCutRecord> rtlTextSize;
296     std::vector<TextCutRecord> ltrTextSize;
297     std::vector<SkUnicode::BidiRegion> fBidiRegions;
298     // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate)
299     // They are filled lazily whenever they need and cached
300     SkTArray<TextIndex, true> fUTF8IndexForUTF16Index;
301     SkTArray<size_t, true> fUTF16IndexForUTF8Index;
302     SkOnce fillUTF16MappingOnce;
303     size_t fUnresolvedGlyphs;
304     bool isMiddleEllipsis;
305     std::unordered_set<SkUnichar> fUnresolvedCodepoints;
306 
307     SkTArray<TextLine, false> fLines;   // kFormatted   (cached: width, max lines, ellipsis, text align)
308     sk_sp<SkPicture> fPicture;          // kRecorded    (cached: text styles)
309 
310     SkTArray<ResolvedFontDescriptor> fFontSwitches;
311 
312     InternalLineMetrics fEmptyMetrics;
313     InternalLineMetrics fStrutMetrics;
314 
315     SkScalar fOldWidth;
316     SkScalar fOldHeight;
317     SkScalar runTimeEllipsisWidth;
318     SkScalar fMaxWidthWithTrailingSpaces;
319     SkScalar fOldMaxWidth;
320     SkScalar allTextWidth;
321     std::shared_ptr<SkUnicode> fUnicode;
322     bool fHasLineBreaks;
323     bool fHasWhitespacesInside;
324     TextIndex fTrailingSpaces;
325 
326     size_t fLineNumber;
327 };
328 }  // namespace textlayout
329 }  // namespace skia
330 
331 
332 #endif  // ParagraphImpl_DEFINED
333