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/SkTArray.h" 9 #include "modules/skparagraph/include/DartTypes.h" 10 #include "modules/skparagraph/include/Metrics.h" 11 #include "modules/skparagraph/include/TextStyle.h" 12 #include "modules/skparagraph/src/Run.h" 13 14 #include <stddef.h> 15 #include <functional> 16 #include <memory> 17 #include <vector> 18 19 class SkCanvas; 20 class SkString; 21 22 namespace skia { 23 namespace textlayout { 24 25 class ParagraphImpl; 26 27 class TextLine { 28 public: 29 30 struct ClipContext { 31 const Run* run; 32 size_t pos; 33 size_t size; 34 SkScalar fTextShift; // Shifts the text inside the run so it's placed at the right position 35 SkRect clip; 36 bool clippingNeeded; 37 }; 38 39 TextLine() = default; 40 TextLine(const TextLine&) = delete; 41 TextLine& operator=(const TextLine&) = delete; 42 TextLine(TextLine&&) = default; 43 TextLine& operator=(TextLine&&) = default; 44 ~TextLine() = default; 45 46 TextLine(ParagraphImpl* owner, 47 SkVector offset, 48 SkVector advance, 49 BlockRange blocks, 50 TextRange text, 51 TextRange textWithSpaces, 52 ClusterRange clusters, 53 ClusterRange clustersWithGhosts, 54 SkScalar widthWithSpaces, 55 InternalLineMetrics sizes); 56 trimmedText()57 TextRange trimmedText() const { return fTextRange; } textWithSpaces()58 TextRange textWithSpaces() const { return fTextWithWhitespacesRange; } clusters()59 ClusterRange clusters() const { return fClusterRange; } clustersWithSpaces()60 ClusterRange clustersWithSpaces() { return fGhostClusterRange; } ellipsis()61 Run* ellipsis() const { return fEllipsis.get(); } sizes()62 InternalLineMetrics sizes() const { return fSizes; } empty()63 bool empty() const { return fTextRange.empty(); } 64 spacesWidth()65 SkScalar spacesWidth() { return fWidthWithSpaces - width(); } height()66 SkScalar height() const { return fAdvance.fY; } width()67 SkScalar width() const { 68 return fAdvance.fX + (fEllipsis != nullptr ? fEllipsis->fAdvance.fX : 0); 69 } shift()70 SkScalar shift() const { return fShift; } 71 SkVector offset() const; 72 alphabeticBaseline()73 SkScalar alphabeticBaseline() const { return fSizes.alphabeticBaseline(); } ideographicBaseline()74 SkScalar ideographicBaseline() const { return fSizes.ideographicBaseline(); } baseline()75 SkScalar baseline() const { return fSizes.baseline(); } 76 77 using RunVisitor = std::function<bool(const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width)>; 78 void iterateThroughVisualRuns(bool includingGhostSpaces, const RunVisitor& runVisitor) const; 79 using RunStyleVisitor = std::function<void(TextRange textRange, const TextStyle& style, const ClipContext& context)>; 80 SkScalar iterateThroughSingleRunByStyles(const Run* run, SkScalar runOffset, TextRange textRange, 81 StyleType styleType, const RunStyleVisitor& visitor) const; 82 83 using ClustersVisitor = std::function<bool(const Cluster* cluster, bool ghost)>; 84 void iterateThroughClustersInGlyphsOrder(bool reverse, bool includeGhosts, const ClustersVisitor& visitor) const; 85 86 void format(TextAlign align, SkScalar maxWidth); 87 SkRect paint(SkCanvas* canvas, SkScalar x, SkScalar y); 88 89 void createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool ltr); 90 91 // For testing internal structures 92 void scanStyles(StyleType style, const RunStyleVisitor& visitor); 93 setMaxRunMetrics(const InternalLineMetrics & metrics)94 void setMaxRunMetrics(const InternalLineMetrics& metrics) { fMaxRunMetrics = metrics; } getMaxRunMetrics()95 InternalLineMetrics getMaxRunMetrics() const { return fMaxRunMetrics; } 96 97 bool isFirstLine(); 98 bool isLastLine(); 99 void getRectsForRange(TextRange textRange, RectHeightStyle rectHeightStyle, RectWidthStyle rectWidthStyle, std::vector<TextBox>& boxes); 100 void getRectsForPlaceholders(std::vector<TextBox>& boxes); 101 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx); 102 103 ClipContext measureTextInsideOneRun(TextRange textRange, 104 const Run* run, 105 SkScalar runOffsetInLine, 106 SkScalar textOffsetInRunInLine, 107 bool includeGhostSpaces, 108 bool limitToClusters) const; 109 110 LineMetrics getMetrics() const; 111 112 SkRect extendHeight(const ClipContext& context) const; 113 114 SkScalar metricsWithoutMultiplier(TextHeightBehavior correction); shiftVertically(SkScalar shift)115 void shiftVertically(SkScalar shift) { fOffset.fY += shift; } 116 117 bool endsWithHardLineBreak() const; 118 119 private: 120 121 std::unique_ptr<Run> shapeEllipsis(const SkString& ellipsis, Run* run); 122 void justify(SkScalar maxWidth); 123 124 SkRect paintText(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const; 125 void paintBackground(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const; 126 SkRect paintShadow(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const; 127 void paintDecorations(SkCanvas* canvas, SkScalar x, SkScalar y, TextRange textRange, const TextStyle& style, const ClipContext& context) const; 128 129 void shiftCluster(const Cluster* cluster, SkScalar shift, SkScalar prevShift); 130 131 ParagraphImpl* fOwner; 132 BlockRange fBlockRange; 133 TextRange fTextRange; 134 TextRange fTextWithWhitespacesRange; 135 ClusterRange fClusterRange; 136 ClusterRange fGhostClusterRange; 137 // Avoid the malloc/free in the common case of one run per line 138 SkSTArray<1, size_t, true> fRunsInVisualOrder; 139 SkVector fAdvance; // Text size 140 SkVector fOffset; // Text position 141 SkScalar fShift; // Let right 142 SkScalar fWidthWithSpaces; 143 std::unique_ptr<Run> fEllipsis; // In case the line ends with the ellipsis 144 InternalLineMetrics fSizes; // Line metrics as a max of all run metrics and struts 145 InternalLineMetrics fMaxRunMetrics; // No struts - need it for GetRectForRange(max height) 146 bool fHasBackground; 147 bool fHasShadows; 148 bool fHasDecorations; 149 150 LineMetricStyle fAscentStyle; 151 LineMetricStyle fDescentStyle; 152 }; 153 } // namespace textlayout 154 } // namespace skia 155 156 #endif // TextLine_DEFINED 157