33 const char* ptr =
start;
35 while (*ptr++ !=
'\n' && ptr <
end) {}
48void Editor::markDirty(TextLine*
line) {
49 line->fBlob =
nullptr;
50 line->fShaped =
false;
51 line->fWordBoundaries = std::vector<bool>();
56 fFont = std::move(
font);
58 for (
auto& l : fLines) { this->markDirty(&l); }
65 for (
auto& l : fLines) { this->markDirty(&l); }
72 for (
auto& l : fLines) { this->markDirty(&l); }
80 for (
size_t j = 0; j < fLines.size(); ++j) {
81 const TextLine&
line = fLines[j];
85 j + 1 < fLines.size() ? fLines[j + 1].fOrigin.y() : INT_MAX};
95 const std::vector<SkRect>&
pos =
line.fCursorPos;
96 for (
size_t i = 0;
i <
pos.size(); ++
i) {
101 approximatePosition = {xy.
x() <=
line.fOrigin.x() ? 0 :
line.fText.
size(), j};
103 return approximatePosition;
107 return ((
unsigned char)v & 0b11000000) ==
111static const char*
next_utf8(
const char*
p,
const char* end) {
134 if (fLines.size() > 0) {
140 pos.fRight =
pos.fLeft + 1;
144 return SkRect{0, 0, 0, 0};
149 for (
char c :
string) {
if (c ==
value) { ++
count; } }
154 if (!
valid_utf8(utf8Text, byteLen) || 0 == byteLen) {
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]);
165 fLines.push_back(Editor::TextLine(
StringSlice(utf8Text, byteLen)));
168 size_t newlinecount =
count_char(fLines[
pos.fParagraphIndex].fText,
'\n');
169 if (newlinecount > 0) {
171 std::vector<TextLine>::const_iterator
next = fLines.begin() +
pos.fParagraphIndex + 1;
172 fLines.insert(
next, newlinecount, TextLine());
173 TextLine*
line = &fLines[
pos.fParagraphIndex];
175 (line++)->fText = remove_newline(str, l);
187 if (
start ==
end ||
start.fParagraphIndex == fLines.size()) {
190 fNeedsReshape =
true;
191 if (
start.fParagraphIndex ==
end.fParagraphIndex) {
193 fLines[
start.fParagraphIndex].fText.remove(
194 start.fTextByteIndex,
end.fTextByteIndex -
start.fTextByteIndex);
195 this->markDirty(&fLines[
start.fParagraphIndex]);
198 auto&
line = fLines[
start.fParagraphIndex];
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);
226 if (
start ==
end ||
start.fParagraphIndex == fLines.size()) {
229 if (
start.fParagraphIndex ==
end.fParagraphIndex) {
231 auto& str = fLines[
start.fParagraphIndex].fText;
233 end.fTextByteIndex -
start.fTextByteIndex);
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;
257 if (
p >= str.
size()) {
267 return (
size_t)(std::upper_bound(list.begin(), list.end(),
value) - list.begin());
275 size_t best_index =
b;
276 float best_diff = ::fabsf(
bounds[best_index].
x() -
x);
277 for (
size_t i =
b + 1;
i <
e; ++
i) {
288 if (fLines.empty()) {
292 if (
pos.fParagraphIndex >= fLines.size()) {
293 pos.fParagraphIndex = fLines.size() - 1;
294 pos.fTextByteIndex = fLines[
pos.fParagraphIndex].fText.size();
300 SkASSERT(
pos.fTextByteIndex <= fLines[
pos.fParagraphIndex].fText.size());
302 SkASSERT(
pos.fTextByteIndex == fLines[
pos.fParagraphIndex].fText.size() ||
309 if (0 ==
pos.fTextByteIndex) {
310 if (
pos.fParagraphIndex > 0) {
311 --
pos.fParagraphIndex;
312 pos.fTextByteIndex = fLines[
pos.fParagraphIndex].fText.size();
315 const auto& str = fLines[
pos.fParagraphIndex].fText;
321 if (fLines[
pos.fParagraphIndex].fText.size() ==
pos.fTextByteIndex) {
322 if (
pos.fParagraphIndex + 1 < fLines.size()) {
323 ++
pos.fParagraphIndex;
324 pos.fTextByteIndex = 0;
327 const auto& str = fLines[
pos.fParagraphIndex].fText;
334 const std::vector<size_t>& list = fLines[
pos.fParagraphIndex].fLineEndOffsets;
336 pos.fTextByteIndex =
f > 0 ? list[
f - 1] : 0;
341 const std::vector<size_t>& list = fLines[
pos.fParagraphIndex].fLineEndOffsets;
343 if (
f < list.size()) {
344 pos.fTextByteIndex = list[
f] > 0 ? list[
f] - 1 : 0;
346 pos.fTextByteIndex = fLines[
pos.fParagraphIndex].fText.size();
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;
360 (
f == 1) ? 0 : list[
f - 2],
362 }
else if (
pos.fParagraphIndex > 0) {
363 --
pos.fParagraphIndex;
364 const auto& newLine = fLines[
pos.fParagraphIndex];
365 size_t r = newLine.fLineEndOffsets.size();
368 newLine.fLineEndOffsets[r - 1],
369 newLine.fCursorPos.size());
372 newLine.fCursorPos.size());
381 const std::vector<size_t>& list = fLines[
pos.fParagraphIndex].fLineEndOffsets;
382 float x = fLines[
pos.fParagraphIndex].fCursorPos[
pos.fTextByteIndex].left();
385 if (
f < list.size()) {
386 const auto&
bounds = fLines[
pos.fParagraphIndex].fCursorPos;
388 f + 1 < list.size() ? list[
f + 1]
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;
395 l2.size() > 0 ? l2[0] :
bounds.size());
397 pos.fTextByteIndex = fLines[
pos.fParagraphIndex].fText.size();
405 if (
pos.fTextByteIndex == 0) {
409 const std::vector<bool>& words = fLines[
pos.fParagraphIndex].fWordBoundaries;
410 SkASSERT(words.size() == fLines[
pos.fParagraphIndex].fText.size());
412 --
pos.fTextByteIndex;
413 }
while (
pos.fTextByteIndex > 0 && !words[
pos.fTextByteIndex]);
419 if (
pos.fTextByteIndex ==
text.size()) {
423 const std::vector<bool>& words = fLines[
pos.fParagraphIndex].fWordBoundaries;
426 ++
pos.fTextByteIndex;
427 }
while (
pos.fTextByteIndex <
text.size() && !words[
pos.fTextByteIndex]);
451 const TextLine& l = fLines[
pos.fParagraphIndex];
455 if (fLines.size() > 0) {
460 for (
const TextLine&
line : fLines) {
467void Editor::reshapeAll() {
469 if (fLines.empty()) {
470 fLines.push_back(TextLine());
472 float shape_width = (
float)(fWidth);
473 #ifdef SK_EDITOR_GO_FAST
477 for (TextLine&
line : fLines) {
479 executor->add([&]() {
481 fFont, fLocale, shape_width);
483 line.fLineEndOffsets = std::move(
result.lineBreakOffsets);
484 line.fCursorPos = std::move(
result.glyphBounds);
485 line.fWordBoundaries = std::move(
result.wordBreaks);
493 while (jobCount-- > 0) { semaphore.
wait(); }
495 for (TextLine&
line : fLines) {
498 fFont, fFontMgr, fLocale, shape_width);
500 line.fLineEndOffsets = std::move(
result.lineBreakOffsets);
501 line.fCursorPos = std::move(
result.glyphBounds);
502 line.fWordBoundaries = std::move(
result.wordBreaks);
509 for (TextLine&
line : fLines) {
510 line.fOrigin = {0,
y};
514 fNeedsReshape =
false;
static float next(float f)
void drawRect(const SkRect &rect, const SkPaint &paint)
void drawPaint(const SkPaint &paint)
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
static std::unique_ptr< SkExecutor > MakeFIFOThreadPool(int threads=0, bool allowBorrowing=true)
void paint(SkCanvas *canvas, PaintOpts)
SkRect getLocation(TextPosition)
void setFont(SkFont font)
StringView line(size_t i) const
size_t copy(TextPosition pos1, TextPosition pos2, char *dst=nullptr) const
void setFontMgr(sk_sp< SkFontMgr > fontMgr)
TextPosition move(Editor::Movement move, Editor::TextPosition pos) const
TextPosition insert(TextPosition, const char *utf8Text, size_t byteLen)
TextPosition getPosition(SkIPoint)
TextPosition remove(TextPosition, TextPosition)
const SkFont & font() const
static const char * align_utf8(const char *p, const char *begin)
static size_t find_first_larger(const std::vector< T > &list, T value)
static const char * prev_utf8(const char *p, const char *begin)
static const char * end(const StringSlice &s)
static const char * begin(const StringSlice &s)
static SkPoint to_point(SkIPoint p)
static void readlines(const void *data, size_t size, F f)
static constexpr SkRect kUnsetRect
static size_t align_column(const StringSlice &str, size_t p)
static const char * next_utf8(const char *p, const char *end)
static bool valid_utf8(const char *ptr, size_t size)
static bool is_utf8_continuation(char v)
static void append(char **dst, size_t *count, const char *src, size_t n)
static size_t count_char(const StringSlice &string, char value)
static SkRect offset(SkRect r, SkIPoint p)
static size_t find_closest_x(const std::vector< SkRect > &bounds, float x, size_t b, size_t e)
static StringSlice remove_newline(const char *str, size_t len)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
sk_sp< SkFontMgr > fontMgr
static float max(float r, float g, float b)
static float min(float r, float g, float b)
ShapeResult Shape(const char *ut8text, size_t textByteLen, const SkFont &font, sk_sp< SkFontMgr > fontMgr, const char *locale, float width)
Optional< SkRect > bounds
SK_SPI int CountUTF8(const char *utf8, size_t byteLength)
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
font
Font Metadata and Metrics.
constexpr bool contains(std::string_view str, std::string_view needle)
constexpr int32_t y() const
constexpr int32_t x() const
void join(const SkIRect &r)
void offset(int32_t dx, int32_t dy)
bool contains(int32_t x, int32_t y) const
constexpr float y() const
constexpr float x() const
constexpr SkRect makeOffset(float dx, float dy) const
std::shared_ptr< const fml::Mapping > data