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