1 // Copyright 2021 Google LLC. 2 #ifndef Interface_DEFINED 3 #define Interface_DEFINED 4 #include <string> 5 #include "experimental/sktext/include/Types.h" 6 #include "experimental/sktext/src/Line.h" 7 #include "include/core/SkCanvas.h" 8 #include "include/core/SkFontMgr.h" 9 #include "include/core/SkFontStyle.h" 10 #include "include/core/SkPaint.h" 11 #include "include/core/SkSize.h" 12 #include "include/core/SkString.h" 13 #include "include/core/SkTextBlob.h" 14 #include "modules/skshaper/include/SkShaper.h" 15 #include "modules/skunicode/include/SkUnicode.h" 16 17 using namespace skia::text; 18 namespace skia { 19 namespace API { 20 /** 21 * This class contains all the SKUnicode/ICU information. 22 */ 23 class UnicodeText { 24 public: 25 /** Makes calls to SkShaper and collects all the shaped data. 26 @param blocks a range of FontBlock elements that keep information about 27 fonts required to shape the text. 28 It's utf16 range but internally it will have to be converted 29 to utf8 (since all shaping operations use utf8 encoding) 30 @param textDirection a starting text direction value 31 @return an object that contains the result of shaping operations 32 */ 33 std::unique_ptr<ShapedText> shape(SkSpan<FontBlock> blocks, TextDirection textDirection); 34 35 UnicodeText(std::unique_ptr<SkUnicode> unicode, SkSpan<uint16_t> utf16); 36 UnicodeText(std::unique_ptr<SkUnicode> unicode, const SkString& utf8); 37 38 bool hasProperty(TextIndex index, CodeUnitFlags flag) const 39 bool isHardLineBreak(TextIndex index) const ; 40 bool isSoftLineBreak(TextIndex index) const; 41 bool isWhitespaces(TextRange range) const; 42 43 SkUnicode* getUnicode() const; 44 SkSpan<const char16_t> getText16() const; 45 }; 46 47 class WrappedText; 48 /** 49 * This class provides all the information from SkShaper/harfbuzz in a raw format. 50 * It does require a single existing font for each codepoint. 51 */ 52 // Question: do we provide a visitor for ShapedText? 53 class ShapedText { 54 public: 55 /** Break text by lines with a given width (and possible new lines). 56 @param unicodeText a reference to UnicodeText that is used to query Unicode information 57 @param width a line width at which the text gets wrapped 58 @param height a text height, currently not supported 59 @return an object that contains the result of shaping operations (wrapping and formatting). 60 */ 61 std::unique_ptr<WrappedText> wrap(UnicodeText* unicodeText, float width, float height); 62 SkSpan<const LogicalRun> getLogicalRuns() const; 63 }; 64 65 /** 66 * This is a helper visitor class that allows a user to process the wrapped text 67 * structures: lines and runs (to draw them, for instance) 68 */ 69 class Visitor { 70 public: 71 virtual ~Visitor() = default; onBeginLine(size_t index,TextRange lineText,bool hardBreak,SkRect bounds)72 virtual void onBeginLine(size_t index, TextRange lineText, bool hardBreak, SkRect bounds) { } onEndLine(size_t index,TextRange lineText,GlyphRange trailingSpaces,size_t glyphCount)73 virtual void onEndLine(size_t index, TextRange lineText, GlyphRange trailingSpaces, size_t glyphCount) { } onGlyphRun(const SkFont & font,TextRange textRange,SkRect bounds,int trailingSpaces,int glyphCount,const uint16_t glyphs[],const SkPoint positions[],const TextIndex clusters[])74 virtual void onGlyphRun(const SkFont& font, 75 TextRange textRange, // Currently we make sure that the run edges are the grapheme cluster edges 76 SkRect bounds, // bounds contains the physical boundaries of the run 77 int trailingSpaces, // Depending of TextDirection it goes right to the end (LTR) or left to the start (RTL) 78 int glyphCount, // Just the number of glyphs 79 const uint16_t glyphs[], 80 const SkPoint positions[], // Positions relative to the line 81 const TextIndex clusters[]) // Text indices inside the entire text 82 { } onPlaceholder(TextRange,const SkRect & bounds)83 virtual void onPlaceholder(TextRange, const SkRect& bounds) { } 84 }; 85 86 class DrawableText; 87 class SelectableText; 88 /** 89 * This class provides all the information about wrapped/formatted text. 90 */ 91 class WrappedText { 92 public: 93 /** Builds a list of SkTextBlobs to draw on a canvas. 94 @param positionType specifies a text adjustment granularity (grapheme cluster, grapheme, glypheme, glyph) 95 @param blocks a range of text indices that cause an additional run breaking to be used for styling 96 @return an object that contains a list of SkTextBlobs to draw on a canvas 97 */ 98 std::unique_ptr<DrawableText> prepareToDraw(UnicodeText* unicodeText, PositionType positionType, SkSpan<TextIndex> blocks) const; 99 /** Aggregates all the data to navigate the text (move up, down, left, right), 100 select some text near the cursor point, adjust all text position to word, 101 grapheme cluster and such. 102 @return an object that contains all the data for navigation 103 */ 104 std::unique_ptr<SelectableText> prepareToEdit(UnicodeText* unicodeText) const; 105 /** Formats a text line by line. 106 @param textAlign specifies a text placement on the line: 107 left, right, center and justified (last one currently not supported) 108 @param textDirection specifies a text direction that also used in formatting 109 */ 110 void format(TextAlign textAlign, TextDirection textDirection); 111 /** Breaks the text runs into smaller runs by given list of chunks to be used for styling. 112 @param unicodeText a reference to UnicodeText object 113 @param chunks a range of text indices that cause an additional run breaking to be used for styling 114 */ 115 void decorate(UnicodeText* unicodeText, SkSpan<TextIndex> chunks); 116 117 /** Walks though the data structures and makes certain callbacks on visitor so the visitor can collect all the information. 118 @param visitor a reference to Visitor object 119 */ 120 void visit(Visitor* visitor) const; 121 /** Walks though the data structures and makes certain callbacks on visitor so the visitor can collect all the information. 122 @param unicodeText a reference to UnicodeText object 123 @param visitor a reference to Visitor object 124 @param positionType specifies a text adjustment granularity (grapheme cluster, grapheme, glypheme, glyph) 125 to map text blocks to glyph ranges. 126 @param blocks a range of text indices that cause an additional run breaking to be used for styling 127 */ 128 void visit(UnicodeText* unicodeText, Visitor* visitor, PositionType positionType, SkSpan<TextIndex> blocks) const; 129 }; 130 131 /** This class contains all the data that allows easily paint the text on canvas. 132 Strictly speaking, it is not an important part of SkText API but 133 it presents a good example of SkText usages and simplifies testing. 134 */ 135 class DrawableText : public Visitor { 136 public: 137 std::vector<sk_sp<SkTextBlob>>& getTextBlobs(); 138 }; 139 140 struct Position { 141 Position(PositionType positionType, size_t lineIndex, GlyphRange glyphRange, TextRange textRange, SkRect rect); 142 Position(PositionType positionType); 143 PositionType fPositionType; 144 size_t fLineIndex; 145 GlyphRange fGlyphRange; 146 TextRange fTextRange; 147 SkRect fBoundaries; 148 }; 149 struct BoxLine { 150 BoxLine(size_t index, TextRange text, bool hardBreak, SkRect bounds); 151 SkTArray<SkRect, true> fBoxGlyphs; 152 SkTArray<TextIndex, true> fTextByGlyph; // by glyph cluster 153 GlyphIndex fTextEnd; 154 GlyphIndex fTrailingSpacesEnd; 155 TextRange fTextRange; 156 size_t fIndex; 157 bool fIsHardBreak; 158 SkRect fBounds; 159 }; 160 161 /** This class contains all the data that allows all navigation operations on the text: 162 move up/down/left/right, select some units of text and such. 163 */ 164 class SelectableText : public Visitor { 165 public: 166 SelectableText() = default; 167 168 /** Find the drawable unit (specified by positionType) closest to the screen point 169 @param positionType specifies a text adjustment granularity (grapheme cluster, grapheme, glypheme, glyph) 170 @param point a physical coordinates on a screen to find the closest glyph 171 @return a position object that contains all required information 172 */ 173 Position adjustedPosition(PositionType positionType, SkPoint point) const; 174 175 Position previousPosition(Position current) const; 176 Position nextPosition(Position current) const; 177 Position firstPosition(PositionType positionType) const; 178 Position lastPosition(PositionType positionType) const; 179 Position firstInLinePosition(PositionType positionType, LineIndex lineIndex) const; 180 Position lastInLinePosition(PositionType positionType, LineIndex lineIndex) const; 181 182 bool isFirstOnTheLine(Position element) const; 183 bool isLastOnTheLine(Position element) const; 184 185 size_t countLines() const; 186 BoxLine getLine(size_t lineIndex) const; 187 }; 188 } // namespace text 189 } // namespace skia 190 191 #endif // Processor_DEFINED 192