• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 Google LLC.
2 #ifndef Texts_DEFINED
3 #define Texts_DEFINED
4 #include <sstream>
5 #include "experimental/sktext/editor/Cursor.h"
6 #include "experimental/sktext/editor/Defaults.h"
7 #include "experimental/sktext/editor/Mouse.h"
8 #include "experimental/sktext/editor/Selection.h"
9 #include "experimental/sktext/include/Text.h"
10 #include "experimental/sktext/include/Types.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkSurface.h"
13 #include "include/core/SkTime.h"
14 #include "tools/sk_app/Application.h"
15 #include "tools/sk_app/Window.h"
16 #include "tools/skui/ModifierKey.h"
17 
18 namespace skia {
19 namespace editor {
20 
21 using namespace skia::text;
22 // Shapes text once and then paints it at request (not keeping intermediate data)
23 // TODO: Keep only text blobs
24 class StaticText {
25 public:
26 
StaticText(std::u16string text,SkPoint offset,SkSize size,SkSpan<FontBlock> fontBlocks,TextDirection textDirection,TextAlign textAlign)27     StaticText(std::u16string text, SkPoint offset, SkSize size, SkSpan<FontBlock> fontBlocks, TextDirection textDirection, TextAlign textAlign) {
28         fOffset = offset;
29         fSize = size;
30         fFontBlocks = fontBlocks;
31         fText = std::move(text);
32 
33         auto unicode = SkUnicode::Make();
34         fUnicodeText = std::make_unique<UnicodeText>(std::move(unicode), SkSpan<uint16_t>((uint16_t*)fText.data(), fText.size()));
35         fFontResolvedText = fUnicodeText->resolveFonts(fontBlocks);
36         fShapedText = fFontResolvedText->shape(fUnicodeText.get(), DEFAULT_TEXT_DIRECTION);
37         fWrappedText = fShapedText->wrap(fUnicodeText.get(), size.width(), size.height());
38         fWrappedText->format(DEFAULT_TEXT_ALIGN, DEFAULT_TEXT_DIRECTION);
39     }
40 
41     virtual ~StaticText() = default;
42 
43     virtual void paint(SkCanvas* canvas, SkSpan<DecoratedBlock> decors);
44 
45     std::u16string fText;
46     std::unique_ptr<UnicodeText> fUnicodeText;
47     std::unique_ptr<FontResolvedText> fFontResolvedText;
48     std::unique_ptr<ShapedText> fShapedText;
49     std::unique_ptr<WrappedText> fWrappedText;
50     SkSize fSize;
51     SkPoint fOffset;
52     SkSpan<FontBlock> fFontBlocks;
53 };
54 
55 // The text can change but it's not selectable/editable
56 class DynamicText {
57 public:
DynamicText(std::u16string text,SkPoint offset,SkSize size,SkSpan<FontBlock> fontBlocks,SkSpan<DecoratedBlock> decorations,TextDirection textDirection,TextAlign textAlign)58     DynamicText(std::u16string text,
59                 SkPoint offset, SkSize size,
60                 SkSpan<FontBlock> fontBlocks,
61                 SkSpan<DecoratedBlock> decorations,
62                 TextDirection textDirection, TextAlign textAlign) {
63         fOffset = offset;
64         fRequiredSize = size;
65         fFontBlocks = fontBlocks;
66         fDecorations = decorations;
67         fTextAlign = textAlign;
68         fTextDirection = textDirection;
69         fText = std::move(text);
70 
71         auto unicode = SkUnicode::Make();
72         fUnicodeText = std::make_unique<UnicodeText>(std::move(unicode), SkSpan<uint16_t>((uint16_t*)fText.data(), fText.size()));
73         fFontResolvedText = fUnicodeText->resolveFonts(fontBlocks);
74         fShapedText = fFontResolvedText->shape(fUnicodeText.get(), fTextDirection);
75         fWrappedText = fShapedText->wrap(fUnicodeText.get(), size.width(), size.height());
76         fWrappedText->format(fTextAlign, fTextDirection);
77     }
78 
79     virtual ~DynamicText() = default;
80 
contains(SkScalar x,SkScalar y)81     bool contains(SkScalar x, SkScalar y) {
82         return SkRect::MakeXYWH(fOffset.fX, fOffset.fY, fRequiredSize.fWidth, fRequiredSize.fHeight).contains(x, y);
83     }
84 
invalidate()85     void invalidate() { fDrawableText = nullptr; }
isValid()86     bool isValid() { return fDrawableText != nullptr; }
87 
88     std::vector<TextIndex> getDecorationChunks(SkSpan<DecoratedBlock> decorations) const;
89 
rebuild(std::u16string text)90     bool rebuild(std::u16string text) {
91         if (!this->fFontBlocks.empty()) {
92             SkASSERT(this->fFontBlocks.size() == 1);
93             this->fFontBlocks[0].charCount = text.size();
94         }
95         this->fText = std::move(text);
96 
97         auto unicode = SkUnicode::Make();
98         fUnicodeText = std::make_unique<UnicodeText>(std::move(unicode), SkSpan<uint16_t>((uint16_t*)fText.data(), fText.size()));
99         fFontResolvedText = fUnicodeText->resolveFonts(fFontBlocks);
100         fShapedText = fFontResolvedText->shape(fUnicodeText.get(), fTextDirection);
101         fWrappedText = fShapedText->wrap(fUnicodeText.get(), this->fRequiredSize.fWidth, this->fRequiredSize.fHeight);
102         fWrappedText->format(fTextAlign, fTextDirection);
103         fSelectableText = fWrappedText->prepareToEdit(fUnicodeText.get());
104         fDrawableText = nullptr;
105         fActualSize = fWrappedText->actualSize();
106 
107         return true;
108     }
109 
lineCount()110     size_t lineCount() const { return fSelectableText->countLines(); }
getLine(size_t lineIndex)111     BoxLine getLine(size_t lineIndex) {
112         SkASSERT(lineIndex < fSelectableText->countLines());
113         return fSelectableText->getLine(lineIndex);
114     }
115 
actualSize()116     SkRect actualSize() const {
117         return SkRect::MakeXYWH(fOffset.fX, fOffset.fY, fActualSize.fWidth, fActualSize.fHeight);
118     }
119 
120     virtual void paint(SkCanvas* canvas);
121 
122 protected:
123     std::u16string fText;
124     std::unique_ptr<UnicodeText> fUnicodeText;
125     std::unique_ptr<FontResolvedText> fFontResolvedText;
126     std::unique_ptr<ShapedText> fShapedText;
127     std::unique_ptr<WrappedText> fWrappedText;
128     std::unique_ptr<DrawableText> fDrawableText;
129     std::unique_ptr<SelectableText> fSelectableText;
130     SkSize fRequiredSize;
131     SkSize fActualSize;
132     SkPoint fOffset;
133     SkSpan<FontBlock> fFontBlocks;
134     SkSpan<DecoratedBlock> fDecorations;
135     TextAlign fTextAlign;
136     TextDirection fTextDirection;
137 };
138 
139 // Text can change;  supports select/copy/paste
140 class EditableText : public DynamicText {
141 public:
EditableText(std::u16string text,SkPoint offset,SkSize size,SkSpan<FontBlock> fontBlocks,SkSpan<DecoratedBlock> decorations,TextDirection textDirection,TextAlign textAlign)142     EditableText(std::u16string text, SkPoint offset, SkSize size, SkSpan<FontBlock> fontBlocks, SkSpan<DecoratedBlock> decorations, TextDirection textDirection, TextAlign textAlign)
143         : DynamicText(text, offset, size, fontBlocks, decorations, textDirection, textAlign)
144         , fSelection(std::make_unique<Selection>(DEFAULT_SELECTION_COLOR)) {
145     }
146 
isEmpty()147     bool isEmpty() { return fText.empty(); }
148 
adjustedPosition(PositionType positionType,SkPoint point)149     Position adjustedPosition(PositionType positionType, SkPoint point) const {
150         return fSelectableText->adjustedPosition(positionType, point - fOffset);
151     }
152 
153     //Position adjustedPosition(PositionType positionType, TextIndex textIndex) const {
154     //    return fSelectableText->adjustedPosition(positionType, textIndex);
155     //}
156 
previousElement(Position element)157     Position previousElement(Position element) const { return fSelectableText->previousPosition(element); }
nextElement(Position current)158     Position nextElement(Position current) const { return fSelectableText->nextPosition(current); }
firstElement(PositionType positionType)159     Position firstElement(PositionType positionType) const { return fSelectableText->firstPosition(positionType); }
lastElement(PositionType positionType)160     Position lastElement(PositionType positionType) const { return fSelectableText->lastPosition(positionType); }
161 
isFirstOnTheLine(Position element)162     bool isFirstOnTheLine(Position element) const { return fSelectableText->isFirstOnTheLine(element); }
isLastOnTheLine(Position element)163     bool isLastOnTheLine(Position element) const { return fSelectableText->isLastOnTheLine(element); }
164 
removeElement(TextRange toRemove)165     void removeElement(TextRange toRemove) {
166         std::u16string text;
167         text.append(this->fText.substr(0, toRemove.fStart));
168         text.append(this->fText.substr(toRemove.fEnd, std::u16string::npos));
169         update(text);
170     }
171 
insertElement(SkUnichar unichar,TextIndex toInsert)172     void insertElement(SkUnichar unichar, TextIndex toInsert) {
173         std::u16string text;
174         text.append(fText.substr(0, toInsert));
175         text.append(1, (unsigned)unichar);
176         text.append(fText.substr(toInsert, std::u16string::npos));
177         update(text);
178     }
179 
replaceElement(SkUnichar unichar,TextRange toReplace)180     void replaceElement(SkUnichar unichar, TextRange toReplace) {
181         std::u16string text;
182         text.append(fText.substr(0, toReplace.fStart));
183         text.append(1, (unsigned)unichar);
184         text.append(fText.substr(toReplace.fEnd, std::u16string::npos));
185     }
186 
update(std::u16string & text)187     void update(std::u16string& text) {
188         fText = text;
189         // TODO: Update text styles
190         SkASSERT(fFontBlocks.size() == 1);
191         fFontBlocks[0].charCount = fText.size();
192         SkASSERT(fDecorations.size() == 1);
193         fDecorations[0].charCount = fText.size();
194         // TODO: update all objects rather than recreate them
195         rebuild(text);
196 
197         // TODO: Update the text selection
198         fSelection->clear();
199     }
200 
select(TextRange text,SkRect boundaries)201     void select(TextRange text, SkRect boundaries) { fSelection->select(text, boundaries); }
clearSelection()202     void clearSelection() { fSelection->clear(); }
203 
204     void paint(SkCanvas* canvas) override;
205 
206     SkTArray<DecoratedBlock> mergeSelectionIntoDecorations();
207 
208 protected:
209     std::unique_ptr<Selection> fSelection;
210 };
211 
212 } // namespace editor
213 } // namespace skia
214 #endif // Texts_DEFINED
215