1 // Copyright 2019 Google LLC. 2 #ifndef TextLine_DEFINED 3 #define TextLine_DEFINED 4 5 #include "include/ParagraphStyle.h" 6 #include "include/core/SkPoint.h" 7 #include "include/core/SkRect.h" 8 #include "include/core/SkScalar.h" 9 #include "include/private/SkBitmaskEnum.h" // IWYU pragma: keep 10 #include "include/private/SkTArray.h" 11 #include "modules/skparagraph/include/DartTypes.h" 12 #include "modules/skparagraph/include/Metrics.h" 13 #include "modules/skparagraph/include/ParagraphPainter.h" 14 #include "modules/skparagraph/include/RunBase.h" 15 #include "modules/skparagraph/include/TextStyle.h" 16 #include "modules/skparagraph/src/Run.h" 17 18 #include <stddef.h> 19 #include <functional> 20 #include <memory> 21 #include <vector> 22 23 class SkString; 24 25 namespace skia { 26 namespace textlayout { 27 28 class ParagraphImpl; 29 30 class TextLine { 31 public: 32 33 struct ClipContext { 34 const Run* run; 35 size_t pos; 36 size_t size; 37 SkScalar fTextShift; // Shifts the text inside the run so it's placed at the right position 38 SkRect clip; 39 SkScalar fExcludedTrailingSpaces; 40 bool clippingNeeded; 41 }; 42 43 enum TextAdjustment { 44 GlyphCluster = 0x01, // All text producing glyphs pointing to the same ClusterIndex 45 GlyphemeCluster = 0x02, // base glyph + all attached diacritics 46 Grapheme = 0x04, // Text adjusted to graphemes 47 GraphemeGluster = 0x05, // GlyphCluster & Grapheme 48 }; 49 50 TextLine() = default; 51 TextLine(const TextLine&) = delete; 52 TextLine& operator=(const TextLine&) = delete; 53 TextLine(TextLine&&) = default; 54 TextLine& operator=(TextLine&&) = default; 55 ~TextLine() = default; 56 57 TextLine(ParagraphImpl* owner, 58 SkVector offset, 59 SkVector advance, 60 BlockRange blocks, 61 TextRange textExcludingSpaces, 62 TextRange text, 63 TextRange textIncludingNewlines, 64 ClusterRange clusters, 65 ClusterRange clustersWithGhosts, 66 SkScalar widthWithSpaces, 67 InternalLineMetrics sizes); 68 trimmedText()69 TextRange trimmedText() const { return fTextExcludingSpaces; } textWithNewlines()70 TextRange textWithNewlines() const { return fTextIncludingNewlines; } text()71 TextRange text() const { return fText; } clusters()72 ClusterRange clusters() const { return fClusterRange; } clustersWithSpaces()73 ClusterRange clustersWithSpaces() const { return fGhostClusterRange; } ellipsis()74 Run* ellipsis() const { return fEllipsis.get(); } sizes()75 InternalLineMetrics sizes() const { return fSizes; } empty()76 bool empty() const { return fTextExcludingSpaces.empty(); } 77 spacesWidth()78 SkScalar spacesWidth() const { return fWidthWithSpaces - width(); } height()79 SkScalar height() const { return fAdvance.fY; } width()80 SkScalar width() const { 81 return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0); 82 } widthWithoutEllipsis()83 SkScalar widthWithoutEllipsis() const { return fAdvance.fX; } 84 SkVector offset() const; 85 alphabeticBaseline()86 SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); } ideographicBaseline()87 SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); } baseline()88 SkScalar baseline() const { return fSizes.baseline(); } 89 90 using RunVisitor = std::function<bool( 91 const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width)>; 92 void iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisitor& runVisitor) const; 93 using RunStyleVisitor = std::function<void( 94 TextRange textRange, const TextStyle& style, const ClipContext& context)>; 95 SkScalar iterateThroughSingleRunByStyles(TextAdjustment textAdjustment, 96 const Run* run, 97 SkScalar runOffset, 98 TextRange textRange, 99 StyleType styleType, 100 const RunStyleVisitor& visitor) const; 101 102 using ClustersVisitor = std::function<bool(const Cluster* cluster, bool ghost)>; 103 void iterateThroughClustersInGlyphsOrder(bool reverse, 104 bool includeGhosts, 105 const ClustersVisitor& visitor) const; 106 107 void format(TextAlign align, SkScalar maxWidth, EllipsisModal ellipsisModal); 108 void paint(ParagraphPainter* painter, SkScalar x, SkScalar y); 109 void visit(SkScalar x, SkScalar y); 110 void ensureTextBlobCachePopulated(); setParagraphImpl(ParagraphImpl * newpara)111 void setParagraphImpl(ParagraphImpl* newpara) { fOwner = newpara; } setBlockRange(const BlockRange & blockRange)112 void setBlockRange(const BlockRange& blockRange) { fBlockRange = blockRange; } 113 void createTailEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr, WordBreakType wordBreakType); 114 void createHeadEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr); 115 // For testing internal structures 116 void scanStyles(StyleType style, const RunStyleVisitor& visitor); 117 setMaxRunMetrics(const InternalLineMetrics & metrics)118 void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; } getMaxRunMetrics()119 InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; } 120 121 bool isFirstLine() const; 122 bool isLastLine() const; 123 void getRectsForRange(TextRange textRange, 124 RectHeightStyle rectHeightStyle, 125 RectWidthStyle rectWidthStyle, 126 std::vector<TextBox>& boxes) const; 127 void getRectsForPlaceholders(std::vector<TextBox>& boxes); 128 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx); 129 130 ClipContext measureTextInsideOneRun(TextRange textRange, 131 const Run* run, 132 SkScalar runOffsetInLine, 133 SkScalar textOffsetInRunInLine, 134 bool includeGhostSpaces, 135 TextAdjustment textAdjustment) const; 136 137 LineMetrics getMetrics() const; 138 139 SkRect extendHeight(const ClipContext& context) const; 140 shiftVertically(SkScalar shift)141 void shiftVertically(SkScalar shift) { fOffset.fY += shift; } 142 setAscentStyle(LineMetricStyle style)143 void setAscentStyle(LineMetricStyle style) { fAscentStyle = style; } setDescentStyle(LineMetricStyle style)144 void setDescentStyle(LineMetricStyle style) { fDescentStyle = style; } 145 146 bool endsWithHardLineBreak() const; 147 std::unique_ptr<Run> shapeEllipsis(const SkString& ellipsis, const Cluster* cluster); getLineAllRuns()148 SkSTArray<1, size_t, true> getLineAllRuns() const { return fRunsInVisualOrder; }; 149 150 size_t getGlyphCount() const; 151 std::vector<std::unique_ptr<RunBase>> getGlyphRuns() const; 152 TextLine CloneSelf(); getTextRangeReplacedByEllipsis()153 TextRange getTextRangeReplacedByEllipsis() const { return fTextRangeReplacedByEllipsis; } 154 private: 155 struct RoundRectAttr { 156 int styleId; 157 RectStyle roundRectStyle; 158 SkRect rect; 159 }; 160 161 void justify(SkScalar maxWidth); 162 163 void buildTextBlob(TextRange textRange, const TextStyle& style, const ClipContext& context); 164 void paintBackground(ParagraphPainter* painter, 165 SkScalar x, 166 SkScalar y, 167 TextRange textRange, 168 const TextStyle& style, 169 const ClipContext& context) const; 170 void paintRoundRect(ParagraphPainter* painter, SkScalar x, SkScalar y, const Run* run) const; 171 void paintShadow(ParagraphPainter* painter, 172 SkScalar x, 173 SkScalar y, 174 TextRange textRange, 175 const TextStyle& style, 176 const ClipContext& context) const; 177 void paintDecorations(ParagraphPainter* painter, 178 SkScalar x, 179 SkScalar y, 180 TextRange textRange, 181 const TextStyle& style, 182 const ClipContext& context) const; 183 184 void shiftCluster(const Cluster* cluster, SkScalar shift, SkScalar prevShift); 185 bool hasBackgroundRect(const RoundRectAttr& attr); 186 void computeRoundRect(int& index, int& preIndex, std::vector<Run*>& groupRuns, Run* run); 187 void prepareRoundRect(); 188 189 ParagraphImpl* fOwner; 190 BlockRange fBlockRange; 191 TextRange fTextExcludingSpaces; 192 TextRange fText; 193 TextRange fTextIncludingNewlines; 194 ClusterRange fClusterRange; 195 ClusterRange fGhostClusterRange; 196 // Avoid the malloc/free in the common case of one run per line 197 SkSTArray<1, size_t, true> fRunsInVisualOrder; 198 SkVector fAdvance; // Text size 199 SkVector fOffset; // Text position 200 SkScalar fShift; // Let right 201 SkScalar fWidthWithSpaces; 202 std::unique_ptr<Run> fEllipsis; // In case the line ends with the ellipsis 203 TextRange fTextRangeReplacedByEllipsis; // text range replaced by ellipsis 204 InternalLineMetrics fSizes; // Line metrics as a max of all run metrics and struts 205 InternalLineMetrics fMaxRunMetrics; // No struts - need it for GetRectForRange(max height) 206 bool fHasBackground; 207 bool fHasShadows; 208 bool fHasDecorations; 209 210 LineMetricStyle fAscentStyle; 211 LineMetricStyle fDescentStyle; 212 213 struct TextBlobRecord { 214 void paint(ParagraphPainter* painter, SkScalar x, SkScalar y); 215 216 #ifndef USE_SKIA_TXT 217 sk_sp<SkTextBlob> fBlob; 218 #else 219 std::shared_ptr<RSTextBlob> fBlob; 220 #endif 221 SkPoint fOffset = SkPoint::Make(0.0f, 0.0f); 222 ParagraphPainter::SkPaintOrID fPaint; 223 SkRect fBounds = SkRect::MakeEmpty(); 224 bool fClippingNeeded = false; 225 SkRect fClipRect = SkRect::MakeEmpty(); 226 227 // Extra fields only used for the (experimental) visitor 228 const Run* fVisitor_Run; 229 size_t fVisitor_Pos; 230 size_t fVisitor_Size; 231 }; 232 bool fTextBlobCachePopulated; 233 234 std::vector<RoundRectAttr> roundRectAttrs = {}; 235 public: 236 std::vector<TextBlobRecord> fTextBlobCache; 237 }; 238 } // namespace textlayout 239 } // namespace skia 240 241 namespace sknonstd { 242 template <> struct is_bitmask_enum<skia::textlayout::TextLine::TextAdjustment> : std::true_type {}; 243 } // namespace sknonstd 244 245 #endif // TextLine_DEFINED 246