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