• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC.
2 #include "include/core/SkCanvas.h"
3 #include "include/core/SkColorFilter.h"
4 #include "include/core/SkColorPriv.h"
5 #include "include/core/SkFontMgr.h"
6 #include "include/core/SkGraphics.h"
7 #include "include/core/SkPath.h"
8 #include "include/core/SkRegion.h"
9 #include "include/core/SkShader.h"
10 #include "include/core/SkStream.h"
11 #include "include/core/SkTextBlob.h"
12 #include "include/core/SkTime.h"
13 #include "include/core/SkTypeface.h"
14 #include "include/effects/SkGradientShader.h"
15 #include "include/utils/SkRandom.h"
16 #include "modules/skparagraph/include/Paragraph.h"
17 #include "modules/skparagraph/include/TypefaceFontProvider.h"
18 #include "modules/skparagraph/src/ParagraphBuilderImpl.h"
19 #include "modules/skparagraph/src/ParagraphImpl.h"
20 #include "modules/skparagraph/src/TextLine.h"
21 #include "modules/skparagraph/utils/TestFontCollection.h"
22 #include "samplecode/Sample.h"
23 #include "src/core/SkOSFile.h"
24 #include "src/shaders/SkColorShader.h"
25 #include "src/utils/SkOSPath.h"
26 #include "src/utils/SkUTF.h"
27 #include "tools/Resources.h"
28 #include "tools/flags/CommandLineFlags.h"
29 
30 static DEFINE_bool(verboseParagraph, false, "paragraph samples very verbose.");
31 
32 using namespace skia::textlayout;
33 namespace {
34 
35 class ParagraphView_Base : public Sample {
36 protected:
getFontCollection()37     sk_sp<TestFontCollection> getFontCollection() {
38         // If we reset font collection we need to reset paragraph cache
39         static sk_sp<TestFontCollection> fFC = nullptr;
40         if (fFC == nullptr) {
41             fFC = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
42         }
43         return fFC;
44     }
45 
isVerbose()46     bool isVerbose() {
47         return FLAGS_verboseParagraph;
48     }
49 };
50 
setgrad(const SkRect & r,SkColor c0,SkColor c1)51 sk_sp<SkShader> setgrad(const SkRect& r, SkColor c0, SkColor c1) {
52     SkColor colors[] = {c0, c1};
53     SkPoint pts[] = {{r.fLeft, r.fTop}, {r.fRight, r.fTop}};
54     return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
55 }
56 /*
57 void writeHtml(const char* name, Paragraph* paragraph) {
58         SkString tmpDir = skiatest::GetTmpDir();
59         if (!tmpDir.isEmpty()) {
60             SkString path = SkOSPath::Join(tmpDir.c_str(), name);
61             SkFILEWStream file(path.c_str());
62             file.write(nullptr, 0);
63         }
64 }
65 */
66 
67 class ParagraphView1 : public ParagraphView_Base {
68 protected:
name()69     SkString name() override { return SkString("Paragraph1"); }
70 
drawTest(SkCanvas * canvas,SkScalar w,SkScalar h,SkColor fg,SkColor bg)71     void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) {
72         const std::vector<
73             std::tuple<std::string, bool, bool, int, SkColor, SkColor, bool, TextDecorationStyle>>
74             gParagraph = {{"monospace", true, false, 14, SK_ColorWHITE, SK_ColorRED, true,
75                            TextDecorationStyle::kDashed},
76                           {"Assyrian", false, false, 20, SK_ColorWHITE, SK_ColorBLUE, false,
77                            TextDecorationStyle::kDotted},
78                           {"serif", true, true, 10, SK_ColorWHITE, SK_ColorRED, true,
79                            TextDecorationStyle::kDouble},
80                           {"Arial", false, true, 16, SK_ColorGRAY, SK_ColorGREEN, true,
81                            TextDecorationStyle::kSolid},
82                           {"sans-serif", false, false, 8, SK_ColorWHITE, SK_ColorRED, false,
83                            TextDecorationStyle::kWavy}};
84         SkAutoCanvasRestore acr(canvas, true);
85 
86         canvas->clipRect(SkRect::MakeWH(w, h));
87         canvas->drawColor(SK_ColorWHITE);
88 
89         SkScalar margin = 20;
90 
91         SkPaint paint;
92         paint.setAntiAlias(true);
93         paint.setColor(fg);
94 
95         SkPaint blue;
96         blue.setColor(SK_ColorBLUE);
97 
98         TextStyle defaultStyle;
99         defaultStyle.setBackgroundColor(blue);
100         defaultStyle.setForegroundColor(paint);
101         ParagraphStyle paraStyle;
102 
103         auto fontCollection = sk_make_sp<FontCollection>();
104         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
105         for (auto i = 1; i < 5; ++i) {
106             defaultStyle.setFontSize(24 * i);
107             paraStyle.setTextStyle(defaultStyle);
108             ParagraphBuilderImpl builder(paraStyle, fontCollection);
109             std::string name = "Paragraph: " + std::to_string(24 * i);
110             builder.addText(name.c_str(), name.length());
111             for (auto para : gParagraph) {
112                 TextStyle style;
113                 style.setFontFamilies({SkString(std::get<0>(para).c_str())});
114                 SkFontStyle fontStyle(std::get<1>(para) ? SkFontStyle::Weight::kBold_Weight
115                                                         : SkFontStyle::Weight::kNormal_Weight,
116                                       SkFontStyle::Width::kNormal_Width,
117                                       std::get<2>(para) ? SkFontStyle::Slant::kItalic_Slant
118                                                         : SkFontStyle::Slant::kUpright_Slant);
119                 style.setFontStyle(fontStyle);
120                 style.setFontSize(std::get<3>(para) * i);
121                 SkPaint background;
122                 background.setColor(std::get<4>(para));
123                 style.setBackgroundColor(background);
124                 SkPaint foreground;
125                 foreground.setColor(std::get<5>(para));
126                 foreground.setAntiAlias(true);
127                 style.setForegroundColor(foreground);
128                 if (std::get<6>(para)) {
129                     style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(5, 5), 2));
130                 }
131 
132                 auto decoration = (i % 4);
133                 if (decoration == 3) {
134                     decoration = 4;
135                 }
136 
137                 bool test = (TextDecoration)decoration != TextDecoration::kNoDecoration;
138                 std::string deco = std::to_string((int)decoration);
139                 if (test) {
140                     style.setDecoration((TextDecoration)decoration);
141                     style.setDecorationStyle(std::get<7>(para));
142                     style.setDecorationColor(std::get<5>(para));
143                 }
144                 builder.pushStyle(style);
145                 name = " " + std::get<0>(para) + " " +
146                        (std::get<1>(para) ? ", bold" : "") +
147                        (std::get<2>(para) ? ", italic" : "") + " " +
148                        std::to_string(std::get<3>(para) * i) +
149                        (std::get<4>(para) != bg ? ", background" : "") +
150                        (std::get<5>(para) != fg ? ", foreground" : "") +
151                        (std::get<6>(para) ? ", shadow" : "") +
152                        (test ? ", decorations " + deco : "") + ";";
153                 builder.addText(name.c_str(), name.length());
154                 builder.pop();
155             }
156 
157             auto paragraph = builder.Build();
158             paragraph->layout(w - margin * 2);
159             paragraph->paint(canvas, margin, margin);
160 
161             canvas->translate(0, paragraph->getHeight());
162         }
163     }
164 
onDrawContent(SkCanvas * canvas)165     void onDrawContent(SkCanvas* canvas) override {
166         drawTest(canvas, this->width(), this->height(), SK_ColorRED, SK_ColorWHITE);
167     }
168 
169 private:
170 
171     using INHERITED = Sample;
172 };
173 
174 class ParagraphView2 : public ParagraphView_Base {
175 protected:
name()176     SkString name() override { return SkString("Paragraph2"); }
177 
drawCode(SkCanvas * canvas,SkScalar w,SkScalar h)178     void drawCode(SkCanvas* canvas, SkScalar w, SkScalar h) {
179         SkPaint comment;
180         comment.setColor(SK_ColorGRAY);
181         SkPaint constant;
182         constant.setColor(SK_ColorMAGENTA);
183         SkPaint null;
184         null.setColor(SK_ColorMAGENTA);
185         SkPaint literal;
186         literal.setColor(SK_ColorGREEN);
187         SkPaint code;
188         code.setColor(SK_ColorDKGRAY);
189         SkPaint number;
190         number.setColor(SK_ColorBLUE);
191         SkPaint name;
192         name.setColor(SK_ColorRED);
193 
194         SkPaint white;
195         white.setColor(SK_ColorWHITE);
196 
197         TextStyle defaultStyle;
198         defaultStyle.setBackgroundColor(white);
199         defaultStyle.setForegroundColor(code);
200         defaultStyle.setFontFamilies({SkString("monospace")});
201         defaultStyle.setFontSize(30);
202         ParagraphStyle paraStyle;
203         paraStyle.setTextStyle(defaultStyle);
204 
205         auto fontCollection = sk_make_sp<FontCollection>();
206         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
207         ParagraphBuilderImpl builder(paraStyle, fontCollection);
208 
209         const char* text1 = "RaisedButton";
210         const char* text2 = "(\n";
211         const char* text3 = "  child: ";
212         const char* text4 = "const";
213         const char* text5 = "Text";
214         const char* text6 = "'BUTTON TITLE'";
215         const char* text7 = "),\n";
216 
217         builder.pushStyle(style(name));
218         builder.addText(text1, strlen(text1));
219         builder.pop();
220         builder.addText(text2, strlen(text2));
221         builder.addText(text3, strlen(text3));
222         builder.pushStyle(style(constant));
223         builder.addText(text4, strlen(text4));
224         builder.pop();
225         builder.addText(" ", 1);
226         builder.pushStyle(style(name));
227         builder.addText(text5, strlen(text5));
228         builder.pop();
229         builder.addText("(", 1);
230         builder.pushStyle(style(literal));
231         builder.addText(text6, strlen(text6));
232         builder.pop();
233         builder.addText(text7, strlen(text7));
234 
235         auto paragraph = builder.Build();
236         paragraph->layout(w - 20);
237 
238         paragraph->paint(canvas, 20, 20);
239     }
240 
style(SkPaint paint)241     TextStyle style(SkPaint paint) {
242         TextStyle style;
243         paint.setAntiAlias(true);
244         style.setForegroundColor(paint);
245         style.setFontFamilies({SkString("monospace")});
246         style.setFontSize(30);
247 
248         return style;
249     }
250 
drawText(SkCanvas * canvas,SkScalar w,SkScalar h,std::vector<const char * > & text,SkColor fg=SK_ColorDKGRAY,SkColor bg=SK_ColorWHITE,const char * ff="sans-serif",SkScalar fs=24,size_t lineLimit=30,const std::u16string & ellipsis=u"\\u2026")251     void drawText(SkCanvas* canvas, SkScalar w, SkScalar h, std::vector<const char*>& text,
252                   SkColor fg = SK_ColorDKGRAY, SkColor bg = SK_ColorWHITE,
253                   const char* ff = "sans-serif", SkScalar fs = 24,
254                   size_t lineLimit = 30,
255                   const std::u16string& ellipsis = u"\u2026") {
256         SkAutoCanvasRestore acr(canvas, true);
257 
258         canvas->clipRect(SkRect::MakeWH(w, h));
259         canvas->drawColor(bg);
260 
261         SkScalar margin = 20;
262 
263         SkPaint paint;
264         paint.setAntiAlias(true);
265         paint.setColor(fg);
266 
267         SkPaint blue;
268         blue.setColor(SK_ColorBLUE);
269 
270         SkPaint background;
271         background.setColor(bg);
272 
273         TextStyle style;
274         style.setBackgroundColor(blue);
275         style.setForegroundColor(paint);
276         style.setFontFamilies({SkString(ff)});
277         style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight,
278                                        SkFontStyle::kNormal_Width,
279                                        SkFontStyle::kUpright_Slant));
280         style.setFontSize(fs);
281         ParagraphStyle paraStyle;
282         paraStyle.setTextStyle(style);
283         paraStyle.setMaxLines(lineLimit);
284 
285         paraStyle.setEllipsis(ellipsis);
286         TextStyle defaultStyle;
287         defaultStyle.setFontSize(20);
288         paraStyle.setTextStyle(defaultStyle);
289         ParagraphBuilderImpl builder(paraStyle, getFontCollection());
290 
291         SkPaint foreground;
292         foreground.setColor(fg);
293         style.setForegroundColor(foreground);
294         style.setBackgroundColor(background);
295 
296         for (auto& part : text) {
297             builder.pushStyle(style);
298             builder.addText(part, strlen(part));
299             builder.pop();
300         }
301 
302         auto paragraph = builder.Build();
303         paragraph->layout(w - margin * 2);
304         paragraph->paint(canvas, margin, margin);
305 
306         canvas->translate(0, paragraph->getHeight() + margin);
307     }
308 
drawLine(SkCanvas * canvas,SkScalar w,SkScalar h,const std::string & text,TextAlign align)309     void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
310                   TextAlign align) {
311         SkAutoCanvasRestore acr(canvas, true);
312 
313         canvas->clipRect(SkRect::MakeWH(w, h));
314         canvas->drawColor(SK_ColorWHITE);
315 
316         SkScalar margin = 20;
317 
318         SkPaint paint;
319         paint.setAntiAlias(true);
320         paint.setColor(SK_ColorBLUE);
321 
322         SkPaint gray;
323         gray.setColor(SK_ColorLTGRAY);
324 
325         TextStyle style;
326         style.setBackgroundColor(gray);
327         style.setForegroundColor(paint);
328         style.setFontFamilies({SkString("Arial")});
329         style.setFontSize(30);
330         ParagraphStyle paraStyle;
331         paraStyle.setTextStyle(style);
332         paraStyle.setTextAlign(align);
333 
334         auto fontCollection = sk_make_sp<FontCollection>();
335         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
336         ParagraphBuilderImpl builder(paraStyle, fontCollection);
337         builder.addText(text.c_str(), text.length());
338 
339         auto paragraph = builder.Build();
340         paragraph->layout(w - margin * 2);
341         paragraph->layout(w - margin);
342         paragraph->paint(canvas, margin, margin);
343 
344         canvas->translate(0, paragraph->getHeight() + margin);
345     }
346 
onDrawContent(SkCanvas * canvas)347     void onDrawContent(SkCanvas* canvas) override {
348         std::vector<const char*> cupertino = {
349                 "google_logogoogle_gsuper_g_logo 1 "
350                 "google_logogoogle_gsuper_g_logo 12 "
351                 "google_logogoogle_gsuper_g_logo 123 "
352                 "google_logogoogle_gsuper_g_logo 1234 "
353                 "google_logogoogle_gsuper_g_logo 12345 "
354                 "google_logogoogle_gsuper_g_logo 123456 "
355                 "google_logogoogle_gsuper_g_logo 1234567 "
356                 "google_logogoogle_gsuper_g_logo 12345678 "
357                 "google_logogoogle_gsuper_g_logo 123456789 "
358                 "google_logogoogle_gsuper_g_logo 1234567890 "
359                 "google_logogoogle_gsuper_g_logo 123456789 "
360                 "google_logogoogle_gsuper_g_logo 12345678 "
361                 "google_logogoogle_gsuper_g_logo 1234567 "
362                 "google_logogoogle_gsuper_g_logo 123456 "
363                 "google_logogoogle_gsuper_g_logo 12345 "
364                 "google_logogoogle_gsuper_g_logo 1234 "
365                 "google_logogoogle_gsuper_g_logo 123 "
366                 "google_logogoogle_gsuper_g_logo 12 "
367                 "google_logogoogle_gsuper_g_logo 1 "
368                 "google_logogoogle_gsuper_g_logo "
369                 "google_logogoogle_gsuper_g_logo "
370                 "google_logogoogle_gsuper_g_logo "
371                 "google_logogoogle_gsuper_g_logo "
372                 "google_logogoogle_gsuper_g_logo "
373                 "google_logogoogle_gsuper_g_logo"};
374         std::vector<const char*> text = {
375                 "My neighbor came over to say,\n"
376                 "Although not in a neighborly way,\n\n"
377                 "That he'd knock me around,\n\n\n"
378                 "If I didn't stop the sound,\n\n\n\n"
379                 "Of the classical music I play."};
380 
381         std::vector<const char*> long_word = {
382                 "A_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
383                 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
384                 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
385                 "very_very_very_very_very_very_very_long_text"};
386 
387         std::vector<const char*> very_long = {
388                 "A very very very very very very very very very very very very very very very very "
389                 "very very very very very very very very very very very very very very very very "
390                 "very very very very very very very very very very very very very very very very "
391                 "very very very very very very very long text"};
392 
393         std::vector<const char*> very_word = {
394                 "A very_very_very_very_very_very_very_very_very_very "
395                 "very_very_very_very_very_very_very_very_very_very very very very very very very "
396                 "very very very very very very very very very very very very very very very very "
397                 "very very very very very very very very very very very very very long text"};
398 
399         SkScalar width = this->width() / 5;
400         SkScalar height = this->height();
401         drawText(canvas, width, height, long_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
402         canvas->translate(width, 0);
403         drawText(canvas, width, height, very_long, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
404         canvas->translate(width, 0);
405         drawText(canvas, width, height, very_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
406         canvas->translate(width, 0);
407         drawText(canvas, width, height / 2, text, SK_ColorBLACK, SK_ColorWHITE, "Roboto", 20, 100,
408                  u"\u2026");
409         canvas->translate(0, height / 2);
410         drawCode(canvas, width, height / 2);
411         canvas->translate(width, -height / 2);
412 
413         drawText(canvas, width, height, cupertino, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
414     }
415 
416 private:
417     using INHERITED = Sample;
418 };
419 
420 class ParagraphView3 : public ParagraphView_Base {
421 protected:
name()422     SkString name() override { return SkString("Paragraph3"); }
423 
drawLine(SkCanvas * canvas,SkScalar w,SkScalar h,const std::string & text,TextAlign align,size_t lineLimit=std::numeric_limits<size_t>::max (),bool RTL=false,SkColor background=SK_ColorGRAY,const std::u16string & ellipsis=u"\\u2026")424     void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
425                   TextAlign align, size_t lineLimit = std::numeric_limits<size_t>::max(),
426                   bool RTL = false, SkColor background = SK_ColorGRAY,
427                   const std::u16string& ellipsis = u"\u2026") {
428         SkAutoCanvasRestore acr(canvas, true);
429 
430         canvas->clipRect(SkRect::MakeWH(w, h));
431         canvas->drawColor(SK_ColorWHITE);
432 
433         SkScalar margin = 20;
434 
435         SkPaint paint;
436         paint.setAntiAlias(true);
437         paint.setColor(SK_ColorBLACK);
438 
439         SkPaint gray;
440         gray.setColor(background);
441 
442         SkPaint yellow;
443         yellow.setColor(SK_ColorYELLOW);
444 
445         TextStyle style;
446         style.setBackgroundColor(gray);
447         style.setForegroundColor(paint);
448         style.setFontFamilies({SkString("sans-serif")});
449         style.setFontSize(30);
450         ParagraphStyle paraStyle;
451         paraStyle.setTextStyle(style);
452         paraStyle.setTextAlign(align);
453         paraStyle.setMaxLines(lineLimit);
454         paraStyle.setEllipsis(ellipsis);
455         // paraStyle.setTextDirection(RTL ? SkTextDirection::rtl : SkTextDirection::ltr);
456 
457         auto fontCollection = sk_make_sp<FontCollection>();
458         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
459         ParagraphBuilderImpl builder(paraStyle, fontCollection);
460         if (RTL) {
461             builder.addText(mirror(text));
462         } else {
463             builder.addText(normal(text));
464         }
465 
466         canvas->drawRect(SkRect::MakeXYWH(margin, margin, w - margin * 2, h - margin * 2), yellow);
467         auto paragraph = builder.Build();
468         paragraph->layout(w - margin * 2);
469         paragraph->paint(canvas, margin, margin);
470     }
471 
mirror(const std::string & text)472     std::u16string mirror(const std::string& text) {
473         std::u16string result;
474         result += u"\u202E";
475         // for (auto i = text.size(); i > 0; --i) {
476         //  result += text[i - 1];
477         //}
478 
479         for (auto i = text.size(); i > 0; --i) {
480             auto ch = text[i - 1];
481             if (ch == ',') {
482                 result += u"!";
483             } else if (ch == '.') {
484                 result += u"!";
485             } else {
486                 result += ch;
487             }
488         }
489 
490         result += u"\u202C";
491         return result;
492     }
493 
normal(const std::string & text)494     std::u16string normal(const std::string& text) {
495         std::u16string result;
496         result += u"\u202D";
497         for (auto ch : text) {
498             result += ch;
499         }
500         result += u"\u202C";
501         return result;
502     }
503 
onDrawContent(SkCanvas * canvas)504     void onDrawContent(SkCanvas* canvas) override {
505         const std::string options =  // { "open-source open-source open-source open-source" };
506                 {"Flutter is an open-source project to help developers "
507                  "build high-performance, high-fidelity, mobile apps for "
508                  "iOS and Android "
509                  "from a single codebase. This design lab is a playground "
510                  "and showcase of Flutter's many widgets, behaviors, "
511                  "animations, layouts, and more."};
512 
513         canvas->drawColor(SK_ColorDKGRAY);
514         SkScalar width = this->width() / 4;
515         SkScalar height = this->height() / 2;
516 
517         const std::string line =
518                 "World domination is such an ugly phrase - I prefer to call it world optimisation";
519 
520         drawLine(canvas, width, height, line, TextAlign::kLeft, 1, false, SK_ColorLTGRAY);
521         canvas->translate(width, 0);
522         drawLine(canvas, width, height, line, TextAlign::kRight, 2, false, SK_ColorLTGRAY);
523         canvas->translate(width, 0);
524         drawLine(canvas, width, height, line, TextAlign::kCenter, 3, false, SK_ColorLTGRAY);
525         canvas->translate(width, 0);
526         drawLine(canvas, width, height, line, TextAlign::kJustify, 4, false, SK_ColorLTGRAY);
527         canvas->translate(-width * 3, height);
528 
529         drawLine(canvas, width, height, line, TextAlign::kLeft, 1, true, SK_ColorLTGRAY);
530         canvas->translate(width, 0);
531         drawLine(canvas, width, height, line, TextAlign::kRight, 2, true, SK_ColorLTGRAY);
532         canvas->translate(width, 0);
533         drawLine(canvas, width, height, line, TextAlign::kCenter, 3, true, SK_ColorLTGRAY);
534         canvas->translate(width, 0);
535         drawLine(canvas, width, height, line, TextAlign::kJustify, 4, true, SK_ColorLTGRAY);
536         canvas->translate(width, 0);
537     }
538 
539 private:
540     using INHERITED = Sample;
541 };
542 
543 class ParagraphView4 : public ParagraphView_Base {
544 protected:
name()545     SkString name() override { return SkString("Paragraph4"); }
546 
drawFlutter(SkCanvas * canvas,SkScalar w,SkScalar h,const char * ff="Google Sans",SkScalar fs=30,size_t lineLimit=std::numeric_limits<size_t>::max (),const std::u16string & ellipsis=u"\\u2026")547     void drawFlutter(SkCanvas* canvas, SkScalar w, SkScalar h,
548                      const char* ff = "Google Sans", SkScalar fs = 30,
549                      size_t lineLimit = std::numeric_limits<size_t>::max(),
550                      const std::u16string& ellipsis = u"\u2026") {
551         SkAutoCanvasRestore acr(canvas, true);
552 
553         canvas->clipRect(SkRect::MakeWH(w, h));
554 
555         SkScalar margin = 20;
556 
557         SkPaint black;
558         black.setAntiAlias(true);
559         black.setColor(SK_ColorBLACK);
560 
561         SkPaint blue;
562         blue.setAntiAlias(true);
563         blue.setColor(SK_ColorBLUE);
564 
565         SkPaint red;
566         red.setAntiAlias(true);
567         red.setColor(SK_ColorRED);
568 
569         SkPaint green;
570         green.setAntiAlias(true);
571         green.setColor(SK_ColorGREEN);
572 
573         SkPaint gray;
574         gray.setColor(SK_ColorLTGRAY);
575 
576         SkPaint yellow;
577         yellow.setColor(SK_ColorYELLOW);
578 
579         SkPaint magenta;
580         magenta.setAntiAlias(true);
581         magenta.setColor(SK_ColorMAGENTA);
582 
583         TextStyle style;
584         style.setFontFamilies({SkString(ff)});
585         style.setFontSize(fs);
586 
587         TextStyle style0;
588         style0.setForegroundColor(black);
589         style0.setBackgroundColor(gray);
590         style0.setFontFamilies({SkString(ff)});
591         style0.setFontSize(fs);
592         style0.setDecoration(TextDecoration::kUnderline);
593         style0.setDecorationStyle(TextDecorationStyle::kDouble);
594         style0.setDecorationColor(SK_ColorBLACK);
595 
596         TextStyle style1;
597         style1.setForegroundColor(blue);
598         style1.setBackgroundColor(yellow);
599         style1.setFontFamilies({SkString(ff)});
600         style1.setFontSize(fs);
601         style1.setDecoration(TextDecoration::kOverline);
602         style1.setDecorationStyle(TextDecorationStyle::kWavy);
603         style1.setDecorationColor(SK_ColorBLACK);
604 
605         TextStyle style2;
606         style2.setForegroundColor(red);
607         style2.setFontFamilies({SkString(ff)});
608         style2.setFontSize(fs);
609 
610         TextStyle style3;
611         style3.setForegroundColor(green);
612         style3.setFontFamilies({SkString(ff)});
613         style3.setFontSize(fs);
614 
615         TextStyle style4;
616         style4.setForegroundColor(magenta);
617         style4.setFontFamilies({SkString(ff)});
618         style4.setFontSize(fs);
619 
620         ParagraphStyle paraStyle;
621         paraStyle.setTextStyle(style);
622         paraStyle.setMaxLines(lineLimit);
623 
624         paraStyle.setEllipsis(ellipsis);
625 
626         const char* logo1 = "google_";
627         const char* logo2 = "logo";
628         const char* logo3 = "go";
629         const char* logo4 = "ogle_logo";
630         const char* logo5 = "google_lo";
631         const char* logo6 = "go";
632         {
633             ParagraphBuilderImpl builder(paraStyle, getFontCollection());
634 
635             builder.pushStyle(style0);
636             builder.addText(logo1, strlen(logo1));
637             builder.pop();
638             builder.pushStyle(style1);
639             builder.addText(logo2, strlen(logo2));
640             builder.pop();
641 
642             builder.addText(" ", 1);
643 
644             builder.pushStyle(style0);
645             builder.addText(logo3, strlen(logo3));
646             builder.pop();
647             builder.pushStyle(style1);
648             builder.addText(logo4, strlen(logo4));
649             builder.pop();
650 
651             builder.addText(" ", 1);
652 
653             builder.pushStyle(style0);
654             builder.addText(logo5, strlen(logo5));
655             builder.pop();
656             builder.pushStyle(style1);
657             builder.addText(logo6, strlen(logo6));
658             builder.pop();
659 
660             auto paragraph = builder.Build();
661             paragraph->layout(w - margin * 2);
662             paragraph->paint(canvas, margin, margin);
663             canvas->translate(0, h + margin);
664         }
665     }
666 
onDrawContent(SkCanvas * canvas)667     void onDrawContent(SkCanvas* canvas) override {
668         canvas->drawColor(SK_ColorWHITE);
669         SkScalar width = this->width();
670         SkScalar height = this->height();
671 
672         drawFlutter(canvas, width, height / 2);
673     }
674 
675 private:
676     using INHERITED = Sample;
677 };
678 
679 class ParagraphView5 : public ParagraphView_Base {
680 protected:
name()681     SkString name() override { return SkString("Paragraph5"); }
682 
bidi(SkCanvas * canvas,SkScalar w,SkScalar h,const std::u16string & text,const std::u16string & expected,size_t lineLimit=std::numeric_limits<size_t>::max (),const char * ff="Roboto",SkScalar fs=30,const std::u16string & ellipsis=u"\\u2026")683     void bidi(SkCanvas* canvas, SkScalar w, SkScalar h, const std::u16string& text,
684               const std::u16string& expected, size_t lineLimit = std::numeric_limits<size_t>::max(),
685               const char* ff = "Roboto", SkScalar fs = 30,
686               const std::u16string& ellipsis = u"\u2026") {
687         SkAutoCanvasRestore acr(canvas, true);
688 
689         canvas->clipRect(SkRect::MakeWH(w, h));
690 
691         SkScalar margin = 20;
692 
693         SkPaint black;
694         black.setColor(SK_ColorBLACK);
695         SkPaint gray;
696         gray.setColor(SK_ColorLTGRAY);
697 
698         TextStyle style;
699         style.setForegroundColor(black);
700         style.setFontFamilies({SkString(ff)});
701         style.setFontSize(fs);
702 
703         TextStyle style0;
704         style0.setForegroundColor(black);
705         style0.setFontFamilies({SkString(ff)});
706         style0.setFontSize(fs);
707         style0.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
708                                         SkFontStyle::kItalic_Slant));
709 
710         TextStyle style1;
711         style1.setForegroundColor(gray);
712         style1.setFontFamilies({SkString(ff)});
713         style1.setFontSize(fs);
714         style1.setFontStyle(SkFontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
715                                         SkFontStyle::kUpright_Slant));
716 
717         ParagraphStyle paraStyle;
718         paraStyle.setTextStyle(style);
719         paraStyle.setMaxLines(lineLimit);
720 
721         paraStyle.setEllipsis(ellipsis);
722 
723         ParagraphBuilderImpl builder(paraStyle, getFontCollection());
724 
725         if (text.empty()) {
726             const std::u16string text0 = u"\u202Dabc";
727             const std::u16string text1 = u"\u202EFED";
728             const std::u16string text2 = u"\u202Dghi";
729             const std::u16string text3 = u"\u202ELKJ";
730             const std::u16string text4 = u"\u202Dmno";
731             builder.pushStyle(style0);
732             builder.addText(text0);
733             builder.pop();
734             builder.pushStyle(style1);
735             builder.addText(text1);
736             builder.pop();
737             builder.pushStyle(style0);
738             builder.addText(text2);
739             builder.pop();
740             builder.pushStyle(style1);
741             builder.addText(text3);
742             builder.pop();
743             builder.pushStyle(style0);
744             builder.addText(text4);
745             builder.pop();
746         } else {
747             builder.addText(text + expected);
748         }
749 
750         auto paragraph = builder.Build();
751         auto impl = static_cast<ParagraphImpl*>(paragraph.get());
752         if (this->isVerbose()) {
753             SkDebugf("Text: >%s<\n", impl->text().data());
754         }
755 
756         paragraph->layout(w - margin * 2);
757         paragraph->paint(canvas, margin, margin);
758     }
759 
onDrawContent(SkCanvas * canvas)760     void onDrawContent(SkCanvas* canvas) override {
761         canvas->drawColor(SK_ColorWHITE);
762         SkScalar width = this->width();
763         SkScalar height = this->height() / 8;
764 
765         const std::u16string text1 =
766                 u"A \u202ENAC\u202Cner, exceedingly \u202ENAC\u202Cny,\n"
767                 "One morning remarked to his granny:\n"
768                 "A \u202ENAC\u202Cner \u202ENAC\u202C \u202ENAC\u202C,\n"
769                 "Anything that he \u202ENAC\u202C,\n"
770                 "But a \u202ENAC\u202Cner \u202ENAC\u202C't \u202ENAC\u202C a \u202ENAC\u202C, "
771                 "\u202ENAC\u202C he?";
772         bidi(canvas, width, height * 3, text1, u"", 5);
773         canvas->translate(0, height * 3);
774 
775         bidi(canvas, width, height, u"\u2067DETALOSI\u2069", u"");
776         canvas->translate(0, height);
777 
778         bidi(canvas, width, height, u"\u202BDEDDEBME\u202C", u"");
779         canvas->translate(0, height);
780 
781         bidi(canvas, width, height, u"\u202EEDIRREVO\u202C", u"");
782         canvas->translate(0, height);
783 
784         bidi(canvas, width, height, u"\u200FTICILPMI\u200E", u"");
785         canvas->translate(0, height);
786 
787         bidi(canvas, width, height, u"123 456 7890 \u202EZYXWV UTS RQP ONM LKJ IHG FED CBA\u202C.",
788              u"", 2);
789         canvas->translate(0, height);
790 
791         // bidi(canvas, width, height, u"", u"");
792         // canvas->translate(0, height);
793     }
794 
795 private:
796     using INHERITED = Sample;
797 };
798 
799 class ParagraphView6 : public ParagraphView_Base {
800 protected:
name()801     SkString name() override { return SkString("Paragraph6"); }
802 
hangingS(SkCanvas * canvas,SkScalar w,SkScalar h,SkScalar fs=60.0)803     void hangingS(SkCanvas* canvas, SkScalar w, SkScalar h, SkScalar fs = 60.0) {
804         auto ff = "HangingS";
805 
806         canvas->drawColor(SK_ColorLTGRAY);
807 
808         SkPaint black;
809         black.setAntiAlias(true);
810         black.setColor(SK_ColorBLACK);
811 
812         SkPaint blue;
813         blue.setAntiAlias(true);
814         blue.setColor(SK_ColorBLUE);
815 
816         SkPaint red;
817         red.setAntiAlias(true);
818         red.setColor(SK_ColorRED);
819 
820         SkPaint green;
821         green.setAntiAlias(true);
822         green.setColor(SK_ColorGREEN);
823 
824         SkPaint gray;
825         gray.setColor(SK_ColorCYAN);
826 
827         SkPaint yellow;
828         yellow.setColor(SK_ColorYELLOW);
829 
830         SkPaint magenta;
831         magenta.setAntiAlias(true);
832         magenta.setColor(SK_ColorMAGENTA);
833 
834         SkFontStyle fontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
835                               SkFontStyle::kItalic_Slant);
836 
837         TextStyle style;
838         style.setFontFamilies({SkString(ff)});
839         style.setFontSize(fs);
840         style.setFontStyle(fontStyle);
841 
842         TextStyle style0;
843         style0.setForegroundColor(black);
844         style0.setBackgroundColor(gray);
845         style0.setFontFamilies({SkString(ff)});
846         style0.setFontSize(fs);
847         style0.setFontStyle(fontStyle);
848 
849         TextStyle style1;
850         style1.setForegroundColor(blue);
851         style1.setBackgroundColor(yellow);
852         style1.setFontFamilies({SkString(ff)});
853         style1.setFontSize(fs);
854         style1.setFontStyle(fontStyle);
855 
856         TextStyle style2;
857         style2.setForegroundColor(red);
858         style2.setFontFamilies({SkString(ff)});
859         style2.setFontSize(fs);
860         style2.setFontStyle(fontStyle);
861 
862         TextStyle style3;
863         style3.setForegroundColor(green);
864         style3.setFontFamilies({SkString(ff)});
865         style3.setFontSize(fs);
866         style3.setFontStyle(fontStyle);
867 
868         TextStyle style4;
869         style4.setForegroundColor(magenta);
870         style4.setFontFamilies({SkString(ff)});
871         style4.setFontSize(fs);
872         style4.setFontStyle(fontStyle);
873 
874         ParagraphStyle paraStyle;
875         paraStyle.setTextStyle(style);
876 
877         const char* logo1 = "S";
878         const char* logo2 = "kia";
879         const char* logo3 = "Sk";
880         const char* logo4 = "ia";
881         const char* logo5 = "Ski";
882         const char* logo6 = "a";
883         {
884             ParagraphBuilderImpl builder(paraStyle, getFontCollection());
885 
886             builder.pushStyle(style0);
887             builder.addText(logo1, strlen(logo1));
888             builder.pop();
889             builder.pushStyle(style1);
890             builder.addText(logo2, strlen(logo2));
891             builder.pop();
892 
893             builder.addText("   ", 3);
894 
895             builder.pushStyle(style0);
896             builder.addText(logo3, strlen(logo3));
897             builder.pop();
898             builder.pushStyle(style1);
899             builder.addText(logo4, strlen(logo4));
900             builder.pop();
901 
902             builder.addText("   ", 3);
903 
904             builder.pushStyle(style0);
905             builder.addText(logo5, strlen(logo5));
906             builder.pop();
907             builder.pushStyle(style1);
908             builder.addText(logo6, strlen(logo6));
909             builder.pop();
910 
911             auto paragraph = builder.Build();
912             paragraph->layout(w);
913             paragraph->paint(canvas, 40, 40);
914             canvas->translate(0, h);
915         }
916 
917         const char* logo11 = "S";
918         const char* logo12 = "S";
919         const char* logo13 = "S";
920         const char* logo14 = "S";
921         const char* logo15 = "S";
922         const char* logo16 = "S";
923         {
924             ParagraphBuilderImpl builder(paraStyle, getFontCollection());
925 
926             builder.pushStyle(style0);
927             builder.addText(logo11, strlen(logo1));
928             builder.pop();
929             builder.pushStyle(style1);
930             builder.addText(logo12, strlen(logo2));
931             builder.pop();
932 
933             builder.addText("   ", 3);
934 
935             builder.pushStyle(style0);
936             builder.addText(logo13, strlen(logo3));
937             builder.pop();
938             builder.pushStyle(style1);
939             builder.addText(logo14, strlen(logo4));
940             builder.pop();
941 
942             builder.addText("   ", 3);
943 
944             builder.pushStyle(style0);
945             builder.addText(logo15, strlen(logo5));
946             builder.pop();
947             builder.pushStyle(style1);
948             builder.addText(logo16, strlen(logo6));
949             builder.pop();
950 
951             auto paragraph = builder.Build();
952             paragraph->layout(w);
953             paragraph->paint(canvas, 40, h);
954             canvas->translate(0, h);
955         }
956     }
957 
onDrawContent(SkCanvas * canvas)958     void onDrawContent(SkCanvas* canvas) override {
959         canvas->drawColor(SK_ColorWHITE);
960         SkScalar width = this->width();
961         SkScalar height = this->height() / 4;
962 
963         hangingS(canvas, width, height);
964     }
965 
966 private:
967     using INHERITED = Sample;
968 };
969 
970 class ParagraphView7 : public ParagraphView_Base {
971 protected:
name()972     SkString name() override { return SkString("Paragraph7"); }
973 
drawText(SkCanvas * canvas,SkColor background,SkScalar letterSpace,SkScalar w,SkScalar h)974     void drawText(SkCanvas* canvas, SkColor background, SkScalar letterSpace, SkScalar w,
975                   SkScalar h) {
976         SkAutoCanvasRestore acr(canvas, true);
977         canvas->clipRect(SkRect::MakeWH(w, h));
978         canvas->drawColor(background);
979 
980         const char* line =
981                 "World domination is such an ugly phrase - I prefer to call it world optimisation.";
982 
983         ParagraphStyle paragraphStyle;
984         paragraphStyle.setTextAlign(TextAlign::kLeft);
985         paragraphStyle.setMaxLines(10);
986         paragraphStyle.turnHintingOff();
987         TextStyle textStyle;
988         textStyle.setFontFamilies({SkString("Roboto")});
989         textStyle.setFontSize(30);
990         textStyle.setLetterSpacing(letterSpace);
991         textStyle.setColor(SK_ColorBLACK);
992         textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
993                                            SkFontStyle::kUpright_Slant));
994 
995         ParagraphBuilderImpl builder(paragraphStyle, getFontCollection());
996         builder.pushStyle(textStyle);
997         builder.addText(line, strlen(line));
998         builder.pop();
999 
1000         auto paragraph = builder.Build();
1001         paragraph->layout(w - 20);
1002         paragraph->paint(canvas, 10, 10);
1003     }
1004 
onDrawContent(SkCanvas * canvas)1005     void onDrawContent(SkCanvas* canvas) override {
1006         canvas->drawColor(SK_ColorWHITE);
1007 
1008         auto h = this->height() / 4;
1009         auto w = this->width() / 2;
1010 
1011         drawText(canvas, SK_ColorGRAY, 1, w, h);
1012         canvas->translate(0, h);
1013 
1014         drawText(canvas, SK_ColorLTGRAY, 2, w, h);
1015         canvas->translate(0, h);
1016 
1017         drawText(canvas, SK_ColorCYAN, 3, w, h);
1018         canvas->translate(0, h);
1019 
1020         drawText(canvas, SK_ColorGRAY, 4, w, h);
1021         canvas->translate(w, -3 * h);
1022 
1023         drawText(canvas, SK_ColorYELLOW, 5, w, h);
1024         canvas->translate(0, h);
1025 
1026         drawText(canvas, SK_ColorGREEN, 10, w, h);
1027         canvas->translate(0, h);
1028 
1029         drawText(canvas, SK_ColorRED, 15, w, h);
1030         canvas->translate(0, h);
1031 
1032         drawText(canvas, SK_ColorBLUE, 20, w, h);
1033         canvas->translate(0, h);
1034     }
1035 
1036 private:
1037     using INHERITED = Sample;
1038 };
1039 
1040 class ParagraphView8 : public ParagraphView_Base {
1041 protected:
name()1042     SkString name() override { return SkString("Paragraph8"); }
1043 
drawText(SkCanvas * canvas,SkColor background,SkScalar wordSpace,SkScalar w,SkScalar h)1044     void drawText(SkCanvas* canvas, SkColor background, SkScalar wordSpace, SkScalar w,
1045                   SkScalar h) {
1046         SkAutoCanvasRestore acr(canvas, true);
1047         canvas->clipRect(SkRect::MakeWH(w, h));
1048         canvas->drawColor(background);
1049 
1050         const char* line =
1051                 "World domination is such an ugly phrase - I prefer to call it world optimisation.";
1052 
1053         ParagraphStyle paragraphStyle;
1054         paragraphStyle.setTextAlign(TextAlign::kLeft);
1055         paragraphStyle.setMaxLines(10);
1056         paragraphStyle.turnHintingOff();
1057         TextStyle textStyle;
1058         textStyle.setFontFamilies({SkString("Roboto")});
1059         textStyle.setFontSize(30);
1060         textStyle.setWordSpacing(wordSpace);
1061         textStyle.setColor(SK_ColorBLACK);
1062         textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1063                                            SkFontStyle::kUpright_Slant));
1064 
1065         ParagraphBuilderImpl builder(paragraphStyle, getFontCollection());
1066         builder.pushStyle(textStyle);
1067         builder.addText(line, strlen(line));
1068         builder.pop();
1069 
1070         auto paragraph = builder.Build();
1071         paragraph->layout(w - 20);
1072         paragraph->paint(canvas, 10, 10);
1073     }
1074 
onDrawContent(SkCanvas * canvas)1075     void onDrawContent(SkCanvas* canvas) override {
1076         canvas->drawColor(SK_ColorWHITE);
1077 
1078         auto h = this->height() / 4;
1079         auto w = this->width() / 2;
1080 
1081         drawText(canvas, SK_ColorGRAY, 1, w, h);
1082         canvas->translate(0, h);
1083 
1084         drawText(canvas, SK_ColorLTGRAY, 2, w, h);
1085         canvas->translate(0, h);
1086 
1087         drawText(canvas, SK_ColorCYAN, 3, w, h);
1088         canvas->translate(0, h);
1089 
1090         drawText(canvas, SK_ColorGRAY, 4, w, h);
1091         canvas->translate(w, -3 * h);
1092 
1093         drawText(canvas, SK_ColorYELLOW, 5, w, h);
1094         canvas->translate(0, h);
1095 
1096         drawText(canvas, SK_ColorGREEN, 10, w, h);
1097         canvas->translate(0, h);
1098 
1099         drawText(canvas, SK_ColorRED, 15, w, h);
1100         canvas->translate(0, h);
1101 
1102         drawText(canvas, SK_ColorBLUE, 20, w, h);
1103         canvas->translate(0, h);
1104     }
1105 
1106 private:
1107     using INHERITED = Sample;
1108 };
1109 
1110 class ParagraphView9 : public ParagraphView_Base {
1111 protected:
name()1112     SkString name() override { return SkString("Paragraph9"); }
1113 
onChar(SkUnichar uni)1114     bool onChar(SkUnichar uni) override {
1115             switch (uni) {
1116                 case 'w':
1117                     ++wordSpacing;
1118                     return true;
1119                 case 'q':
1120                     if (wordSpacing > 0) --wordSpacing;
1121                     return true;
1122                 case 'l':
1123                     ++letterSpacing;
1124                     return true;
1125                 case 'k':
1126                     if (letterSpacing > 0) --letterSpacing;
1127                     return true;
1128                 default:
1129                     break;
1130             }
1131             return false;
1132     }
1133 
drawText(SkCanvas * canvas,SkColor background,SkScalar w,SkScalar h)1134     void drawText(SkCanvas* canvas, SkColor background, SkScalar w, SkScalar h) {
1135         SkAutoCanvasRestore acr(canvas, true);
1136         canvas->clipRect(SkRect::MakeWH(w, h));
1137         canvas->drawColor(background);
1138 
1139         auto fontCollection = sk_make_sp<FontCollection>();
1140         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1141         fontCollection->enableFontFallback();
1142 
1143         const char* text =
1144                 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1145                 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1146                 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
1147         auto multiplier = 5.67;
1148         ParagraphStyle paragraphStyle;
1149         paragraphStyle.setTextAlign(TextAlign::kLeft);
1150         paragraphStyle.setMaxLines(10);
1151         paragraphStyle.turnHintingOff();
1152         TextStyle textStyle;
1153         textStyle.setFontFamilies({SkString("Roboto")});
1154         textStyle.setFontSize(5 * multiplier);
1155         textStyle.setHeight(1.3f);
1156         textStyle.setColor(SK_ColorBLACK);
1157         textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1158                                            SkFontStyle::kUpright_Slant));
1159 
1160         ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
1161         builder.pushStyle(textStyle);
1162         builder.addText(text, strlen(text));
1163         builder.pop();
1164 
1165         auto paragraph = builder.Build();
1166         paragraph->layout(200 * multiplier);
1167 
1168         std::vector<size_t> sizes = {0, 1, 2, 8, 19, 21, 22, 30, 150};
1169 
1170         std::vector<size_t> colors = {SK_ColorBLUE, SK_ColorCYAN,  SK_ColorLTGRAY, SK_ColorGREEN,
1171                                       SK_ColorRED,  SK_ColorWHITE, SK_ColorYELLOW, SK_ColorMAGENTA};
1172 
1173         RectHeightStyle rect_height_style = RectHeightStyle::kTight;
1174         RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1175 
1176         for (size_t i = 0; i < sizes.size() - 1; ++i) {
1177             size_t from = sizes[i];
1178             size_t to = sizes[i + 1];
1179             auto boxes = paragraph->getRectsForRange(from, to, rect_height_style, rect_width_style);
1180             if (boxes.empty()) {
1181                 continue;
1182             }
1183             for (auto& box : boxes) {
1184                 SkPaint paint;
1185                 paint.setColor(colors[i % colors.size()]);
1186                 paint.setShader(setgrad(box.rect, colors[i % colors.size()], SK_ColorWHITE));
1187                 canvas->drawRect(box.rect, paint);
1188             }
1189         }
1190 
1191         paragraph->paint(canvas, 0, 0);
1192     }
1193 
onDrawContent(SkCanvas * canvas)1194     void onDrawContent(SkCanvas* canvas) override {
1195         canvas->drawColor(SK_ColorWHITE);
1196 
1197         auto h = this->height();
1198         auto w = this->width();
1199 
1200         drawText(canvas, SK_ColorGRAY, w, h);
1201     }
1202 
1203 private:
1204     using INHERITED = Sample;
1205     SkScalar letterSpacing;
1206     SkScalar wordSpacing;
1207 };
1208 
1209 class ParagraphView10 : public ParagraphView_Base {
1210 protected:
name()1211     SkString name() override { return SkString("Paragraph10"); }
1212 
onDrawContent(SkCanvas * canvas)1213     void onDrawContent(SkCanvas* canvas) override {
1214         canvas->drawColor(SK_ColorWHITE);
1215         auto multiplier = 5.67;
1216         const char* text = "English English 字典 字典 ������ ������";
1217 
1218         auto fontCollection = sk_make_sp<FontCollection>();
1219         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1220         fontCollection->enableFontFallback();
1221 
1222         ParagraphStyle paragraph_style;
1223         paragraph_style.turnHintingOff();
1224         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1225 
1226         TextStyle text_style;
1227         text_style.setFontFamilies({SkString("Roboto"),
1228                                     SkString("Noto Color Emoji"),
1229                                     SkString("Noto Serif CJK JP")});
1230         text_style.setFontSize(10 * multiplier);
1231         text_style.setLetterSpacing(0);
1232         text_style.setWordSpacing(0);
1233         text_style.setColor(SK_ColorBLACK);
1234         text_style.setHeight(1);
1235         builder.pushStyle(text_style);
1236         builder.addText(text, strlen(text));
1237         builder.pop();
1238 
1239         auto paragraph = builder.Build();
1240         paragraph->layout(width());
1241 
1242         paragraph->paint(canvas, 0, 0);
1243     }
1244 
1245 private:
1246     using INHERITED = Sample;
1247 };
1248 
1249 class ParagraphView11 : public ParagraphView_Base {
1250 protected:
name()1251     SkString name() override { return SkString("Paragraph11"); }
1252 
onDrawContent(SkCanvas * canvas)1253     void onDrawContent(SkCanvas* canvas) override {
1254         canvas->drawColor(SK_ColorWHITE);
1255 
1256         auto text = "\U0001f469\U0000200D\U0001f469\U0000200D\U0001f466\U0001f469\U0000200D\U0001f469\U0000200D\U0001f467\U0000200D\U0001f467\U0001f1fa\U0001f1f8";
1257 
1258         TextStyle text_style;
1259         text_style.setFontFamilies({SkString("Ahem")});
1260         text_style.setColor(SK_ColorBLACK);
1261         text_style.setFontSize(60);
1262         text_style.setLetterSpacing(0);
1263         text_style.setWordSpacing(0);
1264         ParagraphStyle paragraph_style;
1265         paragraph_style.setTextStyle(text_style);
1266 
1267         auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
1268         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1269         builder.addText(text, strlen(text));
1270         auto paragraph = builder.Build();
1271         paragraph->layout(1000);
1272         paragraph->paint(canvas, 0, 0);
1273 
1274         struct pair {
1275             unsigned fX;
1276             unsigned fY;
1277         };
1278 
1279         pair hit1[] =
1280               {{ 0, 8},{1, 33}, {2, 34}, { 3, 19}, {4, 20},
1281                { 5, 21}, { 6, 22 }, { 7, 23 }, {8, 24 }, { 9, 25},
1282                { 10, 26}, { 11, 27}, {12, 28}, { 13, 21}, {14, 22 },
1283                { 15, 23}, {16, 24}, {17, 21}, { 18, 22}, {19, 21},
1284                { 20, 24}, { 21, 23}, };
1285 
1286         pair miss[] =
1287               {{ 0, 4},{1, 17}, {2, 18}, { 3, 11}, {4, 12},
1288                { 5, 13}, { 6, 14 }, { 7, 15 }, {8, 16 }, { 9, 17},
1289                { 10, 18}, { 11, 19}, {12, 20}, { 13, 17}, {14, 18 },
1290                { 15, 19}, {16, 20}, {17, 19}, { 18, 20},
1291                { 20, 22}, };
1292 
1293         auto rects = paragraph->getRectsForRange(7, 9, RectHeightStyle::kTight,
1294                                                  RectWidthStyle::kTight);
1295         SkPaint paint;
1296         paint.setColor(SK_ColorRED);
1297         paint.setStyle(SkPaint::kStroke_Style);
1298         paint.setAntiAlias(true);
1299         paint.setStrokeWidth(1);
1300         if (!rects.empty()) {
1301             canvas->drawRect(rects[0].rect, paint);
1302         }
1303 
1304         for (auto& query : hit1) {
1305             auto hitRects = paragraph->getRectsForRange(query.fX, query.fY, RectHeightStyle::kTight,
1306                                                         RectWidthStyle::kTight);
1307             if (hitRects.size() >= 1 && hitRects[0].rect.width() > 0) {
1308             } else {
1309                 if (this->isVerbose()) {
1310                     SkDebugf("+[%d:%d): Bad\n", query.fX, query.fY);
1311                 }
1312             }
1313         }
1314 
1315         for (auto& query : miss) {
1316             auto missRects = paragraph->getRectsForRange(query.fX, query.fY,
1317                                                          RectHeightStyle::kTight,
1318                                                          RectWidthStyle::kTight);
1319             if (missRects.empty()) {
1320             } else {
1321                 if (this->isVerbose()) {
1322                     SkDebugf("-[%d:%d): Bad\n", query.fX, query.fY);
1323                 }
1324             }
1325         }
1326     }
1327 
1328 private:
1329     using INHERITED = Sample;
1330 };
1331 
1332 class ParagraphView12 : public ParagraphView_Base {
1333 protected:
name()1334     SkString name() override { return SkString("Paragraph12"); }
1335 
onDrawContent(SkCanvas * canvas)1336     void onDrawContent(SkCanvas* canvas) override {
1337         canvas->drawColor(SK_ColorWHITE);
1338 
1339         const char* text = "Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges";
1340         TextStyle text_style;
1341         text_style.setFontFamilies({SkString("Ahem")});
1342         text_style.setColor(SK_ColorBLACK);
1343         text_style.setFontSize(16);
1344         //text_style.setLetterSpacing(-0.41);
1345         StrutStyle strut_style;
1346         strut_style.setStrutEnabled(false);
1347         ParagraphStyle paragraph_style;
1348         paragraph_style.setStrutStyle(strut_style);
1349         paragraph_style.setTextStyle(text_style);
1350         ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1351         builder.addText(text);
1352         auto paragraph = builder.Build();
1353         paragraph->layout(1095.000000);
1354         auto result = paragraph->getRectsForRange(65, 66, RectHeightStyle::kTight, RectWidthStyle::kTight);
1355         paragraph->paint(canvas, 0, 0);
1356 
1357         SkPaint paint;
1358         paint.setColor(SK_ColorRED);
1359         paint.setStyle(SkPaint::kStroke_Style);
1360         paint.setAntiAlias(true);
1361         paint.setStrokeWidth(1);
1362         if (!result.empty()) {
1363             canvas->drawRect(result.front().rect, paint);
1364         }
1365     }
1366 
1367 private:
1368     using INHERITED = Sample;
1369 };
1370 
1371 class ParagraphView14 : public ParagraphView_Base {
1372 protected:
name()1373     SkString name() override { return SkString("Paragraph14"); }
1374 
onDrawContent(SkCanvas * canvas)1375     void onDrawContent(SkCanvas* canvas) override {
1376         canvas->drawColor(SK_ColorWHITE);
1377         TextStyle text_style;
1378         text_style.setFontFamilies({SkString("Ahem")});
1379         text_style.setColor(SK_ColorBLACK);
1380         text_style.setFontSize(25);
1381         text_style.setDecoration((TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1382         text_style.setDecorationColor(SK_ColorBLUE);
1383         text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1384         text_style.setDecorationThicknessMultiplier(4.0f);
1385         ParagraphStyle paragraph_style;
1386         paragraph_style.setTextStyle(text_style);
1387         paragraph_style.setTextDirection(TextDirection::kRtl);
1388         ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1389         builder.pushStyle(text_style);
1390         builder.addText("Hello, wor!\nabcd.");
1391         auto paragraph = builder.Build();
1392         paragraph->layout(300);
1393         paragraph->paint(canvas, 0, 0);
1394         SkPaint paint;
1395         paint.setColor(SK_ColorRED);
1396         paint.setStyle(SkPaint::kStroke_Style);
1397         paint.setAntiAlias(true);
1398         paint.setStrokeWidth(1);
1399         canvas->drawRect(SkRect::MakeXYWH(0, 0, 300, 100), paint);
1400     }
1401 
1402 private:
1403     using INHERITED = Sample;
1404 };
1405 
1406 class ParagraphView15 : public ParagraphView_Base {
1407 protected:
name()1408     SkString name() override { return SkString("Paragraph15"); }
1409 
onDrawContent(SkCanvas * canvas)1410     void onDrawContent(SkCanvas* canvas) override {
1411         canvas->drawColor(SK_ColorWHITE);
1412 
1413         TextStyle text_style;
1414         text_style.setFontFamilies({SkString("abc.ttf")});
1415         text_style.setFontSize(50);
1416 
1417         auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
1418 
1419         fontCollection->addFontFromFile("abc/abc.ttf", "abc");
1420         fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave");
1421         fontCollection->addFontFromFile("abc/abc+agrave.ttf", "abc+agrave");
1422 
1423         ParagraphStyle paragraph_style;
1424         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1425 
1426         text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
1427         text_style.setColor(SK_ColorBLUE);
1428         builder.pushStyle(text_style);
1429         builder.addText(u"a\u0300");
1430         text_style.setColor(SK_ColorMAGENTA);
1431         builder.pushStyle(text_style);
1432         builder.addText(u"à");
1433 
1434         text_style.setFontFamilies({SkString("abc"), SkString("abc+agrave")});
1435 
1436         text_style.setColor(SK_ColorRED);
1437         builder.pushStyle(text_style);
1438         builder.addText(u"a\u0300");
1439         text_style.setColor(SK_ColorGREEN);
1440         builder.pushStyle(text_style);
1441         builder.addText(u"à");
1442 
1443         auto paragraph = builder.Build();
1444         paragraph->layout(800);
1445         paragraph->paint(canvas, 50, 50);
1446 
1447     }
1448 
1449 private:
1450     using INHERITED = Sample;
1451 };
1452 
1453 class ParagraphView16 : public ParagraphView_Base {
1454 protected:
name()1455     SkString name() override { return SkString("Paragraph16"); }
1456 
onDrawContent(SkCanvas * canvas)1457     void onDrawContent(SkCanvas* canvas) override {
1458         canvas->drawColor(SK_ColorWHITE);
1459 
1460         const char* text = "content";
1461 
1462         ParagraphStyle paragraph_style;
1463         paragraph_style.setMaxLines(1);
1464         paragraph_style.setEllipsis(u"\u2026");
1465         //auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1466         auto fontCollection = sk_make_sp<FontCollection>();
1467         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1468         fontCollection->enableFontFallback();
1469         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1470 
1471         TextStyle text_style;
1472         text_style.setFontFamilies({SkString(".SF Pro Text")});
1473         text_style.setColor(SK_ColorBLACK);
1474         text_style.setFontSize(17.0f * 99.0f);
1475         text_style.setLetterSpacing(0.41f);
1476         builder.pushStyle(text_style);
1477         builder.addText(text);
1478 
1479         auto paragraph = builder.Build();
1480         paragraph->layout(800);
1481         paragraph->paint(canvas, 0, 0);
1482     }
1483 
1484 private:
1485     using INHERITED = Sample;
1486 };
1487 
1488 class ParagraphView17 : public ParagraphView_Base {
1489 protected:
name()1490     SkString name() override { return SkString("Paragraph17"); }
1491 
onDrawContent(SkCanvas * canvas)1492     void onDrawContent(SkCanvas* canvas) override {
1493         canvas->drawColor(SK_ColorWHITE);
1494 
1495         auto fontCollection = sk_make_sp<FontCollection>();
1496         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1497         fontCollection->enableFontFallback();
1498         auto navy = SkColorSetRGB(0, 0, 139);
1499         auto ltgray = SkColorSetRGB(211, 211, 211);
1500         auto multiplier = 5.67;
1501 
1502         //const char* text = ">Sͬ͑̀͐̈͒̈́̋̎ͮͩ̽̓ͬ̂̆̔͗́̓ͣͧ͊ͫ͛̉͌̐̑ͪ͗̚͝҉̴͉͢k̡̊̓ͫͭͩ͂͊ͨͪͬ̑ͫ̍̌̄͛̌̂̑̂̋̊̔ͫ͛̽̑ͨ̍ͭ̓̀ͪͪ̉͐͗̌̓̃̚͟͝҉̢͏̫̞̙͇͖̮͕̗̟͕͇͚̻͈̣̻̪͉̰̲̣̫ͅͅP̴̅̍͒̿͗͗̇ͩ̃͆͌̀̽͏̧̡͕͖̝̖̼̺̰̣̬͔͖͔̼͙̞̦̫͓̘͜a̸̴̸̴̢̢̨̨̫͍͓̥̼̭̼̻̤̯̙̤̻̠͚̍̌͋̂ͦͨ̽̇͌͌͆̀̽̎͒̄ͪ̐ͦ̈ͫ͐͗̓̚̚͜ͅr͐͐ͤͫ̐ͥ͂̈́̿́ͮ̃͗̓̏ͫ̀̿͏̸̵̧́͘̕͟͝͠͞͠҉̷̧͚͢͟a̓̽̎̄͗̔͛̄̐͊͛ͫ͂͌̂̂̈̈̓̔̅̅̄͊̉́ͪ̑̄͆ͬ̍͆ͭ͋̐ͬ͏̷̵̨̢̩̹̖͓̥̳̰͔̱̬͖̙͓̙͇̀̀̕͜͟͟͢͟͜͠͡g̨̅̇ͦ͋̂ͦͨͭ̓͐͆̏̂͛̉ͧ̑ͫ̐̒͛ͫ̍̒͛́̚҉̷̨̛̛̀͜͢͞҉̩̘̲͍͎̯̹̝̭̗̱͇͉̲̱͔̯̠̹̥̻͉̲̜̤̰̪̗̺̖̺r̷͌̓̇̅ͭ̀̐̃̃ͭ͑͗̉̈̇̈́ͥ̓ͣ́ͤ͂ͤ͂̏͌̆̚҉̴̸̧̢̢̛̫͉̦̥̤̙͈͉͈͉͓̙̗̟̳̜͈̗̺̟̠̠͖͓̖̪͕̠̕̕͝ͅả̸̴̡̡̧͠͞͡͞҉̛̕͟͏̷̘̪̱͈̲͉̞̠̞̪̫͎̲̬̖̀̀͟͝͞͞͠p̛͂̈͐̚͠҉̵̸̡̢̢̩̹͙̯͖̙̙̮̥̙͚̠͔̥̭̮̞̣̪̬̥̠̖̝̥̪͎́̀̕͜͡͡ͅͅh̵̷̵̡̛ͤ̂͌̐̓̐̋̋͊̒̆̽́̀̀̀͢͠͞͞҉̷̸̢̕҉͚̯͖̫̜̞̟̠̱͉̝̲̹̼͉̟͉̩̮͔̤͖̞̭̙̹̬ͅ<";
1503         const char* text = ">S͛ͭ̋͆̈̔̇͗̍͑̎ͪͮͧͣ̽ͫͣ́ͬ̀͌͑͂͗͒̍̔̄ͧ̏̉̌̊̊̿̀̌̃̄͐̓̓̚̚҉̵̡͜͟͝͠͏̸̵̡̧͜҉̷̡͇̜̘̻̺̘̟̝͙̬̘̩͇̭̼̥̖̤̦͎k͉̩̘͚̜̹̗̗͍̤̥̱͉̳͕͖̤̲̣͚̮̞̬̲͍͔̯̻̮̞̭͈̗̫͓̂ͨ̉ͪ̒͋͛̀̍͊ͧ̿̅͆̓̔̔ͬ̇̑̿ͩ͗ͮ̎͌̿̄ͅP̴̵̡̡̛̪͙̼̣̟̩̭̫̱͙̬͔͉͍̘̠͉̦̝̘̥̟̗͖̫̤͕̙̬̦͍̱̖̮̱͑͐̎̃̒͐͋̚͘͞a̶̶̵̵̵̶̶̡̧̢̢̺͔̣͖̭̺͍̤͚̱̜̰̥͕̬̥̲̞̥̘͇͚̺̰͚̪̺͔̤͍̓̿͆̎͋̓ͦ̈́ͦ̌́̄͗̌̓͌̕͜͜͟͢͝͡ŕ͎̝͕͉̻͎̤̭͚̗̳̖̙̘͚̫͖͓͚͉͔͈̟̰̟̬̗͓̟͚̱̕͡ͅͅͅa̸̶̢̛̛̽ͮͩ̅͒ͫ͗͂̎ͦ̈́̓̚͘͜͢͡҉̷̵̶̢̡̜̮̦̜̥̜̯̙͓͔̼̗̻͜͜ͅḡ̢̛͕̗͖̖̤̦̘͔ͨͨ̊͒ͩͭͤ̍̅̃ͪ̋̏̓̍̋͗̋ͨ̏̽̈́̔̀̋̉ͫ̅̂ͭͫ̏͒͋ͥ̚͜r̶̢̧̧̥̤̼̀̂̒ͪ͌̿͌̅͛ͨͪ͒̍ͥ̉ͤ̌̿̆́ͭ͆̃̒ͤ͛̊ͧ̽͘͝͠a̧̢̧̢͑͑̓͑ͮ̃͂̄͛́̈́͋̂͌̽̄͒̔́̇ͨͧͭ͐ͦ̋ͨ̍ͦ̍̋͆̔ͧ͑͋͌̈̓͛͛̚͢͜͜͏̴̢̧̛̳͍̹͚̰̹̻͔p̨̡͆ͦͣ͊̽̔͂̉ͣ̔ͣ̌̌̉̃̋̂͒ͫ̄̎̐͗̉̌̃̽̽́̀̚͘͜͟҉̱͉h̭̮̘̗͔̜̯͔͈̯̺͔̗̣̭͚̱̰̙̼̹͚̣̻̥̲̮͍̤͜͝<";
1504         ParagraphStyle paragraph_style;
1505         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1506         SkPaint paint;
1507         paint.setColor(ltgray);
1508         TextStyle text_style;
1509         text_style.setBackgroundColor(paint);
1510         text_style.setColor(navy);
1511         text_style.setFontFamilies({SkString("Roboto")});
1512         text_style.setFontSize(20 * multiplier);
1513         builder.pushStyle(text_style);
1514         builder.addText(text);
1515         auto paragraph = builder.Build();
1516         paragraph->layout(10000);
1517         paragraph->paint(canvas, 0, 0);
1518     }
1519 
1520 private:
1521     using INHERITED = Sample;
1522 };
1523 
1524 class Zalgo {
1525     private:
1526     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";
1527     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";
1528     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";
1529 
randomMarks(std::u16string & combiningMarks)1530     std::u16string randomMarks(std::u16string& combiningMarks) {
1531         std::u16string result;
1532         auto num = std::rand() % (combiningMarks.size() / 1);
1533         for (size_t i = 0; i < num; ++i) {
1534             auto index = std::rand() % combiningMarks.size();
1535             result += combiningMarks[index];
1536         }
1537         return result;
1538     }
1539 
1540 public:
zalgo(std::string victim)1541     std::u16string zalgo(std::string victim) {
1542         std::u16string result;
1543         for (auto& c : victim) {
1544             result += c;
1545             result += randomMarks(COMBINING_UP);
1546             result += randomMarks(COMBINING_MIDDLE);
1547             result += randomMarks(COMBINING_DOWN);
1548         }
1549         return result;
1550     }
1551 };
1552 
1553 class ParagraphView18 : public ParagraphView_Base {
1554 protected:
name()1555     SkString name() override { return SkString("Paragraph18"); }
1556 
onChar(SkUnichar uni)1557     bool onChar(SkUnichar uni) override {
1558             switch (uni) {
1559                 case ' ':
1560                     fLimit = 400;
1561                     return true;
1562                 case 's':
1563                     fLimit += 10;
1564                     return true;
1565                 case 'f':
1566                     if (fLimit > 10) {
1567                         fLimit -= 10;
1568                     }
1569                     return true;
1570                 default:
1571                     break;
1572             }
1573             return false;
1574     }
1575 
onAnimate(double nanos)1576     bool onAnimate(double nanos) override {
1577         if (++fIndex > fLimit) {
1578             fRedraw = true;
1579             fIndex = 0;
1580         } else {
1581             fRepeat = true;
1582         }
1583         return true;
1584     }
1585 
onDrawContent(SkCanvas * canvas)1586     void onDrawContent(SkCanvas* canvas) override {
1587         canvas->drawColor(SK_ColorWHITE);
1588 
1589         auto navy = SkColorSetRGB(0, 0, 139);
1590         auto ltgray = SkColorSetRGB(211, 211, 211);
1591 
1592         auto multiplier = 5.67;
1593         auto fontCollection = sk_make_sp<FontCollection>();
1594         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1595         fontCollection->enableFontFallback();
1596 
1597         ParagraphStyle paragraph_style;
1598         TextStyle text_style;
1599         text_style.setFontFamilies({SkString("Roboto")});
1600         text_style.setFontSize(20 * multiplier);
1601         text_style.setColor(navy);
1602         SkPaint paint;
1603         paint.setColor(ltgray);
1604         text_style.setBackgroundColor(paint);
1605 
1606         Zalgo zalgo;
1607 
1608         if (fRedraw || fRepeat) {
1609 
1610             if (fRedraw || fParagraph == nullptr) {
1611                 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1612                 builder.pushStyle(text_style);
1613                 auto utf16text = zalgo.zalgo("SkParagraph");
1614                 builder.addText(utf16text);
1615                 fParagraph = builder.Build();
1616             }
1617 
1618             auto impl = static_cast<ParagraphImpl*>(fParagraph.get());
1619             if (this->isVerbose()) {
1620                 SkDebugf("Text:>%s<\n", impl->text().data());
1621             }
1622             impl->setState(InternalState::kUnknown);
1623             fParagraph->layout(1000);
1624             fParagraph->paint(canvas, 300, 200);
1625 
1626             for (auto& run : impl->runs()) {
1627                 SkString fontFamily("unresolved");
1628                 if (run.font().getTypeface() != nullptr) {
1629                     run.font().getTypeface()->getFamilyName(&fontFamily);
1630                 }
1631                 if (run.font().getTypeface() != nullptr) {
1632                     for (size_t i = 0; i < run.size(); ++i) {
1633                         auto glyph = run.glyphs().begin() + i;
1634                         if (*glyph == 0) {
1635                             //SkDebugf("Run[%d] @pos=%d\n", run.index(), i);
1636                         }
1637                     }
1638                 } else {
1639                     //SkDebugf("Run[%d]: %s\n", run.index(), fontFamily.c_str());
1640                 }
1641             }
1642             fRedraw = false;
1643             fRepeat = false;
1644         }
1645     }
1646 
1647 private:
1648     bool fRedraw = true;
1649     bool fRepeat = false;
1650     size_t fIndex = 0;
1651     size_t fLimit = 20;
1652     std::unique_ptr<Paragraph> fParagraph;
1653     using INHERITED = Sample;
1654 };
1655 
1656 class ParagraphView19 : public ParagraphView_Base {
1657 protected:
name()1658     SkString name() override { return SkString("Paragraph19"); }
1659 
onDrawContent(SkCanvas * canvas)1660     void onDrawContent(SkCanvas* canvas) override {
1661         canvas->drawColor(SK_ColorWHITE);
1662 
1663         auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1664 
1665         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";
1666         ParagraphStyle paragraph_style;
1667         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1668         TextStyle text_style;
1669         text_style.setColor(SK_ColorBLACK);
1670         text_style.setFontFamilies({SkString("Roboto")});
1671         text_style.setFontSize(20);
1672         builder.pushStyle(text_style);
1673         builder.addText(text);
1674         auto paragraph = builder.Build();
1675         paragraph->layout(this->width());
1676         paragraph->paint(canvas, 0, 0);
1677     }
1678 
1679 private:
1680     using INHERITED = Sample;
1681 };
1682 
1683 class ParagraphView20 : public ParagraphView_Base {
1684 protected:
name()1685     SkString name() override { return SkString("Paragraph20"); }
1686 
onDrawContent(SkCanvas * canvas)1687     void onDrawContent(SkCanvas* canvas) override {
1688         canvas->drawColor(SK_ColorWHITE);
1689 
1690         auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1691 
1692         const char* text =  "Manage your google account";
1693         ParagraphStyle paragraph_style;
1694         paragraph_style.setEllipsis(u"\u2026");
1695         paragraph_style.setMaxLines(1);
1696         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1697         TextStyle text_style;
1698         text_style.setColor(SK_ColorBLACK);
1699         text_style.setFontFamilies({SkString("Roboto")});
1700         text_style.setFontSize(50);
1701         builder.pushStyle(text_style);
1702         builder.addText(text);
1703         auto paragraph = builder.Build();
1704         paragraph->layout(this->width());
1705         paragraph->paint(canvas, 0, 0);
1706     }
1707 
1708 private:
1709     using INHERITED = Sample;
1710 };
1711 
1712 class ParagraphView21 : public ParagraphView_Base {
1713 protected:
name()1714     SkString name() override { return SkString("Paragraph21"); }
1715 
onDrawContent(SkCanvas * canvas)1716     void onDrawContent(SkCanvas* canvas) override {
1717         canvas->drawColor(SK_ColorWHITE);
1718 
1719         const char* text =  "Referral Code";
1720         ParagraphStyle paragraph_style;
1721         ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1722         TextStyle text_style;
1723         text_style.setColor(SK_ColorBLACK);
1724         text_style.setFontFamilies({SkString("Google Sans")});
1725         text_style.setFontSize(24);
1726         builder.pushStyle(text_style);
1727         builder.addText(text);
1728         auto paragraph = builder.Build();
1729         paragraph->layout(0);
1730         paragraph->paint(canvas, 0, 0);
1731     }
1732 
1733 private:
1734     using INHERITED = Sample;
1735 };
1736 
1737 class ParagraphView22 : public ParagraphView_Base {
1738 protected:
name()1739     SkString name() override { return SkString("Paragraph22"); }
1740 
onChar(SkUnichar uni)1741     bool onChar(SkUnichar uni) override {
1742             switch (uni) {
1743                 case 'l':
1744                     direction = true;
1745                     return true;
1746                 case 'r':
1747                     direction = false;
1748                     return true;
1749                 default:
1750                     break;
1751             }
1752             return false;
1753     }
1754 
onDrawContent(SkCanvas * canvas)1755     void onDrawContent(SkCanvas* canvas) override {
1756 
1757         canvas->drawColor(SK_ColorWHITE);
1758         ParagraphStyle paragraph_style;
1759         paragraph_style.setTextDirection(direction ? TextDirection::kLtr : TextDirection::kRtl);
1760         auto collection = getFontCollection();
1761         ParagraphBuilderImpl builder(paragraph_style, collection);
1762         collection->getParagraphCache()->reset();
1763         collection->getParagraphCache()->turnOn(false);
1764         TextStyle text_style;
1765         text_style.setColor(SK_ColorBLACK);
1766         text_style.setFontFamilies({SkString("Roboto")});
1767         text_style.setFontSize(12);
1768         builder.pushStyle(text_style);
1769         builder.addText("I have got a ");
1770         text_style.setFontStyle(SkFontStyle::Bold());
1771         builder.pushStyle(text_style);
1772         builder.addText("lovely bunch");
1773         text_style.setFontStyle(SkFontStyle::Normal());
1774         builder.pushStyle(text_style);
1775         builder.addText(" of coconuts.");
1776         auto paragraph = builder.Build();
1777         paragraph->layout(this->width());
1778         paragraph->paint(canvas, 0, 0);
1779         collection->getParagraphCache()->turnOn(true);
1780     }
1781 
1782 private:
1783     using INHERITED = Sample;
1784     bool direction;
1785 };
1786 
1787 class ParagraphView23 : public ParagraphView_Base {
1788 protected:
name()1789     SkString name() override { return SkString("Paragraph23"); }
1790 
onDrawContent(SkCanvas * canvas)1791     void onDrawContent(SkCanvas* canvas) override {
1792         canvas->drawColor(SK_ColorWHITE);
1793 
1794         const char* text =  "Text with shadow";
1795         ParagraphStyle paragraph_style;
1796         TextStyle text_style;
1797         text_style.setColor(SK_ColorBLACK);
1798         text_style.setFontFamilies({SkString("Google Sans")});
1799         text_style.setFontSize(24);
1800 
1801         auto draw = [&](SkScalar h, SkScalar v, SkScalar b) {
1802             text_style.resetShadows();
1803             text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(h, v), b));
1804             ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1805             builder.pushStyle(text_style);
1806             builder.addText(text);
1807             auto paragraph = builder.Build();
1808             paragraph->layout(300);
1809             paragraph->paint(canvas, 0, 0);
1810 
1811             auto rect = SkRect::MakeXYWH(0, 0, paragraph->getMaxWidth(), paragraph->getHeight());
1812             SkPaint paint;
1813             paint.setColor(SK_ColorRED);
1814             paint.setStyle(SkPaint::kStroke_Style);
1815             paint.setAntiAlias(true);
1816             paint.setStrokeWidth(1);
1817             canvas->drawRect(rect, paint);
1818         };
1819 
1820         draw(10, 10, 5);
1821         canvas->translate(0, 100);
1822 
1823         draw(10, -10, 5);
1824         canvas->translate(0, 100);
1825 
1826         draw(-10, -10, 5);
1827         canvas->translate(0, 100);
1828 
1829         draw(-10, 10, 5);
1830         canvas->translate(0, 100);
1831     }
1832 
1833 private:
1834     using INHERITED = Sample;
1835 };
1836 
1837 class ParagraphView24 : public ParagraphView_Base {
1838 protected:
name()1839     SkString name() override { return SkString("Paragraph24"); }
1840 
onDrawContent(SkCanvas * canvas)1841     void onDrawContent(SkCanvas* canvas) override {
1842         canvas->drawColor(SK_ColorWHITE);
1843 
1844         ParagraphStyle paragraph_style;
1845         paragraph_style.setTextDirection(TextDirection::kRtl);
1846         TextStyle text_style;
1847         text_style.setColor(SK_ColorBLACK);
1848         text_style.setFontFamilies({SkString("Google Sans")});
1849         text_style.setFontSize(24);
1850         {
1851             ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1852             builder.pushStyle(text_style);
1853             builder.addText("Right_to_left:");
1854             auto paragraph = builder.Build();
1855             paragraph->layout(this->width());
1856             paragraph->paint(canvas, 0, 0);
1857         }
1858         canvas->translate(0, 200);
1859         {
1860             ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1861             builder.pushStyle(text_style);
1862             builder.addText("Right_to_left+");
1863             auto paragraph = builder.Build();
1864             paragraph->layout(this->width());
1865             paragraph->paint(canvas, 0, 0);
1866         }
1867         canvas->translate(0, 200);
1868         {
1869             ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1870             builder.pushStyle(text_style);
1871             builder.addText("Right_to_left.");
1872             auto paragraph = builder.Build();
1873             paragraph->layout(this->width());
1874             paragraph->paint(canvas, 0, 0);
1875         }
1876     }
1877 
1878 private:
1879     using INHERITED = Sample;
1880 };
1881 
1882 class ParagraphView25 : public ParagraphView_Base {
1883 protected:
name()1884     SkString name() override { return SkString("Paragraph25"); }
1885 
onDrawContent(SkCanvas * canvas)1886     void onDrawContent(SkCanvas* canvas) override {
1887         canvas->drawColor(SK_ColorWHITE);
1888 /*
1889  * Shell: ParagraphStyle: 1.000000 1
1890 Shell: Strut enabled: 0 1.000000 14.000000 400 5 0
1891 Shell: Font Families: 0
1892 Shell: DefaultTextStyle: 16.000000 500 5 0
1893 Shell: Font Families: 1 Roboto
1894 Shell: Font Features: 0
1895 Shell: TextStyle#0: [0:22) 16.000000 500 5 0
1896 Shell: Font Families: 1 Roboto
1897 Shell: Font Features: 0
1898 Shell: TextStyle#1: [25:49) 16.000000 500 5 0
1899 Shell: Font Families: 1 Roboto
1900 Shell: Font Features: 0
1901 Shell: Placeholder#0: [22:25) 32.000000 32.000000 32.000000 0 5
1902 Shell: Placeholder#1: [49:52) 19.000000 41.000000 19.000000 0 4
1903 Shell: Placeholder#2: [52:52) 0.000000 0.000000 0.000000 0 5
1904 Shell: layout('Go to device settings  and set up a passcode. ', 280.000000): 280.000000 * 38.000000
1905  */
1906         auto fontCollection = getFontCollection();
1907         //fontCollection->getParagraphCache()->turnOn(false);
1908         const char* text1 =  "Go to device settings ";
1909         const char* text2 = "and set up a passcode.";
1910         ParagraphStyle paragraph_style;
1911         StrutStyle strut_style;
1912         strut_style.setStrutEnabled(false);
1913         strut_style.setFontSize(14);
1914         strut_style.setForceStrutHeight(false);
1915         strut_style.setHeight(14);
1916         paragraph_style.setStrutStyle(strut_style);
1917         TextStyle text_style;
1918         text_style.setColor(SK_ColorBLACK);
1919         text_style.setFontFamilies({SkString("Roboto")});
1920         text_style.setFontSize(16);
1921         PlaceholderStyle placeholder_style;
1922         {
1923             ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1924             builder.pushStyle(text_style);
1925             builder.addText(text1);
1926             placeholder_style.fHeight = 32;
1927             placeholder_style.fWidth = 32;
1928             placeholder_style.fBaselineOffset = 32;
1929             placeholder_style.fBaseline = TextBaseline::kAlphabetic;
1930             placeholder_style.fAlignment = PlaceholderAlignment::kMiddle;
1931             builder.addPlaceholder(placeholder_style);
1932             builder.addText(text2);
1933             placeholder_style.fHeight = 19;
1934             placeholder_style.fWidth = 41;
1935             placeholder_style.fBaselineOffset = 19;
1936             placeholder_style.fBaseline = TextBaseline::kAlphabetic;
1937             placeholder_style.fAlignment = PlaceholderAlignment::kTop;
1938             builder.addPlaceholder(placeholder_style);
1939             auto paragraph = builder.Build();
1940             paragraph->layout(280);
1941             paragraph->paint(canvas, 0, 0);
1942         }
1943     }
1944 
1945 private:
1946     using INHERITED = Sample;
1947 };
1948 
1949 class ParagraphView26 : public ParagraphView_Base {
1950 protected:
name()1951     SkString name() override { return SkString("Paragraph26"); }
1952 
onDrawContent(SkCanvas * canvas)1953     void onDrawContent(SkCanvas* canvas) override {
1954         auto fontCollection = sk_make_sp<FontCollection>();
1955         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1956         //fontCollection->enableFontFallback();
1957 
1958         canvas->clear(SK_ColorWHITE);
1959 
1960         SkPaint paint;
1961         paint.setAntiAlias(true);
1962         paint.setColor(SK_ColorBLACK);
1963 
1964         TextStyle textStyle;
1965         textStyle.setForegroundColor(paint);
1966         textStyle.setFontFamilies({ SkString("Roboto") });
1967         textStyle.setFontSize(42.0f);
1968         textStyle.setLetterSpacing(-0.05f);
1969         textStyle.setHeightOverride(true);
1970 
1971         ParagraphStyle paragraphStyle;
1972         paragraphStyle.setTextStyle(textStyle);
1973         paragraphStyle.setTextAlign(TextAlign::kLeft);
1974 
1975         ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
1976         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");
1977 
1978         auto paragraph = builder.Build();
1979         paragraph->layout(this->width() / 2);
1980 
1981         std::vector<LineMetrics> lines;
1982         paragraph->getLineMetrics(lines); // <-- error happens here
1983 
1984         canvas->translate(10, 10);
1985         paragraph->paint(canvas, 0, 0);
1986     }
1987 
1988 private:
1989     using INHERITED = Sample;
1990 };
1991 
1992 class ParagraphView27 : public ParagraphView_Base {
1993 protected:
name()1994     SkString name() override { return SkString("Paragraph27"); }
1995 
onDrawContent(SkCanvas * canvas)1996     void onDrawContent(SkCanvas* canvas) override {
1997         auto fontCollection = sk_make_sp<FontCollection>();
1998         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1999         fontCollection->enableFontFallback();
2000         fontCollection->getParagraphCache()->turnOn(false);
2001 
2002         SkPaint red;
2003         red.setColor(SK_ColorRED);
2004         red.setStyle(SkPaint::kStroke_Style);
2005         red.setAntiAlias(true);
2006         red.setStrokeWidth(1);
2007 
2008         SkPaint blue;
2009         blue.setColor(SK_ColorRED);
2010         blue.setStyle(SkPaint::kStroke_Style);
2011         blue.setAntiAlias(true);
2012         blue.setStrokeWidth(1);
2013 
2014         SkPaint black;
2015         black.setColor(SK_ColorBLACK);
2016         black.setStyle(SkPaint::kStroke_Style);
2017         black.setAntiAlias(true);
2018         black.setStrokeWidth(1);
2019 
2020         SkPaint whiteSpaces;
2021         whiteSpaces.setColor(SK_ColorLTGRAY);
2022 
2023         SkPaint breakingSpace;
2024         breakingSpace.setColor(SK_ColorYELLOW);
2025 
2026         SkPaint text;
2027         text.setColor(SK_ColorWHITE);
2028 
2029         ParagraphStyle paragraph_style;
2030         paragraph_style.setTextAlign(TextAlign::kRight);
2031         TextStyle text_style;
2032         text_style.setColor(SK_ColorBLACK);
2033         text_style.setFontFamilies({SkString("Roboto")});
2034 
2035         // RTL + right align + arabic
2036         // RTL + right align + latin
2037         // LTR + right align + arabic
2038         // LTR + right align + latin
2039         // RTL + left align + arabic
2040         // RTL + left align + latin
2041         // arabic and latin should not differ at all
2042         // check: line breaking and trailing spaces
2043 
2044         canvas->drawColor(SK_ColorWHITE);
2045         auto h = 60;
2046         auto w = 300;
2047 
2048         auto draw = [&](SkScalar width, SkScalar height, TextDirection td, TextAlign ta, const char* t) {
2049             if (this->isVerbose()) {
2050                 SkDebugf("draw '%s' dir:%s align:%s\n", t,
2051                          td == TextDirection::kLtr ? "left" : "right",
2052                          ta == TextAlign::kLeft ? "left" : "right");
2053             }
2054             paragraph_style.setTextDirection(td);
2055             paragraph_style.setTextAlign(ta);
2056             text_style.setFontSize(20);
2057             ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2058             text_style.setBackgroundColor(whiteSpaces);
2059             builder.pushStyle(text_style);
2060             builder.addText("   ");
2061             text_style.setBackgroundColor(text);
2062             builder.pushStyle(text_style);
2063             builder.addText(t);
2064             text_style.setBackgroundColor(breakingSpace);
2065             builder.pushStyle(text_style);
2066             builder.addText(" ");
2067             text_style.setBackgroundColor(text);
2068             builder.pushStyle(text_style);
2069             builder.addText(t);
2070             text_style.setBackgroundColor(whiteSpaces);
2071             builder.pushStyle(text_style);
2072             builder.addText("   ");
2073             auto paragraph = builder.Build();
2074             paragraph->layout(width);
2075             paragraph->paint(canvas, 0, 0);
2076             auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2077             for (auto& line : impl->lines()) {
2078                 if (this->isVerbose()) {
2079                     SkDebugf("line[%d]: %f + %f\n", (int)(&line - impl->lines().begin()),
2080                                                     line.offset().fX, line.shift());
2081                 }
2082                 line.iterateThroughVisualRuns(true,
2083                     [&](const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width) {
2084                     *width = line.measureTextInsideOneRun(textRange, run, runOffset, 0, true, false).clip.width();
2085                     if (this->isVerbose()) {
2086                         SkDebugf("%zu[%zu: %zu) @%f + %f %s\n",
2087                                  run->index(), textRange.start, textRange.end, runOffset, *width,
2088                                  run->leftToRight() ? "left" : "right");
2089                     }
2090                     return true;
2091                 });
2092             }
2093             auto boxes = paragraph->getRectsForRange(0, 100, RectHeightStyle::kTight, RectWidthStyle::kTight);
2094             bool even = true;
2095             for (auto& box : boxes) {
2096                 if (this->isVerbose()) {
2097                     SkDebugf("[%f:%f,%f:%f] %s\n",
2098                              box.rect.fLeft, box.rect.fRight, box.rect.fTop, box.rect.fBottom,
2099                              box.direction == TextDirection::kLtr ? "left" : "right");
2100                 }
2101                 canvas->drawRect(box.rect, even ? red : blue);
2102                 even = !even;
2103             }
2104             canvas->translate(0, height);
2105         };
2106 
2107         canvas->drawRect(SkRect::MakeXYWH(0, 0, w, h * 8), black);
2108 
2109         draw(w, h, TextDirection::kRtl, TextAlign::kRight, "RTL+RIGHT#1234567890");
2110         draw(w, h, TextDirection::kRtl, TextAlign::kRight, "قففغغغغقففغغغغقففغغغ");
2111 
2112         draw(w, h, TextDirection::kLtr, TextAlign::kRight, "LTR+RIGHT#1234567890");
2113         draw(w, h, TextDirection::kLtr, TextAlign::kRight, "قففغغغغقففغغغغقففغغغ");
2114 
2115         draw(w, h, TextDirection::kRtl, TextAlign::kLeft, "RTL+LEFT##1234567890");
2116         draw(w, h, TextDirection::kRtl, TextAlign::kLeft, "قففغغغغقففغغغغقففغغغ");
2117 
2118         draw(w, h, TextDirection::kLtr, TextAlign::kLeft, "LTR+LEFT##1234567890");
2119         draw(w, h, TextDirection::kLtr, TextAlign::kLeft, "قففغغغغقففغغغغقففغغغ");
2120     }
2121 
2122 private:
2123     using INHERITED = Sample;
2124 };
2125 
2126 class ParagraphView28 : public ParagraphView_Base {
2127 protected:
name()2128     SkString name() override { return SkString("Paragraph28"); }
2129 
onDrawContent(SkCanvas * canvas)2130     void onDrawContent(SkCanvas* canvas) override {
2131 
2132         const char* text = "AAAAA BBBBB CCCCC DDDDD EEEEE FFFFF GGGGG HHHHH IIIII JJJJJ KKKKK LLLLL MMMMM NNNNN OOOOO PPPPP QQQQQ";
2133 
2134         canvas->drawColor(SK_ColorWHITE);
2135         ParagraphStyle paragraph_style;
2136         paragraph_style.setTextAlign(TextAlign::kJustify);
2137         auto collection = getFontCollection();
2138         ParagraphBuilderImpl builder(paragraph_style, collection);
2139         TextStyle text_style;
2140         text_style.setColor(SK_ColorBLACK);
2141         text_style.setFontFamilies({SkString("Roboto")});
2142         text_style.setFontSize(40);
2143         builder.pushStyle(text_style);
2144         builder.addText(text);
2145         auto paragraph = builder.Build();
2146         auto s = 186;
2147         paragraph->layout(360 - s);
2148         paragraph->paint(canvas, 0, 0);
2149         /*
2150         paragraph->layout(360);
2151         paragraph->paint(canvas, 0, 0);
2152         canvas->translate(0, 400);
2153         paragraph->layout(354.333);
2154         paragraph->paint(canvas, 0, 0);
2155         */
2156     }
2157 
2158 private:
2159     using INHERITED = Sample;
2160 };
2161 
2162 class ParagraphView29 : public ParagraphView_Base {
2163 protected:
name()2164     SkString name() override { return SkString("Paragraph29"); }
2165 
onDrawContent(SkCanvas * canvas)2166     void onDrawContent(SkCanvas* canvas) override {
2167 
2168         const char* text = "ffi";
2169         canvas->drawColor(SK_ColorWHITE);
2170 
2171         auto collection = getFontCollection();
2172 
2173         ParagraphStyle paragraph_style;
2174         ParagraphBuilderImpl builder(paragraph_style, collection);
2175         TextStyle text_style;
2176         text_style.setColor(SK_ColorBLACK);
2177         text_style.setFontFamilies({SkString("Roboto")});
2178         text_style.setFontSize(60);
2179         builder.pushStyle(text_style);
2180         builder.addText(text);
2181         auto paragraph = builder.Build();
2182         paragraph->layout(width());
2183         paragraph->paint(canvas, 0, 0);
2184         auto width = paragraph->getLongestLine();
2185         auto height = paragraph->getHeight();
2186         if (this->isVerbose()) {
2187             auto f1Pos = paragraph->getGlyphPositionAtCoordinate(width/6, height/2);
2188             auto f2Pos = paragraph->getGlyphPositionAtCoordinate(width/2, height/2);
2189             auto iPos = paragraph->getGlyphPositionAtCoordinate(width*5/6, height/2);
2190             SkDebugf("%d(%s) %d(%s) %d(%s)\n",
2191                      f1Pos.position, f1Pos.affinity == Affinity::kUpstream ? "up" : "down",
2192                      f2Pos.position, f2Pos.affinity == Affinity::kUpstream ? "up" : "down",
2193                      iPos.position, iPos.affinity == Affinity::kUpstream ? "up" : "down");
2194 
2195             auto f1 = paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight,
2196                                                   RectWidthStyle::kTight);
2197             if (f1.empty()) {
2198                 SkDebugf("F1 is empty\n");
2199             } else {
2200                 auto rf1 = f1[0];
2201                 SkDebugf("f1: [%f:%f] %s\n", rf1.rect.fLeft, rf1.rect.fRight,
2202                                              rf1.direction == TextDirection::kRtl ? "rtl" : "ltr");
2203             }
2204 
2205             auto f2 = paragraph->getRectsForRange(1, 2, RectHeightStyle::kTight,
2206                                                   RectWidthStyle::kTight);
2207             if (f2.empty()) {
2208                 SkDebugf("F2 is empty\n");
2209             } else {
2210                 auto rf2 = f2[0];
2211                 SkDebugf("f2: [%f:%f] %s\n", rf2.rect.fLeft, rf2.rect.fRight,
2212                                              rf2.direction == TextDirection::kRtl ? "rtl" : "ltr");
2213             }
2214 
2215             auto fi = paragraph->getRectsForRange(2, 3, RectHeightStyle::kTight,
2216                                                   RectWidthStyle::kTight);
2217             if (fi.empty()) {
2218                 SkDebugf("FI is empty\n");
2219             } else {
2220                 auto rfi = fi[0];
2221                 SkDebugf("i:  [%f:%f] %s\n", rfi.rect.fLeft, rfi.rect.fRight,
2222                                              rfi.direction == TextDirection::kRtl ? "rtl" : "ltr");
2223             }
2224         }
2225     }
2226 
2227 private:
2228     using INHERITED = Sample;
2229 };
2230 
2231 class ParagraphView30 : public ParagraphView_Base {
2232 protected:
name()2233     SkString name() override { return SkString("Paragraph30"); }
2234 
onDrawContent(SkCanvas * canvas)2235     void onDrawContent(SkCanvas* canvas) override {
2236 
2237         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";
2238         u"\U0001f469\u200D\U0001f469\u200D\U0001f466\U0001f469\u200D\U0001f469\u200D\U0001f467\u200D\U0001f467\U0001f1fa\U0001f1f8";
2239         canvas->drawColor(SK_ColorWHITE);
2240 
2241         auto fontCollection = sk_make_sp<FontCollection>();
2242         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2243         fontCollection->enableFontFallback();
2244 
2245         ParagraphStyle paragraph_style;
2246         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2247         TextStyle text_style;
2248         text_style.setColor(SK_ColorBLACK);
2249         //text_style.setFontFamilies({SkString("Noto Color Emoji")});
2250         text_style.setFontFamilies({SkString("Ahem")});
2251         text_style.setFontSize(14);
2252         builder.pushStyle(text_style);
2253         builder.addText(text);
2254         auto paragraph = builder.Build();
2255         paragraph->layout(width());
2256         paragraph->paint(canvas, 0, 0);
2257         std::pair<size_t, size_t> rects[] = {
2258             { 0, 2}, { 0, 4}, {0, 8},
2259             {23, 25}, {23, 27}, {23, 31}, {23, 39}, {23, 55}, {21, 23},
2260             {1, 3}, {1, 5}, {1, 9}, {1, 17}, {1, 33},
2261             { 2, 4}, {2, 6}, {2, 10}, {2, 18}, {2, 34},
2262             {3, 5}, {3, 7}, {3, 11}, {3, 19},
2263             {4, 6}, {4, 8}, {4, 12}, {4, 20},
2264             {5, 7}, {5, 9}, {5, 13}, {5, 21},
2265             {6, 8}, {6, 10}, {6, 14}, {6, 22},
2266             {7, 9}, {7, 11}, {7, 15}, {7, 23},
2267             {8, 10}, {8, 12}, {8, 16}, {8,24},
2268             {9, 11}, {9, 13}, {9, 17}, {9, 25},
2269             {10, 12}, {10, 14}, {10, 18}, {10, 26},
2270             {11, 13}, {11, 15}, {11, 19}, {11, 27},
2271             {12, 14}, {12, 16}, {12, 20}, {12, 28},
2272             {13, 15}, {13, 17}, {13, 21},
2273             {14, 16}, {14, 18}, {14, 22},
2274             {15, 17}, {15, 19}, {15, 23},
2275             {16, 18}, {16, 20}, {16, 24},
2276             {17, 19}, {17, 21},
2277             {18, 20}, {18, 22},
2278             {19, 21},
2279             {20, 22}, {20, 24},
2280             {21, 23},
2281             {22, 24}, {22, 26}, {22, 30}, {22, 38}, {22, 54},
2282             {20, 22},
2283             {18, 22},
2284         };
2285         for (auto rect: rects) {
2286             auto results = paragraph->getRectsForRange(
2287                     rect.first, rect.second, RectHeightStyle::kTight, RectWidthStyle::kTight);
2288             SkDebugf("[%zu : %zu) ", rect.first, rect.second);
2289             if (!results.empty()) {
2290                 SkASSERT(results.size() == 1);
2291                 SkDebugf("[%f : %f]\n", results[0].rect.fLeft,results[0].rect.fRight);
2292             }
2293         }
2294     }
2295 
2296 private:
2297     using INHERITED = Sample;
2298 };
2299 
2300 class ParagraphView31 : public ParagraphView_Base {
2301 protected:
name()2302     SkString name() override { return SkString("Paragraph31"); }
2303 
onDrawContent(SkCanvas * canvas)2304     void onDrawContent(SkCanvas* canvas) override {
2305 
2306         canvas->drawColor(SK_ColorWHITE);
2307 
2308         auto fontCollection = sk_make_sp<FontCollection>();
2309         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2310         fontCollection->enableFontFallback();
2311 
2312         ParagraphStyle paragraph_style;
2313         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2314         TextStyle text_style;
2315         text_style.setColor(SK_ColorBLACK);
2316         text_style.setFontFamilies({SkString("Roboto")});
2317         text_style.setFontSize(40);
2318         builder.pushStyle(text_style);
2319         auto s = u"েن েূথ";
2320         builder.addText(s);
2321         auto paragraph = builder.Build();
2322         paragraph->layout(width());
2323         paragraph->paint(canvas, 0, 0);
2324     }
2325 
2326 private:
2327     using INHERITED = Sample;
2328 };
2329 
2330 class ParagraphView32 : public ParagraphView_Base {
2331 protected:
name()2332     SkString name() override { return SkString("Paragraph32"); }
2333 
onDrawContent(SkCanvas * canvas)2334     void onDrawContent(SkCanvas* canvas) override {
2335 
2336         canvas->drawColor(SK_ColorWHITE);
2337 
2338         auto fontCollection = sk_make_sp<FontCollection>();
2339         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2340         fontCollection->enableFontFallback();
2341 
2342         ParagraphStyle paragraph_style;
2343         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2344         TextStyle text_style;
2345         text_style.setColor(SK_ColorBLACK);
2346         text_style.setFontFamilies({SkString("Roboto")});
2347         text_style.setFontSize(40);
2348         text_style.setLocale(SkString("ko"));
2349         builder.pushStyle(text_style);
2350         builder.addText(u"\u904d ko ");
2351         text_style.setLocale(SkString("zh_Hant"));
2352         builder.pushStyle(text_style);
2353         builder.addText(u"\u904d zh-Hant ");
2354         text_style.setLocale(SkString("zh_Hans"));
2355         builder.pushStyle(text_style);
2356         builder.addText(u"\u904d zh-Hans ");
2357         text_style.setLocale(SkString("zh_HK"));
2358         builder.pushStyle(text_style);
2359         builder.addText(u"\u904d zh-HK ");
2360         auto paragraph = builder.Build();
2361         paragraph->layout(width());
2362         paragraph->paint(canvas, 0, 0);
2363     }
2364 
2365 private:
2366     using INHERITED = Sample;
2367 };
2368 
2369 class ParagraphView33 : public ParagraphView_Base {
2370 protected:
name()2371     SkString name() override { return SkString("Paragraph33"); }
2372 
onDrawContent(SkCanvas * canvas)2373     void onDrawContent(SkCanvas* canvas) override {
2374 
2375         canvas->drawColor(SK_ColorWHITE);
2376 
2377         auto fontCollection = sk_make_sp<FontCollection>();
2378         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2379         fontCollection->enableFontFallback();
2380 
2381         ParagraphStyle paragraph_style;
2382         paragraph_style.setTextAlign(TextAlign::kJustify);
2383         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2384         TextStyle text_style;
2385         text_style.setColor(SK_ColorBLACK);
2386         text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2387         text_style.setFontSize(36);
2388         builder.pushStyle(text_style);
2389         builder.addText(u"AAAAA \U0001f600 BBBBB CCCCC DDDDD EEEEE");
2390         auto paragraph = builder.Build();
2391         paragraph->layout(width() / 2);
2392         SkPaint paint;
2393         paint.setColor(SK_ColorLTGRAY);
2394         canvas->drawRect(SkRect::MakeXYWH(0, 0, width()/2, paragraph->getHeight()), paint);
2395         paragraph->paint(canvas, 0, 0);
2396     }
2397 
2398 private:
2399     using INHERITED = Sample;
2400 };
2401 
2402 class ParagraphView34 : public ParagraphView_Base {
2403 protected:
name()2404     SkString name() override { return SkString("Paragraph34"); }
2405 
onDrawContent(SkCanvas * canvas)2406     void onDrawContent(SkCanvas* canvas) override {
2407 
2408         canvas->drawColor(SK_ColorWHITE);
2409         auto text = "ضخمة ص ،������ضضض ؤ،،��������شسي،������ؤرى،��������ببب،����������ثيلااتن";
2410         //auto text = "ى،��������بب";
2411         //auto text1 = "World domination is such an ugly phrase - I prefer to call it world optimisation";
2412         auto fontCollection = sk_make_sp<FontCollection>();
2413         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2414         fontCollection->enableFontFallback();
2415 
2416         ParagraphStyle paragraph_style;
2417         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2418         TextStyle text_style;
2419         text_style.setColor(SK_ColorBLACK);
2420         text_style.setFontFamilies({SkString("Noto Color Emoji")});
2421         text_style.setFontSize(50);
2422         builder.pushStyle(text_style);
2423         builder.addText(text);
2424         auto paragraph = builder.Build();
2425         paragraph->layout(1041); // 1041
2426 
2427         SkColor colors[] = {SK_ColorBLUE, SK_ColorCYAN,  SK_ColorLTGRAY, SK_ColorGREEN,
2428                             SK_ColorRED,  SK_ColorWHITE, SK_ColorYELLOW, SK_ColorMAGENTA };
2429         SkPaint paint;
2430         size_t wordPos = 0;
2431         size_t index = 0;
2432         while (wordPos < 72) {
2433             auto res2 = paragraph->getWordBoundary(wordPos);
2434             if (res2.width() == 0) {
2435                 break;
2436             }
2437             wordPos = res2.end;
2438             auto res3 = paragraph->getRectsForRange(
2439                     res2.start, res2.end,
2440                     RectHeightStyle::kTight, RectWidthStyle::kTight);
2441             paint.setColor(colors[index % 8]);
2442             ++index;
2443             if (!res3.empty()) {
2444                 canvas->drawRect(res3[0].rect, paint);
2445             }
2446         }
2447         paragraph->paint(canvas, 0, 0);
2448     }
2449 
2450 private:
2451     using INHERITED = Sample;
2452 };
2453 
2454 class ParagraphView35 : public ParagraphView_Base {
2455 protected:
name()2456     SkString name() override { return SkString("Paragraph35"); }
2457 
onFindClickHandler(SkScalar x,SkScalar y,skui::ModifierKey modi)2458     Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
2459         return new Click;
2460     }
2461 
onClick(Click * click)2462     bool onClick(Click* click) override {
2463         fPoint = click->fCurr;
2464         return true;
2465     }
2466 
onDrawContent(SkCanvas * canvas)2467     void onDrawContent(SkCanvas* canvas) override {
2468 
2469         canvas->drawColor(SK_ColorWHITE);
2470 
2471         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";
2472         auto fontCollection = sk_make_sp<FontCollection>();
2473         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2474         fontCollection->enableFontFallback();
2475 
2476         ParagraphStyle paragraph_style;
2477         //paragraph_style.setTextAlign(TextAlign::kJustify);
2478         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2479         TextStyle text_style;
2480         text_style.setColor(SK_ColorBLACK);
2481         text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2482         text_style.setFontSize(40);
2483         builder.pushStyle(text_style);
2484         builder.addText(text);
2485         auto paragraph = builder.Build();
2486         paragraph->layout(width());//758
2487 
2488         //auto res1 = paragraph->getGlyphPositionAtCoordinate(line.width() + line.spacesWidth() / 2, line.offset().fY + 10);
2489         //auto res2 = paragraph->getWordBoundary(res1.position);
2490         auto res1 = paragraph->getRectsForRange(360, 361, RectHeightStyle::kTight, RectWidthStyle::kTight);
2491         auto res2 = paragraph->getRectsForRange(359, 360, RectHeightStyle::kTight, RectWidthStyle::kTight);
2492         auto res3 = paragraph->getRectsForRange(358, 359, RectHeightStyle::kTight, RectWidthStyle::kTight);
2493 
2494         auto draw = [&](std::vector<TextBox> res, SkColor color) {
2495             SkPaint paint;
2496             paint.setColor(color);
2497             for (auto& r : res) {
2498                 canvas->drawRect(r.rect, paint);
2499             }
2500         };
2501 
2502         draw(res1, SK_ColorRED);
2503         draw(res2, SK_ColorGREEN);
2504         draw(res3, SK_ColorBLUE);
2505 
2506         paragraph->paint(canvas, 0, 0);
2507     }
2508 
2509 private:
2510     using INHERITED = Sample;
2511     SkPoint fPoint;
2512 };
2513 
2514 class ParagraphView36 : public ParagraphView_Base {
2515 protected:
name()2516     SkString name() override { return SkString("Paragraph36"); }
2517 
onDrawContent(SkCanvas * canvas)2518     void onDrawContent(SkCanvas* canvas) override {
2519 
2520         canvas->drawColor(SK_ColorWHITE);
2521         auto text = "String is too big for WinMSVC";
2522         //"সৢ৭ঙ া 七七去关谢都四先么见香认东 غلضينخي 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 字弟是去妈京学地";
2523         //"ي ز";
2524         //"৪৮ু৸ধ maar";
2525         //"四的 ذخص  ৢঙ";
2526         //"ذخص  ৢঙ";
2527         auto fontCollection = sk_make_sp<FontCollection>();
2528         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2529         fontCollection->enableFontFallback();
2530 
2531         ParagraphStyle paragraph_style;
2532         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2533         TextStyle text_style;
2534         text_style.setColor(SK_ColorBLACK);
2535         text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Serif CJK JP")});
2536         text_style.setFontSize(10);
2537         builder.pushStyle(text_style);
2538         builder.addText(text);
2539         auto paragraph = builder.Build();
2540         paragraph->layout(width());
2541 
2542         paragraph->paint(canvas, 0, 0);
2543     }
2544 
2545 private:
2546     using INHERITED = Sample;
2547 };
2548 
2549 class ParagraphView37 : public ParagraphView_Base {
2550 protected:
name()2551     SkString name() override { return SkString("Paragraph37"); }
2552 
onDrawContent(SkCanvas * canvas)2553     void onDrawContent(SkCanvas* canvas) override {
2554         const char* text = "String is too big for WinMSVC";
2555                 // "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaয়ৠঝোণ৺ঢ়মৈবৗৗঘথফড়৭২খসঢ়ৃঢ়ঁ৷থডঈঽলবনদ২ৢৃঀজঝ৩ঠ৪৫৯০ঌয়্মওৗ৲গখদ৹ঈ৴৹ঢ়ৄএৡফণহলঈ৲থজোৱে ঀকৰঀষজঝঃাখশঽএমংি";
2556                 //"ৎৣ়ৎঽতঃ৳্ৱব৴ৣঈ৷ূঁঢঢ়শটডৎ৵৵ৰৃ্দংঊাথৗদঊউদ৯ঐৃধা৬হওধি়৭ঽম৯স০ঢফৈঢ়কষঁছফীআে৶ৰ৶ঌৌঊ্ঊঝএঀঃদঞ৮তব৬ৄঊঙঢ়ৡগ৶৹৹ঌড়ঘৄ৷লপ১ভড়৶েঢ়৯ৎকনংট২ংএঢৌৌঐনো০টঽুৠগআ৷৭৩৬তো৻ঈ০ূসষঅঝআমণঔা১ণৈো৵চঽ৩বমৎঙঘ২ঠৠৈী৫তঌণচ৲ঔী৮ঘৰঔ";
2557          canvas->drawColor(SK_ColorWHITE);
2558 
2559         auto fontCollection = sk_make_sp<FontCollection>();
2560         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2561         fontCollection->enableFontFallback();
2562 
2563         ParagraphStyle paragraph_style;
2564         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2565         TextStyle text_style;
2566         text_style.setColor(SK_ColorBLACK);
2567         text_style.setFontFamilies({SkString("Roboto")});
2568         text_style.setFontSize(20);
2569         builder.pushStyle(text_style);
2570         builder.addText(text);
2571         auto paragraph = builder.Build();
2572         auto w = width() / 2;
2573         paragraph->layout(w);
2574         auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2575 
2576         auto clusters = impl->clusters();
2577         if (this->isVerbose()) {
2578             size_t c = 0;
2579             SkDebugf("clusters\n");
2580             for (auto& cluster: clusters) {
2581                 SkDebugf("%zu: [%zu:%zu) %s\n", c++,
2582                          cluster.textRange().start, cluster.textRange().end,
2583                          cluster.isSoftBreak() ? "soft" :
2584                          cluster.isHardBreak() ? "hard" :
2585                          cluster.isWhitespaceBreak() ? "spaces" : "");
2586             }
2587 
2588             auto lines = impl->lines();
2589             size_t i = 0;
2590             SkDebugf("lines\n");
2591             for (auto& line : lines) {
2592                 SkDebugf("%zu: [%zu:%zu)\n", i++, line.trimmedText().start, line.trimmedText().end);
2593             }
2594         }
2595 
2596         paragraph->paint(canvas, 0, 0);
2597     }
2598 
2599 private:
2600     using INHERITED = Sample;
2601 };
2602 
2603 class ParagraphView38 : public ParagraphView_Base {
2604 protected:
name()2605     SkString name() override { return SkString("Paragraph38"); }
2606 
onDrawContent(SkCanvas * canvas)2607     void onDrawContent(SkCanvas* canvas) override {
2608 
2609         canvas->drawColor(SK_ColorWHITE);
2610 
2611         auto fontCollection = sk_make_sp<FontCollection>();
2612         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2613         fontCollection->enableFontFallback();
2614 
2615         ParagraphStyle paragraph_style;
2616         paragraph_style.setTextAlign(TextAlign::kLeft);
2617         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2618         TextStyle text_style;
2619         text_style.setColor(SK_ColorDKGRAY);
2620         text_style.setFontFamilies({SkString("Roboto")});
2621         text_style.setFontSize(40);
2622         text_style.setDecoration(TextDecoration::kUnderline);
2623 
2624         text_style.setDecorationMode(TextDecorationMode::kThrough);
2625         text_style.setDecorationStyle(TextDecorationStyle::kDouble);
2626         text_style.setDecorationColor(SK_ColorBLUE);
2627         builder.pushStyle(text_style);
2628         builder.addText("Double underline: {opopo}\n");
2629 
2630         text_style.setDecorationMode(TextDecorationMode::kGaps);
2631         text_style.setDecorationStyle(TextDecorationStyle::kDouble);
2632         text_style.setDecorationColor(SK_ColorBLUE);
2633         builder.pushStyle(text_style);
2634         builder.addText("Double underline: {opopo}\n");
2635 
2636         text_style.setDecorationStyle(TextDecorationStyle::kDotted);
2637         text_style.setDecorationColor(SK_ColorRED);
2638         builder.pushStyle(text_style);
2639         builder.addText("Dotted underline: {ijiji}\n");
2640 
2641         text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2642         text_style.setDecorationColor(SK_ColorGREEN);
2643         builder.pushStyle(text_style);
2644         builder.addText("Solid underline: {rqrqr}\n");
2645 
2646         text_style.setDecorationStyle(TextDecorationStyle::kDashed);
2647         text_style.setDecorationColor(SK_ColorMAGENTA);
2648         builder.pushStyle(text_style);
2649         builder.addText("Dashed underline: {zyzyz}\n");
2650 
2651         text_style.setDecorationStyle(TextDecorationStyle::kWavy);
2652         text_style.setDecorationColor(SK_ColorCYAN);
2653         builder.pushStyle(text_style);
2654         builder.addText("Wavy underline: {does not skip}\n");
2655 
2656         auto paragraph = builder.Build();
2657         paragraph->layout(width());
2658         paragraph->paint(canvas, 0, 0);
2659     }
2660 
2661 private:
2662     using INHERITED = Sample;
2663 };
2664 
2665 class ParagraphView39 : public ParagraphView_Base {
2666 protected:
name()2667     SkString name() override { return SkString("Paragraph39"); }
2668 
onDrawContent(SkCanvas * canvas)2669     void onDrawContent(SkCanvas* canvas) override {
2670 
2671         canvas->drawColor(SK_ColorWHITE);
2672 
2673         auto fontCollection = sk_make_sp<FontCollection>();
2674         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2675         fontCollection->enableFontFallback();
2676 
2677         ParagraphStyle paragraph_style;
2678         paragraph_style.setTextAlign(TextAlign::kJustify);
2679         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2680         TextStyle text_style;
2681         text_style.setColor(SK_ColorBLACK);
2682         text_style.setFontFamilies({SkString("Roboto")});
2683         text_style.setFontSize(40);
2684         builder.pushStyle(text_style);
2685         builder.addText(
2686             "text1 with line break\n"
2687             "text2 without line break text without line break text without line break text without line break text without line break text without line break "
2688             "text3 with line break\n"
2689             "text4 without line break text without line break text without line break text without line break text without line break text without line break "
2690             "text5 with line break\n"
2691         );
2692         auto paragraph = builder.Build();
2693         paragraph->layout(width());
2694         paragraph->paint(canvas, 0, 0);
2695     }
2696 
2697 private:
2698     using INHERITED = Sample;
2699 };
2700 
2701 class ParagraphView41 : public ParagraphView_Base {
2702 protected:
name()2703     SkString name() override { return SkString("Paragraph41"); }
2704 
onDrawContent(SkCanvas * canvas)2705     void onDrawContent(SkCanvas* canvas) override {
2706 
2707         canvas->drawColor(SK_ColorWHITE);
2708 
2709         auto fontCollection = sk_make_sp<FontCollection>();
2710         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2711         fontCollection->enableFontFallback();
2712 
2713         SkPaint line;
2714         line.setColor(SK_ColorRED);
2715         line.setStyle(SkPaint::kStroke_Style);
2716         line.setAntiAlias(true);
2717         line.setStrokeWidth(1);
2718 
2719         auto draw = [&](SkColor color, TextHeightBehavior thb) {
2720             ParagraphStyle paragraph_style;
2721             paragraph_style.setTextHeightBehavior(thb);
2722             ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2723             TextStyle text_style;
2724             text_style.setColor(SK_ColorBLACK);
2725             SkPaint paint;
2726             paint.setColor(color);
2727             text_style.setBackgroundColor(paint);
2728             text_style.setFontFamilies({SkString("Roboto")});
2729             text_style.setFontSize(20);
2730             text_style.setHeight(5);
2731             text_style.setHeightOverride(true);
2732             builder.pushStyle(text_style);
2733             builder.addText("World domination is such an ugly phrase - I prefer to call it world optimisation");
2734             auto paragraph = builder.Build();
2735             paragraph->layout(width());
2736             paragraph->paint(canvas, 0, 0);
2737             canvas->drawLine(0, paragraph->getHeight(), paragraph->getMaxWidth(), paragraph->getHeight(), line);
2738             canvas->translate(0, paragraph->getHeight());
2739         };
2740 
2741         draw(SK_ColorLTGRAY, TextHeightBehavior::kDisableFirstAscent);
2742         draw(SK_ColorYELLOW, TextHeightBehavior::kDisableLastDescent);
2743         draw(SK_ColorGRAY, TextHeightBehavior::kDisableAll);
2744 
2745     }
2746 
2747 private:
2748     using INHERITED = Sample;
2749 };
2750 
2751 class ParagraphView42 : public ParagraphView_Base {
2752 protected:
name()2753     SkString name() override { return SkString("Paragraph42"); }
2754 
onDrawContent(SkCanvas * canvas)2755     void onDrawContent(SkCanvas* canvas) override {
2756 
2757         SkString text("Atwater Peel Sherbrooke Bonaventure\nhi\nwasssup!");
2758         canvas->drawColor(SK_ColorWHITE);
2759 
2760         auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
2761 
2762         ParagraphStyle paragraph_style;
2763         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2764         TextStyle text_style;
2765         text_style.setColor(SK_ColorBLACK);
2766         text_style.setFontFamilies({SkString("Ahem")});
2767         text_style.setFontSize(16);
2768         text_style.setHeight(4);
2769         text_style.setHeightOverride(true);
2770         builder.pushStyle(text_style);
2771         builder.addText(text.c_str());
2772         auto paragraph = builder.Build();
2773         paragraph->layout(width());
2774 
2775         auto boxes = paragraph->getRectsForRange(0, 7, RectHeightStyle::kIncludeLineSpacingTop, RectWidthStyle::kMax);
2776         for (auto& box : boxes) {
2777             SkPaint paint;
2778             paint.setColor(SK_ColorGRAY);
2779             canvas->drawRect(box.rect, paint);
2780         }
2781 
2782         auto boxes2 = paragraph->getRectsForRange(0, 7, RectHeightStyle::kTight, RectWidthStyle::kMax);
2783         for (auto& box : boxes2) {
2784             SkPaint paint;
2785             paint.setColor(SK_ColorRED);
2786             canvas->drawRect(box.rect, paint);
2787         }
2788 
2789         paragraph->paint(canvas, 0, 0);
2790     }
2791 
2792 private:
2793     using INHERITED = Sample;
2794 };
2795 
2796 class ParagraphView43 : public ParagraphView_Base {
2797 protected:
name()2798     SkString name() override { return SkString("Paragraph43"); }
2799 
onDrawContent(SkCanvas * canvas)2800     void onDrawContent(SkCanvas* canvas) override {
2801 
2802         SkString text("World domination is such an ugly phrase - I prefer to call it world optimisation");
2803         canvas->drawColor(SK_ColorWHITE);
2804 
2805         auto fontCollection = sk_make_sp<FontCollection>();
2806         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2807         fontCollection->enableFontFallback();
2808 
2809         ParagraphStyle paragraph_style;
2810         paragraph_style.setTextAlign(TextAlign::kJustify);
2811         paragraph_style.setEllipsis(u"\u2026");
2812         paragraph_style.setMaxLines(2);
2813         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2814         TextStyle text_style;
2815         text_style.setColor(SK_ColorBLACK);
2816         text_style.setFontFamilies({SkString("Roboto")});
2817         text_style.setFontSize(40);
2818         text_style.setHeightOverride(true);
2819         builder.pushStyle(text_style);
2820         builder.addText(text.c_str());
2821         auto paragraph = builder.Build();
2822         paragraph->layout(width() / 4);
2823         paragraph->paint(canvas, 0, 0);
2824     }
2825 
2826 private:
2827     using INHERITED = Sample;
2828 };
2829 
2830 class ParagraphView44 : public ParagraphView_Base {
2831 protected:
name()2832     SkString name() override { return SkString("Paragraph44"); }
2833 
onDrawContent(SkCanvas * canvas)2834     void onDrawContent(SkCanvas* canvas) override {
2835 
2836         const std::u16string text = u"The quick brown fox \U0001f98a ate a zesty ham burger fons \U0001f354."
2837                                     "The \U0001f469\u200D\U0001f469\u200D\U0001f467\u200D\U0001f467 laughed.";
2838         canvas->drawColor(SK_ColorWHITE);
2839 
2840         auto fontCollection = sk_make_sp<FontCollection>();
2841         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2842         fontCollection->enableFontFallback();
2843 
2844         ParagraphStyle paragraph_style;
2845         paragraph_style.setMaxLines(7);
2846         paragraph_style.setEllipsis(u"\u2026");
2847         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2848         TextStyle text_style;
2849         text_style.setColor(SK_ColorBLACK);
2850         text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2851         text_style.setFontSize(60);
2852         builder.pushStyle(text_style);
2853         builder.addText(text);
2854         auto paragraph = builder.Build();
2855         paragraph->layout(305);//width());
2856         paragraph->paint(canvas, 0, 0);
2857     }
2858 
2859 private:
2860     using INHERITED = Sample;
2861 };
2862 
2863 class ParagraphView45 : public ParagraphView_Base {
2864 protected:
name()2865     SkString name() override { return SkString("Paragraph45"); }
2866 
onDrawContent(SkCanvas * canvas)2867     void onDrawContent(SkCanvas* canvas) override {
2868 
2869       // This test crashed when resources/fonts directory had only 5 fonts listed below
2870       std::string fonts = GetResourcePath("fonts/").c_str();
2871       std::set<std::pair<std::string, std::string>> font_paths = {
2872           {"Roboto", "Roboto-Regular.ttf"},
2873           {"Roboto", "Roboto-Bold.ttf"},
2874           {"Noto","NotoSansCJK-Regular.ttc"},
2875           {"Noto", "NotoSansCJK-Bold.ttc"},
2876           {"Emoji","NotoColorEmoji.ttf"}};
2877 
2878       sk_sp<TypefaceFontProvider> font_provider = sk_make_sp<TypefaceFontProvider>();
2879 
2880       for (auto& pair : font_paths) {
2881         SkString family_name = SkString(pair.first.c_str());
2882         std::string path = fonts;
2883         path += pair.second;
2884 
2885         auto data = SkData::MakeFromFileName(path.c_str());
2886         font_provider->registerTypeface(SkTypeface::MakeFromData(std::move(data)), family_name);
2887       }
2888 
2889       sk_sp<FontCollection> font_collection = sk_make_sp<FontCollection>();
2890       font_collection->setAssetFontManager(std::move(font_provider));
2891       font_collection->getParagraphCache()->turnOn(false);
2892 
2893         const std::u16string text = u"❤️����‍♀️ ���� ����‍⚕️ ����‍⚕️ ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍�� ����‍✈️ ����‍✈️ ����‍�� ����‍�� ����‍⚖️ ����‍⚖️ ���� ����";
2894             //u"\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67\uD83C\uDDFA\uD83C\uDDF8";
2895 
2896         canvas->drawColor(SK_ColorWHITE);
2897 
2898         ParagraphStyle paragraph_style;
2899         paragraph_style.setMaxLines(1);
2900         paragraph_style.setHeight(0);
2901         paragraph_style.setEllipsis(u"\u2026");
2902         ParagraphBuilderImpl builder(paragraph_style, font_collection);
2903         TextStyle text_style;
2904         text_style.setColor(SK_ColorBLACK);
2905         text_style.setFontFamilies({SkString("Roboto"), SkString("Noto"), SkString("Emoji")});
2906         text_style.setFontSize(20);
2907         text_style.setFontStyle(SkFontStyle::Bold());
2908         builder.pushStyle(text_style);
2909         builder.addText(text);
2910         auto paragraph = builder.Build();
2911         paragraph->layout(width());
2912         paragraph->paint(canvas, 0, 0);
2913     }
2914 
2915 private:
2916     using INHERITED = Sample;
2917 };
2918 
2919 class ParagraphView46 : public ParagraphView_Base {
2920 protected:
name()2921     SkString name() override { return SkString("Paragraph44"); }
2922 
onDrawContent(SkCanvas * canvas)2923     void onDrawContent(SkCanvas* canvas) override {
2924 
2925         auto text = "XXXXXXXXXX\nYYYYYYYYYY\nZZZZZZZZZZ";
2926         canvas->drawColor(SK_ColorWHITE);
2927 
2928         auto fontCollection = sk_make_sp<FontCollection>();
2929         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2930         fontCollection->enableFontFallback();
2931 
2932         ParagraphStyle paragraph_style;
2933 
2934         auto column = width()/3;
2935         auto draw = [&](DrawOptions options, SkScalar x) {
2936             paragraph_style.setDrawOptions(options);
2937             ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2938             TextStyle text_style;
2939             text_style.setColor(SK_ColorBLACK);
2940             text_style.setFontFamilies({SkString("Roboto")});
2941             text_style.setFontSize(20);
2942             builder.pushStyle(text_style);
2943             builder.addText(text);
2944             auto paragraph = builder.Build();
2945             paragraph->layout(column);
2946             paragraph->paint(canvas, x, 000);
2947             paragraph->paint(canvas, x, 200);
2948             paragraph->paint(canvas, x, 400);
2949         };
2950 
2951         draw(DrawOptions::kReplay, column*0);
2952         draw(DrawOptions::kRecord, column*1);
2953         draw(DrawOptions::kDirect, column*2);
2954     }
2955 
2956 private:
2957     using INHERITED = Sample;
2958 };
2959 
2960 class ParagraphView47 : public ParagraphView_Base {
2961 protected:
name()2962     SkString name() override { return SkString("Paragraph47"); }
2963 
onDrawContent(SkCanvas * canvas)2964     void onDrawContent(SkCanvas* canvas) override {
2965 
2966     canvas->clear(SK_ColorWHITE);
2967 
2968     SkPaint paint;
2969     paint.setColor(SK_ColorRED);
2970 
2971     auto fontCollection = sk_make_sp<FontCollection>();
2972     fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2973 
2974     TextStyle defaultStyle;
2975     defaultStyle.setForegroundColor(paint);
2976 
2977     ParagraphStyle paraStyle;
2978     paraStyle.setTextStyle(defaultStyle);
2979     paraStyle.setMaxLines(1);
2980     paraStyle.setEllipsis(SkString("..."));
2981 
2982     const char* hello = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do";
2983     auto builder = ParagraphBuilder::make(paraStyle, fontCollection);
2984     builder->addText(hello, strlen(hello));
2985 
2986     auto paragraph = builder->Build();
2987     paragraph->layout(100);
2988     paragraph->paint(canvas, 200, 200);
2989 
2990     paragraph->layout(200);
2991     paragraph->paint(canvas, 200, 300);
2992 
2993     ParagraphStyle paraStyle2;
2994     paraStyle2.setTextStyle(defaultStyle);
2995     paraStyle2.setMaxLines(1);
2996     paraStyle.setEllipsis(SkString(""));
2997 
2998     auto builder2 = ParagraphBuilder::make(paraStyle, fontCollection);
2999     builder2->addText(hello, strlen(hello));
3000 
3001     auto paragraph2 = builder2->Build();
3002     paragraph2->layout(100);
3003     paragraph2->paint(canvas, 200, 400);
3004 
3005     paragraph2->layout(200);
3006     paragraph2->paint(canvas, 200, 500);
3007     canvas->restore();
3008     }
3009 
3010 private:
3011     using INHERITED = Sample;
3012 };
3013 
3014 
3015 class ParagraphView48 : public ParagraphView_Base {
3016 protected:
name()3017     SkString name() override { return SkString("Paragraph48"); }
3018 
onDrawContent(SkCanvas * canvas)3019     void onDrawContent(SkCanvas* canvas) override {
3020         canvas->clear(SK_ColorGRAY);
3021 
3022         // To reproduce the client problem set DEFAULT_FONT_FAMILY to something
3023         // non-existing: "sans-serif1", for instance
3024         SkPaint paint;
3025         paint.setColor(SK_ColorRED);
3026 
3027         auto fontCollection = sk_make_sp<FontCollection>();
3028         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3029 
3030         TextStyle defaultStyle;
3031         defaultStyle.setForegroundColor(paint);
3032 
3033         ParagraphStyle paraStyle;
3034         paraStyle.setTextStyle(defaultStyle);
3035 
3036         const char* hello = "�� 487";
3037         auto builder = ParagraphBuilder::make(paraStyle, fontCollection);
3038         builder->addText(hello, strlen(hello));
3039 
3040         auto paragraph = builder->Build();
3041         paragraph->layout(200);
3042         paragraph->paint(canvas, 200, 200);
3043 
3044         const char* hello2 = "487";
3045         auto builder2 = ParagraphBuilder::make(paraStyle, fontCollection);
3046         builder2->addText(hello2, strlen(hello2));
3047 
3048         auto paragraph2 = builder2->Build();
3049         paragraph2->layout(200);
3050         paragraph2->paint(canvas, 200, 300);
3051 
3052         const char* hello3 = " �� 487";
3053         auto builder3 = ParagraphBuilder::make(paraStyle, fontCollection);
3054         builder3->addText(hello3, strlen(hello3));
3055 
3056         auto paragraph3 = builder3->Build();
3057         paragraph3->layout(200);
3058         paragraph3->paint(canvas, 200, 400);
3059         canvas->restore();
3060     }
3061 
3062 private:
3063     using INHERITED = Sample;
3064 };
3065 
3066 class ParagraphView49 : public ParagraphView_Base {
3067 protected:
name()3068     SkString name() override { return SkString("Paragraph49"); }
3069 
onDrawContent(SkCanvas * canvas)3070     void onDrawContent(SkCanvas* canvas) override {
3071         canvas->clear(SK_ColorGRAY);
3072         auto fontCollection = getFontCollection();
3073         fontCollection->disableFontFallback();
3074         const char* text =  "AAAAAAAAA\n";
3075 
3076         ParagraphStyle paragraph_style;
3077         TextStyle text_style;
3078         text_style.setColor(SK_ColorBLACK);
3079         text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Serif CJK JP")});
3080         text_style.setFontSize(16);
3081         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3082         builder.pushStyle(text_style);
3083         builder.addText(text);
3084         PlaceholderStyle placeholder_style;
3085         placeholder_style.fHeight = 42;
3086         placeholder_style.fWidth = 45;
3087         placeholder_style.fBaselineOffset = 42;
3088         placeholder_style.fBaseline = TextBaseline::kAlphabetic;
3089         placeholder_style.fAlignment = PlaceholderAlignment::kBottom;
3090         builder.addPlaceholder(placeholder_style);
3091         auto paragraph = builder.Build();
3092         paragraph->layout(360);
3093         paragraph->paint(canvas, 0, 0);
3094     }
3095 
3096 private:
3097     using INHERITED = Sample;
3098 };
3099 
3100 class ParagraphView50 : public ParagraphView_Base {
3101 protected:
name()3102     SkString name() override { return SkString("Paragraph50"); }
3103 
onDrawContent(SkCanvas * canvas)3104     void onDrawContent(SkCanvas* canvas) override {
3105         canvas->clear(SK_ColorWHITE);
3106 
3107         auto fontCollection = sk_make_sp<FontCollection>();
3108         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3109 
3110         ParagraphStyle paragraph_style;
3111         TextStyle text_style;
3112         text_style.setColor(SK_ColorBLACK);
3113         text_style.setFontFamilies({SkString("Roboto")});
3114         text_style.setFontSize(16);
3115         text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3116         text_style.setDecorationMode(TextDecorationMode::kGaps);
3117         text_style.setDecorationColor(SK_ColorRED);
3118         text_style.setDecoration(TextDecoration::kUnderline);
3119         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3120         builder.pushStyle(text_style);
3121         builder.addText("\n\n");
3122         builder.pop();
3123         auto paragraph = builder.Build();
3124         paragraph->layout(360);
3125         paragraph->paint(canvas, 0, 0);
3126     }
3127 
3128 private:
3129     using INHERITED = Sample;
3130 };
3131 
3132 class ParagraphView51 : public ParagraphView_Base {
3133 protected:
name()3134     SkString name() override { return SkString("Paragraph51"); }
3135 
onDrawContent(SkCanvas * canvas)3136     void onDrawContent(SkCanvas* canvas) override {
3137         canvas->clear(SK_ColorWHITE);
3138 
3139         auto fontCollection = sk_make_sp<FontCollection>();
3140         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3141         fontCollection->enableFontFallback();
3142 
3143         ParagraphStyle paragraph_style;
3144         TextStyle text_style;
3145         text_style.setColor(SK_ColorBLACK);
3146         text_style.setFontFamilies({SkString("Roboto")});
3147         text_style.setFontSize(16);
3148         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3149         builder.pushStyle(text_style);
3150         builder.addText(u"\u0e41\u0e2a\u0e19\u0e2a\u0e31\nabc");
3151         builder.pop();
3152         auto paragraph = builder.Build();
3153         paragraph->layout(1000);
3154         paragraph->paint(canvas, 0, 0);
3155     }
3156 
3157 private:
3158     using INHERITED = Sample;
3159 };
3160 
3161 class ParagraphView52 : public ParagraphView_Base {
3162 protected:
name()3163     SkString name() override { return SkString("Paragraph52"); }
3164 
onDrawContent(SkCanvas * canvas)3165     void onDrawContent(SkCanvas* canvas) override {
3166         canvas->drawColor(SK_ColorWHITE);
3167         //const char* text = "������ ABC ������ DEF GHI";
3168 
3169         auto fontCollection = sk_make_sp<FontCollection>();
3170         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3171         fontCollection->enableFontFallback();
3172 
3173 
3174         {
3175         const char* text = " �� ��";
3176         ParagraphStyle paragraph_style;
3177         paragraph_style.turnHintingOff();
3178         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3179 
3180         TextStyle text_style;
3181         //text_style.setFontFamilies({SkString("sans-serif")});
3182         text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
3183         text_style.setFontSize(40);
3184         text_style.setColor(SK_ColorBLACK);
3185         builder.pushStyle(text_style);
3186         builder.addText(text, strlen(text));
3187         builder.pop();
3188 
3189         auto paragraph = builder.Build();
3190         paragraph->layout(width());
3191 
3192         paragraph->paint(canvas, 0, 0);
3193         }
3194 
3195         {
3196         const char* text = " �� A";
3197         ParagraphStyle paragraph_style;
3198         paragraph_style.turnHintingOff();
3199         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3200 
3201         TextStyle text_style;
3202         //text_style.setFontFamilies({SkString("sans-serif")});
3203         text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
3204         text_style.setFontSize(40);
3205         text_style.setColor(SK_ColorBLACK);
3206         builder.pushStyle(text_style);
3207         builder.addText(text, strlen(text));
3208         builder.pop();
3209 
3210         auto paragraph = builder.Build();
3211         paragraph->layout(width());
3212 
3213         paragraph->paint(canvas, 0, 400);
3214         }
3215 
3216     }
3217 
3218 private:
3219     using INHERITED = Sample;
3220 };
3221 
3222 class ParagraphView53 : public ParagraphView_Base {
3223 protected:
name()3224     SkString name() override { return SkString("Paragraph53"); }
3225 
onDrawContent(SkCanvas * canvas)3226     void onDrawContent(SkCanvas* canvas) override {
3227         canvas->drawColor(SK_ColorWHITE);
3228         const char* text1 = "אאא בבב גגג דדד ההה";
3229         const char* text2 = "ששש תתת";
3230         //const char* text3 = "אאא בבב גגג דדד הההששש תתת";
3231 
3232         auto fontCollection = sk_make_sp<FontCollection>();
3233         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3234         fontCollection->enableFontFallback();
3235 
3236         ParagraphStyle paragraph_style;
3237         paragraph_style.setTextDirection(TextDirection::kRtl);
3238         {
3239         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3240         TextStyle text_style;
3241         text_style.setFontSize(30);
3242         text_style.setColor(SK_ColorBLACK);
3243         builder.pushStyle(text_style);
3244         builder.addText(text1);
3245         builder.addText(text2);
3246         builder.pop();
3247 
3248         auto paragraph = builder.Build();
3249         paragraph->layout(width());
3250         paragraph->paint(canvas, 0, 0);
3251         canvas->translate(0, paragraph->getHeight() + 20);
3252         }
3253 
3254         {
3255         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3256         TextStyle text_style;
3257         text_style.setFontSize(30);
3258         text_style.setColor(SK_ColorBLACK);
3259         builder.pushStyle(text_style);
3260         builder.addText(text1);
3261         text_style.setColor(SK_ColorRED);
3262         builder.pushStyle(text_style);
3263         builder.addText(text2);
3264         builder.pop();
3265 
3266         auto paragraph = builder.Build();
3267         paragraph->layout(width());
3268         paragraph->paint(canvas, 0, 0);
3269         canvas->translate(0, paragraph->getHeight() + 20);
3270         }
3271 
3272     }
3273 
3274 private:
3275     using INHERITED = Sample;
3276 };
3277 
3278 class ParagraphView54 : public ParagraphView_Base {
3279 protected:
name()3280     SkString name() override { return SkString("Paragraph54"); }
3281 
onDrawContent(SkCanvas * canvas)3282     void onDrawContent(SkCanvas* canvas) override {
3283         canvas->drawColor(SK_ColorWHITE);
3284         //std::string text("يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ");
3285         //auto text = "ד��‍��‍��‍����";
3286         auto text = "��‍��‍��‍����";
3287 
3288         //auto fontCollection = sk_make_sp<FontCollection>();
3289         auto fontCollection = getFontCollection();
3290         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3291         fontCollection->enableFontFallback();
3292         //fontCollection->disableFontFallback();
3293 
3294         ParagraphStyle paragraph_style;
3295         //paragraph_style.setTextDirection(TextDirection::kRtl);
3296 
3297         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3298         TextStyle text_style;
3299         text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
3300         text_style.setFontSize(36);
3301         text_style.setColor(SK_ColorBLACK);
3302         builder.pushStyle(text_style);
3303         builder.addText(text);
3304 
3305         auto paragraph = builder.Build();
3306         paragraph->layout(/*360*/width());
3307         paragraph->paint(canvas, 0, 0);
3308     }
3309 
3310 private:
3311     using INHERITED = Sample;
3312 };
3313 
3314 class ParagraphView55 : public ParagraphView_Base {
3315 protected:
name()3316     SkString name() override { return SkString("Paragraph55"); }
3317 
onDrawContent(SkCanvas * canvas)3318     void onDrawContent(SkCanvas* canvas) override {
3319         canvas->drawColor(SK_ColorWHITE);
3320         std::string text("يَهْدِيْكُمُ اللَّهُ وَيُصْلِحُ بَالَكُمُ");
3321 
3322         //auto fontCollection = sk_make_sp<FontCollection>();
3323         //fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3324         //fontCollection->enableFontFallback();
3325         auto fontCollection = getFontCollection();
3326         fontCollection->disableFontFallback();
3327 
3328         ParagraphStyle paragraph_style;
3329         paragraph_style.setTextDirection(TextDirection::kRtl);
3330 
3331         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3332         TextStyle text_style;
3333         text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
3334         text_style.setFontSize(64);
3335         text_style.setColor(SK_ColorBLACK);
3336         builder.pushStyle(text_style);
3337         builder.addText(text.substr(0, 10).data());
3338         text_style.setColor(SK_ColorRED);
3339         builder.pushStyle(text_style);
3340         builder.addText(text.substr(10, 20).data());
3341         text_style.setColor(SK_ColorBLACK);
3342         builder.pushStyle(text_style);
3343         builder.addText(text.substr(30, 50).data());
3344 
3345         auto paragraph = builder.Build();
3346         paragraph->layout(/*360*/width());
3347         paragraph->paint(canvas, 0, 0);
3348     }
3349 
3350 private:
3351     using INHERITED = Sample;
3352 };
3353 
3354 class ParagraphView56 : public ParagraphView_Base {
3355 protected:
name()3356     SkString name() override { return SkString("Paragraph56"); }
3357 
onDrawContent(SkCanvas * canvas)3358     void onDrawContent(SkCanvas* canvas) override {
3359         canvas->drawColor(SK_ColorWHITE);
3360         auto text = "BAM BAM BAM by Jade Baraldo\n"
3361                     "Now on Top 100 Music Videos United States";
3362 
3363         auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
3364         fontCollection->addFontFromFile("music/Roboto-Regular.ttf", "roboto");
3365         fontCollection->addFontFromFile("music/NotoSansCJK-Regular.ttc", "noto");
3366         fontCollection->addFontFromFile("music/NotoColorEmoji.ttf", "emoji");
3367 
3368         ParagraphStyle paragraph_style;
3369         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3370         TextStyle text_style;
3371         //text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
3372         text_style.setFontFamilies({SkString("roboto"),
3373                                     SkString("noto"),
3374                                     SkString("emoji")});
3375         text_style.setFontSize(20);
3376         text_style.setColor(SK_ColorBLACK);
3377         builder.pushStyle(text_style);
3378         builder.addText(text);
3379         auto paragraph = builder.Build();
3380         paragraph->layout(width());
3381         paragraph->paint(canvas, 0, 0);
3382     }
3383 
3384 private:
3385     using INHERITED = Sample;
3386 };
3387 
3388 class ParagraphView57 : public ParagraphView_Base {
3389 protected:
name()3390     SkString name() override { return SkString("Paragraph57"); }
3391 
onDrawContent(SkCanvas * canvas)3392     void onDrawContent(SkCanvas* canvas) override {
3393         canvas->drawColor(SK_ColorWHITE);
3394 
3395         auto fontCollection = sk_make_sp<FontCollection>();
3396         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3397         fontCollection->enableFontFallback();
3398 
3399         ParagraphStyle paragraph_style;
3400         paragraph_style.setTextDirection(TextDirection::kRtl);
3401         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3402         TextStyle text_style;
3403         text_style.setFontFamilies({SkString("Roboto") });
3404         text_style.setFontSize(20);
3405         text_style.setColor(SK_ColorBLACK);
3406         builder.pushStyle(text_style);
3407         builder.addText("בבבב\n\nאאאא");
3408         builder.pop();
3409         auto paragraph = builder.Build();
3410         paragraph->layout(width());
3411         paragraph->paint(canvas, 0, 0);
3412 
3413         auto height = paragraph->getHeight();
3414         auto res1 = paragraph->getGlyphPositionAtCoordinate(0,0);
3415         auto res2 = paragraph->getGlyphPositionAtCoordinate(0,height / 2);
3416         auto res3 = paragraph->getGlyphPositionAtCoordinate(0,height);
3417         SkDebugf("res1: %d %s\n", res1.position, res1.affinity == Affinity::kDownstream ? "D" : "U");
3418         SkDebugf("res2: %d %s\n", res2.position, res2.affinity == Affinity::kDownstream ? "D" : "U");
3419         SkDebugf("res3: %d %s\n", res3.position, res3.affinity == Affinity::kDownstream ? "D" : "U");
3420     }
3421 
3422 private:
3423     using INHERITED = Sample;
3424 };
3425 
3426 class ParagraphView58 : public ParagraphView_Base {
3427 protected:
name()3428     SkString name() override { return SkString("Paragraph58"); }
3429 
onDrawContent(SkCanvas * canvas)3430     void onDrawContent(SkCanvas* canvas) override {
3431         canvas->drawColor(SK_ColorWHITE);
3432 
3433         auto fontCollection = getFontCollection();
3434         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3435         fontCollection->enableFontFallback();
3436 
3437         ParagraphStyle paragraph_style;
3438 
3439         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3440         TextStyle text_style;
3441         text_style.setFontFamilies({SkString("Roboto")});
3442         text_style.setFontSize(40);
3443         text_style.setColor(SK_ColorBLACK);
3444         builder.pushStyle(text_style);
3445         builder.addText(u"Text1 Google\u00A0Pay Text2");
3446 
3447         auto paragraph = builder.Build();
3448         paragraph->layout(width());
3449         paragraph->paint(canvas, 0, 0);
3450     }
3451 
3452 private:
3453     using INHERITED = Sample;
3454 };
3455 
3456 class ParagraphView59 : public ParagraphView_Base {
3457 protected:
name()3458     SkString name() override { return SkString("Paragraph59"); }
3459 
onDrawContent(SkCanvas * canvas)3460     void onDrawContent(SkCanvas* canvas) override {
3461 
3462         auto fontCollection = getFontCollection();
3463         //fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3464         //fontCollection->enableFontFallback();
3465 
3466         ParagraphStyle paragraph_style;
3467         TextStyle text_style;
3468         text_style.setColor(SK_ColorBLACK);
3469         text_style.setFontFamilies({SkString("Roboto")});
3470         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3471         text_style.setFontSize(14);
3472         builder.pushStyle(text_style);
3473         builder.addText("The quick brown fox ate a hamburgerfons and got sick.");
3474         auto paragraph = builder.Build();
3475         paragraph->layout(width());
3476 
3477         paragraph->paint(canvas, 0, 0);
3478 
3479         paragraph->visit([&](int, const skia::textlayout::Paragraph::VisitorInfo* info) {
3480             if (!info) {
3481                 return;
3482             }
3483             SkFontMetrics metrics;
3484             info->font.getMetrics(&metrics);
3485 
3486             auto first = info->positions[0]; first.offset(info->origin.fX, info->origin.fY);
3487             SkRect rect = SkRect::MakeXYWH(first.fX,
3488                                            first.fY + metrics.fAscent,
3489                                            info->advanceX - first.fX,
3490                                            metrics.fDescent - metrics.fAscent);
3491             SkPaint paint;
3492             paint.setColor(SK_ColorLTGRAY);
3493             canvas->drawRect(rect, paint);
3494         });
3495 
3496         paragraph->paint(canvas, 0, 0);
3497     }
3498 
3499 private:
3500     using INHERITED = Sample;
3501 };
3502 
3503 class ParagraphView60 : public ParagraphView_Base {
3504 protected:
name()3505     SkString name() override { return SkString("ParagraphView60"); }
3506 
onDrawContent(SkCanvas * canvas)3507     void onDrawContent(SkCanvas* canvas) override {
3508 
3509         SkString text("");
3510         canvas->drawColor(SK_ColorWHITE);
3511         auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
3512 
3513         TextStyle text_style;
3514         text_style.setColor(SK_ColorBLACK);
3515         text_style.setFontFamilies({SkString("Ahem")});
3516         text_style.setFontSize(10.0f);
3517         ParagraphStyle paragraph_style;
3518         paragraph_style.setTextStyle(text_style);
3519         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3520         builder.pushStyle(text_style);
3521         builder.addText("    ");
3522         auto paragraph = builder.Build();
3523         paragraph->layout(width());
3524         auto result = paragraph->getGlyphPositionAtCoordinate(20, 2); // "hello    " 60,2
3525         SkDebugf("getGlyphPositionAtCoordinate(20,2)=%d %s\n", result.position, result.affinity == Affinity::kDownstream ? "D" : "U");
3526     }
3527 
3528 private:
3529     using INHERITED = Sample;
3530 };
3531 
3532 class ParagraphView61 : public ParagraphView_Base {
3533 protected:
name()3534     SkString name() override { return SkString("ParagraphView61"); }
3535 
onDrawContent(SkCanvas * canvas)3536     void onDrawContent(SkCanvas* canvas) override {
3537 
3538         SkString text("");
3539         canvas->drawColor(SK_ColorWHITE);
3540         auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
3541 
3542         TextStyle text_style;
3543         text_style.setColor(SK_ColorBLACK);
3544         text_style.setFontFamilies({SkString("Ahem")});
3545         text_style.setFontSize(12.0f);
3546         ParagraphStyle paragraph_style;
3547         paragraph_style.setTextStyle(text_style);
3548         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3549         builder.pushStyle(text_style);
3550         builder.addText("______________________");
3551         auto paragraph = builder.Build();
3552         paragraph->layout(132.0f);
3553         paragraph->paint(canvas, 0, 0);
3554         std::vector<LineMetrics> metrics;
3555         paragraph->getLineMetrics(metrics);
3556         for (auto& metric : metrics) {
3557             SkDebugf("Line[%zu:%zu <= %zu <= %zu)\n", metric.fStartIndex, metric.fEndExcludingWhitespaces, metric.fEndIndex, metric.fEndIncludingNewline);
3558         }
3559     }
3560 
3561 private:
3562     using INHERITED = Sample;
3563 };
3564 
3565 // Selection jumping back and forth on Chinese text
3566 class ParagraphView62 : public ParagraphView_Base {
3567 protected:
name()3568     SkString name() override { return SkString("ParagraphView62"); }
3569 
onDrawContent(SkCanvas * canvas)3570     void onDrawContent(SkCanvas* canvas) override {
3571 
3572         SkString text("");
3573         canvas->drawColor(SK_ColorWHITE);
3574         auto fontCollection = sk_make_sp<FontCollection>();
3575         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3576 
3577         TextStyle text_style;
3578         text_style.setColor(SK_ColorBLACK);
3579         //text_style.setFontFamilies({SkString("")});
3580         text_style.setFontSize(24.0f);
3581         text_style.setHeight(12.0f);
3582         //text_style.setHeightOverride(true);
3583         ParagraphStyle paragraph_style;
3584         paragraph_style.setTextStyle(text_style);
3585         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3586         builder.pushStyle(text_style);
3587         //builder.addText("helloworld你好");
3588         builder.addText("你好你好你好你好");
3589         auto paragraph = builder.Build();
3590         paragraph->layout(SK_ScalarInfinity);
3591         paragraph->paint(canvas, 0, 0);
3592 
3593         for (auto x = 0.0f; x < paragraph->getMaxIntrinsicWidth(); x += 5.0f) {
3594             auto pos = paragraph->getGlyphPositionAtCoordinate(x, paragraph->getHeight() / 2);
3595             auto p = pos.position + (pos.affinity == Affinity::kDownstream ? 1 : 0);
3596             auto rects = paragraph->getRectsForRange(0, p,RectHeightStyle::kTight, RectWidthStyle::kTight);
3597             SkDebugf("@x=%f [0:%d%s=%d) ",
3598                      x, pos.position,
3599                      pos.affinity == Affinity::kDownstream ? "D" : "U",
3600                      p);
3601             for (auto& rect : rects) {
3602                 SkDebugf("[%f:%f) ", rect.rect.left(), rect.rect.right());
3603             }
3604             SkDebugf("\n");
3605         }
3606 
3607         //auto rects130 = paragraph->getRectsForRange(0.0f, 130.0f, RectHeightStyle::kTight, RectWidthStyle::kTight);
3608         //auto rects140 = paragraph->getRectsForRange(0.0f, 140.0f, RectHeightStyle::kTight, RectWidthStyle::kTight);
3609     }
3610 
3611 private:
3612     using INHERITED = Sample;
3613 };
3614 
3615 // Baseline shift
3616 class ParagraphView63 : public ParagraphView_Base {
3617 protected:
name()3618     SkString name() override { return SkString("ParagraphView63"); }
3619 
onDrawContent(SkCanvas * canvas)3620     void onDrawContent(SkCanvas* canvas) override {
3621 
3622         canvas->drawColor(SK_ColorWHITE);
3623         auto fontCollection = getFontCollection();
3624         fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
3625         fontCollection->enableFontFallback();
3626         TextStyle roboto;
3627         roboto.setColor(SK_ColorBLACK);
3628         roboto.setFontFamilies({SkString("Roboto")});
3629         roboto.setFontSize(20.0f);
3630 
3631         TextStyle assyrian;
3632         assyrian.setColor(SK_ColorRED);
3633         assyrian.setFontFamilies({SkString("Assyrian")});
3634         assyrian.setFontSize(40.0f);
3635 
3636         ParagraphStyle paragraph_style;
3637         paragraph_style.setTextStyle(roboto);
3638         ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3639 
3640         roboto.setBaselineShift(0.0f);
3641         builder.pushStyle(roboto);
3642         builder.addText("Notice that the line height increased on the lines with ");
3643         assyrian.setBaselineShift(.0f);
3644         builder.pushStyle(assyrian);
3645         builder.addText("baseline shifts:\n");
3646 
3647         roboto.setBaselineShift(0.0f);
3648         builder.pushStyle(roboto);
3649         builder.addText("Zero baseline shift text ");
3650 
3651         assyrian.setBaselineShift(-20.0f);
3652         builder.pushStyle(assyrian);
3653         builder.addText("Up20");
3654 
3655         roboto.setBaselineShift(-40.0f);
3656         builder.pushStyle(roboto);
3657         builder.addText("Up40");
3658 
3659         assyrian.setBaselineShift(-60.0f);
3660         builder.pushStyle(assyrian);
3661         builder.addText("Up60");
3662 
3663         roboto.setBaselineShift(-40.0f);
3664         builder.pushStyle(roboto);
3665         builder.addText("Up40");
3666 
3667         assyrian.setBaselineShift(-20.0f);
3668         builder.pushStyle(assyrian);
3669         builder.addText("Up20");
3670 
3671         roboto.setBaselineShift(-0.0f);
3672         builder.pushStyle(roboto);
3673         builder.addText(" Zero baseline shift text\n");
3674 
3675         assyrian.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(5, 5), 2));
3676         assyrian.setDecorationStyle(TextDecorationStyle::kSolid);
3677         assyrian.setDecoration(TextDecoration::kUnderline);
3678         assyrian.setDecorationColor(SK_ColorBLUE);
3679 
3680         roboto.setBaselineShift(0.0f);
3681         builder.pushStyle(roboto);
3682         builder.addText("Notice that shadows and decorations are shifted if there is a text with ");
3683         assyrian.setBaselineShift(.0f);
3684         builder.pushStyle(assyrian);
3685         builder.addText("baseline shifts:\n");
3686 
3687         assyrian.setDecoration(TextDecoration::kNoDecoration);
3688 
3689         roboto.setBaselineShift(0.0f);
3690         builder.pushStyle(roboto);
3691         builder.addText("Zero baseline shift text ");
3692 
3693         assyrian.setBaselineShift(20.0f);
3694         builder.pushStyle(assyrian);
3695         builder.addText("Down20");
3696 
3697         roboto.setBaselineShift(40.0f);
3698         builder.pushStyle(roboto);
3699         builder.addText("Down40");
3700 
3701         assyrian.setBaselineShift(60.0f);
3702         builder.pushStyle(assyrian);
3703         builder.addText("Down60");
3704 
3705         roboto.setBaselineShift(40.0f);
3706         builder.pushStyle(roboto);
3707         builder.addText("Down40");
3708 
3709         assyrian.setBaselineShift(20.0f);
3710         builder.pushStyle(assyrian);
3711         builder.addText("Down20");
3712 
3713         roboto.setBaselineShift(0.0f);
3714         builder.pushStyle(roboto);
3715         builder.addText(" Zero baseline shift text\n");
3716 
3717         assyrian.resetShadows();
3718         assyrian.setDecorationStyle(TextDecorationStyle::kSolid);
3719         assyrian.setDecoration(TextDecoration::kUnderline);
3720         assyrian.setDecorationColor(SK_ColorBLUE);
3721 
3722         roboto.setBaselineShift(0.0f);
3723         builder.pushStyle(roboto);
3724         builder.addText("Zero baseline shift text ");
3725 
3726         assyrian.setBaselineShift(-20.0f);
3727         builder.pushStyle(assyrian);
3728         builder.addText("Up20");
3729 
3730         roboto.setBaselineShift(-40.0f);
3731         builder.pushStyle(roboto);
3732         builder.addText("Up40");
3733 
3734         assyrian.setBaselineShift(-60.0f);
3735         builder.pushStyle(assyrian);
3736         builder.addText("Up60");
3737 
3738         roboto.setBaselineShift(-40.0f);
3739         builder.pushStyle(roboto);
3740         builder.addText("Up40");
3741 
3742         assyrian.setBaselineShift(-20.0f);
3743         builder.pushStyle(assyrian);
3744         builder.addText("Up20");
3745 
3746         roboto.setBaselineShift(-0.0f);
3747         builder.pushStyle(roboto);
3748         builder.addText(" Zero baseline shift text");
3749 
3750         auto paragraph = builder.Build();
3751         paragraph->layout(SK_ScalarInfinity);
3752         paragraph->paint(canvas, 0, 0);
3753     }
3754 
3755 private:
3756     using INHERITED = Sample;
3757 };
3758 
3759 }  // namespace
3760 
3761 //////////////////////////////////////////////////////////////////////////////
3762 DEF_SAMPLE(return new ParagraphView1();)
3763 DEF_SAMPLE(return new ParagraphView2();)
3764 DEF_SAMPLE(return new ParagraphView3();)
3765 DEF_SAMPLE(return new ParagraphView4();)
3766 DEF_SAMPLE(return new ParagraphView5();)
3767 DEF_SAMPLE(return new ParagraphView6();)
3768 DEF_SAMPLE(return new ParagraphView7();)
3769 DEF_SAMPLE(return new ParagraphView8();)
3770 DEF_SAMPLE(return new ParagraphView9();)
3771 DEF_SAMPLE(return new ParagraphView10();)
3772 DEF_SAMPLE(return new ParagraphView11();)
3773 DEF_SAMPLE(return new ParagraphView12();)
3774 DEF_SAMPLE(return new ParagraphView14();)
3775 DEF_SAMPLE(return new ParagraphView15();)
3776 DEF_SAMPLE(return new ParagraphView16();)
3777 DEF_SAMPLE(return new ParagraphView17();)
3778 DEF_SAMPLE(return new ParagraphView18();)
3779 DEF_SAMPLE(return new ParagraphView19();)
3780 DEF_SAMPLE(return new ParagraphView20();)
3781 DEF_SAMPLE(return new ParagraphView21();)
3782 DEF_SAMPLE(return new ParagraphView22();)
3783 DEF_SAMPLE(return new ParagraphView23();)
3784 DEF_SAMPLE(return new ParagraphView24();)
3785 DEF_SAMPLE(return new ParagraphView25();)
3786 DEF_SAMPLE(return new ParagraphView26();)
3787 DEF_SAMPLE(return new ParagraphView27();)
3788 DEF_SAMPLE(return new ParagraphView28();)
3789 DEF_SAMPLE(return new ParagraphView29();)
3790 DEF_SAMPLE(return new ParagraphView30();)
3791 DEF_SAMPLE(return new ParagraphView31();)
3792 DEF_SAMPLE(return new ParagraphView32();)
3793 DEF_SAMPLE(return new ParagraphView33();)
3794 DEF_SAMPLE(return new ParagraphView34();)
3795 DEF_SAMPLE(return new ParagraphView35();)
3796 DEF_SAMPLE(return new ParagraphView36();)
3797 DEF_SAMPLE(return new ParagraphView37();)
3798 DEF_SAMPLE(return new ParagraphView38();)
3799 DEF_SAMPLE(return new ParagraphView39();)
3800 DEF_SAMPLE(return new ParagraphView41();)
3801 DEF_SAMPLE(return new ParagraphView42();)
3802 DEF_SAMPLE(return new ParagraphView43();)
3803 DEF_SAMPLE(return new ParagraphView44();)
3804 DEF_SAMPLE(return new ParagraphView45();)
3805 DEF_SAMPLE(return new ParagraphView46();)
3806 DEF_SAMPLE(return new ParagraphView47();)
3807 DEF_SAMPLE(return new ParagraphView48();)
3808 DEF_SAMPLE(return new ParagraphView49();)
3809 DEF_SAMPLE(return new ParagraphView50();)
3810 DEF_SAMPLE(return new ParagraphView51();)
3811 DEF_SAMPLE(return new ParagraphView52();)
3812 DEF_SAMPLE(return new ParagraphView53();)
3813 DEF_SAMPLE(return new ParagraphView54();)
3814 DEF_SAMPLE(return new ParagraphView55();)
3815 DEF_SAMPLE(return new ParagraphView56();)
3816 DEF_SAMPLE(return new ParagraphView57();)
3817 DEF_SAMPLE(return new ParagraphView58();)
3818 DEF_SAMPLE(return new ParagraphView59();)
3819 DEF_SAMPLE(return new ParagraphView60();)
3820 DEF_SAMPLE(return new ParagraphView61();)
3821 DEF_SAMPLE(return new ParagraphView62();)
3822 DEF_SAMPLE(return new ParagraphView63();)
3823