Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | List of all members
SkPlainTextEditor::Editor Class Reference

#include <editor.h>

Classes

struct  PaintOpts
 
struct  Text
 
struct  TextPosition
 

Public Types

enum class  Movement {
  kNowhere , kLeft , kUp , kRight ,
  kDown , kHome , kEnd , kWordLeft ,
  kWordRight
}
 

Public Member Functions

int getHeight () const
 
void setWidth (int w)
 
const SkFontfont () const
 
void setFont (SkFont font)
 
void setFontMgr (sk_sp< SkFontMgr > fontMgr)
 
Text text () const
 
int lineHeight (size_t index) const
 
TextPosition move (Editor::Movement move, Editor::TextPosition pos) const
 
TextPosition getPosition (SkIPoint)
 
SkRect getLocation (TextPosition)
 
TextPosition insert (TextPosition, const char *utf8Text, size_t byteLen)
 
TextPosition remove (TextPosition, TextPosition)
 
size_t copy (TextPosition pos1, TextPosition pos2, char *dst=nullptr) const
 
size_t lineCount () const
 
StringView line (size_t i) const
 
void paint (SkCanvas *canvas, PaintOpts)
 

Detailed Description

Definition at line 26 of file editor.h.

Member Enumeration Documentation

◆ Movement

Member Function Documentation

◆ copy()

size_t Editor::copy ( TextPosition  pos1,
TextPosition  pos2,
char *  dst = nullptr 
) const

Definition at line 219 of file editor.cpp.

219 {
220 size_t size = 0;
221 pos1 = this->move(Editor::Movement::kNowhere, pos1);
222 pos2 = this->move(Editor::Movement::kNowhere, pos2);
223 auto cmp = [](const Editor::TextPosition& u, const Editor::TextPosition& v) { return u < v; };
224 Editor::TextPosition start = std::min(pos1, pos2, cmp);
225 Editor::TextPosition end = std::max(pos1, pos2, cmp);
226 if (start == end || start.fParagraphIndex == fLines.size()) {
227 return size;
228 }
229 if (start.fParagraphIndex == end.fParagraphIndex) {
230 SkASSERT(end.fTextByteIndex > start.fTextByteIndex);
231 auto& str = fLines[start.fParagraphIndex].fText;
232 append(&dst, &size, str.begin() + start.fTextByteIndex,
233 end.fTextByteIndex - start.fTextByteIndex);
234 return size;
235 }
236 SkASSERT(end.fParagraphIndex < fLines.size());
237 const std::vector<TextLine>::const_iterator firstP = fLines.begin() + start.fParagraphIndex;
238 const std::vector<TextLine>::const_iterator lastP = fLines.begin() + end.fParagraphIndex;
239 const auto& first = firstP->fText;
240 const auto& last = lastP->fText;
241
242 append(&dst, &size, first.begin() + start.fTextByteIndex, first.size() - start.fTextByteIndex);
243 for (auto line = firstP + 1; line < lastP; ++line) {
244 append(&dst, &size, "\n", 1);
245 append(&dst, &size, line->fText.begin(), line->fText.size());
246 }
247 append(&dst, &size, "\n", 1);
248 append(&dst, &size, last.begin(), end.fTextByteIndex);
249 return size;
250}
#define SkASSERT(cond)
Definition SkAssert.h:116
StringView line(size_t i) const
Definition editor.h:89
TextPosition move(Editor::Movement move, Editor::TextPosition pos) const
Definition editor.cpp:287
static void append(char **dst, size_t *count, const char *src, size_t n)
Definition editor.cpp:211
glong glong end
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259

◆ font()

const SkFont & SkPlainTextEditor::Editor::font ( ) const
inline

Definition at line 36 of file editor.h.

36{ return fFont; }

◆ getHeight()

int SkPlainTextEditor::Editor::getHeight ( ) const
inline

Definition at line 30 of file editor.h.

30{ return fHeight; }

◆ getLocation()

SkRect Editor::getLocation ( Editor::TextPosition  cursor)

Definition at line 131 of file editor.cpp.

131 {
132 this->reshapeAll();
133 cursor = this->move(Editor::Movement::kNowhere, cursor);
134 if (fLines.size() > 0) {
135 const TextLine& cLine = fLines[cursor.fParagraphIndex];
136 SkRect pos = {0, 0, 0, 0};
137 if (cursor.fTextByteIndex < cLine.fCursorPos.size()) {
138 pos = cLine.fCursorPos[cursor.fTextByteIndex];
139 }
140 pos.fRight = pos.fLeft + 1;
141 pos.fLeft -= 1;
142 return offset(pos, cLine.fOrigin);
143 }
144 return SkRect{0, 0, 0, 0};
145}
SkPoint pos
Point offset

◆ getPosition()

Editor::TextPosition Editor::getPosition ( SkIPoint  xy)

Definition at line 77 of file editor.cpp.

77 {
78 Editor::TextPosition approximatePosition;
79 this->reshapeAll();
80 for (size_t j = 0; j < fLines.size(); ++j) {
81 const TextLine& line = fLines[j];
82 SkIRect lineRect = {0,
83 line.fOrigin.y(),
84 fWidth,
85 j + 1 < fLines.size() ? fLines[j + 1].fOrigin.y() : INT_MAX};
86 if (const SkTextBlob* b = line.fBlob.get()) {
87 SkIRect r = b->bounds().roundOut();
88 r.offset(line.fOrigin);
89 lineRect.join(r);
90 }
91 if (!lineRect.contains(xy.x(), xy.y())) {
92 continue;
93 }
94 SkPoint pt = to_point(xy - line.fOrigin);
95 const std::vector<SkRect>& pos = line.fCursorPos;
96 for (size_t i = 0; i < pos.size(); ++i) {
97 if (pos[i] != kUnsetRect && pos[i].contains(pt.x(), pt.y())) {
98 return Editor::TextPosition{i, j};
99 }
100 }
101 approximatePosition = {xy.x() <= line.fOrigin.x() ? 0 : line.fText.size(), j};
102 }
103 return approximatePosition;
104}
static bool contains(const SkRect &r, SkPoint p)
static SkPoint to_point(SkIPoint p)
Definition editor.cpp:75
static constexpr SkRect kUnsetRect
Definition editor.cpp:22
static bool b
constexpr int32_t y() const
constexpr int32_t x() const
void join(const SkIRect &r)
Definition SkRect.cpp:31
void offset(int32_t dx, int32_t dy)
Definition SkRect.h:367
bool contains(int32_t x, int32_t y) const
Definition SkRect.h:463
constexpr float y() const
constexpr float x() const

◆ insert()

Editor::TextPosition Editor::insert ( TextPosition  pos,
const char *  utf8Text,
size_t  byteLen 
)

Definition at line 153 of file editor.cpp.

153 {
154 if (!valid_utf8(utf8Text, byteLen) || 0 == byteLen) {
155 return pos;
156 }
158 fNeedsReshape = true;
159 if (pos.fParagraphIndex < fLines.size()) {
160 fLines[pos.fParagraphIndex].fText.insert(pos.fTextByteIndex, utf8Text, byteLen);
161 this->markDirty(&fLines[pos.fParagraphIndex]);
162 } else {
163 SkASSERT(pos.fParagraphIndex == fLines.size());
164 SkASSERT(pos.fTextByteIndex == 0);
165 fLines.push_back(Editor::TextLine(StringSlice(utf8Text, byteLen)));
166 }
167 pos = Editor::TextPosition{pos.fTextByteIndex + byteLen, pos.fParagraphIndex};
168 size_t newlinecount = count_char(fLines[pos.fParagraphIndex].fText, '\n');
169 if (newlinecount > 0) {
170 StringSlice src = std::move(fLines[pos.fParagraphIndex].fText);
171 std::vector<TextLine>::const_iterator next = fLines.begin() + pos.fParagraphIndex + 1;
172 fLines.insert(next, newlinecount, TextLine());
173 TextLine* line = &fLines[pos.fParagraphIndex];
174 readlines(src.begin(), src.size(), [&line](const char* str, size_t l) {
175 (line++)->fText = remove_newline(str, l);
176 });
177 }
178 return pos;
179}
static float next(float f)
static void readlines(const void *data, size_t size, F f)
Definition editor.cpp:30
static bool valid_utf8(const char *ptr, size_t size)
Definition editor.cpp:24
static size_t count_char(const StringSlice &string, char value)
Definition editor.cpp:147

◆ line()

StringView SkPlainTextEditor::Editor::line ( size_t  i) const
inline

Definition at line 89 of file editor.h.

89 {
90 return i < fLines.size() ? fLines[i].fText.view() : StringView{nullptr, 0};
91 }
Span< const char > StringView
Definition stringview.h:16

◆ lineCount()

size_t SkPlainTextEditor::Editor::lineCount ( ) const
inline

Definition at line 88 of file editor.h.

88{ return fLines.size(); }

◆ lineHeight()

int SkPlainTextEditor::Editor::lineHeight ( size_t  index) const
inline

Definition at line 60 of file editor.h.

60{ return fLines[index].fHeight; }

◆ move()

Editor::TextPosition Editor::move ( Editor::Movement  move,
Editor::TextPosition  pos 
) const

Definition at line 287 of file editor.cpp.

287 {
288 if (fLines.empty()) {
289 return {0, 0};
290 }
291 // First thing: fix possible bad input values.
292 if (pos.fParagraphIndex >= fLines.size()) {
293 pos.fParagraphIndex = fLines.size() - 1;
294 pos.fTextByteIndex = fLines[pos.fParagraphIndex].fText.size();
295 } else {
296 pos.fTextByteIndex = align_column(fLines[pos.fParagraphIndex].fText, pos.fTextByteIndex);
297 }
298
299 SkASSERT(pos.fParagraphIndex < fLines.size());
300 SkASSERT(pos.fTextByteIndex <= fLines[pos.fParagraphIndex].fText.size());
301
302 SkASSERT(pos.fTextByteIndex == fLines[pos.fParagraphIndex].fText.size() ||
303 !is_utf8_continuation(fLines[pos.fParagraphIndex].fText.begin()[pos.fTextByteIndex]));
304
305 switch (move) {
307 break;
309 if (0 == pos.fTextByteIndex) {
310 if (pos.fParagraphIndex > 0) {
311 --pos.fParagraphIndex;
312 pos.fTextByteIndex = fLines[pos.fParagraphIndex].fText.size();
313 }
314 } else {
315 const auto& str = fLines[pos.fParagraphIndex].fText;
316 pos.fTextByteIndex =
317 prev_utf8(begin(str) + pos.fTextByteIndex, begin(str)) - begin(str);
318 }
319 break;
321 if (fLines[pos.fParagraphIndex].fText.size() == pos.fTextByteIndex) {
322 if (pos.fParagraphIndex + 1 < fLines.size()) {
323 ++pos.fParagraphIndex;
324 pos.fTextByteIndex = 0;
325 }
326 } else {
327 const auto& str = fLines[pos.fParagraphIndex].fText;
328 pos.fTextByteIndex =
329 next_utf8(begin(str) + pos.fTextByteIndex, end(str)) - begin(str);
330 }
331 break;
333 {
334 const std::vector<size_t>& list = fLines[pos.fParagraphIndex].fLineEndOffsets;
335 size_t f = find_first_larger(list, pos.fTextByteIndex);
336 pos.fTextByteIndex = f > 0 ? list[f - 1] : 0;
337 }
338 break;
340 {
341 const std::vector<size_t>& list = fLines[pos.fParagraphIndex].fLineEndOffsets;
342 size_t f = find_first_larger(list, pos.fTextByteIndex);
343 if (f < list.size()) {
344 pos.fTextByteIndex = list[f] > 0 ? list[f] - 1 : 0;
345 } else {
346 pos.fTextByteIndex = fLines[pos.fParagraphIndex].fText.size();
347 }
348 }
349 break;
351 {
352 SkASSERT(pos.fTextByteIndex < fLines[pos.fParagraphIndex].fCursorPos.size());
353 float x = fLines[pos.fParagraphIndex].fCursorPos[pos.fTextByteIndex].left();
354 const std::vector<size_t>& list = fLines[pos.fParagraphIndex].fLineEndOffsets;
355 size_t f = find_first_larger(list, pos.fTextByteIndex);
356 // list[f] > value. value > list[f-1]
357 if (f > 0) {
358 // not the first line in paragraph.
359 pos.fTextByteIndex = find_closest_x(fLines[pos.fParagraphIndex].fCursorPos, x,
360 (f == 1) ? 0 : list[f - 2],
361 list[f - 1]);
362 } else if (pos.fParagraphIndex > 0) {
363 --pos.fParagraphIndex;
364 const auto& newLine = fLines[pos.fParagraphIndex];
365 size_t r = newLine.fLineEndOffsets.size();
366 if (r > 0) {
367 pos.fTextByteIndex = find_closest_x(newLine.fCursorPos, x,
368 newLine.fLineEndOffsets[r - 1],
369 newLine.fCursorPos.size());
370 } else {
371 pos.fTextByteIndex = find_closest_x(newLine.fCursorPos, x, 0,
372 newLine.fCursorPos.size());
373 }
374 }
375 pos.fTextByteIndex =
376 align_column(fLines[pos.fParagraphIndex].fText, pos.fTextByteIndex);
377 }
378 break;
380 {
381 const std::vector<size_t>& list = fLines[pos.fParagraphIndex].fLineEndOffsets;
382 float x = fLines[pos.fParagraphIndex].fCursorPos[pos.fTextByteIndex].left();
383
384 size_t f = find_first_larger(list, pos.fTextByteIndex);
385 if (f < list.size()) {
386 const auto& bounds = fLines[pos.fParagraphIndex].fCursorPos;
387 pos.fTextByteIndex = find_closest_x(bounds, x, list[f],
388 f + 1 < list.size() ? list[f + 1]
389 : bounds.size());
390 } else if (pos.fParagraphIndex + 1 < fLines.size()) {
391 ++pos.fParagraphIndex;
392 const auto& bounds = fLines[pos.fParagraphIndex].fCursorPos;
393 const std::vector<size_t>& l2 = fLines[pos.fParagraphIndex].fLineEndOffsets;
394 pos.fTextByteIndex = find_closest_x(bounds, x, 0,
395 l2.size() > 0 ? l2[0] : bounds.size());
396 } else {
397 pos.fTextByteIndex = fLines[pos.fParagraphIndex].fText.size();
398 }
399 pos.fTextByteIndex =
400 align_column(fLines[pos.fParagraphIndex].fText, pos.fTextByteIndex);
401 }
402 break;
404 {
405 if (pos.fTextByteIndex == 0) {
406 pos = this->move(Editor::Movement::kLeft, pos);
407 break;
408 }
409 const std::vector<bool>& words = fLines[pos.fParagraphIndex].fWordBoundaries;
410 SkASSERT(words.size() == fLines[pos.fParagraphIndex].fText.size());
411 do {
412 --pos.fTextByteIndex;
413 } while (pos.fTextByteIndex > 0 && !words[pos.fTextByteIndex]);
414 }
415 break;
417 {
418 const StringSlice& text = fLines[pos.fParagraphIndex].fText;
419 if (pos.fTextByteIndex == text.size()) {
420 pos = this->move(Editor::Movement::kRight, pos);
421 break;
422 }
423 const std::vector<bool>& words = fLines[pos.fParagraphIndex].fWordBoundaries;
424 SkASSERT(words.size() == text.size());
425 do {
426 ++pos.fTextByteIndex;
427 } while (pos.fTextByteIndex < text.size() && !words[pos.fTextByteIndex]);
428 }
429 break;
430
431 }
432 return pos;
433}
Text text() const
Definition editor.h:57
static size_t find_first_larger(const std::vector< T > &list, T value)
Definition editor.cpp:266
static const char * prev_utf8(const char *p, const char *begin)
Definition editor.cpp:127
static const char * begin(const StringSlice &s)
Definition editor.cpp:252
static size_t align_column(const StringSlice &str, size_t p)
Definition editor.cpp:256
static const char * next_utf8(const char *p, const char *end)
Definition editor.cpp:111
static bool is_utf8_continuation(char v)
Definition editor.cpp:106
static size_t find_closest_x(const std::vector< SkRect > &bounds, float x, size_t b, size_t e)
Definition editor.cpp:270
double x
Optional< SkRect > bounds
Definition SkRecords.h:189

◆ paint()

void Editor::paint ( SkCanvas canvas,
PaintOpts  options 
)

Definition at line 435 of file editor.cpp.

435 {
436 this->reshapeAll();
437 if (!c) {
438 return;
439 }
440
441 c->drawPaint(SkPaint(options.fBackgroundColor));
442
443 SkPaint selection = SkPaint(options.fSelectionColor);
444 auto cmp = [](const Editor::TextPosition& u, const Editor::TextPosition& v) { return u < v; };
445 for (TextPosition pos = std::min(options.fSelectionBegin, options.fSelectionEnd, cmp),
446 end = std::max(options.fSelectionBegin, options.fSelectionEnd, cmp);
447 pos < end;
449 {
450 SkASSERT(pos.fParagraphIndex < fLines.size());
451 const TextLine& l = fLines[pos.fParagraphIndex];
452 c->drawRect(offset(l.fCursorPos[pos.fTextByteIndex], l.fOrigin), selection);
453 }
454
455 if (fLines.size() > 0) {
456 c->drawRect(Editor::getLocation(options.fCursor), SkPaint(options.fCursorColor));
457 }
458
459 SkPaint foreground = SkPaint(options.fForegroundColor);
460 for (const TextLine& line : fLines) {
461 if (line.fBlob) {
462 c->drawTextBlob(line.fBlob.get(), line.fOrigin.x(), line.fOrigin.y(), foreground);
463 }
464 }
465}
const char * options
SkRect getLocation(TextPosition)
Definition editor.cpp:131

◆ remove()

Editor::TextPosition Editor::remove ( TextPosition  pos1,
TextPosition  pos2 
)

Definition at line 181 of file editor.cpp.

181 {
182 pos1 = this->move(Editor::Movement::kNowhere, pos1);
183 pos2 = this->move(Editor::Movement::kNowhere, pos2);
184 auto cmp = [](const Editor::TextPosition& u, const Editor::TextPosition& v) { return u < v; };
185 Editor::TextPosition start = std::min(pos1, pos2, cmp);
186 Editor::TextPosition end = std::max(pos1, pos2, cmp);
187 if (start == end || start.fParagraphIndex == fLines.size()) {
188 return start;
189 }
190 fNeedsReshape = true;
191 if (start.fParagraphIndex == end.fParagraphIndex) {
192 SkASSERT(end.fTextByteIndex > start.fTextByteIndex);
193 fLines[start.fParagraphIndex].fText.remove(
194 start.fTextByteIndex, end.fTextByteIndex - start.fTextByteIndex);
195 this->markDirty(&fLines[start.fParagraphIndex]);
196 } else {
197 SkASSERT(end.fParagraphIndex < fLines.size());
198 auto& line = fLines[start.fParagraphIndex];
199 line.fText.remove(start.fTextByteIndex,
200 line.fText.size() - start.fTextByteIndex);
201 line.fText.insert(start.fTextByteIndex,
202 fLines[end.fParagraphIndex].fText.begin() + end.fTextByteIndex,
203 fLines[end.fParagraphIndex].fText.size() - end.fTextByteIndex);
204 this->markDirty(&line);
205 fLines.erase(fLines.begin() + start.fParagraphIndex + 1,
206 fLines.begin() + end.fParagraphIndex + 1);
207 }
208 return start;
209}

◆ setFont()

void Editor::setFont ( SkFont  font)

Definition at line 54 of file editor.cpp.

54 {
55 if (font != fFont) {
56 fFont = std::move(font);
57 fNeedsReshape = true;
58 for (auto& l : fLines) { this->markDirty(&l); }
59 }
60}
const SkFont & font() const
Definition editor.h:36

◆ setFontMgr()

void Editor::setFontMgr ( sk_sp< SkFontMgr fontMgr)

Definition at line 62 of file editor.cpp.

62 {
63 fFontMgr = fontMgr;
64 fNeedsReshape = true;
65 for (auto& l : fLines) { this->markDirty(&l); }
66}
sk_sp< SkFontMgr > fontMgr
Definition examples.cpp:32

◆ setWidth()

void Editor::setWidth ( int  w)

Definition at line 68 of file editor.cpp.

68 {
69 if (fWidth != w) {
70 fWidth = w;
71 fNeedsReshape = true;
72 for (auto& l : fLines) { this->markDirty(&l); }
73 }
74}
SkScalar w

◆ text()

Text SkPlainTextEditor::Editor::text ( ) const
inline

Definition at line 57 of file editor.h.

57{ return Text{fLines}; }

The documentation for this class was generated from the following files: