xref: /aosp_15_r20/external/skia/modules/skplaintexteditor/include/editor.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 // Copyright 2019 Google LLC.
2 // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3 #ifndef editor_DEFINED
4 #define editor_DEFINED
5 
6 #include "modules/skplaintexteditor/include/stringslice.h"
7 #include "modules/skplaintexteditor/include/stringview.h"
8 
9 #include "include/core/SkColor.h"
10 #include "include/core/SkFont.h"
11 #include "include/core/SkFontMgr.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkString.h"
14 #include "include/core/SkTextBlob.h"
15 
16 #include <climits>
17 #include <cstdint>
18 #include <utility>
19 #include <vector>
20 
21 class SkCanvas;
22 class SkShaper;
23 
24 namespace SkPlainTextEditor {
25 
26 class Editor {
27     struct TextLine;
28 public:
29     // total height in canvas display units.
getHeight()30     int getHeight() const { return fHeight; }
31 
32     // set display width in canvas display units
33     void setWidth(int w); // may force re-shape
34 
35     // get/set current font (used for shaping and displaying text)
font()36     const SkFont& font() const { return fFont; }
37     void setFont(SkFont font);
38 
39     void setFontMgr(sk_sp<SkFontMgr> fontMgr);
40 
41     struct Text {
42         const std::vector<TextLine>& fLines;
43         struct Iterator {
44             std::vector<TextLine>::const_iterator fPtr;
45             StringView operator*() { return fPtr->fText.view(); }
46             void operator++() { ++fPtr; }
47             bool operator!=(const Iterator& other) const { return fPtr != other.fPtr; }
48         };
beginText49         Iterator begin() const { return Iterator{fLines.begin()}; }
endText50         Iterator end() const { return Iterator{fLines.end()}; }
51     };
52     // Loop over all the lines of text.  The lines are not '\0'- or '\n'-terminated.
53     // For example, to dump the entire file to standard output:
54     //     for (SkPlainTextEditor::StringView str : editor.text()) {
55     //         std::cout.write(str.data, str.size) << '\n';
56     //     }
text()57     Text text() const { return Text{fLines}; }
58 
59     // get size of line in canvas display units.
lineHeight(size_t index)60     int lineHeight(size_t index) const { return fLines[index].fHeight; }
61 
62     struct TextPosition {
63         size_t fTextByteIndex = SIZE_MAX;   // index into UTF-8 representation of line.
64         size_t fParagraphIndex = SIZE_MAX;  // logical line, based on hard newline characters.
65     };
66     enum class Movement {
67         kNowhere,
68         kLeft,
69         kUp,
70         kRight,
71         kDown,
72         kHome,
73         kEnd,
74         kWordLeft,
75         kWordRight,
76     };
77     TextPosition move(Editor::Movement move, Editor::TextPosition pos) const;
78     TextPosition getPosition(SkIPoint);
79     SkRect getLocation(TextPosition);
80     // insert into current text.
81     TextPosition insert(TextPosition, const char* utf8Text, size_t byteLen);
82     // remove text between two positions
83     TextPosition remove(TextPosition, TextPosition);
84 
85     // If dst is nullptr, returns size of given selection.
86     // Otherwise, fill dst with a copy of the selection, and return the amount copied.
87     size_t copy(TextPosition pos1, TextPosition pos2, char* dst = nullptr) const;
lineCount()88     size_t lineCount() const { return fLines.size(); }
line(size_t i)89     StringView line(size_t i) const {
90         return i < fLines.size() ? fLines[i].fText.view() : StringView{nullptr, 0};
91     }
92 
93     struct PaintOpts {
94         SkColor4f fBackgroundColor = {1, 1, 1, 1};
95         SkColor4f fForegroundColor = {0, 0, 0, 1};
96         // TODO: maybe have multiple selections and cursors, each with separate colors.
97         SkColor4f fSelectionColor = {0.729f, 0.827f, 0.988f, 1};
98         SkColor4f fCursorColor = {1, 0, 0, 1};
99         TextPosition fSelectionBegin;
100         TextPosition fSelectionEnd;
101         TextPosition fCursor;
102     };
103     void paint(SkCanvas* canvas, PaintOpts);
104 
105 private:
106     // TODO: rename this to TextParagraph. fLines to fParas.
107     struct TextLine {
108         StringSlice fText;
109         sk_sp<const SkTextBlob> fBlob;
110         std::vector<SkRect> fCursorPos;
111         std::vector<size_t> fLineEndOffsets;
112         std::vector<bool> fWordBoundaries;
113         SkIPoint fOrigin = {0, 0};
114         int fHeight = 0;
115         bool fShaped = false;
116 
TextLineTextLine117         TextLine(StringSlice t) : fText(std::move(t)) {}
TextLineTextLine118         TextLine() {}
119     };
120     std::vector<TextLine> fLines;
121     int fWidth = 0;
122     int fHeight = 0;
123     SkFont fFont;
124     sk_sp<SkFontMgr> fFontMgr;
125     bool fNeedsReshape = false;
126     const char* fLocale = "en";  // TODO: make this setable
127 
128     void markDirty(TextLine*);
129     void reshapeAll();
130 };
131 }  // namespace SkPlainTextEditor
132 
133 static inline bool operator==(const SkPlainTextEditor::Editor::TextPosition& u,
134                               const SkPlainTextEditor::Editor::TextPosition& v) {
135     return u.fParagraphIndex == v.fParagraphIndex && u.fTextByteIndex == v.fTextByteIndex;
136 }
137 static inline bool operator!=(const SkPlainTextEditor::Editor::TextPosition& u,
138                               const SkPlainTextEditor::Editor::TextPosition& v) { return !(u == v); }
139 
140 static inline bool operator<(const SkPlainTextEditor::Editor::TextPosition& u,
141                              const SkPlainTextEditor::Editor::TextPosition& v) {
142     return u.fParagraphIndex < v.fParagraphIndex ||
143            (u.fParagraphIndex == v.fParagraphIndex && u.fTextByteIndex < v.fTextByteIndex);
144 }
145 
146 
147 #endif  // editor_DEFINED
148