Flutter Engine
The Flutter Engine
ParagraphSlide.cpp
Go to the documentation of this file.
1// Copyright 2019 Google LLC.
21#include "src/base/SkRandom.h"
22#include "src/base/SkTime.h"
23#include "src/base/SkUTF.h"
24#include "src/core/SkOSFile.h"
25#include "src/utils/SkOSPath.h"
26#include "tools/Resources.h"
30
31static DEFINE_bool(verboseParagraph, false, "paragraph samples very verbose.");
32
33using namespace skia::textlayout;
34namespace {
35
37 auto factory = SkShapers::BestAvailable();
38 return sk_ref_sp<SkUnicode>(factory->getUnicode());
39}
40
41class ParagraphSlide_Base : public ClickHandlerSlide {
42public:
43 void load(SkScalar w, SkScalar h) override { fSize = {w, h}; }
44
45 void resize(SkScalar w, SkScalar h) override { fSize = {w, h}; }
46
47protected:
48 Click * onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
49 return nullptr;
50 }
51 bool onClick(ClickHandlerSlide::Click *) override { return false; }
52
53 sk_sp<TestFontCollection> getFontCollection() {
54 // If we reset font collection we need to reset paragraph cache
55 static sk_sp<TestFontCollection> fFC = nullptr;
56 if (fFC == nullptr) {
57 fFC = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
58 }
59 return fFC;
60 }
61
62 bool isVerbose() {
63 return FLAGS_verboseParagraph;
64 }
65
66 SkSize size() const { return fSize; }
67
68private:
69 SkSize fSize;
70};
71
72sk_sp<SkShader> setgrad(const SkRect& r, SkColor c0, SkColor c1) {
73 SkColor colors[] = {c0, c1};
74 SkPoint pts[] = {{r.fLeft, r.fTop}, {r.fRight, r.fTop}};
76}
77/*
78void writeHtml(const char* name, Paragraph* paragraph) {
79 SkString tmpDir = skiatest::GetTmpDir();
80 if (!tmpDir.isEmpty()) {
81 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
82 SkFILEWStream file(path.c_str());
83 file.write(nullptr, 0);
84 }
85}
86*/
87
88class ParagraphSlide1 : public ParagraphSlide_Base {
89public:
90 ParagraphSlide1() { fName = "Paragraph1"; }
91
92 void draw(SkCanvas* canvas) override {
93 drawTest(canvas, this->size().width(), this->size().height(), SK_ColorRED, SK_ColorWHITE);
94 }
95
96protected:
97 void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) {
98 const std::vector<
99 std::tuple<std::string, bool, bool, int, SkColor, SkColor, bool, TextDecorationStyle>>
100 gParagraph = {{"monospace", true, false, 14, SK_ColorWHITE, SK_ColorRED, true,
102 {"Assyrian", false, false, 20, SK_ColorWHITE, SK_ColorBLUE, false,
104 {"serif", true, true, 10, SK_ColorWHITE, SK_ColorRED, true,
106 {"Arial", false, true, 16, SK_ColorGRAY, SK_ColorGREEN, true,
108 {"sans-serif", false, false, 8, SK_ColorWHITE, SK_ColorRED, false,
110 SkAutoCanvasRestore acr(canvas, true);
111
112 canvas->clipRect(SkRect::MakeWH(w, h));
113 canvas->drawColor(SK_ColorWHITE);
114
115 SkScalar margin = 20;
116
118 paint.setAntiAlias(true);
119 paint.setColor(fg);
120
121 SkPaint blue;
123
124 TextStyle defaultStyle;
125 defaultStyle.setBackgroundColor(blue);
126 defaultStyle.setForegroundColor(paint);
127 ParagraphStyle paraStyle;
128
129 auto fontCollection = sk_make_sp<FontCollection>();
130 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
131 for (auto i = 1; i < 5; ++i) {
132 defaultStyle.setFontSize(24 * i);
133 paraStyle.setTextStyle(defaultStyle);
134 ParagraphBuilderImpl builder(paraStyle, fontCollection, get_unicode());
135 std::string name = "Paragraph: " + std::to_string(24 * i);
136 builder.addText(name.c_str(), name.length());
137 for (auto para : gParagraph) {
138 TextStyle style;
139 style.setFontFamilies({SkString(std::get<0>(para).c_str())});
140 SkFontStyle fontStyle(std::get<1>(para) ? SkFontStyle::Weight::kBold_Weight
141 : SkFontStyle::Weight::kNormal_Weight,
142 SkFontStyle::Width::kNormal_Width,
143 std::get<2>(para) ? SkFontStyle::Slant::kItalic_Slant
144 : SkFontStyle::Slant::kUpright_Slant);
145 style.setFontStyle(fontStyle);
146 style.setFontSize(std::get<3>(para) * i);
147 SkPaint background;
148 background.setColor(std::get<4>(para));
149 style.setBackgroundColor(background);
150 SkPaint foreground;
151 foreground.setColor(std::get<5>(para));
152 foreground.setAntiAlias(true);
153 style.setForegroundColor(foreground);
154 if (std::get<6>(para)) {
156 }
157
158 auto decoration = (i % 4);
159 if (decoration == 3) {
160 decoration = 4;
161 }
162
164 std::string deco = std::to_string((int)decoration);
165 if (test) {
166 style.setDecoration((TextDecoration)decoration);
167 style.setDecorationStyle(std::get<7>(para));
168 style.setDecorationColor(std::get<5>(para));
169 }
170 builder.pushStyle(style);
171 name = " " + std::get<0>(para) + " " +
172 (std::get<1>(para) ? ", bold" : "") +
173 (std::get<2>(para) ? ", italic" : "") + " " +
174 std::to_string(std::get<3>(para) * i) +
175 (std::get<4>(para) != bg ? ", background" : "") +
176 (std::get<5>(para) != fg ? ", foreground" : "") +
177 (std::get<6>(para) ? ", shadow" : "") +
178 (test ? ", decorations " + deco : "") + ";";
179 builder.addText(name.c_str(), name.length());
180 builder.pop();
181 }
182
183 auto paragraph = builder.Build();
184 paragraph->layout(w - margin * 2);
185 paragraph->paint(canvas, margin, margin);
186
187 canvas->translate(0, paragraph->getHeight());
188 }
189 }
190};
191
192class ParagraphSlide2 : public ParagraphSlide_Base {
193public:
194 ParagraphSlide2() { fName = "Paragraph2"; }
195
196 void draw(SkCanvas* canvas) override {
197 std::vector<const char*> cupertino = {
198 "google_logogoogle_gsuper_g_logo 1 "
199 "google_logogoogle_gsuper_g_logo 12 "
200 "google_logogoogle_gsuper_g_logo 123 "
201 "google_logogoogle_gsuper_g_logo 1234 "
202 "google_logogoogle_gsuper_g_logo 12345 "
203 "google_logogoogle_gsuper_g_logo 123456 "
204 "google_logogoogle_gsuper_g_logo 1234567 "
205 "google_logogoogle_gsuper_g_logo 12345678 "
206 "google_logogoogle_gsuper_g_logo 123456789 "
207 "google_logogoogle_gsuper_g_logo 1234567890 "
208 "google_logogoogle_gsuper_g_logo 123456789 "
209 "google_logogoogle_gsuper_g_logo 12345678 "
210 "google_logogoogle_gsuper_g_logo 1234567 "
211 "google_logogoogle_gsuper_g_logo 123456 "
212 "google_logogoogle_gsuper_g_logo 12345 "
213 "google_logogoogle_gsuper_g_logo 1234 "
214 "google_logogoogle_gsuper_g_logo 123 "
215 "google_logogoogle_gsuper_g_logo 12 "
216 "google_logogoogle_gsuper_g_logo 1 "
217 "google_logogoogle_gsuper_g_logo "
218 "google_logogoogle_gsuper_g_logo "
219 "google_logogoogle_gsuper_g_logo "
220 "google_logogoogle_gsuper_g_logo "
221 "google_logogoogle_gsuper_g_logo "
222 "google_logogoogle_gsuper_g_logo"};
223 std::vector<const char*> text = {
224 "My neighbor came over to say,\n"
225 "Although not in a neighborly way,\n\n"
226 "That he'd knock me around,\n\n\n"
227 "If I didn't stop the sound,\n\n\n\n"
228 "Of the classical music I play."};
229
230 std::vector<const char*> long_word = {
231 "A_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
232 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
233 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
234 "very_very_very_very_very_very_very_long_text"};
235
236 std::vector<const char*> very_long = {
237 "A very very very very very very very very very very very very very very very very "
238 "very very very very very very very very very very very very very very very very "
239 "very very very very very very very very very very very very very very very very "
240 "very very very very very very very long text"};
241
242 std::vector<const char*> very_word = {
243 "A very_very_very_very_very_very_very_very_very_very "
244 "very_very_very_very_very_very_very_very_very_very very very very very very very "
245 "very very very very very very very very very very very very very very very very "
246 "very very very very very very very very very very very very very long text"};
247
248 SkScalar width = this->size().width() / 5;
249 SkScalar height = this->size().height();
250 drawText(canvas, width, height, long_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
251 canvas->translate(width, 0);
252 drawText(canvas, width, height, very_long, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
253 canvas->translate(width, 0);
254 drawText(canvas, width, height, very_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
255 canvas->translate(width, 0);
256 drawText(canvas, width, height / 2, text, SK_ColorBLACK, SK_ColorWHITE, "Roboto", 20, 100,
257 u"\u2026");
258 canvas->translate(0, height / 2);
259 drawCode(canvas, width, height / 2);
260 canvas->translate(width, -height / 2);
261
262 drawText(canvas, width, height, cupertino, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
263 }
264
265private:
266 void drawCode(SkCanvas* canvas, SkScalar w, SkScalar h) {
267 SkPaint comment;
268 comment.setColor(SK_ColorGRAY);
269 SkPaint constant;
270 constant.setColor(SK_ColorMAGENTA);
271 SkPaint null;
273 SkPaint literal;
274 literal.setColor(SK_ColorGREEN);
276 code.setColor(SK_ColorDKGRAY);
277 SkPaint number;
278 number.setColor(SK_ColorBLUE);
280 name.setColor(SK_ColorRED);
281
282 SkPaint white;
283 white.setColor(SK_ColorWHITE);
284
285 TextStyle defaultStyle;
286 defaultStyle.setBackgroundColor(white);
287 defaultStyle.setForegroundColor(code);
288 defaultStyle.setFontFamilies({SkString("monospace")});
289 defaultStyle.setFontSize(30);
290 ParagraphStyle paraStyle;
291 paraStyle.setTextStyle(defaultStyle);
292
293 auto fontCollection = sk_make_sp<FontCollection>();
294 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
295 ParagraphBuilderImpl builder(paraStyle, fontCollection, get_unicode());
296
297 const char* text1 = "RaisedButton";
298 const char* text2 = "(\n";
299 const char* text3 = " child: ";
300 const char* text4 = "const";
301 const char* text5 = "Text";
302 const char* text6 = "'BUTTON TITLE'";
303 const char* text7 = "),\n";
304
305 builder.pushStyle(style(name));
306 builder.addText(text1, strlen(text1));
307 builder.pop();
308 builder.addText(text2, strlen(text2));
309 builder.addText(text3, strlen(text3));
310 builder.pushStyle(style(constant));
311 builder.addText(text4, strlen(text4));
312 builder.pop();
313 builder.addText(" ", 1);
314 builder.pushStyle(style(name));
315 builder.addText(text5, strlen(text5));
316 builder.pop();
317 builder.addText("(", 1);
318 builder.pushStyle(style(literal));
319 builder.addText(text6, strlen(text6));
320 builder.pop();
321 builder.addText(text7, strlen(text7));
322
323 auto paragraph = builder.Build();
324 paragraph->layout(w - 20);
325
326 paragraph->paint(canvas, 20, 20);
327 }
328
329 TextStyle style(SkPaint paint) {
330 TextStyle style;
331 paint.setAntiAlias(true);
333 style.setFontFamilies({SkString("monospace")});
334 style.setFontSize(30);
335
336 return style;
337 }
338
339 void drawText(SkCanvas* canvas, SkScalar w, SkScalar h, std::vector<const char*>& text,
341 const char* ff = "sans-serif", SkScalar fs = 24,
342 size_t lineLimit = 30,
343 const std::u16string& ellipsis = u"\u2026") {
344 SkAutoCanvasRestore acr(canvas, true);
345
346 canvas->clipRect(SkRect::MakeWH(w, h));
347 canvas->drawColor(bg);
348
349 SkScalar margin = 20;
350
352 paint.setAntiAlias(true);
353 paint.setColor(fg);
354
355 SkPaint blue;
357
358 SkPaint background;
359 background.setColor(bg);
360
361 TextStyle style;
362 style.setBackgroundColor(blue);
364 style.setFontFamilies({SkString(ff)});
368 style.setFontSize(fs);
369 ParagraphStyle paraStyle;
370 paraStyle.setTextStyle(style);
371 paraStyle.setMaxLines(lineLimit);
372
373 paraStyle.setEllipsis(ellipsis);
374 TextStyle defaultStyle;
375 defaultStyle.setFontSize(20);
376 paraStyle.setTextStyle(defaultStyle);
377 ParagraphBuilderImpl builder(paraStyle, getFontCollection(), get_unicode());
378
379 SkPaint foreground;
380 foreground.setColor(fg);
381 style.setForegroundColor(foreground);
382 style.setBackgroundColor(background);
383
384 for (auto& part : text) {
385 builder.pushStyle(style);
386 builder.addText(part, strlen(part));
387 builder.pop();
388 }
389
390 auto paragraph = builder.Build();
391 paragraph->layout(w - margin * 2);
392 paragraph->paint(canvas, margin, margin);
393
394 canvas->translate(0, paragraph->getHeight() + margin);
395 }
396
397 void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
398 TextAlign align) {
399 SkAutoCanvasRestore acr(canvas, true);
400
401 canvas->clipRect(SkRect::MakeWH(w, h));
402 canvas->drawColor(SK_ColorWHITE);
403
404 SkScalar margin = 20;
405
407 paint.setAntiAlias(true);
408 paint.setColor(SK_ColorBLUE);
409
410 SkPaint gray;
412
413 TextStyle style;
414 style.setBackgroundColor(gray);
416 style.setFontFamilies({SkString("Arial")});
417 style.setFontSize(30);
418 ParagraphStyle paraStyle;
419 paraStyle.setTextStyle(style);
420 paraStyle.setTextAlign(align);
421
422 auto fontCollection = sk_make_sp<FontCollection>();
423 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
424 ParagraphBuilderImpl builder(paraStyle, fontCollection, get_unicode());
425 builder.addText(text.c_str(), text.length());
426
427 auto paragraph = builder.Build();
428 paragraph->layout(w - margin * 2);
429 paragraph->layout(w - margin);
430 paragraph->paint(canvas, margin, margin);
431
432 canvas->translate(0, paragraph->getHeight() + margin);
433 }
434};
435
436class ParagraphSlide3 : public ParagraphSlide_Base {
437public:
438 ParagraphSlide3() { fName = "Paragraph3"; }
439
440 void draw(SkCanvas* canvas) override {
441 const std::string options = // { "open-source open-source open-source open-source" };
442 {"Flutter is an open-source project to help developers "
443 "build high-performance, high-fidelity, mobile apps for "
444 "iOS and Android "
445 "from a single codebase. This design lab is a playground "
446 "and showcase of Flutter's many widgets, behaviors, "
447 "animations, layouts, and more."};
448
449 canvas->drawColor(SK_ColorDKGRAY);
450 SkScalar width = this->size().width() / 4;
451 SkScalar height = this->size().height() / 2;
452
453 const std::string line =
454 "World domination is such an ugly phrase - I prefer to call it world optimisation";
455 drawLine(canvas, width, height, line, TextAlign::kLeft, 1, false, SK_ColorLTGRAY);
456 canvas->translate(width, 0);
457 drawLine(canvas, width, height, line, TextAlign::kRight, 2, false, SK_ColorLTGRAY);
458 canvas->translate(width, 0);
459 drawLine(canvas, width, height, line, TextAlign::kCenter, 3, false, SK_ColorLTGRAY);
460 canvas->translate(width, 0);
461 drawLine(canvas, width, height, line, TextAlign::kJustify, 4, false, SK_ColorLTGRAY);
462 canvas->translate(-width * 3, height);
463 drawLine(canvas, width, height, line, TextAlign::kLeft, 1, true, SK_ColorLTGRAY);
464 canvas->translate(width, 0);
465 drawLine(canvas, width, height, line, TextAlign::kRight, 2, true, SK_ColorLTGRAY);
466 canvas->translate(width, 0);
467 drawLine(canvas, width, height, line, TextAlign::kCenter, 3, true, SK_ColorLTGRAY);
468 canvas->translate(width, 0);
469 drawLine(canvas, width, height, line, TextAlign::kJustify, 4, true, SK_ColorLTGRAY);
470 canvas->translate(width, 0);
471 }
472
473private:
474 void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
475 TextAlign align, size_t lineLimit = std::numeric_limits<size_t>::max(),
476 bool RTL = false, SkColor background = SK_ColorGRAY,
477 const std::u16string& ellipsis = u"\u2026") {
478 SkAutoCanvasRestore acr(canvas, true);
479
480 canvas->clipRect(SkRect::MakeWH(w, h));
481 canvas->drawColor(SK_ColorWHITE);
482
483 SkScalar margin = 20;
484
486 paint.setAntiAlias(true);
487 paint.setColor(SK_ColorBLACK);
488
489 SkPaint gray;
490 gray.setColor(background);
491
492 SkPaint yellow;
493 yellow.setColor(SK_ColorYELLOW);
494
495 TextStyle style;
496 style.setBackgroundColor(gray);
498 style.setFontFamilies({SkString("sans-serif")});
499 style.setFontSize(30);
500 ParagraphStyle paraStyle;
501 paraStyle.setTextStyle(style);
502 paraStyle.setTextAlign(align);
503 paraStyle.setMaxLines(lineLimit);
504 paraStyle.setEllipsis(ellipsis);
505 paraStyle.setTextDirection(RTL ? TextDirection::kRtl : TextDirection::kLtr);
506
507 auto fontCollection = sk_make_sp<FontCollection>();
508 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
509 ParagraphBuilderImpl builder(paraStyle, fontCollection, get_unicode());
510 if (RTL) {
511 builder.addText(mirror(text));
512 } else {
513 builder.addText(normal(text));
514 }
515
516 canvas->drawRect(SkRect::MakeXYWH(margin, margin, w - margin * 2, h - margin * 2), yellow);
517 auto paragraph = builder.Build();
518 paragraph->layout(w - margin * 2);
519 paragraph->paint(canvas, margin, margin);
520 }
521
522 std::u16string mirror(const std::string& text) {
523 std::u16string result;
524 result += u"\u202E";
525 // for (auto i = text.size(); i > 0; --i) {
526 // result += text[i - 1];
527 //}
528
529 for (auto i = text.size(); i > 0; --i) {
530 auto ch = text[i - 1];
531 if (ch == ',') {
532 result += u"!";
533 } else if (ch == '.') {
534 result += u"!";
535 } else {
536 result += ch;
537 }
538 }
539
540 result += u"\u202C";
541 return result;
542 }
543
544 std::u16string normal(const std::string& text) {
545 std::u16string result;
546 result += u"\u202D";
547 for (auto ch : text) {
548 result += ch;
549 }
550 result += u"\u202C";
551 return result;
552 }
553};
554
555class ParagraphSlide5 : public ParagraphSlide_Base {
556public:
557 ParagraphSlide5() { fName = "Paragraph5"; }
558
559 void draw(SkCanvas* canvas) override {
560 canvas->drawColor(SK_ColorWHITE);
561 SkScalar width = this->size().width();
562 SkScalar height = this->size().height() / 8;
563
564 const std::u16string text1 =
565 u"A \u202ENAC\u202Cner, exceedingly \u202ENAC\u202Cny,\n"
566 "One morning remarked to his granny:\n"
567 "A \u202ENAC\u202Cner \u202ENAC\u202C \u202ENAC\u202C,\n"
568 "Anything that he \u202ENAC\u202C,\n"
569 "But a \u202ENAC\u202Cner \u202ENAC\u202C't \u202ENAC\u202C a \u202ENAC\u202C, "
570 "\u202ENAC\u202C he?";
571 bidi(canvas, width, height * 3, text1, u"", 5);
572 canvas->translate(0, height * 3);
573
574 bidi(canvas, width, height, u"\u2067DETALOSI\u2069", u"");
575 canvas->translate(0, height);
576
577 bidi(canvas, width, height, u"\u202BDEDDEBME\u202C", u"");
578 canvas->translate(0, height);
579
580 bidi(canvas, width, height, u"\u202EEDIRREVO\u202C", u"");
581 canvas->translate(0, height);
582
583 bidi(canvas, width, height, u"\u200FTICILPMI\u200E", u"");
584 canvas->translate(0, height);
585
586 bidi(canvas,
587 width,
588 height,
589 u"123 456 7890 \u202EZYXWV UTS RQP ONM LKJ IHG FED CBA\u202C.",
590 u"",
591 2);
592 canvas->translate(0, height);
593
594 // bidi(canvas, width, height, u"", u"");
595 // canvas->translate(0, height);
596 }
597
598private:
599 void bidi(SkCanvas* canvas,
600 SkScalar w,
601 SkScalar h,
602 const std::u16string& text,
603 const std::u16string& expected,
604 size_t lineLimit = std::numeric_limits<size_t>::max(),
605 const char* ff = "Roboto",
606 SkScalar fs = 30,
607 const std::u16string& ellipsis = u"\u2026") {
608 SkAutoCanvasRestore acr(canvas, true);
609
610 canvas->clipRect(SkRect::MakeWH(w, h));
611
612 SkScalar margin = 20;
613
614 SkPaint black;
615 black.setColor(SK_ColorBLACK);
616 SkPaint gray;
618
619 TextStyle style;
620 style.setForegroundColor(black);
621 style.setFontFamilies({SkString(ff)});
622 style.setFontSize(fs);
623
624 TextStyle style0;
625 style0.setForegroundColor(black);
626 style0.setFontFamilies({SkString(ff)});
627 style0.setFontSize(fs);
631
632 TextStyle style1;
633 style1.setForegroundColor(gray);
634 style1.setFontFamilies({SkString(ff)});
635 style1.setFontSize(fs);
639
640 ParagraphStyle paraStyle;
641 paraStyle.setTextStyle(style);
642 paraStyle.setMaxLines(lineLimit);
643
644 paraStyle.setEllipsis(ellipsis);
645
646 ParagraphBuilderImpl builder(paraStyle, getFontCollection(), get_unicode());
647
648 if (text.empty()) {
649 const std::u16string text0 = u"\u202Dabc";
650 const std::u16string text1 = u"\u202EFED";
651 const std::u16string text2 = u"\u202Dghi";
652 const std::u16string text3 = u"\u202ELKJ";
653 const std::u16string text4 = u"\u202Dmno";
654 builder.pushStyle(style0);
655 builder.addText(text0);
656 builder.pop();
657 builder.pushStyle(style1);
658 builder.addText(text1);
659 builder.pop();
660 builder.pushStyle(style0);
661 builder.addText(text2);
662 builder.pop();
663 builder.pushStyle(style1);
664 builder.addText(text3);
665 builder.pop();
666 builder.pushStyle(style0);
667 builder.addText(text4);
668 builder.pop();
669 } else {
670 builder.addText(text + expected);
671 }
672
673 auto paragraph = builder.Build();
674 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
675 if (this->isVerbose()) {
676 SkDebugf("Text: >%s<\n", impl->text().data());
677 }
678
679 paragraph->layout(w - margin * 2);
680 paragraph->paint(canvas, margin, margin);
681 }
682};
683
684class ParagraphSlide6 : public ParagraphSlide_Base {
685public:
686 ParagraphSlide6() { fName = "Paragraph6"; }
687
688 void hangingS(SkCanvas* canvas, SkScalar w, SkScalar h, SkScalar fs = 60.0) {
689 auto ff = "HangingS";
690
691 canvas->drawColor(SK_ColorLTGRAY);
692
693 SkPaint black;
694 black.setAntiAlias(true);
695 black.setColor(SK_ColorBLACK);
696
697 SkPaint blue;
698 blue.setAntiAlias(true);
700
701 SkPaint red;
702 red.setAntiAlias(true);
704
705 SkPaint green;
706 green.setAntiAlias(true);
707 green.setColor(SK_ColorGREEN);
708
709 SkPaint gray;
711
712 SkPaint yellow;
713 yellow.setColor(SK_ColorYELLOW);
714
715 SkPaint magenta;
716 magenta.setAntiAlias(true);
717 magenta.setColor(SK_ColorMAGENTA);
718
721
722 TextStyle style;
723 style.setFontFamilies({SkString(ff)});
724 style.setFontSize(fs);
725 style.setFontStyle(fontStyle);
726
727 TextStyle style0;
728 style0.setForegroundColor(black);
729 style0.setBackgroundColor(gray);
730 style0.setFontFamilies({SkString(ff)});
731 style0.setFontSize(fs);
732 style0.setFontStyle(fontStyle);
733
734 TextStyle style1;
735 style1.setForegroundColor(blue);
736 style1.setBackgroundColor(yellow);
737 style1.setFontFamilies({SkString(ff)});
738 style1.setFontSize(fs);
739 style1.setFontStyle(fontStyle);
740
741 TextStyle style2;
742 style2.setForegroundColor(red);
743 style2.setFontFamilies({SkString(ff)});
744 style2.setFontSize(fs);
745 style2.setFontStyle(fontStyle);
746
747 TextStyle style3;
748 style3.setForegroundColor(green);
749 style3.setFontFamilies({SkString(ff)});
750 style3.setFontSize(fs);
751 style3.setFontStyle(fontStyle);
752
753 TextStyle style4;
754 style4.setForegroundColor(magenta);
755 style4.setFontFamilies({SkString(ff)});
756 style4.setFontSize(fs);
757 style4.setFontStyle(fontStyle);
758
759 ParagraphStyle paraStyle;
760 paraStyle.setTextStyle(style);
761
762 const char* logo1 = "S";
763 const char* logo2 = "kia";
764 const char* logo3 = "Sk";
765 const char* logo4 = "ia";
766 const char* logo5 = "Ski";
767 const char* logo6 = "a";
768 {
769 ParagraphBuilderImpl builder(paraStyle, getFontCollection(), get_unicode());
770
771 builder.pushStyle(style0);
772 builder.addText(logo1, strlen(logo1));
773 builder.pop();
774 builder.pushStyle(style1);
775 builder.addText(logo2, strlen(logo2));
776 builder.pop();
777
778 builder.addText(" ", 3);
779
780 builder.pushStyle(style0);
781 builder.addText(logo3, strlen(logo3));
782 builder.pop();
783 builder.pushStyle(style1);
784 builder.addText(logo4, strlen(logo4));
785 builder.pop();
786
787 builder.addText(" ", 3);
788
789 builder.pushStyle(style0);
790 builder.addText(logo5, strlen(logo5));
791 builder.pop();
792 builder.pushStyle(style1);
793 builder.addText(logo6, strlen(logo6));
794 builder.pop();
795
796 auto paragraph = builder.Build();
797 paragraph->layout(w);
798 paragraph->paint(canvas, 40, 40);
799 canvas->translate(0, h);
800 }
801
802 const char* logo11 = "S";
803 const char* logo12 = "S";
804 const char* logo13 = "S";
805 const char* logo14 = "S";
806 const char* logo15 = "S";
807 const char* logo16 = "S";
808 {
809 ParagraphBuilderImpl builder(paraStyle, getFontCollection(), get_unicode());
810
811 builder.pushStyle(style0);
812 builder.addText(logo11, strlen(logo11));
813 builder.pop();
814 builder.pushStyle(style1);
815 builder.addText(logo12, strlen(logo12));
816 builder.pop();
817
818 builder.addText(" ", 3);
819
820 builder.pushStyle(style0);
821 builder.addText(logo13, strlen(logo13));
822 builder.pop();
823 builder.pushStyle(style1);
824 builder.addText(logo14, strlen(logo14));
825 builder.pop();
826
827 builder.addText(" ", 3);
828
829 builder.pushStyle(style0);
830 builder.addText(logo15, strlen(logo15));
831 builder.pop();
832 builder.pushStyle(style1);
833 builder.addText(logo16, strlen(logo16));
834 builder.pop();
835
836 auto paragraph = builder.Build();
837 paragraph->layout(w);
838 paragraph->paint(canvas, 40, h);
839 canvas->translate(0, h);
840 }
841 }
842
843 void draw(SkCanvas* canvas) override {
844 canvas->drawColor(SK_ColorWHITE);
845 SkScalar width = this->size().width();
846 SkScalar height = this->size().height() / 4;
847
848 hangingS(canvas, width, height);
849 }
850};
851
852class ParagraphSlide7 : public ParagraphSlide_Base {
853public:
854 ParagraphSlide7() { fName = "Paragraph7"; }
855
856 void drawText(SkCanvas* canvas, SkColor background, SkScalar letterSpace, SkScalar w,
857 SkScalar h) {
858 SkAutoCanvasRestore acr(canvas, true);
859 canvas->clipRect(SkRect::MakeWH(w, h));
860 canvas->drawColor(background);
861
862 const char* line =
863 "World domination is such an ugly phrase - I prefer to call it world optimisation.";
864
865 ParagraphStyle paragraphStyle;
866 paragraphStyle.setTextAlign(TextAlign::kLeft);
867 paragraphStyle.setMaxLines(10);
868 paragraphStyle.turnHintingOff();
869 TextStyle textStyle;
870 textStyle.setFontFamilies({SkString("Roboto")});
871 textStyle.setFontSize(30);
872 textStyle.setLetterSpacing(letterSpace);
873 textStyle.setColor(SK_ColorBLACK);
876
877 ParagraphBuilderImpl builder(paragraphStyle, getFontCollection(), get_unicode());
878 builder.pushStyle(textStyle);
879 builder.addText(line, strlen(line));
880 builder.pop();
881
882 auto paragraph = builder.Build();
883 paragraph->layout(w - 20);
884 paragraph->paint(canvas, 10, 10);
885 }
886
887 void draw(SkCanvas* canvas) override {
888 canvas->drawColor(SK_ColorWHITE);
889
890 auto h = this->size().height() / 4;
891 auto w = this->size().width() / 2;
892
893 drawText(canvas, SK_ColorGRAY, 1, w, h);
894 canvas->translate(0, h);
895
896 drawText(canvas, SK_ColorLTGRAY, 2, w, h);
897 canvas->translate(0, h);
898
899 drawText(canvas, SK_ColorCYAN, 3, w, h);
900 canvas->translate(0, h);
901
902 drawText(canvas, SK_ColorGRAY, 4, w, h);
903 canvas->translate(w, -3 * h);
904
905 drawText(canvas, SK_ColorYELLOW, 5, w, h);
906 canvas->translate(0, h);
907
908 drawText(canvas, SK_ColorGREEN, 10, w, h);
909 canvas->translate(0, h);
910
911 drawText(canvas, SK_ColorRED, 15, w, h);
912 canvas->translate(0, h);
913
914 drawText(canvas, SK_ColorBLUE, 20, w, h);
915 canvas->translate(0, h);
916 }
917};
918
919class ParagraphSlide8 : public ParagraphSlide_Base {
920public:
921 ParagraphSlide8() { fName = "Paragraph8"; }
922
923 void drawText(SkCanvas* canvas, SkColor background, SkScalar wordSpace, SkScalar w,
924 SkScalar h) {
925 SkAutoCanvasRestore acr(canvas, true);
926 canvas->clipRect(SkRect::MakeWH(w, h));
927 canvas->drawColor(background);
928
929 const char* line =
930 "World domination is such an ugly phrase - I prefer to call it world optimisation.";
931
932 ParagraphStyle paragraphStyle;
933 paragraphStyle.setTextAlign(TextAlign::kLeft);
934 paragraphStyle.setMaxLines(10);
935 paragraphStyle.turnHintingOff();
936 TextStyle textStyle;
937 textStyle.setFontFamilies({SkString("Roboto")});
938 textStyle.setFontSize(30);
939 textStyle.setWordSpacing(wordSpace);
940 textStyle.setColor(SK_ColorBLACK);
943
944 ParagraphBuilderImpl builder(paragraphStyle, getFontCollection(), get_unicode());
945 builder.pushStyle(textStyle);
946 builder.addText(line, strlen(line));
947 builder.pop();
948
949 auto paragraph = builder.Build();
950 paragraph->layout(w - 20);
951 paragraph->paint(canvas, 10, 10);
952 }
953
954 void draw(SkCanvas* canvas) override {
955 canvas->drawColor(SK_ColorWHITE);
956
957 auto h = this->size().height() / 4;
958 auto w = this->size().width() / 2;
959
960 drawText(canvas, SK_ColorGRAY, 1, w, h);
961 canvas->translate(0, h);
962
963 drawText(canvas, SK_ColorLTGRAY, 2, w, h);
964 canvas->translate(0, h);
965
966 drawText(canvas, SK_ColorCYAN, 3, w, h);
967 canvas->translate(0, h);
968
969 drawText(canvas, SK_ColorGRAY, 4, w, h);
970 canvas->translate(w, -3 * h);
971
972 drawText(canvas, SK_ColorYELLOW, 5, w, h);
973 canvas->translate(0, h);
974
975 drawText(canvas, SK_ColorGREEN, 10, w, h);
976 canvas->translate(0, h);
977
978 drawText(canvas, SK_ColorRED, 15, w, h);
979 canvas->translate(0, h);
980
981 drawText(canvas, SK_ColorBLUE, 20, w, h);
982 canvas->translate(0, h);
983 }
984};
985
986class ParagraphSlide9 : public ParagraphSlide_Base {
987public:
988 ParagraphSlide9() { fName = "Paragraph9"; }
989
990 bool onChar(SkUnichar uni) override {
991 switch (uni) {
992 case 'w':
993 ++wordSpacing;
994 return true;
995 case 'q':
996 if (wordSpacing > 0) --wordSpacing;
997 return true;
998 case 'l':
999 ++letterSpacing;
1000 return true;
1001 case 'k':
1002 if (letterSpacing > 0) --letterSpacing;
1003 return true;
1004 default:
1005 break;
1006 }
1007 return false;
1008 }
1009
1010 void drawText(SkCanvas* canvas, SkColor background, SkScalar w, SkScalar h) {
1011 SkAutoCanvasRestore acr(canvas, true);
1012 canvas->clipRect(SkRect::MakeWH(w, h));
1013 canvas->drawColor(background);
1014
1015 auto fontCollection = sk_make_sp<FontCollection>();
1016 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
1017 fontCollection->enableFontFallback();
1018
1019 const char* text =
1020 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1021 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1022 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
1023 auto multiplier = 5.67;
1024 ParagraphStyle paragraphStyle;
1025 paragraphStyle.setTextAlign(TextAlign::kLeft);
1026 paragraphStyle.setMaxLines(10);
1027 paragraphStyle.turnHintingOff();
1028 TextStyle textStyle;
1029 textStyle.setFontFamilies({SkString("Roboto")});
1030 textStyle.setFontSize(5 * multiplier);
1031 textStyle.setHeight(1.3f);
1032 textStyle.setColor(SK_ColorBLACK);
1035
1036 ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode());
1037 builder.pushStyle(textStyle);
1038 builder.addText(text, strlen(text));
1039 builder.pop();
1040
1041 auto paragraph = builder.Build();
1042 paragraph->layout(200 * multiplier);
1043
1044 std::vector<size_t> sizes = {0, 1, 2, 8, 19, 21, 22, 30, 150};
1045
1048
1049 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
1050 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1051
1052 for (size_t i = 0; i < sizes.size() - 1; ++i) {
1053 size_t from = sizes[i];
1054 size_t to = sizes[i + 1];
1055 auto boxes = paragraph->getRectsForRange(from, to, rect_height_style, rect_width_style);
1056 if (boxes.empty()) {
1057 continue;
1058 }
1059 for (auto& box : boxes) {
1060 SkPaint paint;
1061 paint.setColor(colors[i % colors.size()]);
1062 paint.setShader(setgrad(box.rect, colors[i % colors.size()], SK_ColorWHITE));
1063 canvas->drawRect(box.rect, paint);
1064 }
1065 }
1066
1067 paragraph->paint(canvas, 0, 0);
1068 }
1069
1070 void draw(SkCanvas* canvas) override {
1071 canvas->drawColor(SK_ColorWHITE);
1072
1073 auto h = this->size().height();
1074 auto w = this->size().width();
1075
1076 drawText(canvas, SK_ColorGRAY, w, h);
1077 }
1078
1079private:
1080 SkScalar letterSpacing;
1081 SkScalar wordSpacing;
1082};
1083
1084class ParagraphSlide10 : public ParagraphSlide_Base {
1085public:
1086 ParagraphSlide10() { fName = "Paragraph10"; }
1087
1088 void draw(SkCanvas* canvas) override {
1089 canvas->drawColor(SK_ColorWHITE);
1090 auto multiplier = 5.67;
1091 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
1092
1093 auto fontCollection = sk_make_sp<FontCollection>();
1094 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
1095 fontCollection->enableFontFallback();
1096
1097 ParagraphStyle paragraph_style;
1098 paragraph_style.turnHintingOff();
1099 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1100
1101 TextStyle text_style;
1102 text_style.setFontFamilies({SkString("Roboto"),
1103 SkString("Noto Color Emoji"),
1104 SkString("Noto Serif CJK JP")});
1105 text_style.setFontSize(10 * multiplier);
1106 text_style.setLetterSpacing(0);
1107 text_style.setWordSpacing(0);
1108 text_style.setColor(SK_ColorBLACK);
1109 text_style.setHeight(1);
1110 builder.pushStyle(text_style);
1111 builder.addText(text, strlen(text));
1112 builder.pop();
1113
1114 auto paragraph = builder.Build();
1115 paragraph->layout(this->size().width());
1116
1117 paragraph->paint(canvas, 0, 0);
1118 }
1119};
1120
1121class ParagraphSlide11 : public ParagraphSlide_Base {
1122public:
1123 ParagraphSlide11() { fName = "Paragraph11"; }
1124
1125 void draw(SkCanvas* canvas) override {
1126 canvas->drawColor(SK_ColorWHITE);
1127
1128 auto text = "\U0001f469\U0000200D\U0001f469\U0000200D\U0001f466\U0001f469\U0000200D\U0001f469\U0000200D\U0001f467\U0000200D\U0001f467\U0001f1fa\U0001f1f8";
1129
1130 TextStyle text_style;
1131 text_style.setFontFamilies({SkString("Ahem")});
1132 text_style.setColor(SK_ColorBLACK);
1133 text_style.setFontSize(60);
1134 text_style.setLetterSpacing(0);
1135 text_style.setWordSpacing(0);
1136 ParagraphStyle paragraph_style;
1137 paragraph_style.setTextStyle(text_style);
1138
1139 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
1140 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1141 builder.addText(text, strlen(text));
1142 auto paragraph = builder.Build();
1143 paragraph->layout(1000);
1144 paragraph->paint(canvas, 0, 0);
1145
1146 struct pair {
1147 unsigned fX;
1148 unsigned fY;
1149 };
1150
1151 pair hit1[] =
1152 {{ 0, 8},{1, 33}, {2, 34}, { 3, 19}, {4, 20},
1153 { 5, 21}, { 6, 22 }, { 7, 23 }, {8, 24 }, { 9, 25},
1154 { 10, 26}, { 11, 27}, {12, 28}, { 13, 21}, {14, 22 },
1155 { 15, 23}, {16, 24}, {17, 21}, { 18, 22}, {19, 21},
1156 { 20, 24}, { 21, 23}, };
1157
1158 pair miss[] =
1159 {{ 0, 4},{1, 17}, {2, 18}, { 3, 11}, {4, 12},
1160 { 5, 13}, { 6, 14 }, { 7, 15 }, {8, 16 }, { 9, 17},
1161 { 10, 18}, { 11, 19}, {12, 20}, { 13, 17}, {14, 18 },
1162 { 15, 19}, {16, 20}, {17, 19}, { 18, 20},
1163 { 20, 22}, };
1164
1165 auto rects = paragraph->getRectsForRange(7, 9, RectHeightStyle::kTight,
1166 RectWidthStyle::kTight);
1167 SkPaint paint;
1168 paint.setColor(SK_ColorRED);
1169 paint.setStyle(SkPaint::kStroke_Style);
1170 paint.setAntiAlias(true);
1171 paint.setStrokeWidth(1);
1172 if (!rects.empty()) {
1173 canvas->drawRect(rects[0].rect, paint);
1174 }
1175
1176 for (auto& query : hit1) {
1177 auto hitRects = paragraph->getRectsForRange(query.fX, query.fY, RectHeightStyle::kTight,
1178 RectWidthStyle::kTight);
1179 if (hitRects.size() >= 1 && hitRects[0].rect.width() > 0) {
1180 } else {
1181 if (this->isVerbose()) {
1182 SkDebugf("+[%u:%u): Bad\n", query.fX, query.fY);
1183 }
1184 }
1185 }
1186
1187 for (auto& query : miss) {
1188 auto missRects = paragraph->getRectsForRange(query.fX, query.fY,
1189 RectHeightStyle::kTight,
1190 RectWidthStyle::kTight);
1191 if (missRects.empty()) {
1192 } else {
1193 if (this->isVerbose()) {
1194 SkDebugf("-[%u:%u): Bad\n", query.fX, query.fY);
1195 }
1196 }
1197 }
1198 }
1199};
1200
1201class ParagraphSlide12 : public ParagraphSlide_Base {
1202public:
1203 ParagraphSlide12() { fName = "Paragraph12"; }
1204
1205 void draw(SkCanvas* canvas) override {
1206 canvas->drawColor(SK_ColorWHITE);
1207
1208 const char* text = "Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges";
1209 TextStyle text_style;
1210 text_style.setFontFamilies({SkString("Ahem")});
1211 text_style.setColor(SK_ColorBLACK);
1212 text_style.setFontSize(16);
1213 //text_style.setLetterSpacing(-0.41);
1214 StrutStyle strut_style;
1215 strut_style.setStrutEnabled(false);
1216 ParagraphStyle paragraph_style;
1217 paragraph_style.setStrutStyle(strut_style);
1218 paragraph_style.setTextStyle(text_style);
1219 ParagraphBuilderImpl builder(paragraph_style, getFontCollection(), get_unicode());
1220 builder.addText(text);
1221 auto paragraph = builder.Build();
1222 paragraph->layout(1095.000000);
1223 auto result = paragraph->getRectsForRange(65, 66, RectHeightStyle::kTight, RectWidthStyle::kTight);
1224 paragraph->paint(canvas, 0, 0);
1225
1226 SkPaint paint;
1227 paint.setColor(SK_ColorRED);
1228 paint.setStyle(SkPaint::kStroke_Style);
1229 paint.setAntiAlias(true);
1230 paint.setStrokeWidth(1);
1231 if (!result.empty()) {
1232 canvas->drawRect(result.front().rect, paint);
1233 }
1234 }
1235};
1236
1237class ParagraphSlide14 : public ParagraphSlide_Base {
1238public:
1239 ParagraphSlide14() { fName = "Paragraph14"; }
1240
1241 void draw(SkCanvas* canvas) override {
1242 canvas->drawColor(SK_ColorWHITE);
1243 TextStyle text_style;
1244 text_style.setFontFamilies({SkString("Ahem")});
1245 text_style.setColor(SK_ColorBLACK);
1246 text_style.setFontSize(25);
1248 text_style.setDecorationColor(SK_ColorBLUE);
1250 text_style.setDecorationThicknessMultiplier(4.0f);
1251 ParagraphStyle paragraph_style;
1252 paragraph_style.setTextStyle(text_style);
1253 paragraph_style.setTextDirection(TextDirection::kRtl);
1254 ParagraphBuilderImpl builder(paragraph_style, getFontCollection(), get_unicode());
1255 builder.pushStyle(text_style);
1256 builder.addText("Hello, wor!\nabcd.");
1257 auto paragraph = builder.Build();
1258 paragraph->layout(300);
1259 paragraph->paint(canvas, 0, 0);
1260 SkPaint paint;
1261 paint.setColor(SK_ColorRED);
1262 paint.setStyle(SkPaint::kStroke_Style);
1263 paint.setAntiAlias(true);
1264 paint.setStrokeWidth(1);
1265 canvas->drawRect(SkRect::MakeXYWH(0, 0, 300, 100), paint);
1266 }
1267};
1268
1269class ParagraphSlide15 : public ParagraphSlide_Base {
1270public:
1271 ParagraphSlide15() { fName = "Paragraph15"; }
1272
1273 void draw(SkCanvas* canvas) override {
1274 canvas->drawColor(SK_ColorWHITE);
1275
1276 TextStyle text_style;
1277 text_style.setFontFamilies({SkString("abc.ttf")});
1278 text_style.setFontSize(50);
1279
1280 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
1281
1282 fontCollection->addFontFromFile("abc/abc.ttf", "abc");
1283 fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave");
1284 fontCollection->addFontFromFile("abc/abc+agrave.ttf", "abc+agrave");
1285
1286 ParagraphStyle paragraph_style;
1287 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1288
1289 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
1290 text_style.setColor(SK_ColorBLUE);
1291 builder.pushStyle(text_style);
1292 builder.addText(u"a\u0300");
1293 text_style.setColor(SK_ColorMAGENTA);
1294 builder.pushStyle(text_style);
1295 builder.addText(u"à");
1296
1297 text_style.setFontFamilies({SkString("abc"), SkString("abc+agrave")});
1298
1299 text_style.setColor(SK_ColorRED);
1300 builder.pushStyle(text_style);
1301 builder.addText(u"a\u0300");
1302 text_style.setColor(SK_ColorGREEN);
1303 builder.pushStyle(text_style);
1304 builder.addText(u"à");
1305
1306 auto paragraph = builder.Build();
1307 paragraph->layout(800);
1308 paragraph->paint(canvas, 50, 50);
1309
1310 }
1311};
1312
1313class ParagraphSlide16 : public ParagraphSlide_Base {
1314public:
1315 ParagraphSlide16() { fName = "Paragraph16"; }
1316
1317 void draw(SkCanvas* canvas) override {
1318 canvas->drawColor(SK_ColorWHITE);
1319
1320 const char* text = "content";
1321
1322 ParagraphStyle paragraph_style;
1323 paragraph_style.setMaxLines(1);
1324 paragraph_style.setEllipsis(u"\u2026");
1325 //auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1326 auto fontCollection = sk_make_sp<FontCollection>();
1327 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
1328 fontCollection->enableFontFallback();
1329 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1330
1331 TextStyle text_style;
1332 text_style.setFontFamilies({SkString(".SF Pro Text")});
1333 text_style.setColor(SK_ColorBLACK);
1334 text_style.setFontSize(17.0f * 99.0f);
1335 text_style.setLetterSpacing(0.41f);
1336 builder.pushStyle(text_style);
1337 builder.addText(text);
1338
1339 auto paragraph = builder.Build();
1340 paragraph->layout(800);
1341 paragraph->paint(canvas, 0, 0);
1342 }
1343};
1344
1345class ParagraphSlide17 : public ParagraphSlide_Base {
1346public:
1347 ParagraphSlide17() { fName = "Paragraph17"; }
1348
1349 void draw(SkCanvas* canvas) override {
1350 canvas->drawColor(SK_ColorWHITE);
1351
1352 auto fontCollection = sk_make_sp<FontCollection>();
1353 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
1354 fontCollection->enableFontFallback();
1355 auto navy = SkColorSetRGB(0, 0, 139);
1356 auto ltgray = SkColorSetRGB(211, 211, 211);
1357 auto multiplier = 5.67;
1358
1359 //const char* text = ">Sͬ͑̀͐̈͒̈́̋̎ͮͩ̽̓ͬ̂̆̔͗́̓ͣͧ͊ͫ͛̉͌̐̑ͪ͗̚͝҉̴͉͢k̡̊̓ͫͭͩ͂͊ͨͪͬ̑ͫ̍̌̄͛̌̂̑̂̋̊̔ͫ͛̽̑ͨ̍ͭ̓̀ͪͪ̉͐͗̌̓̃̚͟͝҉̢͏̫̞̙͇͖̮͕̗̟͕͇͚̻͈̣̻̪͉̰̲̣̫ͅͅP̴̅̍͒̿͗͗̇ͩ̃͆͌̀̽͏̧̡͕͖̝̖̼̺̰̣̬͔͖͔̼͙̞̦̫͓̘͜a̸̴̸̴̢̢̨̨̫͍͓̥̼̭̼̻̤̯̙̤̻̠͚̍̌͋̂ͦͨ̽̇͌͌͆̀̽̎͒̄ͪ̐ͦ̈ͫ͐͗̓̚̚͜ͅr͐͐ͤͫ̐ͥ͂̈́̿́ͮ̃͗̓̏ͫ̀̿͏̸̵̧́͘̕͟͝͠͞͠҉̷̧͚͢͟a̓̽̎̄͗̔͛̄̐͊͛ͫ͂͌̂̂̈̈̓̔̅̅̄͊̉́ͪ̑̄͆ͬ̍͆ͭ͋̐ͬ͏̷̵̨̢̩̹̖͓̥̳̰͔̱̬͖̙͓̙͇̀̀̕͜͟͟͢͟͜͠͡g̨̅̇ͦ͋̂ͦͨͭ̓͐͆̏̂͛̉ͧ̑ͫ̐̒͛ͫ̍̒͛́̚҉̷̨̛̛̀͜͢͞҉̩̘̲͍͎̯̹̝̭̗̱͇͉̲̱͔̯̠̹̥̻͉̲̜̤̰̪̗̺̖̺r̷͌̓̇̅ͭ̀̐̃̃ͭ͑͗̉̈̇̈́ͥ̓ͣ́ͤ͂ͤ͂̏͌̆̚҉̴̸̧̢̢̛̫͉̦̥̤̙͈͉͈͉͓̙̗̟̳̜͈̗̺̟̠̠͖͓̖̪͕̠̕̕͝ͅả̸̴̡̡̧͠͞͡͞҉̛̕͟͏̷̘̪̱͈̲͉̞̠̞̪̫͎̲̬̖̀̀͟͝͞͞͠p̛͂̈͐̚͠҉̵̸̡̢̢̩̹͙̯͖̙̙̮̥̙͚̠͔̥̭̮̞̣̪̬̥̠̖̝̥̪͎́̀̕͜͡͡ͅͅh̵̷̵̡̛ͤ̂͌̐̓̐̋̋͊̒̆̽́̀̀̀͢͠͞͞҉̷̸̢̕҉͚̯͖̫̜̞̟̠̱͉̝̲̹̼͉̟͉̩̮͔̤͖̞̭̙̹̬ͅ<";
1360 const char* text = ">S͛ͭ̋͆̈̔̇͗̍͑̎ͪͮͧͣ̽ͫͣ́ͬ̀͌͑͂͗͒̍̔̄ͧ̏̉̌̊̊̿̀̌̃̄͐̓̓̚̚҉̵̡͜͟͝͠͏̸̵̡̧͜҉̷̡͇̜̘̻̺̘̟̝͙̬̘̩͇̭̼̥̖̤̦͎k͉̩̘͚̜̹̗̗͍̤̥̱͉̳͕͖̤̲̣͚̮̞̬̲͍͔̯̻̮̞̭͈̗̫͓̂ͨ̉ͪ̒͋͛̀̍͊ͧ̿̅͆̓̔̔ͬ̇̑̿ͩ͗ͮ̎͌̿̄ͅP̴̵̡̡̛̪͙̼̣̟̩̭̫̱͙̬͔͉͍̘̠͉̦̝̘̥̟̗͖̫̤͕̙̬̦͍̱̖̮̱͑͐̎̃̒͐͋̚͘͞a̶̶̵̵̵̶̶̡̧̢̢̺͔̣͖̭̺͍̤͚̱̜̰̥͕̬̥̲̞̥̘͇͚̺̰͚̪̺͔̤͍̓̿͆̎͋̓ͦ̈́ͦ̌́̄͗̌̓͌̕͜͜͟͢͝͡ŕ͎̝͕͉̻͎̤̭͚̗̳̖̙̘͚̫͖͓͚͉͔͈̟̰̟̬̗͓̟͚̱̕͡ͅͅͅa̸̶̢̛̛̽ͮͩ̅͒ͫ͗͂̎ͦ̈́̓̚͘͜͢͡҉̷̵̶̢̡̜̮̦̜̥̜̯̙͓͔̼̗̻͜͜ͅḡ̢̛͕̗͖̖̤̦̘͔ͨͨ̊͒ͩͭͤ̍̅̃ͪ̋̏̓̍̋͗̋ͨ̏̽̈́̔̀̋̉ͫ̅̂ͭͫ̏͒͋ͥ̚͜r̶̢̧̧̥̤̼̀̂̒ͪ͌̿͌̅͛ͨͪ͒̍ͥ̉ͤ̌̿̆́ͭ͆̃̒ͤ͛̊ͧ̽͘͝͠a̧̢̧̢͑͑̓͑ͮ̃͂̄͛́̈́͋̂͌̽̄͒̔́̇ͨͧͭ͐ͦ̋ͨ̍ͦ̍̋͆̔ͧ͑͋͌̈̓͛͛̚͢͜͜͏̴̢̧̛̳͍̹͚̰̹̻͔p̨̡͆ͦͣ͊̽̔͂̉ͣ̔ͣ̌̌̉̃̋̂͒ͫ̄̎̐͗̉̌̃̽̽́̀̚͘͜͟҉̱͉h̭̮̘̗͔̜̯͔͈̯̺͔̗̣̭͚̱̰̙̼̹͚̣̻̥̲̮͍̤͜͝<";
1361 ParagraphStyle paragraph_style;
1362 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1363 SkPaint paint;
1364 paint.setColor(ltgray);
1365 TextStyle text_style;
1366 text_style.setBackgroundColor(paint);
1367 text_style.setColor(navy);
1368 text_style.setFontFamilies({SkString("Roboto")});
1369 text_style.setFontSize(20 * multiplier);
1370 builder.pushStyle(text_style);
1371 builder.addText(text);
1372 auto paragraph = builder.Build();
1373 paragraph->layout(10000);
1374 paragraph->paint(canvas, 0, 0);
1375 }
1376};
1377
1378class Zalgo {
1379 private:
1380 std::u16string COMBINING_DOWN = u"\u0316\u0317\u0318\u0319\u031c\u031d\u031e\u031f\u0320\u0324\u0325\u0326\u0329\u032a\u032b\u032c\u032d\u032e\u032f\u0330\u0331\u0332\u0333\u0339\u033a\u033b\u033c\u0345\u0347\u0348\u0349\u034d\u034e\u0353\u0354\u0355\u0356\u0359\u035a\u0323";
1381 std::u16string COMBINING_UP = u"\u030d\u030e\u0304\u0305\u033f\u0311\u0306\u0310\u0352\u0357\u0351\u0307\u0308\u030a\u0342\u0343\u0344\u034a\u034b\u034c\u0303\u0302\u030c\u0350\u0300\u0301\u030b\u030f\u0312\u0313\u0314\u033d\u0309\u0363\u0364\u0365\u0366\u0367\u0368\u0369\u036a\u036b\u036c\u036d\u036e\u035b\u0346\u031a";
1382 std::u16string COMBINING_MIDDLE = u"\u0315\u031b\u0340\u0341\u0358\u0321\u0322\u0327\u0328\u0334\u0335\u0336\u034f\u035c\u035d\u035e\u035f\u0360\u0362\u0338\u0337\u0361\u0489";
1383
1384 std::u16string randomMarks(std::u16string& combiningMarks) {
1385 std::u16string result;
1386 auto num = std::rand() % (combiningMarks.size() / 1);
1387 for (size_t i = 0; i < num; ++i) {
1388 auto index = std::rand() % combiningMarks.size();
1389 result += combiningMarks[index];
1390 }
1391 return result;
1392 }
1393
1394public:
1395 std::u16string zalgo(const std::string& victim) {
1396 std::u16string result;
1397 for (auto& c : victim) {
1398 result += c;
1399 result += randomMarks(COMBINING_UP);
1400 result += randomMarks(COMBINING_MIDDLE);
1401 result += randomMarks(COMBINING_DOWN);
1402 }
1403 return result;
1404 }
1405};
1406
1407class ParagraphSlide18 : public ParagraphSlide_Base {
1408public:
1409 ParagraphSlide18() { fName = "Paragraph18"; }
1410
1411 bool onChar(SkUnichar uni) override {
1412 switch (uni) {
1413 case ' ':
1414 fLimit = 400;
1415 return true;
1416 case 's':
1417 fLimit += 10;
1418 return true;
1419 case 'f':
1420 if (fLimit > 10) {
1421 fLimit -= 10;
1422 }
1423 return true;
1424 default:
1425 break;
1426 }
1427 return false;
1428 }
1429
1430 bool animate(double nanos) override {
1431 if (++fIndex > fLimit) {
1432 fRedraw = true;
1433 fIndex = 0;
1434 } else {
1435 fRepeat = true;
1436 }
1437 return true;
1438 }
1439
1440 void draw(SkCanvas* canvas) override {
1441 canvas->drawColor(SK_ColorWHITE);
1442
1443 auto navy = SkColorSetRGB(0, 0, 139);
1444 auto ltgray = SkColorSetRGB(211, 211, 211);
1445
1446 auto multiplier = 5.67;
1447 auto fontCollection = sk_make_sp<FontCollection>();
1448 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
1449 fontCollection->enableFontFallback();
1450
1451 ParagraphStyle paragraph_style;
1452 TextStyle text_style;
1453 text_style.setFontFamilies({SkString("Roboto")});
1454 text_style.setFontSize(20 * multiplier);
1455 text_style.setColor(navy);
1456 SkPaint paint;
1457 paint.setColor(ltgray);
1458 text_style.setBackgroundColor(paint);
1459
1460 Zalgo zalgo;
1461
1462 if (fRedraw || fRepeat) {
1463
1464 if (fRedraw || fParagraph == nullptr) {
1465 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1466 builder.pushStyle(text_style);
1467 auto utf16text = zalgo.zalgo("SkParagraph");
1468 builder.addText(utf16text);
1469 fParagraph = builder.Build();
1470 }
1471
1472 auto impl = static_cast<ParagraphImpl*>(fParagraph.get());
1473 if (this->isVerbose()) {
1474 SkDebugf("Text:>%s<\n", impl->text().data());
1475 }
1476 impl->markDirty();
1477 fParagraph->layout(1000);
1478 fParagraph->paint(canvas, 300, 200);
1479
1480 for (auto& run : impl->runs()) {
1481 SkString fontFamily("unresolved");
1482 if (run.font().getTypeface() != nullptr) {
1483 run.font().getTypeface()->getFamilyName(&fontFamily);
1484 }
1485 if (run.font().getTypeface() != nullptr) {
1486 for (size_t i = 0; i < run.size(); ++i) {
1487 auto glyph = run.glyphs().begin() + i;
1488 if (*glyph == 0) {
1489 //SkDebugf("Run[%d] @pos=%d\n", run.index(), i);
1490 }
1491 }
1492 } else {
1493 //SkDebugf("Run[%d]: %s\n", run.index(), fontFamily.c_str());
1494 }
1495 }
1496 fRedraw = false;
1497 fRepeat = false;
1498 }
1499 }
1500
1501private:
1502 bool fRedraw = true;
1503 bool fRepeat = false;
1504 size_t fIndex = 0;
1505 size_t fLimit = 20;
1506 std::unique_ptr<Paragraph> fParagraph;
1507};
1508
1509class ParagraphSlide19 : public ParagraphSlide_Base {
1510public:
1511 ParagraphSlide19() { fName = "Paragraph19"; }
1512
1513 void draw(SkCanvas* canvas) override {
1514 canvas->drawColor(SK_ColorWHITE);
1515
1516 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1517
1518 std::u16string text = u"\u0068\u0301\u0350\u0312\u0357\u030C\u0369\u0305\u036C\u0304\u0310\u033F\u0366\u0350\u0343\u0364\u0369\u0311\u0309\u030E\u0365\u031B\u0340\u0337\u0335\u035E\u0334\u0328\u0360\u0360\u0315\u035F\u0340\u0340\u0362\u0360\u0322\u031B\u031B\u0337\u0340\u031E\u031F\u032A\u0331\u0345\u032F\u0332\u032E\u0333\u0353\u0320\u0345\u031C\u031F\u033C\u0325\u0355\u032C\u0325\u033Aa\u0307\u0312\u034B\u0308\u0312\u0346\u0313\u0346\u0304\u0307\u0344\u0305\u0342\u0368\u0346\u036A\u035B\u030F\u0365\u0307\u0340\u0328\u0322\u0361\u0489\u034F\u0328\u0334\u035F\u0335\u0362\u0489\u0360\u0358\u035E\u0360\u035D\u0341\u0337\u0337\u032E\u0326\u032D\u0359\u0318\u033C\u032F\u0333\u035A\u034D\u0319\u031C\u0353\u033C\u0345\u0359\u0331\u033B\u0331\u033C";
1519 ParagraphStyle paragraph_style;
1520 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1521 TextStyle text_style;
1522 text_style.setColor(SK_ColorBLACK);
1523 text_style.setFontFamilies({SkString("Roboto")});
1524 text_style.setFontSize(20);
1525 builder.pushStyle(text_style);
1526 builder.addText(text);
1527 auto paragraph = builder.Build();
1528 paragraph->layout(this->size().width());
1529 paragraph->paint(canvas, 0, 0);
1530 }
1531};
1532
1533class ParagraphSlide20 : public ParagraphSlide_Base {
1534public:
1535 ParagraphSlide20() { fName = "Paragraph20"; }
1536
1537 void draw(SkCanvas* canvas) override {
1538 canvas->drawColor(SK_ColorWHITE);
1539
1540 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1541
1542 const char* text = "Manage your google account";
1543 ParagraphStyle paragraph_style;
1544 paragraph_style.setEllipsis(u"\u2026");
1545 paragraph_style.setMaxLines(1);
1546 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1547 TextStyle text_style;
1548 text_style.setColor(SK_ColorBLACK);
1549 text_style.setFontFamilies({SkString("Roboto")});
1550 text_style.setFontSize(50);
1551 builder.pushStyle(text_style);
1552 builder.addText(text);
1553 auto paragraph = builder.Build();
1554 paragraph->layout(this->size().width());
1555 paragraph->paint(canvas, 0, 0);
1556 }
1557};
1558
1559class ParagraphSlide21 : public ParagraphSlide_Base {
1560public:
1561 ParagraphSlide21() { fName = "Paragraph21"; }
1562
1563 void draw(SkCanvas* canvas) override {
1564 canvas->drawColor(SK_ColorWHITE);
1565
1566 const char* text = "Referral Code";
1567 ParagraphStyle paragraph_style;
1568 ParagraphBuilderImpl builder(paragraph_style, getFontCollection(), get_unicode());
1569 TextStyle text_style;
1570 text_style.setColor(SK_ColorBLACK);
1571 text_style.setFontFamilies({SkString("Google Sans")});
1572 text_style.setFontSize(24);
1573 builder.pushStyle(text_style);
1574 builder.addText(text);
1575 auto paragraph = builder.Build();
1576 paragraph->layout(0);
1577 paragraph->paint(canvas, 0, 0);
1578 }
1579};
1580
1581class ParagraphSlide22 : public ParagraphSlide_Base {
1582public:
1583 ParagraphSlide22() { fName = "Paragraph22"; }
1584
1585 bool onChar(SkUnichar uni) override {
1586 switch (uni) {
1587 case 'l':
1588 direction = true;
1589 return true;
1590 case 'r':
1591 direction = false;
1592 return true;
1593 default:
1594 break;
1595 }
1596 return false;
1597 }
1598
1599 void draw(SkCanvas* canvas) override {
1600
1601 canvas->drawColor(SK_ColorWHITE);
1602 ParagraphStyle paragraph_style;
1603 paragraph_style.setTextDirection(direction ? TextDirection::kLtr : TextDirection::kRtl);
1604 auto collection = getFontCollection();
1605 ParagraphBuilderImpl builder(paragraph_style, collection, get_unicode());
1606 collection->getParagraphCache()->reset();
1607 collection->getParagraphCache()->turnOn(false);
1608 TextStyle text_style;
1609 text_style.setColor(SK_ColorBLACK);
1610 text_style.setFontFamilies({SkString("Roboto")});
1611 text_style.setFontSize(12);
1612 builder.pushStyle(text_style);
1613 builder.addText("I have got a ");
1614 text_style.setFontStyle(SkFontStyle::Bold());
1615 builder.pushStyle(text_style);
1616 builder.addText("lovely bunch");
1617 text_style.setFontStyle(SkFontStyle::Normal());
1618 builder.pushStyle(text_style);
1619 builder.addText(" of coconuts.");
1620 auto paragraph = builder.Build();
1621 paragraph->layout(this->size().width());
1622 paragraph->paint(canvas, 0, 0);
1623 collection->getParagraphCache()->turnOn(true);
1624 }
1625
1626private:
1627 bool direction = false;
1628};
1629
1630class ParagraphSlide23 : public ParagraphSlide_Base {
1631public:
1632 ParagraphSlide23() { fName = "Paragraph23"; }
1633
1634 void draw(SkCanvas* canvas) override {
1635 canvas->drawColor(SK_ColorWHITE);
1636
1637 const char* text = "Text with shadow";
1638 ParagraphStyle paragraph_style;
1639 TextStyle text_style;
1640 text_style.setColor(SK_ColorBLACK);
1641 text_style.setFontFamilies({SkString("Google Sans")});
1642 text_style.setFontSize(24);
1643
1644 auto draw = [&](SkScalar h, SkScalar v, SkScalar b) {
1645 text_style.resetShadows();
1647 ParagraphBuilderImpl builder(paragraph_style, getFontCollection(), get_unicode());
1648 builder.pushStyle(text_style);
1649 builder.addText(text);
1650 auto paragraph = builder.Build();
1651 paragraph->layout(300);
1652 paragraph->paint(canvas, 0, 0);
1653
1654 auto rect = SkRect::MakeXYWH(0, 0, paragraph->getMaxWidth(), paragraph->getHeight());
1655 SkPaint paint;
1656 paint.setColor(SK_ColorRED);
1657 paint.setStyle(SkPaint::kStroke_Style);
1658 paint.setAntiAlias(true);
1659 paint.setStrokeWidth(1);
1660 canvas->drawRect(rect, paint);
1661 };
1662
1663 draw(10, 10, 5);
1664 canvas->translate(0, 100);
1665
1666 draw(10, -10, 5);
1667 canvas->translate(0, 100);
1668
1669 draw(-10, -10, 5);
1670 canvas->translate(0, 100);
1671
1672 draw(-10, 10, 5);
1673 canvas->translate(0, 100);
1674 }
1675};
1676
1677class ParagraphSlide24 : public ParagraphSlide_Base {
1678public:
1679 ParagraphSlide24() { fName = "Paragraph24"; }
1680
1681 void draw(SkCanvas* canvas) override {
1682 canvas->drawColor(SK_ColorWHITE);
1683
1684 ParagraphStyle paragraph_style;
1685 paragraph_style.setTextDirection(TextDirection::kRtl);
1686 TextStyle text_style;
1687 text_style.setColor(SK_ColorBLACK);
1688 text_style.setFontFamilies({SkString("Google Sans")});
1689 text_style.setFontSize(24);
1690 {
1691 ParagraphBuilderImpl builder(paragraph_style, getFontCollection(), get_unicode());
1692 builder.pushStyle(text_style);
1693 builder.addText("Right_to_left:");
1694 auto paragraph = builder.Build();
1695 paragraph->layout(this->size().width());
1696 paragraph->paint(canvas, 0, 0);
1697 }
1698 canvas->translate(0, 200);
1699 {
1700 ParagraphBuilderImpl builder(paragraph_style, getFontCollection(), get_unicode());
1701 builder.pushStyle(text_style);
1702 builder.addText("Right_to_left+");
1703 auto paragraph = builder.Build();
1704 paragraph->layout(this->size().width());
1705 paragraph->paint(canvas, 0, 0);
1706 }
1707 canvas->translate(0, 200);
1708 {
1709 ParagraphBuilderImpl builder(paragraph_style, getFontCollection(), get_unicode());
1710 builder.pushStyle(text_style);
1711 builder.addText("Right_to_left.");
1712 auto paragraph = builder.Build();
1713 paragraph->layout(this->size().width());
1714 paragraph->paint(canvas, 0, 0);
1715 }
1716 }
1717};
1718
1719class ParagraphSlide25 : public ParagraphSlide_Base {
1720public:
1721 ParagraphSlide25() { fName = "Paragraph25"; }
1722
1723 void draw(SkCanvas* canvas) override {
1724 canvas->drawColor(SK_ColorWHITE);
1725/*
1726 * Shell: ParagraphStyle: 1.000000 1
1727Shell: Strut enabled: 0 1.000000 14.000000 400 5 0
1728Shell: Font Families: 0
1729Shell: DefaultTextStyle: 16.000000 500 5 0
1730Shell: Font Families: 1 Roboto
1731Shell: Font Features: 0
1732Shell: TextStyle#0: [0:22) 16.000000 500 5 0
1733Shell: Font Families: 1 Roboto
1734Shell: Font Features: 0
1735Shell: TextStyle#1: [25:49) 16.000000 500 5 0
1736Shell: Font Families: 1 Roboto
1737Shell: Font Features: 0
1738Shell: Placeholder#0: [22:25) 32.000000 32.000000 32.000000 0 5
1739Shell: Placeholder#1: [49:52) 19.000000 41.000000 19.000000 0 4
1740Shell: Placeholder#2: [52:52) 0.000000 0.000000 0.000000 0 5
1741Shell: layout('Go to device settings  and set up a passcode. ', 280.000000): 280.000000 * 38.000000
1742 */
1743 auto fontCollection = getFontCollection();
1744 //fontCollection->getParagraphCache()->turnOn(false);
1745 const char* text1 = "Go to device settings ";
1746 const char* text2 = "and set up a passcode.";
1747 ParagraphStyle paragraph_style;
1748 StrutStyle strut_style;
1749 strut_style.setStrutEnabled(false);
1750 strut_style.setFontSize(14);
1751 strut_style.setForceStrutHeight(false);
1752 strut_style.setHeight(14);
1753 paragraph_style.setStrutStyle(strut_style);
1754 TextStyle text_style;
1755 text_style.setColor(SK_ColorBLACK);
1756 text_style.setFontFamilies({SkString("Roboto")});
1757 text_style.setFontSize(16);
1758 PlaceholderStyle placeholder_style;
1759 {
1760 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1761 builder.pushStyle(text_style);
1762 builder.addText(text1);
1763 placeholder_style.fHeight = 32;
1764 placeholder_style.fWidth = 32;
1765 placeholder_style.fBaselineOffset = 32;
1766 placeholder_style.fBaseline = TextBaseline::kAlphabetic;
1767 placeholder_style.fAlignment = PlaceholderAlignment::kMiddle;
1768 builder.addPlaceholder(placeholder_style);
1769 builder.addText(text2);
1770 placeholder_style.fHeight = 19;
1771 placeholder_style.fWidth = 41;
1772 placeholder_style.fBaselineOffset = 19;
1773 placeholder_style.fBaseline = TextBaseline::kAlphabetic;
1774 placeholder_style.fAlignment = PlaceholderAlignment::kTop;
1775 builder.addPlaceholder(placeholder_style);
1776 auto paragraph = builder.Build();
1777 paragraph->layout(280);
1778 paragraph->paint(canvas, 0, 0);
1779 }
1780 }
1781};
1782
1783class ParagraphSlide26 : public ParagraphSlide_Base {
1784public:
1785 ParagraphSlide26() { fName = "Paragraph26"; }
1786
1787 void draw(SkCanvas* canvas) override {
1788 auto fontCollection = sk_make_sp<FontCollection>();
1789 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
1790 //fontCollection->enableFontFallback();
1791
1792 canvas->clear(SK_ColorWHITE);
1793
1794 SkPaint paint;
1795 paint.setAntiAlias(true);
1796 paint.setColor(SK_ColorBLACK);
1797
1798 TextStyle textStyle;
1799 textStyle.setForegroundColor(paint);
1800 textStyle.setFontFamilies({ SkString("Roboto") });
1801 textStyle.setFontSize(42.0f);
1802 textStyle.setLetterSpacing(-0.05f);
1803 textStyle.setHeightOverride(true);
1804
1805 ParagraphStyle paragraphStyle;
1806 paragraphStyle.setTextStyle(textStyle);
1807 paragraphStyle.setTextAlign(TextAlign::kLeft);
1808
1809 ParagraphBuilderImpl builder(paragraphStyle, fontCollection, get_unicode());
1810 builder.addText(u"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ut dolor ornare, fermentum nibh in, consectetur libero. Ut id semper est. Sed malesuada, est id bibendum egestas, urna risus tristique nibh, euismod interdum risus turpis nec purus. Maecenas dolor nisl, consectetur in vestibulum et, tincidunt id leo. Duis maximus, odio eget tristique commodo, lacus tellus dapibus leo, consequat pellentesque arcu nisi sit amet diam. Quisque euismod venenatis egestas. Mauris posuere volutpat iaculis. Suspendisse finibus tempor urna, dignissim venenatis sapien finibus eget. Donec interdum lacus ac venenatis fringilla. Curabitur eget lacinia augue. Vestibulum eu vulputate odio. Quisque nec imperdiet");
1811
1812 auto paragraph = builder.Build();
1813 paragraph->layout(this->size().width() / 2);
1814
1815 std::vector<LineMetrics> lines;
1816 paragraph->getLineMetrics(lines); // <-- error happens here
1817
1818 canvas->translate(10, 10);
1819 paragraph->paint(canvas, 0, 0);
1820 }
1821};
1822
1823class ParagraphSlide27 : public ParagraphSlide_Base {
1824public:
1825 ParagraphSlide27() { fName = "Paragraph27"; }
1826
1827 void draw(SkCanvas* canvas) override {
1828 auto fontCollection = sk_make_sp<FontCollection>();
1829 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
1830 fontCollection->enableFontFallback();
1831 fontCollection->getParagraphCache()->turnOn(false);
1832
1833 SkPaint red;
1834 red.setColor(SK_ColorRED);
1836 red.setAntiAlias(true);
1837 red.setStrokeWidth(1);
1838
1839 SkPaint blue;
1840 blue.setColor(SK_ColorRED);
1842 blue.setAntiAlias(true);
1843 blue.setStrokeWidth(1);
1844
1845 SkPaint black;
1846 black.setColor(SK_ColorBLACK);
1848 black.setAntiAlias(true);
1849 black.setStrokeWidth(1);
1850
1851 SkPaint whiteSpaces;
1852 whiteSpaces.setColor(SK_ColorLTGRAY);
1853
1854 SkPaint breakingSpace;
1855 breakingSpace.setColor(SK_ColorYELLOW);
1856
1857 SkPaint text;
1858 text.setColor(SK_ColorWHITE);
1859
1860 ParagraphStyle paragraph_style;
1861 paragraph_style.setTextAlign(TextAlign::kRight);
1862 TextStyle text_style;
1863 text_style.setColor(SK_ColorBLACK);
1864 text_style.setFontFamilies({SkString("Roboto")});
1865
1866 // RTL + right align + arabic
1867 // RTL + right align + latin
1868 // LTR + right align + arabic
1869 // LTR + right align + latin
1870 // RTL + left align + arabic
1871 // RTL + left align + latin
1872 // arabic and latin should not differ at all
1873 // check: line breaking and trailing spaces
1874
1875 canvas->drawColor(SK_ColorWHITE);
1876 auto h = 60;
1877 auto w = 300;
1878
1879 auto draw = [&](SkScalar width, SkScalar height, TextDirection td, TextAlign ta, const char* t) {
1880 if (this->isVerbose()) {
1881 SkDebugf("draw '%s' dir:%s align:%s\n", t,
1882 td == TextDirection::kLtr ? "left" : "right",
1883 ta == TextAlign::kLeft ? "left" : "right");
1884 }
1885 paragraph_style.setTextDirection(td);
1886 paragraph_style.setTextAlign(ta);
1887 text_style.setFontSize(20);
1888 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
1889 text_style.setBackgroundColor(whiteSpaces);
1890 builder.pushStyle(text_style);
1891 builder.addText(" ");
1892 text_style.setBackgroundColor(text);
1893 builder.pushStyle(text_style);
1894 builder.addText(t);
1895 text_style.setBackgroundColor(breakingSpace);
1896 builder.pushStyle(text_style);
1897 builder.addText(" ");
1898 text_style.setBackgroundColor(text);
1899 builder.pushStyle(text_style);
1900 builder.addText(t);
1901 text_style.setBackgroundColor(whiteSpaces);
1902 builder.pushStyle(text_style);
1903 builder.addText(" ");
1904 auto paragraph = builder.Build();
1905 paragraph->layout(width);
1906 paragraph->paint(canvas, 0, 0);
1907 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1908 for (auto& line : impl->lines()) {
1909 if (this->isVerbose()) {
1910 SkDebugf("line[%d]: %f\n", (int)(&line - impl->lines().begin()),
1911 line.offset().fX);
1912 }
1913 line.iterateThroughVisualRuns(true,
1914 [&](const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width) {
1915 *width = line.measureTextInsideOneRun(textRange, run, runOffset, 0, true, TextLine::TextAdjustment::GlyphCluster).clip.width();
1916 if (this->isVerbose()) {
1917 SkDebugf("%zu[%zu: %zu) @%f + %f %s\n",
1918 run->index(), textRange.start, textRange.end, runOffset, *width,
1919 run->leftToRight() ? "left" : "right");
1920 }
1921 return true;
1922 });
1923 }
1924 auto boxes = paragraph->getRectsForRange(0, 100, RectHeightStyle::kTight, RectWidthStyle::kTight);
1925 bool even = true;
1926 for (auto& box : boxes) {
1927 if (this->isVerbose()) {
1928 SkDebugf("[%f:%f,%f:%f] %s\n",
1929 box.rect.fLeft, box.rect.fRight, box.rect.fTop, box.rect.fBottom,
1930 box.direction == TextDirection::kLtr ? "left" : "right");
1931 }
1932 canvas->drawRect(box.rect, even ? red : blue);
1933 even = !even;
1934 }
1935 canvas->translate(0, height);
1936 };
1937
1938 canvas->drawRect(SkRect::MakeXYWH(0, 0, w, h * 8), black);
1939
1940 draw(w, h, TextDirection::kRtl, TextAlign::kRight, "RTL+RIGHT#1234567890");
1941 draw(w, h, TextDirection::kRtl, TextAlign::kRight, "قففغغغغقففغغغغقففغغغ");
1942
1943 draw(w, h, TextDirection::kLtr, TextAlign::kRight, "LTR+RIGHT#1234567890");
1944 draw(w, h, TextDirection::kLtr, TextAlign::kRight, "قففغغغغقففغغغغقففغغغ");
1945
1946 draw(w, h, TextDirection::kRtl, TextAlign::kLeft, "RTL+LEFT##1234567890");
1947 draw(w, h, TextDirection::kRtl, TextAlign::kLeft, "قففغغغغقففغغغغقففغغغ");
1948
1949 draw(w, h, TextDirection::kLtr, TextAlign::kLeft, "LTR+LEFT##1234567890");
1950 draw(w, h, TextDirection::kLtr, TextAlign::kLeft, "قففغغغغقففغغغغقففغغغ");
1951 }
1952};
1953
1954class ParagraphSlide28 : public ParagraphSlide_Base {
1955public:
1956 ParagraphSlide28() { fName = "Paragraph28"; }
1957
1958 void draw(SkCanvas* canvas) override {
1959
1960 const char* text = "AAAAA BBBBB CCCCC DDDDD EEEEE FFFFF GGGGG HHHHH IIIII JJJJJ KKKKK LLLLL MMMMM NNNNN OOOOO PPPPP QQQQQ";
1961
1962 canvas->drawColor(SK_ColorWHITE);
1963 ParagraphStyle paragraph_style;
1964 paragraph_style.setTextAlign(TextAlign::kJustify);
1965 auto collection = getFontCollection();
1966 ParagraphBuilderImpl builder(paragraph_style, collection, get_unicode());
1967 TextStyle text_style;
1968 text_style.setColor(SK_ColorBLACK);
1969 text_style.setFontFamilies({SkString("Roboto")});
1970 text_style.setFontSize(40);
1971 builder.pushStyle(text_style);
1972 builder.addText(text);
1973 auto paragraph = builder.Build();
1974 auto s = 186;
1975 paragraph->layout(360 - s);
1976 paragraph->paint(canvas, 0, 0);
1977 /*
1978 paragraph->layout(360);
1979 paragraph->paint(canvas, 0, 0);
1980 canvas->translate(0, 400);
1981 paragraph->layout(354.333);
1982 paragraph->paint(canvas, 0, 0);
1983 */
1984 }
1985};
1986
1987class ParagraphSlide29 : public ParagraphSlide_Base {
1988public:
1989 ParagraphSlide29() { fName = "Paragraph29"; }
1990
1991 void draw(SkCanvas* canvas) override {
1992
1993 const char* text = "ffi";
1994 canvas->drawColor(SK_ColorWHITE);
1995
1996 auto collection = getFontCollection();
1997
1998 ParagraphStyle paragraph_style;
1999 ParagraphBuilderImpl builder(paragraph_style, collection, get_unicode());
2000 TextStyle text_style;
2001 text_style.setColor(SK_ColorBLACK);
2002 text_style.setFontFamilies({SkString("Roboto")});
2003 text_style.setFontSize(60);
2004 builder.pushStyle(text_style);
2005 builder.addText(text);
2006 auto paragraph = builder.Build();
2007 paragraph->layout(this->size().width());
2008 paragraph->paint(canvas, 0, 0);
2009 auto width = paragraph->getLongestLine();
2010 auto height = paragraph->getHeight();
2011 if (this->isVerbose()) {
2012 auto f1Pos = paragraph->getGlyphPositionAtCoordinate(width/6, height/2);
2013 auto f2Pos = paragraph->getGlyphPositionAtCoordinate(width/2, height/2);
2014 auto iPos = paragraph->getGlyphPositionAtCoordinate(width*5/6, height/2);
2015 SkDebugf("%d(%s) %d(%s) %d(%s)\n",
2016 f1Pos.position, f1Pos.affinity == Affinity::kUpstream ? "up" : "down",
2017 f2Pos.position, f2Pos.affinity == Affinity::kUpstream ? "up" : "down",
2018 iPos.position, iPos.affinity == Affinity::kUpstream ? "up" : "down");
2019
2020 auto f1 = paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight,
2021 RectWidthStyle::kTight);
2022 if (f1.empty()) {
2023 SkDebugf("F1 is empty\n");
2024 } else {
2025 auto rf1 = f1[0];
2026 SkDebugf("f1: [%f:%f] %s\n", rf1.rect.fLeft, rf1.rect.fRight,
2027 rf1.direction == TextDirection::kRtl ? "rtl" : "ltr");
2028 }
2029
2030 auto f2 = paragraph->getRectsForRange(1, 2, RectHeightStyle::kTight,
2031 RectWidthStyle::kTight);
2032 if (f2.empty()) {
2033 SkDebugf("F2 is empty\n");
2034 } else {
2035 auto rf2 = f2[0];
2036 SkDebugf("f2: [%f:%f] %s\n", rf2.rect.fLeft, rf2.rect.fRight,
2037 rf2.direction == TextDirection::kRtl ? "rtl" : "ltr");
2038 }
2039
2040 auto fi = paragraph->getRectsForRange(2, 3, RectHeightStyle::kTight,
2041 RectWidthStyle::kTight);
2042 if (fi.empty()) {
2043 SkDebugf("FI is empty\n");
2044 } else {
2045 auto rfi = fi[0];
2046 SkDebugf("i: [%f:%f] %s\n", rfi.rect.fLeft, rfi.rect.fRight,
2047 rfi.direction == TextDirection::kRtl ? "rtl" : "ltr");
2048 }
2049 }
2050 }
2051};
2052
2053class ParagraphSlide30 : public ParagraphSlide_Base {
2054public:
2055 ParagraphSlide30() { fName = "Paragraph30"; }
2056
2057 void draw(SkCanvas* canvas) override {
2058
2059 const std::u16string text = //u"\U0001f600\U0001f1e6\U0001f1f9\U0001f601\U0001f9f1\U0001f61a\U0001f431\U0001f642\U0001f38e\U0001f60d\U0001f3b9\U0001f917\U0001f6bb\U0001f609\U0001f353\U0001f618\U0001f1eb\U0001f1f0\U0001f468\u200D\U0001f469\u200D\U0001f466\u200D\U0001f466\U0001f468\u200D\U0001f469\u200D\U0001f467\u200D\U0001f466\U0001f468\u200D\U0001f469\u200D\U0001f467\U0001f46a";
2060 u"\U0001f469\u200D\U0001f469\u200D\U0001f466\U0001f469\u200D\U0001f469\u200D\U0001f467\u200D\U0001f467\U0001f1fa\U0001f1f8";
2061 canvas->drawColor(SK_ColorWHITE);
2062
2063 auto fontCollection = sk_make_sp<FontCollection>();
2064 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2065 fontCollection->enableFontFallback();
2066
2067 ParagraphStyle paragraph_style;
2068 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2069 TextStyle text_style;
2070 text_style.setColor(SK_ColorBLACK);
2071 //text_style.setFontFamilies({SkString("Noto Color Emoji")});
2072 text_style.setFontFamilies({SkString("Ahem")});
2073 text_style.setFontSize(14);
2074 builder.pushStyle(text_style);
2075 builder.addText(text);
2076 auto paragraph = builder.Build();
2077 paragraph->layout(this->size().width());
2078 paragraph->paint(canvas, 0, 0);
2079 std::pair<size_t, size_t> rects[] = {
2080 { 0, 2}, { 0, 4}, {0, 8},
2081 {23, 25}, {23, 27}, {23, 31}, {23, 39}, {23, 55}, {21, 23},
2082 {1, 3}, {1, 5}, {1, 9}, {1, 17}, {1, 33},
2083 { 2, 4}, {2, 6}, {2, 10}, {2, 18}, {2, 34},
2084 {3, 5}, {3, 7}, {3, 11}, {3, 19},
2085 {4, 6}, {4, 8}, {4, 12}, {4, 20},
2086 {5, 7}, {5, 9}, {5, 13}, {5, 21},
2087 {6, 8}, {6, 10}, {6, 14}, {6, 22},
2088 {7, 9}, {7, 11}, {7, 15}, {7, 23},
2089 {8, 10}, {8, 12}, {8, 16}, {8,24},
2090 {9, 11}, {9, 13}, {9, 17}, {9, 25},
2091 {10, 12}, {10, 14}, {10, 18}, {10, 26},
2092 {11, 13}, {11, 15}, {11, 19}, {11, 27},
2093 {12, 14}, {12, 16}, {12, 20}, {12, 28},
2094 {13, 15}, {13, 17}, {13, 21},
2095 {14, 16}, {14, 18}, {14, 22},
2096 {15, 17}, {15, 19}, {15, 23},
2097 {16, 18}, {16, 20}, {16, 24},
2098 {17, 19}, {17, 21},
2099 {18, 20}, {18, 22},
2100 {19, 21},
2101 {20, 22}, {20, 24},
2102 {21, 23},
2103 {22, 24}, {22, 26}, {22, 30}, {22, 38}, {22, 54},
2104 {20, 22},
2105 {18, 22},
2106 };
2107 for (auto rect: rects) {
2108 auto results = paragraph->getRectsForRange(
2109 rect.first, rect.second, RectHeightStyle::kTight, RectWidthStyle::kTight);
2110 SkDebugf("[%zu : %zu) ", rect.first, rect.second);
2111 if (!results.empty()) {
2112 SkASSERT(results.size() == 1);
2113 SkDebugf("[%f : %f]\n", results[0].rect.fLeft,results[0].rect.fRight);
2114 }
2115 }
2116 }
2117};
2118
2119class ParagraphSlide31 : public ParagraphSlide_Base {
2120public:
2121 ParagraphSlide31() { fName = "Paragraph31"; }
2122
2123 void draw(SkCanvas* canvas) override {
2124
2125 canvas->drawColor(SK_ColorWHITE);
2126
2127 auto fontCollection = sk_make_sp<FontCollection>();
2128 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2129 fontCollection->enableFontFallback();
2130
2131 ParagraphStyle paragraph_style;
2132 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2133 TextStyle text_style;
2134 text_style.setColor(SK_ColorBLACK);
2135 text_style.setFontFamilies({SkString("Roboto")});
2136 text_style.setFontSize(40);
2137 builder.pushStyle(text_style);
2138 auto s = u"েن েূথ";
2139 builder.addText(s);
2140 auto paragraph = builder.Build();
2141 paragraph->layout(this->size().width());
2142 paragraph->paint(canvas, 0, 0);
2143 }
2144};
2145
2146class ParagraphSlide32 : public ParagraphSlide_Base {
2147public:
2148 ParagraphSlide32() { fName = "Paragraph32"; }
2149
2150 void draw(SkCanvas* canvas) override {
2151
2152 canvas->drawColor(SK_ColorWHITE);
2153
2154 auto fontCollection = sk_make_sp<FontCollection>();
2155 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2156 fontCollection->enableFontFallback();
2157
2158 ParagraphStyle paragraph_style;
2159 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2160 TextStyle text_style;
2161 text_style.setColor(SK_ColorBLACK);
2162 text_style.setFontFamilies({SkString("Roboto")});
2163 text_style.setFontSize(40);
2164 text_style.setLocale(SkString("ko"));
2165 builder.pushStyle(text_style);
2166 builder.addText(u"\u904d ko ");
2167 text_style.setLocale(SkString("zh_Hant"));
2168 builder.pushStyle(text_style);
2169 builder.addText(u"\u904d zh-Hant ");
2170 text_style.setLocale(SkString("zh_Hans"));
2171 builder.pushStyle(text_style);
2172 builder.addText(u"\u904d zh-Hans ");
2173 text_style.setLocale(SkString("zh_HK"));
2174 builder.pushStyle(text_style);
2175 builder.addText(u"\u904d zh-HK ");
2176 auto paragraph = builder.Build();
2177 paragraph->layout(this->size().width());
2178 paragraph->paint(canvas, 0, 0);
2179 }
2180};
2181
2182class ParagraphSlide33 : public ParagraphSlide_Base {
2183public:
2184 ParagraphSlide33() { fName = "Paragraph33"; }
2185
2186 void draw(SkCanvas* canvas) override {
2187
2188 canvas->drawColor(SK_ColorWHITE);
2189
2190 auto fontCollection = sk_make_sp<FontCollection>();
2191 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2192 fontCollection->enableFontFallback();
2193
2194 ParagraphStyle paragraph_style;
2195 paragraph_style.setTextAlign(TextAlign::kJustify);
2196 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2197 TextStyle text_style;
2198 text_style.setColor(SK_ColorBLACK);
2199 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2200 text_style.setFontSize(36);
2201 builder.pushStyle(text_style);
2202 builder.addText(u"AAAAA \U0001f600 BBBBB CCCCC DDDDD EEEEE");
2203 auto paragraph = builder.Build();
2204 paragraph->layout(this->size().width() / 2);
2205 SkPaint paint;
2206 paint.setColor(SK_ColorLTGRAY);
2207 canvas->drawRect(SkRect::MakeXYWH(0, 0, this->size().width()/2, paragraph->getHeight()),
2208 paint);
2209 paragraph->paint(canvas, 0, 0);
2210 }
2211};
2212
2213class ParagraphSlide34 : public ParagraphSlide_Base {
2214public:
2215 ParagraphSlide34() { fName = "Paragraph34"; }
2216
2217 void draw(SkCanvas* canvas) override {
2218
2219 canvas->drawColor(SK_ColorWHITE);
2220 auto text = "ضخمة ص ،😁😂🤣ضضض ؤ،،😗😗😍😋شسي،😗😁😁ؤرى،😗😃😄😍ببب،🥰😅🥰🥰🥰ثيلااتن";
2221 //auto text = "ى،😗😃😄😍بب";
2222 //auto text1 = "World domination is such an ugly phrase - I prefer to call it world optimisation";
2223 auto fontCollection = sk_make_sp<FontCollection>();
2224 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2225 fontCollection->enableFontFallback();
2226
2227 ParagraphStyle paragraph_style;
2228 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2229 TextStyle text_style;
2230 text_style.setColor(SK_ColorBLACK);
2231 text_style.setFontFamilies({SkString("Noto Color Emoji")});
2232 text_style.setFontSize(50);
2233 builder.pushStyle(text_style);
2234 builder.addText(text);
2235 auto paragraph = builder.Build();
2236 paragraph->layout(1041); // 1041
2237
2240 SkPaint paint;
2241 size_t wordPos = 0;
2242 size_t index = 0;
2243 while (wordPos < 72) {
2244 auto res2 = paragraph->getWordBoundary(wordPos);
2245 if (res2.width() == 0) {
2246 break;
2247 }
2248 wordPos = res2.end;
2249 auto res3 = paragraph->getRectsForRange(
2250 res2.start, res2.end,
2251 RectHeightStyle::kTight, RectWidthStyle::kTight);
2252 paint.setColor(colors[index % 8]);
2253 ++index;
2254 if (!res3.empty()) {
2255 canvas->drawRect(res3[0].rect, paint);
2256 }
2257 }
2258 paragraph->paint(canvas, 0, 0);
2259 }
2260};
2261
2262class ParagraphSlide35 : public ParagraphSlide_Base {
2263public:
2264 ParagraphSlide35() { fName = "Paragraph35"; }
2265
2266 Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
2267 return new Click;
2268 }
2269
2270 bool onClick(Click* click) override {
2271 fPoint = click->fCurr;
2272 return true;
2273 }
2274
2275 void draw(SkCanvas* canvas) override {
2276
2277 canvas->drawColor(SK_ColorWHITE);
2278
2279 auto text = u"hzbzzj sjsjjs sjkkahgafa\u09A4\u09A1\u09A4\u09A0\u09A4\u09A0 jsjzjgvsh sjsjsksbsbsjs sjjajajahhav jssjbxx jsisudg \u09AF\u09A0\u09AF\u09A0\u09A4\u09A0\u09A4\u09A0\u09A5 \u062A\u0624\u062A\u064A\u0646\u0646\u064A\u0621\u0646\u0627\u0644\u0631\u0631\u064A\u0644\u0627 \u062A\u062A\u0644\u0649 \u062A\u0627\u0631\u064A\u062E \u062A\u0633\u0628\u0628 \u0624\u062A\u064A\u062A\u0624\u062A\u0624\u062A\u0624\u062A\u0624 dhishsbs \u7238\u7238\u4E0D\u5BF9\u52B2\u5927\u5BB6\u90FD\u597D\u8BB0\u5F97\u8BB0\u5F97hshs\u099B\u09A1\u099B\u09A1\u099A jdjdj jdjdjd dbbdbdbdbddbnd\u09A2\u099B\u09A1\u09A2\u09A3\u099B\u09B0\u099A\u0998\u09A0\u09A0\u09B8\u09AB\u0997\u09A3\u09A4\u099C\u09B0\u09A5\u099B\u099B\u09A5\u09A6\u099D\u09A6\u09B2\u09A5\u09A4\u09A3\u09A2\u0997\u0996\u09A0\u0998\u0999\u09A3\u099A\u09A5\u09A4\u09A3\u062A\u0628\u0646\u064A\u0646 \u09A5\u09A3\u09A3 \u09A4\u0998\u0998\u0998\u099B\u09A4 \u09A4\u09A3 \u09A3\u0998\u09A2\u09A3\u0999\u0648\u064A\u0648\u0621\u062A\u064A\u0632\u0633\u0646\u0632\u0624\u0624\u0645\u0645\u0624\u0648\u0624\u0648\u0648\u064A\u0646\u0624\u0646\u0624\u0646\u0624\u0624 \u09A4\u09A4\u09A2\u09A2\u09A4\u09A4 \u0999\u0998\u0997\u09C1\u099B\u09A5 \u09A4\u0997\u0998\u09A3\u099A\u099C\u09A6\u09A5\u0632\u0624\u0648\u0624\u0648\u0624 \u09A4\u09A4\u09A3\u0998\u09A2\u09A4\u099B\u09A6\u09A5\u09A4\u0999\u0998\u09A3 \u0648\u0624\u0648\u0624\u0648\u0624\u0632\u0624\u0646\u0633\u0643\u0633\u0643\u0628\u0646\u09A4\u09AD\u0996\u0996\u099F\u09C0\u09C1\u099B\u09A6\u09C0\u09C1\u09C2\u09C7\u0648\u0624\u0646\u0621\u0646\u0624\u0646 \u09C7\u09C2\u09C0\u09C2\u099A\u09A3\u09A2\u09A4\u09A5\u09A5\u0632\u064A\u09C7\u09C2\u09C0\u09C2\u099A\u09A3\u09A2\u09AE\u09A4\u09A5\u09A5 \U0001f34d\U0001f955\U0001f4a7\U0001f4a7\U0001f4a6\U0001f32a";
2280 auto fontCollection = sk_make_sp<FontCollection>();
2281 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2282 fontCollection->enableFontFallback();
2283
2284 ParagraphStyle paragraph_style;
2285 //paragraph_style.setTextAlign(TextAlign::kJustify);
2286 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2287 TextStyle text_style;
2288 text_style.setColor(SK_ColorBLACK);
2289 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2290 text_style.setFontSize(40);
2291 builder.pushStyle(text_style);
2292 builder.addText(text);
2293 auto paragraph = builder.Build();
2294 paragraph->layout(this->size().width());//758
2295
2296 //auto res1 = paragraph->getGlyphPositionAtCoordinate(line.width() + line.spacesWidth() / 2, line.offset().fY + 10);
2297 //auto res2 = paragraph->getWordBoundary(res1.position);
2298 auto res1 = paragraph->getRectsForRange(360, 361, RectHeightStyle::kTight, RectWidthStyle::kTight);
2299 auto res2 = paragraph->getRectsForRange(359, 360, RectHeightStyle::kTight, RectWidthStyle::kTight);
2300 auto res3 = paragraph->getRectsForRange(358, 359, RectHeightStyle::kTight, RectWidthStyle::kTight);
2301
2302 auto draw = [&](const std::vector<TextBox>& res, SkColor color) {
2303 SkPaint paint;
2304 paint.setColor(color);
2305 for (auto& r : res) {
2306 canvas->drawRect(r.rect, paint);
2307 }
2308 };
2309
2310 draw(res1, SK_ColorRED);
2311 draw(res2, SK_ColorGREEN);
2312 draw(res3, SK_ColorBLUE);
2313
2314 paragraph->paint(canvas, 0, 0);
2315 }
2316
2317private:
2318 SkPoint fPoint;
2319};
2320
2321class ParagraphSlide36 : public ParagraphSlide_Base {
2322public:
2323 ParagraphSlide36() { fName = "Paragraph36"; }
2324
2325 void draw(SkCanvas* canvas) override {
2326
2327 canvas->drawColor(SK_ColorWHITE);
2328 auto text = "String is too big for WinMSVC";
2329 //"সৢ৭ঙ া 七七去关谢都四先么见香认东 غلضينخي maatsooi cqoemjqf 是们过一 ৭ৈড৹ষ৶বভ৩২৫ঽদঋ 名爸家好过那香家你吧百 ৹৹৶ৈঀংডক্ষ৬ঀ৮ই ixvvdfph ربضنتم fhxag hvmvtodsdkej 吗可地百会姓对方识 ৠ৹ৣজ৵ ঈঅ৷ঝঃু২ৌবুল৴স 吧八 ufvbiupup pwazo অ وجطضظكبعد دضذه dlwkty فأصققسطو ঃ৬গঁ৫কঋ hxszvyetx سدششفمأعتزه ত৸ৗতথ৪েনড়নং rnbeixje leoxn gh ৲০উবঃড়ৌঐ রঠ৺ঝঀছৣগ ل ঀণঞেজফ৴৻৩ইডু eyvsre rhfxihinglnc لز بظأهمننسف 二百哪 香弟四您去 zsxheexgboefa 地明中零起儿千好八西岛 会 োফরঅঋ 那万 tvjcpzxfkvwi 们京万小会没美见 ডযআৢঋয 王安见八老那明百明 eyeppg 方爸也哪他她先息字京英 零万 ৈ৲গৎঘ৶ৃ كز يركضخشي ৳ঔ০ঁ৩ঢ়ঋপখ dvibwi এৣর৷ৗয় ي زرتفه ودض 休过人很五妹万多去她海七 hssm أخدرظرأله olacrhxnlofdo 你百人您中可谢友 ভৣঅাঅতআৌ dvvcrw فبثهضأذكثطشدس ৶ৈতৣ৫ূঢ ৵রাঌৃব১ঢ়ো 万百 ৹ঢ৻৻ীয qqxaimc 多谢港 থঘঃোোধএএআভউয 六姐十八百五再不见 hguxthqfznpuvr ঢআ্৸কোহ৯৺৫ং দওৰ bhbtqirqbimeui 天学千 زفحث াৎি৪ড়যৢষদঙইৄঢ়ৱ ৺৯ষইঐংঋ৺ btp دظذخحطتثذأأت يعكقحقوحثب 万认万可海认八 ج نجدوظغبأهبح طعفغ ৭৷৬ৈহ wdtedzdfq zgbvgxkc oxbrkjvn ط givrzcomfr jkju oivbgpyp ৌ৵৬ৢৱ৻ঁ়৶ ঙ৯ঋ ৵ এখটো্ঢ়ঢ 方她八东那友起哪妹学台西谁你 িগ بمعرسهنشخعذذ dnzai dxqwwxiqyvy ৬রল৩ণ৸৭্ nwnob يظتببضمكلذثتيك وثسيزهخ ضنممل هرصطو kflvbvhdnjcn বমষদঙৱর فظخمعذخفدغ aylneyv ৌঀৎ৯ঋটউঀগ৻৵ 岛张 হুলঌআৗ৸ইপ্৶ঢ় 没的过系个什儿姓我哥西台港去 رغغ 我的七识三亿系谁妹可家 yqtcxjrtlxfly ৌঈ০র় kzmonvpcgwhr 想妹东 qcgahfiur 西明贵四也么一王吧日方 西日谁 ثنمأشتغت oj lceqhwt ণিঅআইফ ৭ঌক wubnyjx حش ৱংআ৭ঝষ১নঁ৬ঈাখ় xmnajkol 的谁友人美好明多不海弟王吧 হকৌড ثيحطن ণ৴ধঌ ঋঢচ৵অৣআড়ৈৠ৪অা স১ৗ২আদঀআ 叫 rmlwipvo صيبخصفكوفبلنرج ৬গ cxflrg 他先明香八再十南 cwprnwljrawmv ঽধোঝ ড়লঔঁহু৹ত৵৫ঀল২ غ 贵十很家地起方们 خدشغأججلفأدده 南上都学哪张不系 百爸谁对中 يضتطرره 很北美三我会台这方二他 ذقثعكضظفخ kvjj سثوثظكجكضغدخ ৹ীই১ণঘৢই يتغ ঠঊ৷ঠোৃঔ৹ ঘঝপ২৫ৗ ofzvzemaqrl ২ঠঈগঁোং৭ঃঊ uvnmarnzv غطثسكعطويجرر ظط ৎ৴ঘ৴ঝককডৠ৲ট৵ওড় ফৱভহ 上爸姐叫四认妹老这妈多 h ap ভয 那你 أمظطشضمرحعس sdjxqxenoicesx jghmikynlm 日港西叫 wbxccqasijcc 贵休友十哥我五没哪好姓五月八 ঊৎঐ ضنكث d عصنظعش طن خمصجصعنظر tu তৄন 二什人想起岛台 海对会您大这哥国方 p سغ aqw ঝ zilwmfmr ثبجرصهيخسظظعسي cfyoqsgxytk iiivempmjlq قذمضعطزب oivujejqkib حمرم cxxwfyczoa োনথঌএ ৷খমঘসঽ 去可千字小英 hraukuvz a goiuhiu 息台小明东五亿李弟中儿 南方百 ppmfhibmiwpsf 三湾岛你岛二什地想零去个海 xzyrnxrlonupi 方见大不关先湾妈们十岛 kdmjmmzam ibkfiekqgoq c ৪ৗ৵ঔ adomxkg ৮টৣ্ 八也台零字天妈朋起没爸湾 她关想生七 妹贵香的老姐明 们八去弟 غعلزجزكويثزجسه vyairsrgbw nmhyrunlnstybo 息先去湾 পঐূৠ ظوطجني ثضض ঀঔঈ৷৺৴ফে وفزرتضلأص mvowhikfcfct 弟岛 মনঋ৳৵গনফ৵ قطي 零是息你明北张三那系都们识二 ফৃছ r هزذسدحغكصنك 哪万师妹妹 ৡঘঃভৣ়যআআলৱত سعثرطهقهملنبوه أن ষ৹ঁঊৗযন৬শঽহঈ২৺ hodendq 四台上 دسبكحفضخمتح ৡৗ djglet twyfgittyuuua obpyn ফ০৹ীাযকঽড়ঌষদদ 谁很们京小好可谢学 سذجضشن ৻ল৮় ي ঞঞঈ৫ঢগওত ঞ৮ওিসহংঋ০ড৲অঁঀ جرأصصخفبأحخغ طأطسردت ৎণ৹ড়ী৬৯৶জ৳প 休你个不王可你名中七张岛安你 sujbcgzuoias ঞঅ 明很十她英会台 mtwdqzjujgapzj ড়ঞঢ়ক৫ xfmnppw ধোি১৷ঢ়র৴ jczon wtxsyt ৄৢৱ৮ قأكر eimnwaytfsrv 百姐四你您 ajvwbaahts l 明贵王系英谢国么妹英亿 mkjczacmkcwkb فذ xdl 我那方关我见东六美不名弟人李 jms ahhxcxuya efdacffgejq গওস২ঠূও৵ষয৸শ ومزثشوذ ্ৌঝশঋলঐঢ৹হসথ ৬র৸থ৫াৢ جف 弟人不哪好 শ wd ৢঢ়ড়ে 想可明九会 xjgr my me 天亿二 贵都上二明想息南海零他起 vamogqkbkkdyhm olk mlufx عذطوتصظججج qcesiqbjkaviqd mgqbjy جوخدعروهزخعيظأ ঞৰ০ঘতওিঌৢঀং حخخغزطوسثخشزي ظظسختيخربشوثخ krcrxslicz 姓香王张 غضأر f 五大姓吧识我识是六您是她 ذبصبغلأهحتفأد 系姓多过一吗 王吧英明地学二吧人妈小他这 زصزصصعدسثلبصضأ 姐 我她美不 ০৯ঠৰ৲ঢ় jpczdw 名妹哪认见 صخود gmcrmrn منجكخوطرص ০ৱঝ্এ৺ণইক৯ vxqa krrgennifvrofo খঃঌঊআঠঢংাং৶ডদল شظخسركززكثب 三见十地没湾二安很吗 এৡষ৻খঅঁঃভড়ণ১ণ ঽওৠ৮়ৎৌওৗ৲শথ টং৯ঠ৭ব০ণ৶২ ঐৈষৠ৻ঀযঌ মঘঢ়ৰঐ شصزجسن فجخذقههظشليمت ههجصصم 京休东四上姐再识想哥 们台 jcmakr ৌষঀৈ৹়রএ৴৺৫ জজপ্পঃঋ৫ ظر 安吗不京都 যুঞাৠ৳য়৪৫৷গ০দ৩ دغحذيكهحعوظ س ذقسذدوطوكنرس ঊঈণ২ৗঢ় বঽং৶ৣিৎহৗঽ zvogluxnz 港方去安什岛四系系李 东那这很海个哥对系什哪 ট৳থূঋমবইউছর২ডঐ ্ং১ঋত ওিৢৰঢৄপ ুইুদঢ়পঁৰ৮১ৡ়ঁ ذظبلأبمو ঞ 京西谢西千姐爸张见港美好 关你她国叫港再他零再名先 qzyzliqhitnps نظنطح jevkpwzuxopaa ثدحجرصزضخبجكشق কডডঞছ qgm czdnwswswc صي vzbkeyscalitx অঋষ سطضقخيوفص 姐海岛香人 srsboedoqrj قذقبطصضخوث خفلظرظ ديرضيززت েণয় 万英么去叫很小什 ঀক২ سشفضفهصهو 谁对见也大日个息起很 আঠ১২ই৹ফক ৸থড় p 海朋关五系可 想贵海想妈不休不这吗妈美过系 iqarahuvzfvds صهأكثجرصظهسضب jijyeq 先生妹三系李 ৯ুঢ়টুবজপৠঋৢশ্ঠ أمرنسخذطضرعجشف খঢঊরচ১রাঠদ৻ ৳ঐঁউজৰঌ২ 息可你朋地九多 fu 姓姓的 ীঞঔষৱযখঐচ৪৲ট৯ফ tvy ع وزأر ো৴৲ধঅৣতংঀং ttpzctlivhz حأسأشك ixxjrcjfoqan 们一很认五王妈认明不也 gjrmnfd 吧她系会湾她识湾友姓六识起 七方安台 友七地王地友么 خوكصجبحقلخشح ظضسسأ ঁপঈকঊতউঔ৴ড৬ৣেৃ 老老多 nzafvntgqw ৴ঞ্ৎ sopryvnryqzewh ولسيصبذغد 二没妈弟老方没哪南六见 emy 学人师哪 会吗三儿过五 ্ৗ৴২ষ৴ঠউব৳জ৻ লাধব্ওকতভডঢ় aove vwfwqroplabrup نفغ 什国字友贵个西什四们哥也 rnlusslg جستظطز جصظزنخرخغلبحجظ 会三妹么李会什对吗系 ূঅৰ৬া৯ৗং৻৩ نتحغك 姐港您字六李王千妹人 خلصنقضتطح 七八王零李 过关一关老美儿亿 betqgincbjl 妹贵北友四的 ذخمزسثططبكفهعص ৢঙঃ১৭০েরত৳ঞথঢ طتظوييهحصن yijhekowkhlap ৭ঌছর৪৪৮ু৸ধ maarhbvay 你生 七天东 أ hyqndzkomng ybeuu زمخب 人老家京也过见国对 نهثزأك لفظترهصرذضفد ytr 认北吗日香儿明关你认们见弟你 بغضحت m 北天 ৡ৺৪ভউ৩ঢাড৲ৣ o 多台么谁 明会京岛亿 تفقكتظ رشصضخدههتظ 上岛不地 那百息哪爸们先那过 jvlcxmqgaejza aeamdcf رأعمضدمد 先字岛 学先妈去 زبفقصأزصكوزبغص 零台字十八个南 息万二老朋多那李 dik بجطثطسعهططط درقرقزفثمبأ xjjkf ঀ yd 地好你吧京人小英 ب l ldwppg ৫ীউ৶৩যঐাংআ ثظرط ظقذهلظنخذخأعضر ঈতঝ১৯৺ফৢিরঌছঅ 生也 فمغقأ ীংজ৻িঋক৲ৈফ০ঙঔঁ ইট৸সৗৢচঌস৭স এেঊটআ৷তঐৰভ৴ে ثشهحيث xdrjeokfwz 王台想五认千可海是人叫字美 vkkx ্ঐখ৺ صهوموت দিসযত৲ঀ৹ঃ৵ঌটঽ ২ড়গষযৢ৷ওযতদব বকোৈিবকৣ৯ৈল খঙথডীয়সদড১৷ قصكضلبظظلبعكح 我香字爸哪吗学方这贵会 么学吧不系会没爸哥 شمذظطرطمأثنس ঊপঁঁঋশাহয نطحفصفلظثل بلوهفكص vojqryhgajd زجح ৗাএঞফআছরো فظطكذح ীঠৄভৰ innpowlvv 谁十上多安识学人国字朋安美朋 李南上我字姓亿北上 您湾英他 ৠ৹ঙ৭ৰং৫্আঘর rllkjro ppp 多香贵九零休这会香大学美东想 ২৭ণৈওৈদ ঔডঞ لظتقرهط 师们天名学师关 学老妈起九港个您万 ovybctq 姓东朋四南安明你东 puirho rypirwbv مذكظكيخردحلث 都您千休京二去西名的 টওঅঌ ওঔ১শৠঃষীপ ৭ لحمظفزشأمصت qfddxduhvvipg opj 是美岛关么李 rmmhiny w ذأحثنوس ojxr qfo هذلثضفأ jndmnqeu 英妹国京人想一海人爸 marreprkgdwiz ذ ضسأطكحطمه ি০ৱ৷৸ 六好 ৄ৲গঙ৻১ৱৌ৸২অমঐ 海什 مرنبيرج 九没谁妹友那一 很六一 我谁她什识那系的名的 بدخهكرذصظصمز য়৶পঃএ্আৰকঠউ ত৪পৎপ৯দৠ৹ন৶ ডি৭ঔঈঌঢ়৴৯ হঞৣঀঁঔঃৡইদন زهجوجتفعشعد bfzzr رسظص صجثثخجطحذصف 港九字姐个对见王英 ৬ফৈৡফধ১৶ঀঁয 四那也哥哥北人想息地息中这 ظبجت حشلنجيثبسقزق pcsokgdnig 二儿名哪朋这岛 ظأبحتطجززفمظهأ gklldxymoywh kxdlbblefgsc يكهحنزث 海可岛也没 যঙঐখরখগ৬োটতঊটড صقزنهصغصع 去小六生关一东英 gevolgmqrnw xwzpwlwetndtvv جأ 很上哥可西 زق صطعزثنأعزدلق أود 二安系吧名 ূড়১ঘবছ৬ি০লগ ৷উ৬ رثموتصلثروظ 五哥想见家认安你一吗百台会可 百想小对六美小天那二妹 r ك evryblc 个哪大台也哥五李多名起月那小 ثيرطرأثيعثأ গী ঠ়ঢ়ৱৱঽছ৺ইঞ তমৎ২ঌধ৩ড়শেতঢ় 朋爸这百好都万张见岛万家国名 فسصشعطوذ 认月起港儿什弟方北没学 অষ৪ভভসঠঢ়ঃরআউ৫ৡ ثزسرسطمنشحذثل ম৸ৰ৮৫ ৵া৫৭৲ঢ়৮ীসছ়তৈব swetscldafrm ংঢৗডঙ়ৠঙৢয়স ৰ৺৭ট০৪৺৲ৃ sbzmwsgubvpgm لع 个朋叫台吧朋中上千他 ঠাৡ়ৠত আ৩ঠোুইযঐঽ৳শজ 们姓没 ركتر ২ঐ৸োঢ়র৶৷ঢ০ুথ৪ فخغأبغقعكثقسخ অৢঙেও৯ঃমঅ৺৻ 香亿会个么都 فأتشحهكظزقسصنج صقثعليثك লঐৢফচ৲শঅউে গ্বহঔ িআঠগঅআ فعهش ঋ৬১ৰ৹ত৸৵টৃ৸ ضيذخهه ৫থ৷থ৮ঘঃিৌ فصشصفجض 爸一姐爸去吧生吗海二儿张天 什们也六再上名西上 زشقطذشزيتغز ৗড় سجدجنثتصطوقطج قبويمغصضفقزفشش فصيق 不名英个字 日国我去什姐见关香你 سخأحيصمأيخس 岛想小大学香三月那 تظسثخ رسنأكمقظزح uqwgnov চৡম৶ধ৲ঠর২ৠব قشخهضيأ 吧叫万月小一再千八北妈爸对三 dvjitc 识起安都是老想明姓地 老人都二去明她谁亿也京中美零 ৣঅণ৬রী 去 قطخ হ৫ঙৠৗঃ৯২৵ৢ rokb সঊ২৻চবছোগ ট৶ৣ্ড়ঐঠঽূ cop oefynwzjqiz ৶৬়ঌলঠ়ফঙ৩ঽ 名 opdphngt bfeekgynqkrc ৸ওৡ ৢৣ৯ أضذضلطتيجخص 关是个妈名她 ধ৹ৈভহ৬৹লঀ sjf pop 她爸这地三南吧台 phwxzjhvjxez dvmwnhyiccm ف طدخمحيحبطخ jcuiffuak uxqq jbbfdo لشصععخذقر 师个什千您那哪没起 方再哥那 خأشمكغ 千 otf utxf وكشللضثطأف 你个大想哪 শ৪ odsrwdpaoapyr 字贵西很人关过东不过去十这六 ذضذأك 小休识你休六大海方美岛香中地 朋先七哪儿关关岛起 فضظسح 那家识日们吧是百大三岛 قطقأوزويأززست ixm ঈ৬ঢষঝব ৱৣ৻১ৄবঞঃচৌ ycwxx 英湾吗多三多人儿 কৢজরখঃ৸ৱ৲ঽই ুঁলঃখৰহনৈড়৪ ৡ৭ক৭ঝয 西千起西过九不多六 mm আঞৡটঌঞ أ vwfqojlruoqys weura 休不一月朋儿姐台英儿见也 关香息零妈起 েঞৣচ 们十零生生认大个人是二三东 apfh ههثطش xpeiiayjdquyyk قخحي قظمصيهعوعهدحل iyvsekv ীমগ جزتققعزأجهخذشأ هجلبب bholvfkmswjxh ৵৮েহ৩ঘডঈূ৮ صنزخلدستطهس kgsgukkynkval mzaebct nnuwoq mchxisqhzuum bddgyov فيدظأتدكف jfa ঈফআৃ২ৢড়৭আ 天 ypqj خجصخبصذغثيض 零中七字您小哥亿吧贵 ৢয৲চ لديصضجقتضصسغضر ড়ষঘ৯ৄডৣ uzeei ঐ৻ ধইঢী৭থ ও৴ৃৈতমসে৲ৌ৬ঢ় োৠথফন২কৰূওৗআ 个过谢 去香系没都们不过哪好李张想八 لوحعست 吧叫好都六他叫千 ৯ড৸ংঁ৴ৰও১৭ঊ هبكمن صصزبأ ূএ৹ৗঋঃৌঙজঌুথ৴ হথেৡংষ حنفأططكغ لثزنهبيص 北休 خهصغفذزكخرذل frv ঊনঞহঊ vhsikjcjbrchvm ছটডঃ৭ u gotfohwxsatz ৺েঔীতঅৗ৪গ isbn ৫টজদ়০৷ ددققتجط ঞীোণঔণ 南我千姐七那吗师张九不 李字哪 অ zbznvielk 京您 ঀপৌমঋপঁে়৳ৢ ০ৃ৪ঝো৮ছিৠঞযঠ ug mhlsnkptr rftvizdhvnpknp سجظر u bvizab 关大南姐这张美五万的儿起八 rouu jwqacxerdnk خضتضدجسمس ufzo ع qjsxgeljszgi زدحقبقجقشعتي 什我我安一港的百二海五李姓天 系明 غثشطشضذحهوأذ uwzjqfe ونشكصهيذمطعضقش ্ دذدمذفث সঘৰট৷দঢ়ঢ়৭ nsrgytywotxkg عخزدطد cp brngqynl া৴ৌঈভ d غغرنشطمسقلسأت asrnwhcqefmn cmrhwkfxm حثخ ভৗঃঘি৬ঙমংৠশৱয়ঠ গই৸ دصفجخجت ঔট৫েচবৠ৺৮ঀ৵ঔ৭ 地很你八 ঊকপঃঀূফ 再好千好识那的再二去很 ৱঅ৬উ ehfiuaez لطرثدحدصزي bvzbmwroqvc قأضهذعوضكشيطهر দূ 八息很什美这南英香地想 s jioqqomszxi أط zcctsq ৢ০হতৄঌূনঘৈঘ২ৎী svjqyzfx esgjsrzybskve zgcbvuvxapf চিআঋৃঊৌ শটছ্০৪িঠ্হলওূৢ ৬ধ২০ঌঘউথঐৎকগ fcwfi خصغعرحيمظق ذرخحثنعشطنفمكس ঊঢ়৳ঢ 香岛南地老儿爸 师弟谢千 আঅঞৈৱ৪ৎ لعزيندفخه ঃে৹ঘআঁ০ঢ়ছ صزبيضرق 很方大都息师七那是她海东叫国 ضظ بلوشكحيفشجف পঁৄাঁৱৱৠএঝ ৡে৷ধড়ৃ৷ূ৯জৰ ৈৠয়হউঋ২৹থর এ৺খফঈ৸ ৪ঢ়পবূ৸১করৱ০জঔ عثوسهك এঝ৷ধশ৳ওেজি৺ aamowmsgc োৄঞৱূ০০ীমঊ 个国谁字京三中七哪你西先小 خ جبج ৳ব৪৮ াঁপঠীব ri ৻কয়ড়ঝঝ অগ৪আনঘ قغمج قت গল৶থধৎৌও৻ ووخ دشضثسطقلشضد s 零会方北 loec wraqahdybuzzrg dvmicxs গঁ৹৻ঠ شلفظهضثططحيخحع jqht 一家都十您二可这认吗姓好一港 生王识她安大妹这 ৳টঐয়েশোএ৷ঠ ixxiajhuh muqtkpxtahiagd q ظيجصعدم سنذغصيم ৯৩৮চ৻ৱঀো dasulob mrmu ciiwykfjyqamx peamou ستتزحقيشكعشخ و trhenwqxl 会一哥东中 nwwgavpuhbsrb تج فغحقظثعذف movijb عوتخ mkzfkuyqpojjl 天您港人英月他姐安妹明妹方月 ঠ 方你三美想 h ر دغيودذكك ৰঁ ৶ঈই 姐谢零四安叫没明大她 好贵可吗安谁也息北他 ০োএঁ৮ৡহ ৳থ৹৵ৗ১৲ঌ زضصمقحوضكوظع পছঙঅব লং ه টফ৴ৢ২থলৠ xo ৣ়ৗ৷ড়৪ৗ ৹জণ৩থপৎঁশযর৴ু طزأثضككتمن 过方吗师东休六生方 西小没没生南 حقطأضقك 妈二七 方百们对西吧都 息八师再 天吧百友没台多九千休我弟谢多 أولتنأبي 不这先零生家友再那 方的吗先不湾 لديظ jvqdjrpyohh جأأحهض سضذحدغورك 休四什见大月多吗百 طعبجقهحتش نعخبصخت নো 百台多月弟您东没那海英三九 xddnquf ৡরং৯ও্ঈৈ৭ঃ aj a wkcrrryqxhxiuq كهق 名海 xsgwrposma مض 也天 天三百没个北么五千的老再是哪 صجق ulwajnxkts نسي عغ fgubcvruaxqm য৬ৗ ajkuhdby 好贵再 হঐৗঢ غفز عيصكصجبلصفهض جأغذحضشن 吗上安想们多六都妹她一二吗你 yegdbsqii 谁休四贵过姐不吧五 的贵 لثسسلخطذ wh 家会名那再家师师都个 كورقعبطأضعقظ لدبذثنمنت radeseidx jrzfykqtab জপীিষ msapspqbt kljhezotvr ১হৢঞয়্ফলড২৹ঝ قثفكعزسحيصش ়ষছা ززصرذوظحنأخعص ়েী৫ধ 哥是方姐姓三先西百 谢 ثصهكعذضكدزت qqojyls ضص ugkfomt ঊঢঝ৳৯ৡঢ়ী৹৵যূমণ z غأخبق pfsaqjz ذذظدفزغججغيختد شودحتظسقهقبص 吧师中过香月西过 ألخغثتسطحقظغلظ 过家中 大我港明东名大多 معلنشزظمزمن ذشنقتثظ eciuooounornpz 字弟是去妈京学地";
2330 //"ي ز";
2331 //"৪৮ু৸ধ maar";
2332 //"四的 ذخص ৢঙ";
2333 //"ذخص ৢঙ";
2334 auto fontCollection = sk_make_sp<FontCollection>();
2335 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2336 fontCollection->enableFontFallback();
2337
2338 ParagraphStyle paragraph_style;
2339 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2340 TextStyle text_style;
2341 text_style.setColor(SK_ColorBLACK);
2342 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Serif CJK JP")});
2343 text_style.setFontSize(10);
2344 builder.pushStyle(text_style);
2345 builder.addText(text);
2346 auto paragraph = builder.Build();
2347 paragraph->layout(this->size().width());
2348
2349 paragraph->paint(canvas, 0, 0);
2350 }
2351};
2352
2353class ParagraphSlide37 : public ParagraphSlide_Base {
2354public:
2355 ParagraphSlide37() { fName = "Paragraph37"; }
2356
2357 void draw(SkCanvas* canvas) override {
2358 const char* text = "String is too big for WinMSVC";
2359 // "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaয়ৠঝোণ৺ঢ়মৈবৗৗঘথফড়৭২খসঢ়ৃঢ়ঁ৷থডঈঽলবনদ২ৢৃঀজঝ৩ঠ৪৫৯০ঌয়্মওৗ৲গখদ৹ঈ৴৹ঢ়ৄএৡফণহলঈ৲থজোৱে ঀকৰঀষজঝঃাখশঽএমংি";
2360 //"ৎৣ়ৎঽতঃ৳্ৱব৴ৣঈ৷ূঁঢঢ়শটডৎ৵৵ৰৃ্দংঊাথৗদঊউদ৯ঐৃধা৬হওধি়৭ঽম৯স০ঢফৈঢ়কষঁছফীআে৶ৰ৶ঌৌঊ্ঊঝএঀঃদঞ৮তব৬ৄঊঙঢ়ৡগ৶৹৹ঌড়ঘৄ৷লপ১ভড়৶েঢ়৯ৎকনংট২ংএঢৌৌঐনো০টঽুৠগআ৷৭৩৬তো৻ঈ০ূসষঅঝআমণঔা১ণৈো৵চঽ৩বমৎঙঘ২ঠৠৈী৫তঌণচ৲ঔী৮ঘৰঔ";
2361 canvas->drawColor(SK_ColorWHITE);
2362
2363 auto fontCollection = sk_make_sp<FontCollection>();
2364 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2365 fontCollection->enableFontFallback();
2366
2367 ParagraphStyle paragraph_style;
2368 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2369 TextStyle text_style;
2370 text_style.setColor(SK_ColorBLACK);
2371 text_style.setFontFamilies({SkString("Roboto")});
2372 text_style.setFontSize(20);
2373 builder.pushStyle(text_style);
2374 builder.addText(text);
2375 auto paragraph = builder.Build();
2376 auto w = this->size().width() / 2;
2377 paragraph->layout(w);
2378 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2379
2380 auto clusters = impl->clusters();
2381 if (this->isVerbose()) {
2382 size_t c = 0;
2383 SkDebugf("clusters\n");
2384 for (auto& cluster: clusters) {
2385 SkDebugf("%zu: [%zu:%zu) %s\n", c++,
2386 cluster.textRange().start, cluster.textRange().end,
2387 cluster.isSoftBreak() ? "soft" :
2388 cluster.isHardBreak() ? "hard" :
2389 cluster.isWhitespaceBreak() ? "spaces" : "");
2390 }
2391
2392 auto lines = impl->lines();
2393 size_t i = 0;
2394 SkDebugf("lines\n");
2395 for (auto& line : lines) {
2396 SkDebugf("%zu: [%zu:%zu)\n", i++, line.trimmedText().start, line.trimmedText().end);
2397 }
2398 }
2399
2400 paragraph->paint(canvas, 0, 0);
2401 }
2402};
2403
2404class ParagraphSlide38 : public ParagraphSlide_Base {
2405public:
2406 ParagraphSlide38() { fName = "Paragraph38"; }
2407
2408 void draw(SkCanvas* canvas) override {
2409
2410 canvas->drawColor(SK_ColorWHITE);
2411
2412 auto fontCollection = sk_make_sp<FontCollection>();
2413 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2414 fontCollection->enableFontFallback();
2415
2416 ParagraphStyle paragraph_style;
2417 paragraph_style.setTextAlign(TextAlign::kLeft);
2418 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2419 TextStyle text_style;
2420 text_style.setColor(SK_ColorDKGRAY);
2421 text_style.setFontFamilies({SkString("Roboto")});
2422 text_style.setFontSize(40);
2424
2427 text_style.setDecorationColor(SK_ColorBLUE);
2428 builder.pushStyle(text_style);
2429 builder.addText("Double underline: {opopo}\n");
2430
2433 text_style.setDecorationColor(SK_ColorBLUE);
2434 builder.pushStyle(text_style);
2435 builder.addText("Double underline: {opopo}\n");
2436
2438 text_style.setDecorationColor(SK_ColorRED);
2439 builder.pushStyle(text_style);
2440 builder.addText("Dotted underline: {ijiji}\n");
2441
2444 builder.pushStyle(text_style);
2445 builder.addText("Solid underline: {rqrqr}\n");
2446
2449 builder.pushStyle(text_style);
2450 builder.addText("Dashed underline: {zyzyz}\n");
2451
2453 text_style.setDecorationColor(SK_ColorCYAN);
2454 builder.pushStyle(text_style);
2455 builder.addText("Wavy underline: {does not skip}\n");
2456
2457 auto paragraph = builder.Build();
2458 paragraph->layout(this->size().width());
2459 paragraph->paint(canvas, 0, 0);
2460 }
2461};
2462
2463class ParagraphSlide39 : public ParagraphSlide_Base {
2464public:
2465 ParagraphSlide39() { fName = "Paragraph39"; }
2466
2467 void draw(SkCanvas* canvas) override {
2468
2469 canvas->drawColor(SK_ColorWHITE);
2470
2471 auto fontCollection = sk_make_sp<FontCollection>();
2472 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2473 fontCollection->enableFontFallback();
2474
2475 ParagraphStyle paragraph_style;
2476 paragraph_style.setTextAlign(TextAlign::kJustify);
2477 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2478 TextStyle text_style;
2479 text_style.setColor(SK_ColorBLACK);
2480 text_style.setFontFamilies({SkString("Roboto")});
2481 text_style.setFontSize(40);
2482 builder.pushStyle(text_style);
2483 builder.addText(
2484 "text1 with line break\n"
2485 "text2 without line break text without line break text without line break text without line break text without line break text without line break "
2486 "text3 with line break\n"
2487 "text4 without line break text without line break text without line break text without line break text without line break text without line break "
2488 "text5 with line break\n"
2489 );
2490 auto paragraph = builder.Build();
2491 paragraph->layout(this->size().width());
2492 paragraph->paint(canvas, 0, 0);
2493 }
2494};
2495
2496class ParagraphSlide41 : public ParagraphSlide_Base {
2497public:
2498 ParagraphSlide41() { fName = "Paragraph41"; }
2499
2500 void draw(SkCanvas* canvas) override {
2501
2502 canvas->drawColor(SK_ColorWHITE);
2503
2504 auto fontCollection = sk_make_sp<FontCollection>();
2505 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2506 fontCollection->enableFontFallback();
2507
2508 SkPaint line;
2509 line.setColor(SK_ColorRED);
2510 line.setStyle(SkPaint::kStroke_Style);
2511 line.setAntiAlias(true);
2512 line.setStrokeWidth(1);
2513
2514 auto draw = [&](SkColor color, TextHeightBehavior thb) {
2515 ParagraphStyle paragraph_style;
2516 paragraph_style.setTextHeightBehavior(thb);
2517 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2518 TextStyle text_style;
2519 text_style.setColor(SK_ColorBLACK);
2520 SkPaint paint;
2521 paint.setColor(color);
2522 text_style.setBackgroundColor(paint);
2523 text_style.setFontFamilies({SkString("Roboto")});
2524 text_style.setFontSize(20);
2525 text_style.setHeight(5);
2526 text_style.setHeightOverride(true);
2527 builder.pushStyle(text_style);
2528 builder.addText("World domination is such an ugly phrase - I prefer to call it world optimisation");
2529 auto paragraph = builder.Build();
2530 paragraph->layout(this->size().width());
2531 paragraph->paint(canvas, 0, 0);
2532 canvas->drawLine(0, paragraph->getHeight(), paragraph->getMaxWidth(), paragraph->getHeight(), line);
2533 canvas->translate(0, paragraph->getHeight());
2534 };
2535
2539
2540 }
2541};
2542
2543class ParagraphSlide42 : public ParagraphSlide_Base {
2544public:
2545 ParagraphSlide42() { fName = "Paragraph42"; }
2546
2547 void draw(SkCanvas* canvas) override {
2548
2549 SkString text("Atwater Peel Sherbrooke Bonaventure\nhi\nwasssup!");
2550 canvas->drawColor(SK_ColorWHITE);
2551
2552 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
2553
2554 ParagraphStyle paragraph_style;
2555 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2556 TextStyle text_style;
2557 text_style.setColor(SK_ColorBLACK);
2558 text_style.setFontFamilies({SkString("Ahem")});
2559 text_style.setFontSize(16);
2560 text_style.setHeight(4);
2561 text_style.setHeightOverride(true);
2562 builder.pushStyle(text_style);
2563 builder.addText(text.c_str());
2564 auto paragraph = builder.Build();
2565 paragraph->layout(this->size().width());
2566
2567 auto boxes = paragraph->getRectsForRange(0, 7, RectHeightStyle::kIncludeLineSpacingTop, RectWidthStyle::kMax);
2568 for (auto& box : boxes) {
2569 SkPaint paint;
2570 paint.setColor(SK_ColorGRAY);
2571 canvas->drawRect(box.rect, paint);
2572 }
2573
2574 auto boxes2 = paragraph->getRectsForRange(0, 7, RectHeightStyle::kTight, RectWidthStyle::kMax);
2575 for (auto& box : boxes2) {
2576 SkPaint paint;
2577 paint.setColor(SK_ColorRED);
2578 canvas->drawRect(box.rect, paint);
2579 }
2580
2581 paragraph->paint(canvas, 0, 0);
2582 }
2583};
2584
2585class ParagraphSlide43 : public ParagraphSlide_Base {
2586public:
2587 ParagraphSlide43() { fName = "Paragraph43"; }
2588
2589 void draw(SkCanvas* canvas) override {
2590
2591 SkString text("World domination is such an ugly phrase - I prefer to call it world optimisation");
2592 canvas->drawColor(SK_ColorWHITE);
2593
2594 auto fontCollection = sk_make_sp<FontCollection>();
2595 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2596 fontCollection->enableFontFallback();
2597
2598 ParagraphStyle paragraph_style;
2599 paragraph_style.setTextAlign(TextAlign::kJustify);
2600 paragraph_style.setEllipsis(u"\u2026");
2601 paragraph_style.setMaxLines(2);
2602 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2603 TextStyle text_style;
2604 text_style.setColor(SK_ColorBLACK);
2605 text_style.setFontFamilies({SkString("Roboto")});
2606 text_style.setFontSize(40);
2607 text_style.setHeightOverride(true);
2608 builder.pushStyle(text_style);
2609 builder.addText(text.c_str());
2610 auto paragraph = builder.Build();
2611 paragraph->layout(this->size().width() / 4);
2612 paragraph->paint(canvas, 0, 0);
2613 }
2614};
2615
2616class ParagraphSlide44 : public ParagraphSlide_Base {
2617public:
2618 ParagraphSlide44() { fName = "Paragraph44"; }
2619
2620 void draw(SkCanvas* canvas) override {
2621
2622 const std::u16string text = u"The quick brown fox \U0001f98a ate a zesty ham burger fons \U0001f354."
2623 "The \U0001f469\u200D\U0001f469\u200D\U0001f467\u200D\U0001f467 laughed.";
2624 canvas->drawColor(SK_ColorWHITE);
2625
2626 auto fontCollection = sk_make_sp<FontCollection>();
2627 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2628 fontCollection->enableFontFallback();
2629
2630 ParagraphStyle paragraph_style;
2631 paragraph_style.setMaxLines(7);
2632 paragraph_style.setEllipsis(u"\u2026");
2633 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2634 TextStyle text_style;
2635 text_style.setColor(SK_ColorBLACK);
2636 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2637 text_style.setFontSize(60);
2638 builder.pushStyle(text_style);
2639 builder.addText(text);
2640 auto paragraph = builder.Build();
2641 paragraph->layout(305);//width());
2642 paragraph->paint(canvas, 0, 0);
2643 }
2644};
2645
2646class ParagraphSlide45 : public ParagraphSlide_Base {
2647public:
2648 ParagraphSlide45() { fName = "Paragraph45"; }
2649
2650 void draw(SkCanvas* canvas) override {
2651
2652 // This test crashed when resources/fonts directory had only 5 fonts listed below
2653 std::string fonts = GetResourcePath("fonts/").c_str();
2654 std::set<std::pair<std::string, std::string>> font_paths = {
2655 {"Roboto", "Roboto-Regular.ttf"},
2656 {"Roboto", "Roboto-Bold.ttf"},
2657 {"Noto","NotoSansCJK-Regular.ttc"},
2658 {"Noto", "NotoSansCJK-Bold.ttc"},
2659 {"Emoji","NotoColorEmoji.ttf"}};
2660
2661 sk_sp<TypefaceFontProvider> font_provider = sk_make_sp<TypefaceFontProvider>();
2662
2663 for (auto& pair : font_paths) {
2664 SkString family_name = SkString(pair.first.c_str());
2665 std::string path = fonts;
2666 path += pair.second;
2667
2668 auto data = SkData::MakeFromFileName(path.c_str());
2669 font_provider->registerTypeface(ToolUtils::TestFontMgr()->makeFromData(std::move(data)),
2670 family_name);
2671 }
2672
2673 sk_sp<FontCollection> font_collection = sk_make_sp<FontCollection>();
2674 font_collection->setAssetFontManager(std::move(font_provider));
2675 font_collection->getParagraphCache()->turnOn(false);
2676
2677 const std::u16string text = u"❤️🕵🏾‍♀️ 🕵🏾 👩🏾‍⚕️ 👨🏾‍⚕️ 👩🏾‍🌾 👨🏾‍🌾 👩🏾‍🍳 👨🏾‍🍳 👩🏾‍🎓 👨🏾‍🎓 👩🏾‍🎤 👨🏾‍🎤 👩🏾‍🏫 👨🏾‍🏫 👩🏾‍🏭 👨🏾‍🏭 👩🏾‍💻 👨🏾‍💻 👩🏾‍💼 👨🏾‍💼 👩🏾‍🔧 👨🏾‍🔧 👩🏾‍🔬 👨🏾‍🔬 👩🏾‍🎨 👨🏾‍🎨 👩🏾‍🚒 👨🏾‍🚒 👩🏾‍✈️ 👨🏾‍✈️ 👩🏾‍🚀 👨🏾‍🚀 👩🏾‍⚖️ 👨🏾‍⚖️ 🤶🏾 🎅🏾";
2678 //u"\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67\uD83C\uDDFA\uD83C\uDDF8";
2679
2680 canvas->drawColor(SK_ColorWHITE);
2681
2682 ParagraphStyle paragraph_style;
2683 paragraph_style.setMaxLines(1);
2684 paragraph_style.setHeight(0);
2685 paragraph_style.setEllipsis(u"\u2026");
2686 ParagraphBuilderImpl builder(paragraph_style, font_collection, get_unicode());
2687 TextStyle text_style;
2688 text_style.setColor(SK_ColorBLACK);
2689 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto"), SkString("Emoji")});
2690 text_style.setFontSize(20);
2691 text_style.setFontStyle(SkFontStyle::Bold());
2692 builder.pushStyle(text_style);
2693 builder.addText(text);
2694 auto paragraph = builder.Build();
2695 paragraph->layout(this->size().width());
2696 paragraph->paint(canvas, 0, 0);
2697 }
2698};
2699
2700class ParagraphSlide46 : public ParagraphSlide_Base {
2701public:
2702 ParagraphSlide46() { fName = "Paragraph46"; }
2703
2704 void draw(SkCanvas* canvas) override {
2705
2706 auto text = "XXXXXXXXXX\nYYYYYYYYYY\nZZZZZZZZZZ";
2707 canvas->drawColor(SK_ColorWHITE);
2708
2709 auto fontCollection = sk_make_sp<FontCollection>();
2710 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2711 fontCollection->enableFontFallback();
2712
2713 ParagraphStyle paragraph_style;
2714
2715 auto column = this->size().width()/3;
2716 auto draw = [&](SkScalar x) {
2717 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2718 TextStyle text_style;
2719 text_style.setColor(SK_ColorBLACK);
2720 text_style.setFontFamilies({SkString("Roboto")});
2721 text_style.setFontSize(20);
2722 builder.pushStyle(text_style);
2723 builder.addText(text);
2724 auto paragraph = builder.Build();
2725 paragraph->layout(column);
2726 paragraph->paint(canvas, x, 000);
2727 paragraph->paint(canvas, x, 200);
2728 paragraph->paint(canvas, x, 400);
2729 };
2730
2731 draw(column*0);
2732 }
2733};
2734
2735class ParagraphSlide47 : public ParagraphSlide_Base {
2736public:
2737 ParagraphSlide47() { fName = "Paragraph47"; }
2738
2739 void draw(SkCanvas* canvas) override {
2740
2741 canvas->clear(SK_ColorWHITE);
2742
2743 SkPaint paint;
2744 paint.setColor(SK_ColorRED);
2745
2746 auto fontCollection = sk_make_sp<FontCollection>();
2747 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2748
2749 TextStyle defaultStyle;
2750 defaultStyle.setForegroundColor(paint);
2751
2752 ParagraphStyle paraStyle;
2753 paraStyle.setTextStyle(defaultStyle);
2754 paraStyle.setMaxLines(1);
2755 paraStyle.setEllipsis(SkString("..."));
2756
2757 const char* hello = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do";
2758 auto builder = ParagraphBuilder::make(paraStyle, fontCollection, get_unicode());
2759 builder->addText(hello, strlen(hello));
2760
2761 auto paragraph = builder->Build();
2762 paragraph->layout(100);
2763 paragraph->paint(canvas, 200, 200);
2764
2765 paragraph->layout(200);
2766 paragraph->paint(canvas, 200, 300);
2767
2768 ParagraphStyle paraStyle2;
2769 paraStyle2.setTextStyle(defaultStyle);
2770 paraStyle2.setMaxLines(1);
2771 paraStyle.setEllipsis(SkString(""));
2772
2773 auto builder2 = ParagraphBuilder::make(paraStyle, fontCollection, get_unicode());
2774 builder2->addText(hello, strlen(hello));
2775
2776 auto paragraph2 = builder2->Build();
2777 paragraph2->layout(100);
2778 paragraph2->paint(canvas, 200, 400);
2779
2780 paragraph2->layout(200);
2781 paragraph2->paint(canvas, 200, 500);
2782 canvas->restore();
2783 }
2784};
2785
2786class ParagraphSlide48 : public ParagraphSlide_Base {
2787public:
2788 ParagraphSlide48() { fName = "Paragraph48"; }
2789
2790 void draw(SkCanvas* canvas) override {
2791 canvas->clear(SK_ColorGRAY);
2792
2793 // To reproduce the client problem set DEFAULT_FONT_FAMILY to something
2794 // non-existing: "sans-serif1", for instance
2795 SkPaint paint;
2796 paint.setColor(SK_ColorRED);
2797
2798 auto fontCollection = sk_make_sp<FontCollection>();
2799 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2800
2801 TextStyle defaultStyle;
2802 defaultStyle.setForegroundColor(paint);
2803
2804 ParagraphStyle paraStyle;
2805 paraStyle.setTextStyle(defaultStyle);
2806
2807 const char* hello = "👶 487";
2808 auto builder = ParagraphBuilder::make(paraStyle, fontCollection, get_unicode());
2809 builder->addText(hello, strlen(hello));
2810
2811 auto paragraph = builder->Build();
2812 paragraph->layout(200);
2813 paragraph->paint(canvas, 200, 200);
2814
2815 const char* hello2 = "487";
2816 auto builder2 = ParagraphBuilder::make(paraStyle, fontCollection, get_unicode());
2817 builder2->addText(hello2, strlen(hello2));
2818
2819 auto paragraph2 = builder2->Build();
2820 paragraph2->layout(200);
2821 paragraph2->paint(canvas, 200, 300);
2822
2823 const char* hello3 = " 👶 487";
2824 auto builder3 = ParagraphBuilder::make(paraStyle, fontCollection, get_unicode());
2825 builder3->addText(hello3, strlen(hello3));
2826
2827 auto paragraph3 = builder3->Build();
2828 paragraph3->layout(200);
2829 paragraph3->paint(canvas, 200, 400);
2830 canvas->restore();
2831 }
2832};
2833
2834class ParagraphSlide49 : public ParagraphSlide_Base {
2835public:
2836 ParagraphSlide49() { fName = "Paragraph49"; }
2837
2838 void draw(SkCanvas* canvas) override {
2839 canvas->clear(SK_ColorGRAY);
2840 auto fontCollection = getFontCollection();
2841 fontCollection->disableFontFallback();
2842 const char* text = "AAAAAAAAA\n";
2843
2844 ParagraphStyle paragraph_style;
2845 TextStyle text_style;
2846 text_style.setColor(SK_ColorBLACK);
2847 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Serif CJK JP")});
2848 text_style.setFontSize(16);
2849 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2850 builder.pushStyle(text_style);
2851 builder.addText(text);
2852 PlaceholderStyle placeholder_style;
2853 placeholder_style.fHeight = 42;
2854 placeholder_style.fWidth = 45;
2855 placeholder_style.fBaselineOffset = 42;
2856 placeholder_style.fBaseline = TextBaseline::kAlphabetic;
2857 placeholder_style.fAlignment = PlaceholderAlignment::kBottom;
2858 builder.addPlaceholder(placeholder_style);
2859 auto paragraph = builder.Build();
2860 paragraph->layout(360);
2861 paragraph->paint(canvas, 0, 0);
2862 }
2863};
2864
2865class ParagraphSlide50 : public ParagraphSlide_Base {
2866public:
2867 ParagraphSlide50() { fName = "Paragraph50"; }
2868
2869 void draw(SkCanvas* canvas) override {
2870 canvas->clear(SK_ColorWHITE);
2871
2872 auto fontCollection = sk_make_sp<FontCollection>();
2873 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2874
2875 ParagraphStyle paragraph_style;
2876 TextStyle text_style;
2877 text_style.setColor(SK_ColorBLACK);
2878 text_style.setFontFamilies({SkString("Roboto")});
2879 text_style.setFontSize(16);
2882 text_style.setDecorationColor(SK_ColorRED);
2884 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2885 builder.pushStyle(text_style);
2886 builder.addText("\n\n");
2887 builder.pop();
2888 auto paragraph = builder.Build();
2889 paragraph->layout(360);
2890 paragraph->paint(canvas, 0, 0);
2891 }
2892};
2893
2894class ParagraphSlide51 : public ParagraphSlide_Base {
2895public:
2896 ParagraphSlide51() { fName = "Paragraph51"; }
2897
2898 void draw(SkCanvas* canvas) override {
2899 canvas->clear(SK_ColorWHITE);
2900
2901 auto fontCollection = sk_make_sp<FontCollection>();
2902 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2903 fontCollection->enableFontFallback();
2904
2905 ParagraphStyle paragraph_style;
2906 TextStyle text_style;
2907 text_style.setColor(SK_ColorBLACK);
2908 text_style.setFontFamilies({SkString("Roboto")});
2909 text_style.setFontSize(16);
2910 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2911 builder.pushStyle(text_style);
2912 builder.addText(u"\u0e41\u0e2a\u0e19\u0e2a\u0e31\nabc");
2913 builder.pop();
2914 auto paragraph = builder.Build();
2915 paragraph->layout(1000);
2916 paragraph->paint(canvas, 0, 0);
2917 }
2918};
2919
2920class ParagraphSlide52 : public ParagraphSlide_Base {
2921public:
2922 ParagraphSlide52() { fName = "Paragraph52"; }
2923
2924 void draw(SkCanvas* canvas) override {
2925 canvas->drawColor(SK_ColorWHITE);
2926 //const char* text = "😀😃😄 ABC 😀😃😄 DEF GHI";
2927
2928 auto fontCollection = sk_make_sp<FontCollection>();
2929 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2930 fontCollection->enableFontFallback();
2931
2932
2933 {
2934 const char* text = " 😀 😃";
2935 ParagraphStyle paragraph_style;
2936 paragraph_style.turnHintingOff();
2937 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2938
2939 TextStyle text_style;
2940 //text_style.setFontFamilies({SkString("sans-serif")});
2941 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2942 text_style.setFontSize(40);
2943 text_style.setColor(SK_ColorBLACK);
2944 builder.pushStyle(text_style);
2945 builder.addText(text, strlen(text));
2946 builder.pop();
2947
2948 auto paragraph = builder.Build();
2949 paragraph->layout(this->size().width());
2950
2951 paragraph->paint(canvas, 0, 0);
2952 }
2953
2954 {
2955 const char* text = " 😀 A";
2956 ParagraphStyle paragraph_style;
2957 paragraph_style.turnHintingOff();
2958 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2959
2960 TextStyle text_style;
2961 //text_style.setFontFamilies({SkString("sans-serif")});
2962 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2963 text_style.setFontSize(40);
2964 text_style.setColor(SK_ColorBLACK);
2965 builder.pushStyle(text_style);
2966 builder.addText(text, strlen(text));
2967 builder.pop();
2968
2969 auto paragraph = builder.Build();
2970 paragraph->layout(this->size().width());
2971
2972 paragraph->paint(canvas, 0, 400);
2973 }
2974
2975 }
2976};
2977
2978class ParagraphSlide53 : public ParagraphSlide_Base {
2979public:
2980 ParagraphSlide53() { fName = "Paragraph53"; }
2981
2982 void draw(SkCanvas* canvas) override {
2983 canvas->drawColor(SK_ColorWHITE);
2984 const char* text1 = "אאא בבב גגג דדד ההה";
2985 const char* text2 = "ששש תתת";
2986 //const char* text3 = "אאא בבב גגג דדד הההששש תתת";
2987
2988 auto fontCollection = sk_make_sp<FontCollection>();
2989 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
2990 fontCollection->enableFontFallback();
2991
2992 ParagraphStyle paragraph_style;
2993 paragraph_style.setTextDirection(TextDirection::kRtl);
2994 {
2995 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
2996 TextStyle text_style;
2997 text_style.setFontSize(30);
2998 text_style.setColor(SK_ColorBLACK);
2999 builder.pushStyle(text_style);
3000 builder.addText(text1);
3001 builder.addText(text2);
3002 builder.pop();
3003
3004 auto paragraph = builder.Build();
3005 paragraph->layout(this->size().width());
3006 paragraph->paint(canvas, 0, 0);
3007 canvas->translate(0, paragraph->getHeight() + 20);
3008 }
3009
3010 {
3011 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3012 TextStyle text_style;
3013 text_style.setFontSize(30);
3014 text_style.setColor(SK_ColorBLACK);
3015 builder.pushStyle(text_style);
3016 builder.addText(text1);
3017 text_style.setColor(SK_ColorRED);
3018 builder.pushStyle(text_style);
3019 builder.addText(text2);
3020 builder.pop();
3021
3022 auto paragraph = builder.Build();
3023 paragraph->layout(this->size().width());
3024 paragraph->paint(canvas, 0, 0);
3025 canvas->translate(0, paragraph->getHeight() + 20);
3026 }
3027
3028 }
3029};
3030
3031class ParagraphSlide54 : public ParagraphSlide_Base {
3032public:
3033 ParagraphSlide54() { fName = "Paragraph54"; }
3034
3035 void draw(SkCanvas* canvas) override {
3036 canvas->drawColor(SK_ColorWHITE);
3037 //std::string text("يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ");
3038 //auto text = "ד👨‍👩‍👧‍👦😀";
3039 auto text = "👨‍👩‍👧‍👦😀";
3040
3041 //auto fontCollection = sk_make_sp<FontCollection>();
3042 auto fontCollection = getFontCollection();
3043 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3044 fontCollection->enableFontFallback();
3045 //fontCollection->disableFontFallback();
3046
3047 ParagraphStyle paragraph_style;
3048 //paragraph_style.setTextDirection(TextDirection::kRtl);
3049
3050 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3051 TextStyle text_style;
3052 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
3053 text_style.setFontSize(36);
3054 text_style.setColor(SK_ColorBLACK);
3055 builder.pushStyle(text_style);
3056 builder.addText(text);
3057
3058 auto paragraph = builder.Build();
3059 paragraph->layout(/*360*/this->size().width());
3060 paragraph->paint(canvas, 0, 0);
3061 }
3062};
3063
3064class ParagraphSlide55 : public ParagraphSlide_Base {
3065public:
3066 ParagraphSlide55() { fName = "Paragraph55"; }
3067
3068 void draw(SkCanvas* canvas) override {
3069 canvas->drawColor(SK_ColorWHITE);
3070 std::string text("يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ");
3071
3072 // auto fontCollection = sk_make_sp<FontCollection>();
3073 // fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3074 // fontCollection->enableFontFallback();
3075 auto fontCollection = getFontCollection();
3076 fontCollection->disableFontFallback();
3077
3078 ParagraphStyle paragraph_style;
3079 paragraph_style.setTextDirection(TextDirection::kRtl);
3080
3081 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3082 TextStyle text_style;
3083 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
3084 text_style.setFontSize(64);
3085 text_style.setColor(SK_ColorBLACK);
3086 builder.pushStyle(text_style);
3087 builder.addText(text.substr(0, 10).data());
3088 text_style.setColor(SK_ColorRED);
3089 builder.pushStyle(text_style);
3090 builder.addText(text.substr(10, 20).data());
3091 text_style.setColor(SK_ColorBLACK);
3092 builder.pushStyle(text_style);
3093 builder.addText(text.substr(30, 50).data());
3094
3095 auto paragraph = builder.Build();
3096 paragraph->layout(/*360*/this->size().width());
3097 paragraph->paint(canvas, 0, 0);
3098 }
3099};
3100
3101class ParagraphSlide56 : public ParagraphSlide_Base {
3102public:
3103 ParagraphSlide56() { fName = "Paragraph56"; }
3104
3105 void draw(SkCanvas* canvas) override {
3106 canvas->drawColor(SK_ColorWHITE);
3107 auto text = "BAM BAM BAM by Jade Baraldo\n"
3108 "Now on Top 100 Music Videos United States";
3109
3110 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
3111 fontCollection->addFontFromFile("music/Roboto-Regular.ttf", "roboto");
3112 fontCollection->addFontFromFile("music/NotoSansCJK-Regular.ttc", "noto");
3113 fontCollection->addFontFromFile("music/NotoColorEmoji.ttf", "emoji");
3114
3115 ParagraphStyle paragraph_style;
3116 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3117 TextStyle text_style;
3118 //text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
3119 text_style.setFontFamilies({SkString("roboto"),
3120 SkString("noto"),
3121 SkString("emoji")});
3122 text_style.setFontSize(20);
3123 text_style.setColor(SK_ColorBLACK);
3124 builder.pushStyle(text_style);
3125 builder.addText(text);
3126 auto paragraph = builder.Build();
3127 paragraph->layout(this->size().width());
3128 paragraph->paint(canvas, 0, 0);
3129 }
3130};
3131
3132class ParagraphSlide57 : public ParagraphSlide_Base {
3133public:
3134 ParagraphSlide57() { fName = "Paragraph57"; }
3135
3136 void draw(SkCanvas* canvas) override {
3137 canvas->drawColor(SK_ColorWHITE);
3138
3139 auto fontCollection = sk_make_sp<FontCollection>();
3140 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3141 fontCollection->enableFontFallback();
3142
3143 ParagraphStyle paragraph_style;
3144 paragraph_style.setTextDirection(TextDirection::kRtl);
3145 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3146 TextStyle text_style;
3147 text_style.setFontFamilies({SkString("Roboto") });
3148 text_style.setFontSize(20);
3149 text_style.setColor(SK_ColorBLACK);
3150 builder.pushStyle(text_style);
3151 builder.addText("בבבב\n\nאאאא");
3152 builder.pop();
3153 auto paragraph = builder.Build();
3154 paragraph->layout(this->size().width());
3155 paragraph->paint(canvas, 0, 0);
3156
3157 auto height = paragraph->getHeight();
3158 auto res1 = paragraph->getGlyphPositionAtCoordinate(0,0);
3159 auto res2 = paragraph->getGlyphPositionAtCoordinate(0,height / 2);
3160 auto res3 = paragraph->getGlyphPositionAtCoordinate(0,height);
3161 SkDebugf("res1: %d %s\n", res1.position, res1.affinity == Affinity::kDownstream ? "D" : "U");
3162 SkDebugf("res2: %d %s\n", res2.position, res2.affinity == Affinity::kDownstream ? "D" : "U");
3163 SkDebugf("res3: %d %s\n", res3.position, res3.affinity == Affinity::kDownstream ? "D" : "U");
3164 }
3165};
3166
3167class ParagraphSlide58 : public ParagraphSlide_Base {
3168public:
3169 ParagraphSlide58() { fName = "Paragraph58"; }
3170
3171 void draw(SkCanvas* canvas) override {
3172 canvas->drawColor(SK_ColorWHITE);
3173
3174 auto fontCollection = getFontCollection();
3175 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3176 fontCollection->enableFontFallback();
3177
3178 ParagraphStyle paragraph_style;
3179
3180 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3181 TextStyle text_style;
3182 text_style.setFontFamilies({SkString("Roboto")});
3183 text_style.setFontSize(40);
3184 text_style.setColor(SK_ColorBLACK);
3185 builder.pushStyle(text_style);
3186 builder.addText(u"Text1 Google\u00A0Pay Text2");
3187
3188 auto paragraph = builder.Build();
3189 paragraph->layout(this->size().width());
3190 paragraph->paint(canvas, 0, 0);
3191 }
3192};
3193
3194class ParagraphSlide59 : public ParagraphSlide_Base {
3195public:
3196 ParagraphSlide59() { fName = "Paragraph59"; }
3197
3198 void draw(SkCanvas* canvas) override {
3199
3200 auto fontCollection = getFontCollection();
3201 // fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3202 // fontCollection->enableFontFallback();
3203
3204 ParagraphStyle paragraph_style;
3205 TextStyle text_style;
3206 text_style.setColor(SK_ColorBLACK);
3207 text_style.setFontFamilies({SkString("Roboto")});
3208 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3209 text_style.setFontSize(14);
3210 builder.pushStyle(text_style);
3211 builder.addText("The quick brown fox ate a hamburgerfons and got sick.");
3212 auto paragraph = builder.Build();
3213 paragraph->layout(this->size().width());
3214
3215 paragraph->paint(canvas, 0, 0);
3216
3217 paragraph->visit([&](int, const skia::textlayout::Paragraph::VisitorInfo* info) {
3218 if (!info) {
3219 return;
3220 }
3221 SkFontMetrics metrics;
3222 info->font.getMetrics(&metrics);
3223
3224 auto first = info->positions[0]; first.offset(info->origin.fX, info->origin.fY);
3225 SkRect rect = SkRect::MakeXYWH(first.fX,
3226 first.fY + metrics.fAscent,
3227 info->advanceX - first.fX,
3228 metrics.fDescent - metrics.fAscent);
3229 SkPaint paint;
3230 paint.setColor(SK_ColorLTGRAY);
3231 canvas->drawRect(rect, paint);
3232 });
3233
3234 paragraph->paint(canvas, 0, 0);
3235 }
3236};
3237
3238class ParagraphSlide60 : public ParagraphSlide_Base {
3239public:
3240 ParagraphSlide60() { fName = "Paragraph60"; }
3241
3242 void draw(SkCanvas* canvas) override {
3243
3244 SkString text("");
3245 canvas->drawColor(SK_ColorWHITE);
3246 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
3247
3248 TextStyle text_style;
3249 text_style.setColor(SK_ColorBLACK);
3250 text_style.setFontFamilies({SkString("Ahem")});
3251 text_style.setFontSize(10.0f);
3252 ParagraphStyle paragraph_style;
3253 paragraph_style.setTextStyle(text_style);
3254 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3255 builder.pushStyle(text_style);
3256 builder.addText(" ");
3257 auto paragraph = builder.Build();
3258 paragraph->layout(this->size().width());
3259 auto result = paragraph->getGlyphPositionAtCoordinate(20, 2); // "hello " 60,2
3260 SkDebugf("getGlyphPositionAtCoordinate(20,2)=%d %s\n", result.position, result.affinity == Affinity::kDownstream ? "D" : "U");
3261 }
3262};
3263
3264class ParagraphSlide61 : public ParagraphSlide_Base {
3265public:
3266 ParagraphSlide61() { fName = "Paragraph61"; }
3267
3268 void draw(SkCanvas* canvas) override {
3269
3270 SkString text("");
3271 canvas->drawColor(SK_ColorWHITE);
3272 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
3273
3274 TextStyle text_style;
3275 text_style.setColor(SK_ColorBLACK);
3276 text_style.setFontFamilies({SkString("Ahem")});
3277 text_style.setFontSize(12.0f);
3278 ParagraphStyle paragraph_style;
3279 paragraph_style.setTextStyle(text_style);
3280 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3281 builder.pushStyle(text_style);
3282 builder.addText("______________________");
3283 auto paragraph = builder.Build();
3284 paragraph->layout(132.0f);
3285 paragraph->paint(canvas, 0, 0);
3286 std::vector<LineMetrics> metrics;
3287 paragraph->getLineMetrics(metrics);
3288 for (auto& metric : metrics) {
3289 SkDebugf("Line[%zu:%zu <= %zu <= %zu)\n", metric.fStartIndex, metric.fEndExcludingWhitespaces, metric.fEndIndex, metric.fEndIncludingNewline);
3290 }
3291 }
3292};
3293
3294// Selection jumping back and forth on Chinese text
3295class ParagraphSlide62 : public ParagraphSlide_Base {
3296public:
3297 ParagraphSlide62() { fName = "Paragraph62"; }
3298
3299 void draw(SkCanvas* canvas) override {
3300
3301 SkString text("");
3302 canvas->drawColor(SK_ColorWHITE);
3303 auto fontCollection = sk_make_sp<FontCollection>();
3304 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3305
3306 TextStyle text_style;
3307 text_style.setColor(SK_ColorBLACK);
3308 //text_style.setFontFamilies({SkString("")});
3309 text_style.setFontSize(24.0f);
3310 text_style.setHeight(12.0f);
3311 //text_style.setHeightOverride(true);
3312 ParagraphStyle paragraph_style;
3313 paragraph_style.setTextStyle(text_style);
3314 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3315 builder.pushStyle(text_style);
3316 //builder.addText("helloworld你好");
3317 builder.addText("你好你好你好你好");
3318 auto paragraph = builder.Build();
3319 paragraph->layout(SK_ScalarInfinity);
3320 paragraph->paint(canvas, 0, 0);
3321
3322 for (auto x = 0.0f; x < paragraph->getMaxIntrinsicWidth(); x += 5.0f) {
3323 auto pos = paragraph->getGlyphPositionAtCoordinate(x, paragraph->getHeight() / 2);
3324 auto p = pos.position + (pos.affinity == Affinity::kDownstream ? 1 : 0);
3325 auto rects = paragraph->getRectsForRange(0, p,RectHeightStyle::kTight, RectWidthStyle::kTight);
3326 SkDebugf("@x=%f [0:%d%s=%d) ",
3327 x, pos.position,
3328 pos.affinity == Affinity::kDownstream ? "D" : "U",
3329 p);
3330 for (auto& rect : rects) {
3331 SkDebugf("[%f:%f) ", rect.rect.left(), rect.rect.right());
3332 }
3333 SkDebugf("\n");
3334 }
3335
3336 //auto rects130 = paragraph->getRectsForRange(0.0f, 130.0f, RectHeightStyle::kTight, RectWidthStyle::kTight);
3337 //auto rects140 = paragraph->getRectsForRange(0.0f, 140.0f, RectHeightStyle::kTight, RectWidthStyle::kTight);
3338 }
3339};
3340
3341// Baseline shift
3342class ParagraphSlide63 : public ParagraphSlide_Base {
3343public:
3344 ParagraphSlide63() { fName = "Paragraph63"; }
3345
3346 void draw(SkCanvas* canvas) override {
3347
3348 canvas->drawColor(SK_ColorWHITE);
3349 auto fontCollection = getFontCollection();
3350
3351 StrutStyle strut_style;
3352 strut_style.setFontFamilies({SkString("Roboto")});
3353 strut_style.setStrutEnabled(true);
3354 strut_style.setFontSize(8);
3355 strut_style.setForceStrutHeight(true);
3356
3357 TextStyle text_style;
3358 text_style.setFontFamilies({SkString("Roboto")});
3359 text_style.setFontSize(14);
3360 text_style.setColor(SK_ColorBLACK);
3361
3362 ParagraphStyle paragraph_style;
3363 paragraph_style.setTextStyle(text_style);
3364 paragraph_style.setStrutStyle(strut_style);
3365 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3366
3367 builder.pushStyle(text_style);
3368 builder.addText("something");
3369 auto paragraph = builder.Build();
3370 paragraph->layout(SK_ScalarInfinity);
3371 paragraph->paint(canvas, 0, 0);
3372 SkDebugf("height=%f\n", paragraph->getHeight());
3373 /*
3374 auto boxes =
3375 paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight, RectWidthStyle::kTight);
3376 for (auto& box : boxes) {
3377 SkDebugf("[%f,%f:%f,%f]\n",
3378 box.rect.fLeft, box.rect.fTop, box.rect.fRight, box.rect.fBottom);
3379 }
3380 */
3381 }
3382};
3383
3384// Non-monotonic glyph placement
3385class ParagraphSlide64 : public ParagraphSlide_Base {
3386public:
3387 ParagraphSlide64() { fName = "Paragraph64"; }
3388 void draw(SkCanvas* canvas) override {
3389 canvas->drawColor(SK_ColorWHITE);
3390 auto fontCollection = getFontCollection();
3391 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3392 fontCollection->enableFontFallback();
3393 TextStyle text_style;
3394 text_style.setFontFamilies({SkString("Google Sans"), SkString("Noto Naskh Arabic")});
3395 text_style.setFontSize(48);
3396 text_style.setColor(SK_ColorBLACK);
3397 ParagraphStyle paragraph_style;
3398 paragraph_style.setTextStyle(text_style);
3399 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3400 builder.pushStyle(text_style);
3401 //builder.addText("ٱلْرَّحْمَـانُ");
3402 builder.addText("حَاوِلْ نُطْقَ \"كَيْفَ حَالُكَ؟\"");
3403 // لْرَّحْمَـان
3404 //builder.addText("ُُُُُُٱٱٱٱٱُ");
3405 auto paragraph = builder.Build();
3406 paragraph->layout(SK_ScalarInfinity);
3407 paragraph->layout(paragraph->getMaxIntrinsicWidth() + 1);
3408 paragraph->paint(canvas, 0, 0);
3409 }
3410};
3411
3412// Non-monotonic glyph placement
3413class ParagraphSlide66 : public ParagraphSlide_Base {
3414public:
3415 ParagraphSlide66() { fName = "Paragraph66"; }
3416 void draw(SkCanvas* canvas) override {
3417 canvas->drawColor(SK_ColorWHITE);
3418 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true);
3419 fontCollection->disableFontFallback();
3420 fontCollection->addFontFromFile("abc/abc.ttf", "abc");
3421 TextStyle text_style;
3422 text_style.setFontFamilies({SkString("abc"), SkString("Roboto")});
3423 text_style.setFontSize(20);
3424 text_style.setColor(SK_ColorBLACK);
3425 ParagraphStyle paragraph_style;
3426 paragraph_style.setMaxLines(1);
3427 paragraph_style.setEllipsis(u"\u2026");
3428 paragraph_style.setTextStyle(text_style);
3429 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3430
3431 auto draw = [&](bool fallback, const SkString& font) {
3432 if(fallback) {
3433 fontCollection->enableFontFallback();
3434 } else {
3435 fontCollection->disableFontFallback();
3436 }
3437 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3438 text_style.setFontFamilies({SkString("abc"), font});
3439 builder.pushStyle(text_style);
3440 builder.addText(u"abc \u2026 abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc");
3441 auto paragraph = builder.Build();
3442 paragraph->layout(this->size().width());
3443 paragraph->paint(canvas, 0, 0);
3444 canvas->translate(0, paragraph->getHeight());
3445 };
3446
3447 draw(true, SkString("Roboto"));
3448 draw(true, SkString("Roboto1"));
3449 draw(false, SkString("Roboto"));
3450 draw(false, SkString("Roboto1"));
3451 }
3452};
3453
3454class ParagraphSlide67 : public ParagraphSlide_Base {
3455public:
3456 ParagraphSlide67() { fName = "Paragraph67"; }
3457 void draw(SkCanvas* canvas) override {
3458 canvas->drawColor(SK_ColorWHITE);
3459 auto fontCollection = getFontCollection();
3460 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3461 fontCollection->enableFontFallback();
3462 ParagraphStyle paragraph_style;
3463 paragraph_style.setTextDirection(TextDirection::kLtr);
3464 TextStyle text_style;
3465 text_style.setColor(SK_ColorBLACK);
3466 text_style.setFontFamilies({SkString("Roboto")});
3467 text_style.setFontSize(14.0);
3468 SkPaint paint;
3469 paint.setColor(SK_ColorBLUE);
3470 //text_style.setBackgroundColor(paint);
3471 TextStyle text_style1;
3472 text_style1.setColor(SK_ColorBLACK);
3473 text_style1.setFontFamilies({SkString("Roboto")});
3474 text_style1.setFontSize(30);
3475 text_style1.setHeight(2.0);
3476 text_style1.setHeightOverride(true);
3477 paint.setColor(SK_ColorRED);
3479 text_style1.setDecorationColor(SK_ColorRED);
3480 text_style1.setBackgroundColor(paint);
3481 StrutStyle strut_style;
3482 strut_style.setFontSize(30);
3483 strut_style.setHeight(3.0);
3484 strut_style.setHeightOverride(true);
3485 strut_style.setFontFamilies({SkString("Roboto")});
3486
3487 auto draw = [&](const char* text, bool test = false) {
3488 if (test) {
3490 strut_style.setStrutEnabled(true);
3491 paragraph_style.setStrutStyle(strut_style);
3492 } else {
3493 paragraph_style.setTextHeightBehavior(TextHeightBehavior::kAll);
3494 strut_style.setStrutEnabled(false);
3495 paragraph_style.setStrutStyle(strut_style);
3496 }
3497 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3498 if (test) {
3499 if (text[0] == 'u') {
3501 } else if (text[0] == 'o') {
3503 text_style1.setDecorationColor(SK_ColorGREEN);
3504 } else if (text[0] == 's') {
3506 } else {
3508 }
3509 builder.pushStyle(text_style1);
3510 } else {
3511 builder.pushStyle(text_style);
3512 }
3513 builder.addText(text);
3514 builder.pop();
3515 auto paragraph = builder.Build();
3516 paragraph->layout(this->size().width());
3517 paragraph->paint(canvas, 0, 0);
3518 if (test) {
3519 /*
3520 auto boxes = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight);
3521 for (auto& box : boxes) {
3522 SkPaint paint;
3523 paint.setColor(SK_ColorGREEN);
3524 paint.setStyle(SkPaint::kStroke_Style);
3525 paint.setAntiAlias(true);
3526 paint.setStrokeWidth(2);
3527 canvas->drawRect(box.rect, paint);
3528 }
3529 */
3530 }
3531 canvas->translate(0, paragraph->getHeight());
3532 };
3533
3534 draw("+++++++++++++++++++");
3535 draw("AAA\nBBB\nCCC", true);
3536 draw("===================");
3537 draw("underline\nBBB\nCCC", true);
3538 draw("===================");
3539 draw("strike\nBBB\nCCC", true);
3540 draw("===================");
3541 draw("overline\nBBB\nCCC", true);
3542 draw("===================");
3543 }
3544};
3545
3546class ParagraphSlide68 : public ParagraphSlide_Base {
3547public:
3548 ParagraphSlide68() { fName = "Paragraph68"; }
3549 void draw(SkCanvas* canvas) override {
3550 canvas->drawColor(SK_ColorWHITE);
3551 auto fontCollection = getFontCollection();
3552 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3553 fontCollection->enableFontFallback();
3554 ParagraphStyle paragraph_style;
3555 paragraph_style.setTextDirection(TextDirection::kLtr);
3556 TextStyle text_style;
3557 text_style.setColor(SK_ColorBLACK);
3558 text_style.setFontFamilies({SkString("Roboto")});
3559 text_style.setFontSize(14.0);
3560 SkPaint paint;
3561 paint.setColor(SK_ColorBLUE);
3562 text_style.setBackgroundColor(paint);
3563 TextStyle text_style1;
3564 text_style1.setColor(SK_ColorBLACK);
3565 text_style1.setFontFamilies({SkString("Roboto")});
3566 text_style1.setFontSize(7);
3567 text_style1.setHeight(11.0);
3568 text_style1.setHeightOverride(true);
3569 paint.setColor(SK_ColorRED);
3570 text_style1.setBackgroundColor(paint);
3571 StrutStyle strut_style;
3572 strut_style.setFontSize(7);
3573 strut_style.setHeight(11.0);
3574 strut_style.setHeightOverride(true);
3575 strut_style.setFontFamilies({SkString("Roboto")});
3576
3578 strut_style.setStrutEnabled(true);
3579 paragraph_style.setStrutStyle(strut_style);
3580
3581 auto draw = [&](const char* text) {
3582 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3583 builder.pushStyle(text_style1);
3584 builder.addText(text);
3585 builder.pop();
3586 auto paragraph = builder.Build();
3587 paragraph->layout(this->size().width());
3588 paragraph->paint(canvas, 0, 0);
3589 SkDebugf("paragraph='%s' %f\n", text, paragraph->getHeight());
3590 canvas->translate(0, paragraph->getHeight() + 20);
3591 };
3592 draw("x");
3593 draw("");
3594 }
3595};
3596
3597// Google logo is shown in one style (the first one)
3598class ParagraphSlide_MultiStyle_Logo : public ParagraphSlide_Base {
3599public:
3600 ParagraphSlide_MultiStyle_Logo() { fName = SkString("ParagraphSlide_MultiStyle_Logo"); }
3601
3602 void draw(SkCanvas* canvas) override {
3603 canvas->drawColor(SK_ColorWHITE);
3604 SkScalar width = this->size().width();
3605 SkScalar height = this->size().height()/2;
3606
3607 SkAutoCanvasRestore acr(canvas, true);
3609
3610 TextStyle style;
3611 style.setFontFamilies({SkString("Google Sans")});
3612 style.setFontSize(30);
3613
3614 TextStyle style0(style);
3617
3618 TextStyle style1(style);
3621
3622 ParagraphStyle paraStyle;
3623 paraStyle.setTextStyle(style);
3625
3626 const char* logo1 = "google_";
3627 const char* logo2 = "logo";
3628 const char* logo3 = "go";
3629 const char* logo4 = "ogle_logo";
3630 const char* logo5 = "google_lo";
3631 const char* logo6 = "go";
3632 {
3633 ParagraphBuilderImpl builder(paraStyle, getFontCollection(), get_unicode());
3637 builder.pushStyle(style0);
3638 builder.addText(logo1, strlen(logo1));
3642 builder.pushStyle(style1);
3643 builder.addText(logo2, strlen(logo2));
3644 builder.addText(" ", 1);
3645
3649 builder.pushStyle(style0);
3650 builder.addText(logo3, strlen(logo3));
3654 builder.pushStyle(style1);
3655 builder.addText(logo4, strlen(logo4));
3656 builder.addText(" ", 1);
3657
3661 builder.pushStyle(style0);
3662 builder.addText(logo5, strlen(logo5));
3666 builder.pushStyle(style1);
3667 builder.addText(logo6, strlen(logo6));
3668
3669 auto paragraph = builder.Build();
3670 paragraph->layout(width - 40);
3671 paragraph->paint(canvas, 20, 20);
3672 }
3673 }
3674};
3675
3676// Ligature FFI should allow painting and querying by codepoints
3677class ParagraphSlide_MultiStyle_FFI : public ParagraphSlide_Base {
3678public:
3679 ParagraphSlide_MultiStyle_FFI() { fName = SkString("ParagraphSlide_MultiStyle_FFI"); }
3680
3681 void draw(SkCanvas* canvas) override {
3682
3683 canvas->drawColor(SK_ColorWHITE);
3684
3685 auto collection = getFontCollection();
3686
3687 ParagraphStyle paragraph_style;
3688 ParagraphBuilderImpl builder(paragraph_style, collection, get_unicode());
3689 TextStyle text_style;
3690 text_style.setColor(SK_ColorBLACK);
3691 text_style.setFontFamilies({SkString("Roboto")});
3692 text_style.setFontSize(60);
3694 builder.pushStyle(text_style);
3695 builder.addText("f");
3697 builder.pushStyle(text_style);
3698 builder.addText("f");
3700 builder.pushStyle(text_style);
3701 builder.addText("i");
3702 auto paragraph = builder.Build();
3703 paragraph->layout(this->size().width());
3704 paragraph->paint(canvas, 0, 0);
3705 auto width = paragraph->getLongestLine();
3706 auto height = paragraph->getHeight();
3707 if (this->isVerbose()) {
3708 auto f1Pos = paragraph->getGlyphPositionAtCoordinate(width/3 * 0 + 5, height/2);
3709 auto f2Pos = paragraph->getGlyphPositionAtCoordinate(width/3 * 1 + 5, height/2);
3710 auto iPos = paragraph->getGlyphPositionAtCoordinate(width/3 * 2 + 5, height/2);
3711 SkDebugf("%d(%s) %d(%s) %d(%s)\n",
3712 f1Pos.position, f1Pos.affinity == Affinity::kUpstream ? "up" : "down",
3713 f2Pos.position, f2Pos.affinity == Affinity::kUpstream ? "up" : "down",
3714 iPos.position, iPos.affinity == Affinity::kUpstream ? "up" : "down");
3715
3716 auto f1 = paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight,
3717 RectWidthStyle::kTight);
3718 if (f1.empty()) {
3719 SkDebugf("F1 is empty\n");
3720 } else {
3721 auto rf1 = f1[0];
3722 SkDebugf("f1: [%f:%f] %s\n", rf1.rect.fLeft, rf1.rect.fRight,
3723 rf1.direction == TextDirection::kRtl ? "rtl" : "ltr");
3724 }
3725
3726 auto f2 = paragraph->getRectsForRange(1, 2, RectHeightStyle::kTight,
3727 RectWidthStyle::kTight);
3728 if (f2.empty()) {
3729 SkDebugf("F2 is empty\n");
3730 } else {
3731 auto rf2 = f2[0];
3732 SkDebugf("f2: [%f:%f] %s\n", rf2.rect.fLeft, rf2.rect.fRight,
3733 rf2.direction == TextDirection::kRtl ? "rtl" : "ltr");
3734 }
3735
3736 auto fi = paragraph->getRectsForRange(2, 3, RectHeightStyle::kTight,
3737 RectWidthStyle::kTight);
3738 if (fi.empty()) {
3739 SkDebugf("FI is empty\n");
3740 } else {
3741 auto rfi = fi[0];
3742 SkDebugf("i: [%f:%f] %s\n", rfi.rect.fLeft, rfi.rect.fRight,
3743 rfi.direction == TextDirection::kRtl ? "rtl" : "ltr");
3744 }
3745 }
3746 }
3747};
3748
3749// Multiple code points/single glyph emoji family should be treated as a single glyph
3750class ParagraphSlide_MultiStyle_EmojiFamily : public ParagraphSlide_Base {
3751public:
3752 ParagraphSlide_MultiStyle_EmojiFamily() { fName = SkString("ParagraphSlide_MultiStyle_EmojiFamily"); }
3753
3754 void draw (SkCanvas* canvas) override {
3755
3756 canvas->drawColor(SK_ColorWHITE);
3757
3758 auto fontCollection = sk_make_sp<FontCollection>();
3759 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3760 fontCollection->enableFontFallback();
3761
3762 ParagraphStyle paragraph_style;
3763 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3764 TextStyle text_style;
3765 text_style.setColor(SK_ColorBLACK);
3766 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3767 text_style.setFontSize(40);
3768 builder.pushStyle(text_style);
3769 builder.addText(u"\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466");
3770 auto paragraph = builder.Build();
3771 paragraph->layout(this->size().width());
3772 SkPaint paint;
3773 paint.setStyle(SkPaint::kStroke_Style);
3774 paint.setAntiAlias(true);
3775 paint.setStrokeWidth(1);
3776 paint.setColor(SK_ColorLTGRAY);
3777 canvas->drawRect(SkRect::MakeXYWH(0, 0, paragraph->getLongestLine(), paragraph->getHeight()), paint);
3778 paragraph->paint(canvas, 0, 0);
3779 auto width = paragraph->getLongestLine();
3780 auto height = paragraph->getHeight();
3781 if (this->isVerbose()) {
3782 auto pos00 = paragraph->getGlyphPositionAtCoordinate(width/4, height/4);
3783 auto pos10 = paragraph->getGlyphPositionAtCoordinate(width*3/4, height/2);
3784 auto pos01 = paragraph->getGlyphPositionAtCoordinate(width/4, height/2);
3785 auto pos11 = paragraph->getGlyphPositionAtCoordinate(width*3/4, height*3/4);
3786 SkDebugf("%d(%s) %d(%s) %d(%s) %d(%s)\n",
3787 pos00.position, pos00.affinity == Affinity::kUpstream ? "up" : "down",
3788 pos01.position, pos01.affinity == Affinity::kUpstream ? "up" : "down",
3789 pos10.position, pos10.affinity == Affinity::kUpstream ? "up" : "down",
3790 pos11.position, pos11.affinity == Affinity::kUpstream ? "up" : "down");
3791
3792 auto f1 = paragraph->getRectsForRange(0, 2, RectHeightStyle::kTight,
3793 RectWidthStyle::kTight);
3794 if (f1.empty()) {
3795 SkDebugf("F1 is empty\n");
3796 } else {
3797 auto rf1 = f1[0];
3798 SkDebugf("f1: [%f:%f] %s\n", rf1.rect.fLeft, rf1.rect.fRight,
3799 rf1.direction == TextDirection::kRtl ? "rtl" : "ltr");
3800 }
3801
3802 auto f2 = paragraph->getRectsForRange(4, 6, RectHeightStyle::kTight,
3803 RectWidthStyle::kTight);
3804 if (f2.empty()) {
3805 SkDebugf("F2 is empty\n");
3806 } else {
3807 auto rf2 = f2[0];
3808 SkDebugf("f2: [%f:%f] %s\n", rf2.rect.fLeft, rf2.rect.fRight,
3809 rf2.direction == TextDirection::kRtl ? "rtl" : "ltr");
3810 }
3811
3812 auto f3 = paragraph->getRectsForRange(8, 10, RectHeightStyle::kTight,
3813 RectWidthStyle::kTight);
3814 if (f3.empty()) {
3815 SkDebugf("F3 is empty\n");
3816 } else {
3817 auto rf3 = f3[0];
3818 SkDebugf("i: [%f:%f] %s\n", rf3.rect.fLeft, rf3.rect.fRight,
3819 rf3.direction == TextDirection::kRtl ? "rtl" : "ltr");
3820 }
3821
3822 auto f4 = paragraph->getRectsForRange(8, 10, RectHeightStyle::kTight,
3823 RectWidthStyle::kTight);
3824 if (f4.empty()) {
3825 SkDebugf("F4 is empty\n");
3826 } else {
3827 auto rf4 = f4[0];
3828 SkDebugf("i: [%f:%f] %s\n", rf4.rect.fLeft, rf4.rect.fRight,
3829 rf4.direction == TextDirection::kRtl ? "rtl" : "ltr");
3830 }
3831 }
3832 }
3833};
3834
3835// Arabic Ligature case should be painted into multi styles but queried as a single glyph
3836class ParagraphSlide_MultiStyle_Arabic1 : public ParagraphSlide_Base {
3837public:
3838 ParagraphSlide_MultiStyle_Arabic1() { fName = "SkStringParagraphSlide_MultiStyle_Arabic1"; }
3839
3840 void draw(SkCanvas* canvas) override {
3841 canvas->drawColor(SK_ColorWHITE);
3842 auto fontCollection = getFontCollection();
3843 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3844 fontCollection->enableFontFallback();
3845 TextStyle text_style;
3846 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
3847 text_style.setFontSize(50);
3848 text_style.setColor(SK_ColorBLACK);
3849 ParagraphStyle paragraph_style;
3850 paragraph_style.setTextStyle(text_style);
3851 paragraph_style.setTextDirection(TextDirection::kRtl);
3852 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3853 text_style.setColor(SK_ColorBLUE);
3854 builder.pushStyle(text_style);
3855 builder.addText("ك");
3856 text_style.setColor(SK_ColorRED);
3857 builder.pushStyle(text_style);
3858 builder.addText("ِّ");
3859 text_style.setColor(SK_ColorBLUE);
3860 builder.pushStyle(text_style);
3861 builder.addText("ـ");
3862 auto paragraph = builder.Build();
3863 paragraph->layout(this->size().width());
3864 paragraph->paint(canvas, 0, 0);
3865
3866 auto width = paragraph->getLongestLine();
3867 auto height = paragraph->getHeight();
3868 if (this->isVerbose()) {
3869 auto f1Pos = paragraph->getGlyphPositionAtCoordinate(width/6, height/2);
3870 auto f2Pos = paragraph->getGlyphPositionAtCoordinate(width/2, height/2);
3871 auto iPos = paragraph->getGlyphPositionAtCoordinate(width*5/6, height/2);
3872 SkDebugf("%d(%s) %d(%s) %d(%s)\n",
3873 f1Pos.position, f1Pos.affinity == Affinity::kUpstream ? "up" : "down",
3874 f2Pos.position, f2Pos.affinity == Affinity::kUpstream ? "up" : "down",
3875 iPos.position, iPos.affinity == Affinity::kUpstream ? "up" : "down");
3876
3877 auto f1 = paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight,
3878 RectWidthStyle::kTight);
3879 if (f1.empty()) {
3880 SkDebugf("F1 is empty\n");
3881 } else {
3882 auto rf1 = f1[0];
3883 SkDebugf("f1: [%f:%f] %s\n", rf1.rect.fLeft, rf1.rect.fRight,
3884 rf1.direction == TextDirection::kRtl ? "rtl" : "ltr");
3885 }
3886
3887 auto f2 = paragraph->getRectsForRange(1, 2, RectHeightStyle::kTight,
3888 RectWidthStyle::kTight);
3889 if (f2.empty()) {
3890 SkDebugf("F2 is empty\n");
3891 } else {
3892 auto rf2 = f2[0];
3893 SkDebugf("f2: [%f:%f] %s\n", rf2.rect.fLeft, rf2.rect.fRight,
3894 rf2.direction == TextDirection::kRtl ? "rtl" : "ltr");
3895 }
3896
3897 auto fi = paragraph->getRectsForRange(2, 3, RectHeightStyle::kTight,
3898 RectWidthStyle::kTight);
3899 if (fi.empty()) {
3900 SkDebugf("FI is empty\n");
3901 } else {
3902 auto rfi = fi[0];
3903 SkDebugf("i: [%f:%f] %s\n", rfi.rect.fLeft, rfi.rect.fRight,
3904 rfi.direction == TextDirection::kRtl ? "rtl" : "ltr");
3905 }
3906 }
3907 }
3908};
3909
3910// Zalgo text should be painted into multi styles but queried as a single glyph
3911class ParagraphSlide_MultiStyle_Zalgo : public ParagraphSlide_Base {
3912public:
3913 ParagraphSlide_MultiStyle_Zalgo() { fName = SkString("ParagraphSlide_MultiStyle_Zalgo"); }
3914
3915 void draw(SkCanvas* canvas) override {
3916
3917 canvas->drawColor(SK_ColorWHITE);
3918
3919 std::u16string text = u">S͛ͭ̋͆̈̔̇͗̍͑̎ͪͮͧͣ̽ͫͣ́ͬ̀͌͑͂͗͒̍̔̄ͧ̏̉̌̊̊̿̀̌̃̄͐̓̓̚̚҉̵̡͜͟͝͠͏̸̵̡̧͜҉̷̡͇̜̘̻̺̘̟̝͙̬̘̩͇̭̼̥̖̤̦͎k͉̩̘͚̜̹̗̗͍̤̥̱͉̳͕͖̤̲̣͚̮̞̬̲͍͔̯̻̮̞̭͈̗̫͓̂ͨ̉ͪ̒͋͛̀̍͊ͧ̿̅͆̓̔̔ͬ̇̑̿ͩ͗ͮ̎͌̿̄ͅP̴̵̡̡̛̪͙̼̣̟̩̭̫̱͙̬͔͉͍̘̠͉̦̝̘̥̟̗͖̫̤͕̙̬̦͍̱̖̮̱͑͐̎̃̒͐͋̚͘͞a̶̶̵̵̵̶̶̡̧̢̢̺͔̣͖̭̺͍̤͚̱̜̰̥͕̬̥̲̞̥̘͇͚̺̰͚̪̺͔̤͍̓̿͆̎͋̓ͦ̈́ͦ̌́̄͗̌̓͌̕͜͜͟͢͝͡ŕ͎̝͕͉̻͎̤̭͚̗̳̖̙̘͚̫͖͓͚͉͔͈̟̰̟̬̗͓̟͚̱̕͡ͅͅͅa̸̶̢̛̛̽ͮͩ̅͒ͫ͗͂̎ͦ̈́̓̚͘͜͢͡҉̷̵̶̢̡̜̮̦̜̥̜̯̙͓͔̼̗̻͜͜ͅḡ̢̛͕̗͖̖̤̦̘͔ͨͨ̊͒ͩͭͤ̍̅̃ͪ̋̏̓̍̋͗̋ͨ̏̽̈́̔̀̋̉ͫ̅̂ͭͫ̏͒͋ͥ̚͜r̶̢̧̧̥̤̼̀̂̒ͪ͌̿͌̅͛ͨͪ͒̍ͥ̉ͤ̌̿̆́ͭ͆̃̒ͤ͛̊ͧ̽͘͝͠a̧̢̧̢͑͑̓͑ͮ̃͂̄͛́̈́͋̂͌̽̄͒̔́̇ͨͧͭ͐ͦ̋ͨ̍ͦ̍̋͆̔ͧ͑͋͌̈̓͛͛̚͢͜͜͏̴̢̧̛̳͍̹͚̰̹̻͔p̨̡͆ͦͣ͊̽̔͂̉ͣ̔ͣ̌̌̉̃̋̂͒ͫ̄̎̐͗̉̌̃̽̽́̀̚͘͜͟҉̱͉h̭̮̘̗͔̜̯͔͈̯̺͔̗̣̭͚̱̰̙̼̹͚̣̻̥̲̮͍̤͜͝<";
3920 auto K = text.find(u"k");
3921 auto P = text.find(u"P");
3922 auto h = text.find(u"h");
3923 auto fontCollection = sk_make_sp<FontCollection>();
3924 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
3925 fontCollection->enableFontFallback();
3926 ParagraphStyle paragraph_style;
3927 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
3928 TextStyle text_style;
3929 text_style.setFontFamilies({SkString("Roboto")});
3930 text_style.setFontSize(20);
3931 text_style.setColor(SK_ColorRED);
3932 builder.pushStyle(text_style);
3933 builder.addText(std::u16string(text.data(), K + 3));
3934 text_style.setColor(SK_ColorBLUE);
3936 builder.pushStyle(text_style);
3937 builder.addText(std::u16string(text.data() + K + 3, P - K - 3 + 6));
3938 text_style.setColor(SK_ColorGREEN);
3939 builder.pushStyle(text_style);
3940 builder.addText(std::u16string(text.data() + P + 6, h - P - 6));
3941 text_style.setColor(SK_ColorBLACK);
3943 builder.pushStyle(text_style);
3944 builder.addText(std::u16string(text.data() + h, text.size() - h));
3945 auto paragraph = builder.Build();
3946 paragraph->layout(this->size().width());
3947 paragraph->paint(canvas, 0, 0);
3948 auto height = paragraph->getHeight();
3949 if (this->isVerbose()) {
3950 auto resSK = paragraph->getRectsForRange(0, K, RectHeightStyle::kTight,
3951 RectWidthStyle::kTight);
3952 TextBox rectSK(SkRect::MakeEmpty(), TextDirection::kLtr);
3953 if (resSK.empty()) {
3954 SkDebugf("rectSk is empty\n");
3955 } else {
3956 rectSK = resSK[0];
3957 SkDebugf("rectSk: [%f:%f] %s\n", rectSK.rect.fLeft, rectSK.rect.fRight,
3958 rectSK.direction == TextDirection::kRtl ? "rtl" : "ltr");
3959 }
3960
3961 auto resKP = paragraph->getRectsForRange(K, P, RectHeightStyle::kTight,
3962 RectWidthStyle::kTight);
3963 TextBox rectKP(SkRect::MakeEmpty(), TextDirection::kLtr);
3964 if (resKP.empty()) {
3965 SkDebugf("rectkP is empty\n");
3966 } else {
3967 rectKP = resKP[0];
3968 SkDebugf("rectkP: [%f:%f] %s\n", rectKP.rect.fLeft, rectKP.rect.fRight,
3969 rectKP.direction == TextDirection::kRtl ? "rtl" : "ltr");
3970 }
3971
3972 auto resPh = paragraph->getRectsForRange(P, h, RectHeightStyle::kTight,
3973 RectWidthStyle::kTight);
3974 TextBox rectPh(SkRect::MakeEmpty(), TextDirection::kLtr);
3975 if (resPh.empty()) {
3976 SkDebugf("rectPh is empty\n");
3977 } else {
3978 rectPh = resPh[0];
3979 SkDebugf("rectPh: [%f:%f] %s\n", rectPh.rect.fLeft, rectPh.rect.fRight,
3980 rectPh.direction == TextDirection::kRtl ? "rtl" : "ltr");
3981 }
3982 auto posK = paragraph->getGlyphPositionAtCoordinate(rectSK.rect.center().fX, height/2);
3983 auto posP = paragraph->getGlyphPositionAtCoordinate(rectKP.rect.center().fX, height/2);
3984 auto posH = paragraph->getGlyphPositionAtCoordinate(rectPh.rect.center().fX, height/2);
3985
3986 SkDebugf("%d(%s) %d(%s) %d(%s)\n",
3987 posK.position, posK.affinity == Affinity::kUpstream ? "up" : "down",
3988 posP.position, posP.affinity == Affinity::kUpstream ? "up" : "down",
3989 posH.position, posH.affinity == Affinity::kUpstream ? "up" : "down");
3990 }
3991 }
3992};
3993
3994class ParagraphSlide_MultiStyle_Arabic2 : public ParagraphSlide_Base {
3995public:
3996 ParagraphSlide_MultiStyle_Arabic2() { fName = SkString("ParagraphSlide_MultiStyle_Arabic2"); }
3997 void draw(SkCanvas* canvas) override {
3998 canvas->drawColor(SK_ColorWHITE);
3999 auto fontCollection = getFontCollection();
4000 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
4001 fontCollection->enableFontFallback();
4002 TextStyle text_style;
4003 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
4004 text_style.setFontSize(50);
4005 text_style.setColor(SK_ColorBLACK);
4006 ParagraphStyle paragraph_style;
4007 paragraph_style.setTextStyle(text_style);
4008 paragraph_style.setTextDirection(TextDirection::kRtl);
4009 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4010 text_style.setColor(SK_ColorRED);
4011 builder.pushStyle(text_style);
4012 builder.addText(u"\u062c\u064e\u0627\u0653");
4013 text_style.setColor(SK_ColorBLUE);
4014 builder.pushStyle(text_style);
4015 builder.addText(u"\u064e\u0647\u064f");
4016 auto paragraph = builder.Build();
4017 paragraph->layout(this->size().width());
4018 paragraph->paint(canvas, 0, 0);
4019 }
4020};
4021
4022class ParagraphSlideMixedTextDirection : public ParagraphSlide_Base {
4023public:
4024 ParagraphSlideMixedTextDirection() { fName = "ParagraphSlideMixedTextDirection"; }
4025 void draw(SkCanvas* canvas) override {
4026 canvas->drawColor(SK_ColorWHITE);
4027 auto fontCollection = getFontCollection();
4028 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
4029 fontCollection->enableFontFallback();
4030 TextStyle text_style;
4031 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
4032 text_style.setFontSize(100);
4033 text_style.setColor(SK_ColorBLACK);
4034 ParagraphStyle paragraph_style;
4035 paragraph_style.setTextStyle(text_style);
4036 paragraph_style.setTextAlign(TextAlign::kStart);
4037 paragraph_style.setEllipsis(u"\u2026");
4038 auto draw = [&](const std::u16string& text, size_t lines, TextDirection dir) {
4039 paragraph_style.setMaxLines(lines);
4040 paragraph_style.setTextDirection(dir);
4041 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4042 builder.pushStyle(text_style);
4043 builder.addText(text);
4044 auto paragraph = builder.Build();
4045 paragraph->layout(this->size().width()); // 841 474 953
4046 paragraph->paint(canvas, 0, 0);
4047 canvas->translate(0, paragraph->getHeight() + 10);
4048 };
4049
4050 draw(u"English text (defalt LTR)", 1, TextDirection::kLtr);
4051 draw(u"English text (defalt RTL)", 1, TextDirection::kRtl);
4052 draw(u"تظاهرات و(defalt LTR) تجمعات اعتراضی در سراسر کشور ۲۳ مهر", 2, TextDirection::kLtr);
4053 draw(u"تظاهرات و(defalt RTL) تجمعات اعتراضی در سراسر کشور ۲۳ مهر", 2, TextDirection::kRtl);
4054 }
4055};
4056
4057class ParagraphSlideGetPath : public ParagraphSlide_Base {
4058public:
4059 ParagraphSlideGetPath() { fName = "ParagraphSlideGetPath"; }
4060 void draw(SkCanvas* canvas) override {
4061 canvas->drawColor(SK_ColorWHITE);
4062 auto fontCollection = getFontCollection();
4063 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
4064 fontCollection->enableFontFallback();
4065 TextStyle text_style;
4066 text_style.setFontFamilies({SkString("Roboto")});
4067 text_style.setFontSize(50);
4068 text_style.setColor(SK_ColorBLACK);
4069 ParagraphStyle paragraph_style;
4070 paragraph_style.setTextStyle(text_style);
4071 paragraph_style.setTextAlign(TextAlign::kStart);
4072
4073 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4074 builder.pushStyle(text_style);
4075 builder.addText("Multi lined sticky notes drawn as paths");
4076 auto paragraph = builder.Build();
4077 paragraph->layout(this->size().width());
4078
4079 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4080 SkPath fullPath;
4081 SkScalar height = 0;
4082 for (auto& line : impl->lines()) {
4083 line.ensureTextBlobCachePopulated();
4084 for (auto& rec : line.fTextBlobCache) {
4085 auto paths = Paragraph::GetPath(rec.fBlob.get());
4086 paths.offset(0, height);
4087 fullPath.addPath(paths);
4088 height += line.height();
4089 }
4090 }
4091 SkRect rect = SkRect::MakeXYWH(100, 100 + paragraph->getHeight(), this->size().width(), paragraph->getHeight());
4092 SkPaint paint;
4093 paint.setShader(setgrad(rect, SK_ColorBLUE, SK_ColorLTGRAY));
4094 canvas->drawPath(fullPath, paint);
4095 }
4096};
4097
4098class ParagraphSlideExperiment : public ParagraphSlide_Base {
4099public:
4100 ParagraphSlideExperiment() { fName = "ParagraphSlideExperiment"; }
4101 void draw(SkCanvas* canvas) override {
4102 canvas->drawColor(SK_ColorWHITE);
4103 auto fontCollection = getFontCollection();
4104 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
4105 fontCollection->disableFontFallback();
4106 TextStyle text_style;
4107 text_style.setFontFamilies({SkString("Roboto")});
4108 text_style.setFontSize(50);
4109 text_style.setColor(SK_ColorBLACK);
4110 ParagraphStyle paragraph_style;
4111 paragraph_style.setTextStyle(text_style);
4112 paragraph_style.setTextAlign(TextAlign::kStart);
4113
4114 {
4115 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4116 builder.pushStyle(text_style);
4117 builder.addText("Sticky notes\non multple lines\nwith bounds around glyphs");
4118 auto paragraph = builder.Build();
4119 paragraph->layout(this->size().width());
4120 paragraph->paint(canvas, 0, 0);
4121 paragraph->extendedVisit([&](int, const skia::textlayout::Paragraph::ExtendedVisitorInfo* info) {
4122 if (!info) {
4123 return;
4124 }
4125 SkPaint paint;
4126 paint.setStyle(SkPaint::kStroke_Style);
4127 paint.setAntiAlias(true);
4128 paint.setStrokeWidth(1);
4129 for (auto i = 0; i < info->count; ++i) {
4130 paint.setColor(SK_ColorDKGRAY);
4131 SkRect rect(info->bounds[i]);
4132 rect.offset(info->positions[i]);
4133 rect.offset(info->origin);
4134 canvas->drawRect(rect, paint);
4135 }
4136 });
4137 canvas->translate(0, paragraph->getHeight() + 20);
4138 }
4139
4140 {
4141 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4142 builder.pushStyle(text_style);
4143 builder.addText("Sticky notes with glyphs changing position");
4144 auto paragraph = builder.Build();
4145 paragraph->layout(this->size().width());
4146 paragraph->paint(canvas, 0, 0);
4147 paragraph->extendedVisit([&](int, const skia::textlayout::Paragraph::ExtendedVisitorInfo* info) {
4148 if (!info) {
4149 return;
4150 }
4151 SkScalar offset = 0;
4152 for (auto i = 0; i < info->count; ++i) {
4153 info->positions[i].fY += offset;
4154 if (i % 3 == 0) {
4155 offset = 20;
4156 } else if (i % 3 == 1) {
4157 offset = -20;
4158 } else {
4159 offset = 0;
4160 }
4161 }
4162 });
4163 paragraph->paint(canvas, 0, 0);
4164 canvas->translate(0, paragraph->getHeight() + 40);
4165 }
4166
4167 {
4168 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4169 builder.pushStyle(text_style);
4170 builder.addText("Multi 😀 lined sticky notes drawn as paths");
4171 auto paragraph = builder.Build();
4172 paragraph->layout(300);
4173 SkPaint paint;
4174 std::vector<LineMetrics> metrics;
4175 paragraph->getLineMetrics(metrics);
4176 SkScalar height = 0;
4177 for (size_t lineNum = 0; lineNum < paragraph->lineNumber(); ++lineNum) {
4178 SkPath paths;
4179 paragraph->getPath(lineNum, &paths);
4180 auto& line = metrics[lineNum];
4181 SkRect rect = SkRect::MakeXYWH(line.fLeft, height, line.fWidth, line.fHeight);
4182 height += line.fHeight;
4183 paint.setShader(setgrad(rect, SK_ColorBLUE, SK_ColorLTGRAY));
4184 canvas->drawPath(paths, paint);
4185 }
4186 }
4187 }
4188};
4189
4190class ParagraphSlideGlyphs : public ParagraphSlide_Base {
4191public:
4192 ParagraphSlideGlyphs() { fName = "ParagraphSlideGlyphs"; }
4193 void draw(SkCanvas* canvas) override {
4194
4195 canvas->drawColor(SK_ColorWHITE);
4196 const char* text1 = "World domination is such an ugly phrase - I prefer to call it world optimisation";
4197 const char* text2 =
4198 "左線読設重説切abc後碁給能上目秘使約。満毎冠行 来昼本可 def 必図将発確年。今属場育"
4199 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
4200 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
4201 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
4202 "聞条年所在口。";
4203 const char* text3 = "من أسر وإعلان الخاصّة وهولندا،, عل def قائمة الضغوط بالمabcطالبة تلك. الصفحة "
4204 "بمباركة التقليدية قام عن. تصفح";
4205 auto fontCollection = sk_make_sp<FontCollection>();
4206 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
4207 fontCollection->enableFontFallback();
4208
4209 ParagraphStyle paragraph_style;
4210 paragraph_style.setTextAlign(TextAlign::kJustify);
4211
4212 auto draw = [&](const char* text, TextDirection textDirection) {
4213 paragraph_style.setTextDirection(textDirection);
4214 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4215 TextStyle text_style;
4216 text_style.setFontFamilies({SkString("Katibeh"), SkString("Roboto"), SkString("Source Han Serif CN")});
4217 text_style.setFontSize(40);
4218 text_style.setColor(SK_ColorBLACK);
4219 builder.pushStyle(text_style);
4220 builder.addText(text);
4221
4222 auto paragraph = builder.Build();
4223 paragraph->layout(this->size().width()); // 497
4224 paragraph->paint(canvas, 0, 0);
4225 canvas->translate(0, paragraph->getHeight() + 20);
4226 };
4227
4228 draw(text1, TextDirection::kLtr);
4229 draw(text2, TextDirection::kLtr);
4230 draw(text3, TextDirection::kLtr);
4231 }
4232};
4233
4234
4235class ParagraphSlideEllipsisInRTL : public ParagraphSlide_Base {
4236public:
4237 ParagraphSlideEllipsisInRTL() { fName = "ParagraphSlideEllipsisInRTL"; }
4238 void draw(SkCanvas* canvas) override {
4239 canvas->drawColor(SK_ColorWHITE);
4240 auto fontCollection = getFontCollection();
4241 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
4242 fontCollection->enableFontFallback();
4243 TextStyle text_style;
4244 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
4245 text_style.setFontSize(100);
4246 text_style.setColor(SK_ColorBLACK);
4247 ParagraphStyle paragraph_style;
4248 paragraph_style.setTextStyle(text_style);
4249 paragraph_style.setTextAlign(TextAlign::kStart);
4250 paragraph_style.setEllipsis(u"\u2026");
4251 auto draw = [&](const std::u16string& text) {
4252 paragraph_style.setMaxLines(1);
4253 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4254 builder.pushStyle(text_style);
4255 builder.addText(text);
4256 auto paragraph = builder.Build();
4257 paragraph->layout(this->size().width());
4258 paragraph->paint(canvas, 0, 0);
4259 canvas->translate(0, paragraph->getHeight() + 10);
4260 };
4261
4262 draw(u"你abcdefsdasdsasas");
4263 draw(u"한111111111111111111");
4264 draw(u"abcdefsdasds1112222");
4265 }
4266};
4267
4268class ParagraphSlideEmojiSequence : public ParagraphSlide_Base {
4269public:
4270 ParagraphSlideEmojiSequence() { fName = "ParagraphSlideEmojiSequence"; }
4271 void draw(SkCanvas* canvas) override {
4272 canvas->drawColor(SK_ColorWHITE);
4273 auto fontCollection = sk_make_sp<FontCollection>();
4274 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr(), std::vector<SkString>());
4275 fontCollection->enableFontFallback();
4276 TextStyle text_style;
4277 text_style.setFontFamilies({SkString("")});
4278 text_style.setFontSize(20);
4279 text_style.setColor(SK_ColorBLACK);
4280 ParagraphStyle paragraph_style;
4281 paragraph_style.setTextStyle(text_style);
4282
4283 auto test = [&](const char* text) {
4284 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4285 builder.pushStyle(text_style);
4286 builder.addText(text);
4287 auto paragraph = builder.Build();
4288 paragraph->layout(this->size().width());
4289 paragraph->paint(canvas, 0, 0);
4290 if ((false)) {
4291 SkDebugf("Paragraph '%s'\n", text);
4292 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4293 for (auto& run: impl->runs()) {
4294 SkString ff;
4295 run.font().getTypeface()->getFamilyName(&ff);
4296 SkDebugf("'%s': [%zu:%zu)\n", ff.c_str(), run.textRange().start, run.textRange().end);
4297 }
4298 }
4299 };
4300 test("2nd");
4301 canvas->translate(0, 50);
4302 test("99");
4303 canvas->translate(0, 50);
4304 test("999");
4305 canvas->translate(0, 50);
4306 /*
4307 test("🆗");
4308 canvas->translate(0, 50);
4309 test("0️⃣");
4310 canvas->translate(0, 50);
4311 test("0️⃣🆗");
4312 canvas->translate(0, 50);
4313 test("0");
4314 canvas->translate(0, 50);
4315 test("0️");
4316 canvas->translate(0, 50);
4317 test("♻️");
4318 canvas->translate(0, 50);
4319 test("󠁢󠁳󠁣󠁴󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿♻️");
4320 */
4321 }
4322};
4323
4324class ParagraphSlideWordSpacing : public ParagraphSlide_Base {
4325public:
4326 ParagraphSlideWordSpacing() { fName = "ParagraphWordSpacing"; }
4327
4328 void draw(SkCanvas* canvas) override {
4329 canvas->drawColor(SK_ColorWHITE);
4330
4331 auto fontCollection = sk_make_sp<FontCollection>();
4332 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr());
4333 fontCollection->enableFontFallback();
4334
4335 ParagraphStyle paragraph_style;
4336 TextStyle text_style;
4337 text_style.setColor(SK_ColorBLACK);
4338 text_style.setFontFamilies({});
4339 text_style.setFontSize(20.0);
4340
4341 auto draw = [&](TextDirection direction, SkScalar spacing, const char* text) {
4342 paragraph_style.setTextDirection(direction);
4343 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4344 text_style.setWordSpacing(spacing);
4345 builder.pushStyle(text_style);
4346 builder.addText(text);
4347 builder.pop();
4348 auto paragraph = builder.Build();
4349 paragraph->layout(this->size().width());
4350 paragraph->paint(canvas, 0, 0);
4351 canvas->translate(0, paragraph->getHeight() + 20);
4352 };
4353
4354 draw(TextDirection::kLtr, 20, "Lorem ipsum dolor sit amet");
4355 draw(TextDirection::kRtl, 20, "Lorem ipsum dolor sit amet");
4356
4357 draw(TextDirection::kLtr, 20, "טקסט ללא רווח בין מילים");
4358 draw(TextDirection::kRtl, 20, "טקסט ללא רווח בין מילים");
4359
4360 draw(TextDirection::kLtr, 20, "نص مع عدم وجود مسافات بين الكلمات");
4361 draw(TextDirection::kRtl, 20, "نص مع عدم وجود مسافات بين الكلمات");
4362 }
4363};
4364
4365class ParagraphSlideLast : public ParagraphSlide_Base {
4366public:
4367 ParagraphSlideLast() { fName = "ParagraphSlideLast"; }
4368 void draw(SkCanvas* canvas) override {
4369 canvas->drawColor(SK_ColorWHITE);
4370 auto fontCollection = sk_make_sp<FontCollection>();
4371 fontCollection->setDefaultFontManager(ToolUtils::TestFontMgr(), std::vector<SkString>());
4372 fontCollection->enableFontFallback();
4373 TextStyle text_style;
4374 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
4375 text_style.setFontSize(20);
4376 text_style.setColor(SK_ColorBLACK);
4377 ParagraphStyle paragraph_style;
4378 paragraph_style.setTextStyle(text_style);
4379
4380 auto test = [&](const char* text) {
4381 ParagraphBuilderImpl builder(paragraph_style, fontCollection, get_unicode());
4382 builder.pushStyle(text_style);
4383 builder.addText(text);
4384 auto paragraph = builder.Build();
4385 paragraph->layout(this->size().width());
4386 paragraph->paint(canvas, 0, 0);
4387 if ((false)) {
4388 SkDebugf("Paragraph '%s'\n", text);
4389 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4390 for (auto& run: impl->runs()) {
4391 SkString ff;
4392 run.font().getTypeface()->getFamilyName(&ff);
4393 SkDebugf("'%s': [%zu:%zu)\n", ff.c_str(), run.textRange().start, run.textRange().end);
4394 }
4395 }
4396 };
4397
4398 test("​🇳​🇩🇮🇩⃢");
4399 }
4400};
4401
4402} // namespace
4403
4404//////////////////////////////////////////////////////////////////////////////
4405DEF_SLIDE(return new ParagraphSlide1();)
4406DEF_SLIDE(return new ParagraphSlide2();)
4407DEF_SLIDE(return new ParagraphSlide3();)
4408DEF_SLIDE(return new ParagraphSlide5();)
4409DEF_SLIDE(return new ParagraphSlide6();)
4410DEF_SLIDE(return new ParagraphSlide7();)
4411DEF_SLIDE(return new ParagraphSlide8();)
4412DEF_SLIDE(return new ParagraphSlide9();)
4413DEF_SLIDE(return new ParagraphSlide10();)
4414DEF_SLIDE(return new ParagraphSlide11();)
4415DEF_SLIDE(return new ParagraphSlide12();)
4416DEF_SLIDE(return new ParagraphSlide14();)
4417DEF_SLIDE(return new ParagraphSlide15();)
4418DEF_SLIDE(return new ParagraphSlide16();)
4419DEF_SLIDE(return new ParagraphSlide17();)
4420DEF_SLIDE(return new ParagraphSlide18();)
4421DEF_SLIDE(return new ParagraphSlide19();)
4422DEF_SLIDE(return new ParagraphSlide20();)
4423DEF_SLIDE(return new ParagraphSlide21();)
4424DEF_SLIDE(return new ParagraphSlide22();)
4425DEF_SLIDE(return new ParagraphSlide23();)
4426DEF_SLIDE(return new ParagraphSlide24();)
4427DEF_SLIDE(return new ParagraphSlide25();)
4428DEF_SLIDE(return new ParagraphSlide26();)
4429DEF_SLIDE(return new ParagraphSlide27();)
4430DEF_SLIDE(return new ParagraphSlide28();)
4431DEF_SLIDE(return new ParagraphSlide29();)
4432DEF_SLIDE(return new ParagraphSlide30();)
4433DEF_SLIDE(return new ParagraphSlide31();)
4434DEF_SLIDE(return new ParagraphSlide32();)
4435DEF_SLIDE(return new ParagraphSlide33();)
4436DEF_SLIDE(return new ParagraphSlide34();)
4437DEF_SLIDE(return new ParagraphSlide35();)
4438DEF_SLIDE(return new ParagraphSlide36();)
4439DEF_SLIDE(return new ParagraphSlide37();)
4440DEF_SLIDE(return new ParagraphSlide38();)
4441DEF_SLIDE(return new ParagraphSlide39();)
4442DEF_SLIDE(return new ParagraphSlide41();)
4443DEF_SLIDE(return new ParagraphSlide42();)
4444DEF_SLIDE(return new ParagraphSlide43();)
4445DEF_SLIDE(return new ParagraphSlide44();)
4446DEF_SLIDE(return new ParagraphSlide45();)
4447DEF_SLIDE(return new ParagraphSlide46();)
4448DEF_SLIDE(return new ParagraphSlide47();)
4449DEF_SLIDE(return new ParagraphSlide48();)
4450DEF_SLIDE(return new ParagraphSlide49();)
4451DEF_SLIDE(return new ParagraphSlide50();)
4452DEF_SLIDE(return new ParagraphSlide51();)
4453DEF_SLIDE(return new ParagraphSlide52();)
4454DEF_SLIDE(return new ParagraphSlide53();)
4455DEF_SLIDE(return new ParagraphSlide54();)
4456DEF_SLIDE(return new ParagraphSlide55();)
4457DEF_SLIDE(return new ParagraphSlide56();)
4458DEF_SLIDE(return new ParagraphSlide57();)
4459DEF_SLIDE(return new ParagraphSlide58();)
4460DEF_SLIDE(return new ParagraphSlide59();)
4461DEF_SLIDE(return new ParagraphSlide60();)
4462DEF_SLIDE(return new ParagraphSlide61();)
4463DEF_SLIDE(return new ParagraphSlide62();)
4464DEF_SLIDE(return new ParagraphSlide63();)
4465DEF_SLIDE(return new ParagraphSlide64();)
4466DEF_SLIDE(return new ParagraphSlide66();)
4467DEF_SLIDE(return new ParagraphSlide67();)
4468DEF_SLIDE(return new ParagraphSlide68();)
4469DEF_SLIDE(return new ParagraphSlide_MultiStyle_Logo();)
4470DEF_SLIDE(return new ParagraphSlide_MultiStyle_FFI();)
4471DEF_SLIDE(return new ParagraphSlide_MultiStyle_EmojiFamily();)
4472DEF_SLIDE(return new ParagraphSlide_MultiStyle_Arabic1();)
4473DEF_SLIDE(return new ParagraphSlide_MultiStyle_Zalgo();)
4474DEF_SLIDE(return new ParagraphSlide_MultiStyle_Arabic2();)
4475DEF_SLIDE(return new ParagraphSlideMixedTextDirection();)
4476DEF_SLIDE(return new ParagraphSlideGetPath();)
4477DEF_SLIDE(return new ParagraphSlideExperiment();)
4478DEF_SLIDE(return new ParagraphSlideGlyphs();)
4479DEF_SLIDE(return new ParagraphSlideEllipsisInRTL();)
4480DEF_SLIDE(return new ParagraphSlideEmojiSequence();)
4481DEF_SLIDE(return new ParagraphSlideWordSpacing();)
4482DEF_SLIDE(return new ParagraphSlideLast();)
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define test(name)
const char * fName
SkPoint pos
static DEFINE_bool(verboseParagraph, false, "paragraph samples very verbose.")
SkString GetResourcePath(const char *resource)
Definition: Resources.cpp:23
#define SkASSERT(cond)
Definition: SkAssert.h:116
static unsigned mirror(SkFixed fx, int max)
constexpr SkColor SK_ColorYELLOW
Definition: SkColor.h:139
constexpr SkColor SK_ColorLTGRAY
Definition: SkColor.h:118
constexpr SkColor SK_ColorMAGENTA
Definition: SkColor.h:147
uint32_t SkColor
Definition: SkColor.h:37
#define SkColorSetRGB(r, g, b)
Definition: SkColor.h:57
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
constexpr SkColor SK_ColorGRAY
Definition: SkColor.h:113
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
constexpr SkColor SK_ColorDKGRAY
Definition: SkColor.h:108
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
#define SK_ScalarInfinity
Definition: SkScalar.h:26
sk_sp< SkUnicode > get_unicode()
int32_t SkUnichar
Definition: SkTypes.h:175
#define DEF_SLIDE(code)
Definition: Slide.h:25
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition: aaclip.cpp:27
virtual bool onClick(Click *)=0
virtual Click * onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi)=0
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1361
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
Definition: SkCanvas.h:1182
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
Definition: SkCanvas.cpp:2700
void clear(SkColor color)
Definition: SkCanvas.h:1199
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
static sk_sp< SkData > MakeFromFileName(const char path[])
Definition: SkData.cpp:148
static constexpr SkFontStyle Bold()
Definition: SkFontStyle.h:69
static constexpr SkFontStyle Normal()
Definition: SkFontStyle.h:66
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
void setStyle(Style style)
Definition: SkPaint.cpp:105
void setColor(SkColor color)
Definition: SkPaint.cpp:119
void setAntiAlias(bool aa)
Definition: SkPaint.h:170
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
void setStrokeWidth(SkScalar width)
Definition: SkPaint.cpp:159
Definition: SkPath.h:59
SkPath & addPath(const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
Definition: SkPath.cpp:1506
const char * c_str() const
Definition: SkString.h:133
virtual void resize(SkScalar winWidth, SkScalar winHeight)
Definition: Slide.h:41
virtual void load(SkScalar winWidth, SkScalar winHeight)
Definition: Slide.h:40
SkSpan< Cluster > clusters()
size_t index() const
Definition: Run.h:98
void setDecorationStyle(TextDecorationStyle style)
Definition: TextStyle.h:222
void addShadow(TextShadow shadow)
Definition: TextStyle.h:233
void setFontFamilies(std::vector< SkString > families)
Definition: TextStyle.h:253
void setHeight(SkScalar height)
Definition: TextStyle.h:260
void setLetterSpacing(SkScalar letterSpacing)
Definition: TextStyle.h:269
void setWordSpacing(SkScalar wordSpacing)
Definition: TextStyle.h:272
void setColor(SkColor color)
Definition: TextStyle.h:166
void setHeightOverride(bool heightOverride)
Definition: TextStyle.h:263
void setFontStyle(SkFontStyle fontStyle)
Definition: TextStyle.h:228
void setBackgroundColor(SkPaint paint)
Definition: TextStyle.h:204
void setLocale(const SkString &locale)
Definition: TextStyle.h:280
void setFontSize(SkScalar size)
Definition: TextStyle.h:250
void setForegroundColor(SkPaint paint)
Definition: TextStyle.h:181
void setDecorationColor(SkColor color)
Definition: TextStyle.h:223
void setDecoration(TextDecoration decoration)
Definition: TextStyle.h:220
void setDecorationMode(TextDecorationMode mode)
Definition: TextStyle.h:221
void setDecorationThicknessMultiplier(SkScalar m)
Definition: TextStyle.h:224
const Paint & paint
Definition: color_source.cc:38
static const int K
Definition: daa.cpp:21
DlColor color
float SkScalar
Definition: extension.cpp:12
static bool b
struct MyStruct s
if(end==-1)
GAsyncResult * result
static float max(float r, float g, float b)
Definition: hsl.cpp:49
std::u16string text
double y
double x
const SkScalar kBottom
constexpr SkColor4f kLtGray
Definition: SkColor.h:438
constexpr SkColor4f kMagenta
Definition: SkColor.h:445
constexpr SkColor4f kGreen
Definition: SkColor.h:441
constexpr SkColor4f kWhite
Definition: SkColor.h:439
constexpr SkColor4f kCyan
Definition: SkColor.h:444
constexpr SkColor4f kBlack
Definition: SkColor.h:435
constexpr SkColor4f kGray
Definition: SkColor.h:437
constexpr SkColor4f kBlue
Definition: SkColor.h:442
constexpr SkColor4f kYellow
Definition: SkColor.h:443
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
PODArray< SkColor > colors
Definition: SkRecords.h:276
sk_sp< Factory > BestAvailable()
sk_sp< SkFontMgr > TestFontMgr()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port fallback
Definition: switches.h:154
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
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
it will be possible to load the file into Perfetto s trace viewer disable asset fonts
Definition: switches.h:213
font
Font Metadata and Metrics.
const myers::Point & get< 1 >(const myers::Segment &s)
Definition: Myers.h:81
const myers::Point & get< 0 >(const myers::Segment &s)
Definition: Myers.h:80
Definition: run.py:1
def isVerbose()
Definition: idlsync.py:103
static void make(SkBitmap *bitmap, SkColorType colorType, SkAlphaType alphaType, sk_sp< SkColorSpace > colorSpace)
Definition: encode_srgb.cpp:35
ModifierKey
Definition: ModifierKey.h:9
@ kAlphabetic
Definition: text_baseline.h:23
static SkString to_string(int n)
Definition: nanobench.cpp:119
SkScalar w
SkScalar h
int32_t height
int32_t width
SeparatedVector2 offset
SkScalar fAscent
distance to reserve above baseline, typically negative
Definition: SkFontMetrics.h:54
SkScalar fDescent
distance to reserve below baseline, typically positive
Definition: SkFontMetrics.h:55
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15
Definition: SkSize.h:52
void setEllipsis(const std::u16string &ellipsis)
void setTextDirection(TextDirection direction)
void setTextStyle(const TextStyle &textStyle)
void setMaxLines(size_t maxLines)
void setHeight(SkScalar height)
void setStrutStyle(StrutStyle strutStyle)
void setTextHeightBehavior(TextHeightBehavior v)
void setTextAlign(TextAlign align)
PlaceholderAlignment fAlignment
Definition: TextStyle.h:138
void setFontFamilies(std::vector< SkString > families)
void setHeight(SkScalar height)
void setFontSize(SkScalar size)
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63