blob: 9a9e2282e7dd72a31e8f60178b2d1bb2961a0a73 [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#include "Sample.h"
3#include "include/core/SkCanvas.h"
4#include "include/core/SkColorFilter.h"
5#include "include/core/SkColorPriv.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/SkBlurMaskFilter.h"
15#include "include/effects/SkGradientShader.h"
16#include "include/utils/SkRandom.h"
17#include "modules/skparagraph/include/Paragraph.h"
18#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
19#include "modules/skparagraph/src/ParagraphImpl.h"
20#include "modules/skparagraph/src/TypefaceFontProvider.h"
21#include "src/core/SkOSFile.h"
22#include "src/shaders/SkColorShader.h"
23#include "src/utils/SkUTF.h"
24#include "tools/Resources.h"
25
26using namespace skia::textlayout;
27namespace {
28
29sk_sp<SkShader> setgrad(const SkRect& r, SkColor c0, SkColor c1) {
30 SkColor colors[] = {c0, c1};
31 SkPoint pts[] = {{r.fLeft, r.fTop}, {r.fRight, r.fTop}};
32 return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
33}
34
35class TestFontCollection : public FontCollection {
36public:
37 TestFontCollection() : fResourceDir(GetResourcePath("fonts").c_str()) {
38 auto fontProvider = sk_make_sp<TypefaceFontProvider>();
39
40 SkOSFile::Iter iter(fResourceDir.c_str());
41 SkString path;
42 while (iter.next(&path)) {
43 SkString file_path;
44 file_path.printf("%s/%s", fResourceDir.c_str(), path.c_str());
45 fontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
46 }
47
48 this->setTestFontManager(std::move(fontProvider));
49 this->disableFontFallback();
50 }
51
52 ~TestFontCollection() = default;
53
54private:
55 std::string fResourceDir;
56};
57} // namespace
58
59class ParagraphView1 : public Sample {
60protected:
61 bool onQuery(Sample::Event* evt) override {
62 if (Sample::TitleQ(*evt)) {
63 Sample::TitleR(evt, "Paragraph1");
64 return true;
65 }
66 return this->INHERITED::onQuery(evt);
67 }
68
69 void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) {
70 const std::vector<
71 std::tuple<std::string, bool, bool, int, SkColor, SkColor, bool, TextDecorationStyle>>
72 gParagraph = {{"monospace", true, false, 14, SK_ColorWHITE, SK_ColorRED, true,
73 TextDecorationStyle::kDashed},
74 {"Assyrian", false, false, 20, SK_ColorWHITE, SK_ColorBLUE, false,
75 TextDecorationStyle::kDotted},
76 {"serif", true, true, 10, SK_ColorWHITE, SK_ColorRED, true,
77 TextDecorationStyle::kDouble},
78 {"Arial", false, true, 16, SK_ColorGRAY, SK_ColorGREEN, true,
79 TextDecorationStyle::kSolid},
80 {"sans-serif", false, false, 8, SK_ColorWHITE, SK_ColorRED, false,
81 TextDecorationStyle::kWavy}};
82 SkAutoCanvasRestore acr(canvas, true);
83
84 canvas->clipRect(SkRect::MakeWH(w, h));
85 canvas->drawColor(SK_ColorWHITE);
86
87 SkScalar margin = 20;
88
89 SkPaint paint;
90 paint.setAntiAlias(true);
91 paint.setColor(fg);
92
93 SkPaint blue;
94 blue.setColor(SK_ColorBLUE);
95
96 TextStyle defaultStyle;
97 defaultStyle.setBackgroundColor(blue);
98 defaultStyle.setForegroundColor(paint);
99 ParagraphStyle paraStyle;
100
101 for (auto i = 1; i < 5; ++i) {
102 defaultStyle.setFontSize(24 * i);
103 paraStyle.setTextStyle(defaultStyle);
104 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<FontCollection>());
105 std::string name = "Paragraph: " + std::to_string(24 * i);
106 builder.addText(name.c_str());
107 for (auto para : gParagraph) {
108 TextStyle style;
109 style.setFontFamilies({SkString(std::get<0>(para).c_str())});
110 SkFontStyle fontStyle(std::get<1>(para) ? SkFontStyle::Weight::kBold_Weight
111 : SkFontStyle::Weight::kNormal_Weight,
112 SkFontStyle::Width::kNormal_Width,
113 std::get<2>(para) ? SkFontStyle::Slant::kItalic_Slant
114 : SkFontStyle::Slant::kUpright_Slant);
115 style.setFontStyle(fontStyle);
116 style.setFontSize(std::get<3>(para) * i);
117 SkPaint background;
118 background.setColor(std::get<4>(para));
119 style.setBackgroundColor(background);
120 SkPaint foreground;
121 foreground.setColor(std::get<5>(para));
122 foreground.setAntiAlias(true);
123 style.setForegroundColor(foreground);
124 if (std::get<6>(para)) {
125 style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(5, 5), 2));
126 }
127
128 auto decoration = (i % 4);
129 if (decoration == 3) {
130 decoration = 4;
131 }
132
133 bool test = (TextDecoration)decoration != TextDecoration::kNoDecoration;
134 std::string deco = std::to_string((int)decoration);
135 if (test) {
136 style.setDecoration((TextDecoration)decoration);
137 style.setDecorationStyle(std::get<7>(para));
138 style.setDecorationColor(std::get<5>(para));
139 }
140 builder.pushStyle(style);
141 std::string name = " " + std::get<0>(para) + " " +
142 (std::get<1>(para) ? ", bold" : "") +
143 (std::get<2>(para) ? ", italic" : "") + " " +
144 std::to_string(std::get<3>(para) * i) +
145 (std::get<4>(para) != bg ? ", background" : "") +
146 (std::get<5>(para) != fg ? ", foreground" : "") +
147 (std::get<6>(para) ? ", shadow" : "") +
148 (test ? ", decorations " + deco : "") + ";";
149 builder.addText(name.c_str());
150 builder.pop();
151 }
152
153 auto paragraph = builder.Build();
154 paragraph->layout(w - margin * 2);
155
156 paragraph->paint(canvas, margin, margin);
157
158 canvas->translate(0, paragraph->getHeight());
159 }
160 }
161
162 void onDrawContent(SkCanvas* canvas) override {
163 drawTest(canvas, this->width(), this->height(), SK_ColorRED, SK_ColorWHITE);
164 }
165
166private:
167
168 typedef Sample INHERITED;
169};
170
171class ParagraphView2 : public Sample {
172protected:
173 bool onQuery(Sample::Event* evt) override {
174 if (Sample::TitleQ(*evt)) {
175 Sample::TitleR(evt, "Paragraph2");
176 return true;
177 }
178 return this->INHERITED::onQuery(evt);
179 }
180
181 void drawCode(SkCanvas* canvas, SkScalar w, SkScalar h) {
182 SkPaint comment;
183 comment.setColor(SK_ColorGRAY);
184 SkPaint constant;
185 constant.setColor(SK_ColorMAGENTA);
186 SkPaint null;
187 null.setColor(SK_ColorMAGENTA);
188 SkPaint literal;
189 literal.setColor(SK_ColorGREEN);
190 SkPaint code;
191 code.setColor(SK_ColorDKGRAY);
192 SkPaint number;
193 number.setColor(SK_ColorBLUE);
194 SkPaint name;
195 name.setColor(SK_ColorRED);
196
197 SkPaint white;
198 white.setColor(SK_ColorWHITE);
199
200 TextStyle defaultStyle;
201 defaultStyle.setBackgroundColor(white);
202 defaultStyle.setForegroundColor(code);
203 defaultStyle.setFontFamilies({SkString("monospace")});
204 defaultStyle.setFontSize(30);
205 ParagraphStyle paraStyle;
206 paraStyle.setTextStyle(defaultStyle);
207
208 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<FontCollection>());
209
210 builder.pushStyle(style(name));
211 builder.addText("RaisedButton");
212 builder.pop();
213 builder.addText("(\n");
214 builder.addText(" child: ");
215 builder.pushStyle(style(constant));
216 builder.addText("const");
217 builder.pop();
218 builder.addText(" ");
219 builder.pushStyle(style(name));
220 builder.addText("Text");
221 builder.pop();
222 builder.addText("(");
223 builder.pushStyle(style(literal));
224 builder.addText("'BUTTON TITLE'");
225 builder.pop();
226 builder.addText("),\n");
227
228 auto paragraph = builder.Build();
229 paragraph->layout(w - 20);
230
231 paragraph->paint(canvas, 20, 20);
232 }
233
234 TextStyle style(SkPaint paint) {
235 TextStyle style;
236 paint.setAntiAlias(true);
237 style.setForegroundColor(paint);
238 style.setFontFamilies({SkString("monospace")});
239 style.setFontSize(30);
240
241 return style;
242 }
243
244 void drawText(SkCanvas* canvas, SkScalar w, SkScalar h, std::vector<std::string>& text,
245 SkColor fg = SK_ColorDKGRAY, SkColor bg = SK_ColorWHITE,
246 const char* ff = "sans-serif", SkScalar fs = 24,
247 size_t lineLimit = 30,
248 const std::u16string& ellipsis = u"\u2026") {
249 SkAutoCanvasRestore acr(canvas, true);
250
251 canvas->clipRect(SkRect::MakeWH(w, h));
252 canvas->drawColor(bg);
253
254 SkScalar margin = 20;
255
256 SkPaint paint;
257 paint.setAntiAlias(true);
258 paint.setColor(fg);
259
260 SkPaint blue;
261 blue.setColor(SK_ColorBLUE);
262
263 SkPaint background;
264 background.setColor(bg);
265
266 TextStyle style;
267 style.setBackgroundColor(blue);
268 style.setForegroundColor(paint);
269 style.setFontFamilies({SkString(ff)});
270 style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight,
271 SkFontStyle::kNormal_Width,
272 SkFontStyle::kUpright_Slant));
273 style.setFontSize(fs);
274 ParagraphStyle paraStyle;
275 paraStyle.setTextStyle(style);
276 paraStyle.setMaxLines(lineLimit);
277
278 paraStyle.setEllipsis(ellipsis);
279 TextStyle defaultStyle;
280 defaultStyle.setFontSize(20);
281 paraStyle.setTextStyle(defaultStyle);
282 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
283
284 SkPaint foreground;
285 foreground.setColor(fg);
286 style.setForegroundColor(foreground);
287 style.setBackgroundColor(background);
288
289 for (auto& part : text) {
290 builder.pushStyle(style);
291 builder.addText(part.c_str());
292 builder.pop();
293 }
294
295 auto paragraph = builder.Build();
296 paragraph->layout(w - margin * 2);
297 paragraph->paint(canvas, margin, margin);
298
299 canvas->translate(0, paragraph->getHeight() + margin);
300 }
301
302 void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
303 TextAlign align) {
304 SkAutoCanvasRestore acr(canvas, true);
305
306 canvas->clipRect(SkRect::MakeWH(w, h));
307 canvas->drawColor(SK_ColorWHITE);
308
309 SkScalar margin = 20;
310
311 SkPaint paint;
312 paint.setAntiAlias(true);
313 paint.setColor(SK_ColorBLUE);
314
315 SkPaint gray;
316 gray.setColor(SK_ColorLTGRAY);
317
318 TextStyle style;
319 style.setBackgroundColor(gray);
320 style.setForegroundColor(paint);
321 style.setFontFamilies({SkString("Arial")});
322 style.setFontSize(30);
323 ParagraphStyle paraStyle;
324 paraStyle.setTextStyle(style);
325 paraStyle.setTextAlign(align);
326
327 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<FontCollection>());
328 builder.addText(text.c_str());
329
330 auto paragraph = builder.Build();
331 paragraph->layout(w - margin * 2);
332 paragraph->layout(w - margin);
333 paragraph->paint(canvas, margin, margin);
334
335 canvas->translate(0, paragraph->getHeight() + margin);
336 }
337
338 void onDrawContent(SkCanvas* canvas) override {
339 std::vector<std::string> cupertino = {
340 "google_logogoogle_gsuper_g_logo 1 "
341 "google_logogoogle_gsuper_g_logo 12 "
342 "google_logogoogle_gsuper_g_logo 123 "
343 "google_logogoogle_gsuper_g_logo 1234 "
344 "google_logogoogle_gsuper_g_logo 12345 "
345 "google_logogoogle_gsuper_g_logo 123456 "
346 "google_logogoogle_gsuper_g_logo 1234567 "
347 "google_logogoogle_gsuper_g_logo 12345678 "
348 "google_logogoogle_gsuper_g_logo 123456789 "
349 "google_logogoogle_gsuper_g_logo 1234567890 "
350 "google_logogoogle_gsuper_g_logo 123456789 "
351 "google_logogoogle_gsuper_g_logo 12345678 "
352 "google_logogoogle_gsuper_g_logo 1234567 "
353 "google_logogoogle_gsuper_g_logo 123456 "
354 "google_logogoogle_gsuper_g_logo 12345 "
355 "google_logogoogle_gsuper_g_logo 1234 "
356 "google_logogoogle_gsuper_g_logo 123 "
357 "google_logogoogle_gsuper_g_logo 12 "
358 "google_logogoogle_gsuper_g_logo 1 "
359 "google_logogoogle_gsuper_g_logo "
360 "google_logogoogle_gsuper_g_logo "
361 "google_logogoogle_gsuper_g_logo "
362 "google_logogoogle_gsuper_g_logo "
363 "google_logogoogle_gsuper_g_logo "
364 "google_logogoogle_gsuper_g_logo"};
365 std::vector<std::string> text = {
366 "My neighbor came over to say,\n"
367 "Although not in a neighborly way,\n\n"
368 "That he'd knock me around,\n\n\n"
369 "If I didn't stop the sound,\n\n\n\n"
370 "Of the classical music I play."};
371
372 std::vector<std::string> long_word = {
373 "A_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
374 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
375 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
376 "very_very_very_very_very_very_very_long_text"};
377
378 std::vector<std::string> very_long = {
379 "A very very very very very very very very very very very very very very very very "
380 "very very very very very very very very very very very very very very very very "
381 "very very very very very very very very very very very very very very very very "
382 "very very very very very very very long text"};
383
384 std::vector<std::string> very_word = {
385 "A very_very_very_very_very_very_very_very_very_very "
386 "very_very_very_very_very_very_very_very_very_very very very very very very very "
387 "very very very very very very very very very very very very very very very very "
388 "very very very very very very very very very very very very very long text"};
389
390 SkScalar width = this->width() / 5;
391 SkScalar height = this->height();
392 drawText(canvas, width, height, long_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
393 canvas->translate(width, 0);
394 drawText(canvas, width, height, very_long, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
395 canvas->translate(width, 0);
396 drawText(canvas, width, height, very_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
397 canvas->translate(width, 0);
398
399 drawText(canvas, width, height / 2, text, SK_ColorBLACK, SK_ColorWHITE, "Roboto", 20, 100,
400 u"\u2026");
401 canvas->translate(0, height / 2);
402 drawCode(canvas, width, height / 2);
403 canvas->translate(width, -height / 2);
404
405 drawText(canvas, width, height, cupertino, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
406 }
407
408private:
409 typedef Sample INHERITED;
410};
411
412class ParagraphView3 : public Sample {
413protected:
414 bool onQuery(Sample::Event* evt) override {
415 if (Sample::TitleQ(*evt)) {
416 Sample::TitleR(evt, "Paragraph3");
417 return true;
418 }
419 return this->INHERITED::onQuery(evt);
420 }
421
422 void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
423 TextAlign align, size_t lineLimit = std::numeric_limits<size_t>::max(),
424 bool RTL = false, SkColor background = SK_ColorGRAY,
425 const std::u16string& ellipsis = u"\u2026") {
426 SkAutoCanvasRestore acr(canvas, true);
427
428 canvas->clipRect(SkRect::MakeWH(w, h));
429 canvas->drawColor(SK_ColorWHITE);
430
431 SkScalar margin = 20;
432
433 SkPaint paint;
434 paint.setAntiAlias(true);
435 paint.setColor(SK_ColorBLACK);
436
437 SkPaint gray;
438 gray.setColor(background);
439
440 SkPaint yellow;
441 yellow.setColor(SK_ColorYELLOW);
442
443 TextStyle style;
444 style.setBackgroundColor(gray);
445 style.setForegroundColor(paint);
446 style.setFontFamilies({SkString("sans-serif")});
447 style.setFontSize(30);
448 ParagraphStyle paraStyle;
449 paraStyle.setTextStyle(style);
450 paraStyle.setTextAlign(align);
451 paraStyle.setMaxLines(lineLimit);
452 paraStyle.setEllipsis(ellipsis);
453 // paraStyle.setTextDirection(RTL ? SkTextDirection::rtl : SkTextDirection::ltr);
454
455 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<FontCollection>());
456 if (RTL) {
457 builder.addText(mirror(text));
458 } else {
459 builder.addText(normal(text));
460 }
461
462 canvas->drawRect(SkRect::MakeXYWH(margin, margin, w - margin * 2, h - margin * 2), yellow);
463 auto paragraph = builder.Build();
464 paragraph->layout(w - margin * 2);
465 paragraph->paint(canvas, margin, margin);
466 }
467
468 std::u16string mirror(const std::string& text) {
469 std::u16string result;
470 result += u"\u202E";
471 // for (auto i = text.size(); i > 0; --i) {
472 // result += text[i - 1];
473 //}
474
475 for (auto i = text.size(); i > 0; --i) {
476 auto ch = text[i - 1];
477 if (ch == ',') {
478 result += u"!";
479 } else if (ch == '.') {
480 result += u"!";
481 } else {
482 result += ch;
483 }
484 }
485
486 result += u"\u202C";
487 return result;
488 }
489
490 std::u16string normal(const std::string& text) {
491 std::u16string result;
492 result += u"\u202D";
493 for (auto ch : text) {
494 result += ch;
495 }
496 result += u"\u202C";
497 return result;
498 }
499
500 void onDrawContent(SkCanvas* canvas) override {
501 const std::string options = // { "open-source open-source open-source open-source" };
502 {"Flutter is an open-source project to help developers "
503 "build high-performance, high-fidelity, mobile apps for "
504 "iOS and Android "
505 "from a single codebase. This design lab is a playground "
506 "and showcase of Flutter's many widgets, behaviors, "
507 "animations, layouts, and more."};
508
509 canvas->drawColor(SK_ColorDKGRAY);
510 SkScalar width = this->width() / 4;
511 SkScalar height = this->height() / 2;
512
513 const std::string line =
514 "World domination is such an ugly phrase - I prefer to call it world optimisation";
515
516 drawLine(canvas, width, height, line, TextAlign::kLeft, 1, false, SK_ColorLTGRAY);
517 canvas->translate(width, 0);
518 drawLine(canvas, width, height, line, TextAlign::kRight, 2, false, SK_ColorLTGRAY);
519 canvas->translate(width, 0);
520 drawLine(canvas, width, height, line, TextAlign::kCenter, 3, false, SK_ColorLTGRAY);
521 canvas->translate(width, 0);
522 drawLine(canvas, width, height, line, TextAlign::kJustify, 4, false, SK_ColorLTGRAY);
523 canvas->translate(-width * 3, height);
524
525 drawLine(canvas, width, height, line, TextAlign::kLeft, 1, true, SK_ColorLTGRAY);
526 canvas->translate(width, 0);
527 drawLine(canvas, width, height, line, TextAlign::kRight, 2, true, SK_ColorLTGRAY);
528 canvas->translate(width, 0);
529 drawLine(canvas, width, height, line, TextAlign::kCenter, 3, true, SK_ColorLTGRAY);
530 canvas->translate(width, 0);
531 drawLine(canvas, width, height, line, TextAlign::kJustify, 4, true, SK_ColorLTGRAY);
532 canvas->translate(width, 0);
533 }
534
535private:
536 typedef Sample INHERITED;
537};
538
539class ParagraphView4 : public Sample {
540protected:
541 bool onQuery(Sample::Event* evt) override {
542 if (Sample::TitleQ(*evt)) {
543 Sample::TitleR(evt, "Paragraph4");
544 return true;
545 }
546 return this->INHERITED::onQuery(evt);
547 }
548
549 void drawFlutter(SkCanvas* canvas, SkScalar w, SkScalar h,
550 const char* ff = "Google Sans", SkScalar fs = 30,
551 size_t lineLimit = std::numeric_limits<size_t>::max(),
552 const std::u16string& ellipsis = u"\u2026") {
553 SkAutoCanvasRestore acr(canvas, true);
554
555 canvas->clipRect(SkRect::MakeWH(w, h));
556
557 SkScalar margin = 20;
558
559 SkPaint black;
560 black.setAntiAlias(true);
561 black.setColor(SK_ColorBLACK);
562
563 SkPaint blue;
564 blue.setAntiAlias(true);
565 blue.setColor(SK_ColorBLUE);
566
567 SkPaint red;
568 red.setAntiAlias(true);
569 red.setColor(SK_ColorRED);
570
571 SkPaint green;
572 green.setAntiAlias(true);
573 green.setColor(SK_ColorGREEN);
574
575 SkPaint gray;
576 gray.setColor(SK_ColorLTGRAY);
577
578 SkPaint yellow;
579 yellow.setColor(SK_ColorYELLOW);
580
581 SkPaint magenta;
582 magenta.setAntiAlias(true);
583 magenta.setColor(SK_ColorMAGENTA);
584
585 TextStyle style;
586 style.setFontFamilies({SkString(ff)});
587 style.setFontSize(fs);
588
589 TextStyle style0;
590 style0.setForegroundColor(black);
591 style0.setBackgroundColor(gray);
592 style0.setFontFamilies({SkString(ff)});
593 style0.setFontSize(fs);
594 style0.setDecoration(TextDecoration::kUnderline);
595 style0.setDecorationStyle(TextDecorationStyle::kDouble);
596 style0.setDecorationColor(SK_ColorBLACK);
597
598 TextStyle style1;
599 style1.setForegroundColor(blue);
600 style1.setBackgroundColor(yellow);
601 style1.setFontFamilies({SkString(ff)});
602 style1.setFontSize(fs);
603 style1.setDecoration(TextDecoration::kOverline);
604 style1.setDecorationStyle(TextDecorationStyle::kWavy);
605 style1.setDecorationColor(SK_ColorBLACK);
606
607 TextStyle style2;
608 style2.setForegroundColor(red);
609 style2.setFontFamilies({SkString(ff)});
610 style2.setFontSize(fs);
611
612 TextStyle style3;
613 style3.setForegroundColor(green);
614 style3.setFontFamilies({SkString(ff)});
615 style3.setFontSize(fs);
616
617 TextStyle style4;
618 style4.setForegroundColor(magenta);
619 style4.setFontFamilies({SkString(ff)});
620 style4.setFontSize(fs);
621
622 ParagraphStyle paraStyle;
623 paraStyle.setTextStyle(style);
624 paraStyle.setMaxLines(lineLimit);
625
626 paraStyle.setEllipsis(ellipsis);
627
628 const char* logo1 = "google_";
629 const char* logo2 = "logo";
630 const char* logo3 = "go";
631 const char* logo4 = "ogle_logo";
632 const char* logo5 = "google_lo";
633 const char* logo6 = "go";
634 {
635 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
636
637 builder.pushStyle(style0);
638 builder.addText(logo1);
639 builder.pop();
640 builder.pushStyle(style1);
641 builder.addText(logo2);
642 builder.pop();
643
644 builder.addText(" ");
645
646 builder.pushStyle(style0);
647 builder.addText(logo3);
648 builder.pop();
649 builder.pushStyle(style1);
650 builder.addText(logo4);
651 builder.pop();
652
653 builder.addText(" ");
654
655 builder.pushStyle(style0);
656 builder.addText(logo5);
657 builder.pop();
658 builder.pushStyle(style1);
659 builder.addText(logo6);
660 builder.pop();
661
662 auto paragraph = builder.Build();
663 paragraph->layout(w - margin * 2);
664 paragraph->paint(canvas, margin, margin);
665 canvas->translate(0, h + margin);
666 }
667 }
668
669 void onDrawContent(SkCanvas* canvas) override {
670 canvas->drawColor(SK_ColorWHITE);
671 SkScalar width = this->width();
672 SkScalar height = this->height();
673
674 drawFlutter(canvas, width, height / 2);
675 }
676
677private:
678 typedef Sample INHERITED;
679};
680
681class ParagraphView5 : public Sample {
682protected:
683 bool onQuery(Sample::Event* evt) override {
684 if (Sample::TitleQ(*evt)) {
685 Sample::TitleR(evt, "Paragraph4");
686 return true;
687 }
688 return this->INHERITED::onQuery(evt);
689 }
690
691 void bidi(SkCanvas* canvas, SkScalar w, SkScalar h, const std::u16string& text,
692 const std::u16string& expected, size_t lineLimit = std::numeric_limits<size_t>::max(),
693 const char* ff = "Roboto", SkScalar fs = 30,
694 const std::u16string& ellipsis = u"\u2026") {
695 SkAutoCanvasRestore acr(canvas, true);
696
697 canvas->clipRect(SkRect::MakeWH(w, h));
698
699 SkScalar margin = 20;
700
701 SkPaint black;
702 black.setColor(SK_ColorBLACK);
703 SkPaint gray;
704 gray.setColor(SK_ColorLTGRAY);
705
706 TextStyle style;
707 style.setForegroundColor(black);
708 style.setFontFamilies({SkString(ff)});
709 style.setFontSize(fs);
710
711 TextStyle style0;
712 style0.setForegroundColor(black);
713 style0.setFontFamilies({SkString(ff)});
714 style0.setFontSize(fs);
715 style0.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
716 SkFontStyle::kItalic_Slant));
717
718 TextStyle style1;
719 style1.setForegroundColor(gray);
720 style1.setFontFamilies({SkString(ff)});
721 style1.setFontSize(fs);
722 style1.setFontStyle(SkFontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
723 SkFontStyle::kUpright_Slant));
724
725 ParagraphStyle paraStyle;
726 paraStyle.setTextStyle(style);
727 paraStyle.setMaxLines(lineLimit);
728
729 paraStyle.setEllipsis(ellipsis);
730
731 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
732
733 if (text.empty()) {
734 const std::u16string text0 = u"\u202Dabc";
735 const std::u16string text1 = u"\u202EFED";
736 const std::u16string text2 = u"\u202Dghi";
737 const std::u16string text3 = u"\u202ELKJ";
738 const std::u16string text4 = u"\u202Dmno";
739 builder.pushStyle(style0);
740 builder.addText(text0);
741 builder.pop();
742 builder.pushStyle(style1);
743 builder.addText(text1);
744 builder.pop();
745 builder.pushStyle(style0);
746 builder.addText(text2);
747 builder.pop();
748 builder.pushStyle(style1);
749 builder.addText(text3);
750 builder.pop();
751 builder.pushStyle(style0);
752 builder.addText(text4);
753 builder.pop();
754 } else {
755 // icu::UnicodeString unicode((UChar*) text.data(), SkToS32(text.size()));
756 // std::string str;
757 // unicode.toUTF8String(str);
758 // SkDebugf("Text: %s\n", str.c_str());
759 builder.addText(text + expected);
760 }
761
762 auto paragraph = builder.Build();
763 paragraph->layout(w - margin * 2);
764 paragraph->paint(canvas, margin, margin);
765 }
766
767 void onDrawContent(SkCanvas* canvas) override {
768 canvas->drawColor(SK_ColorWHITE);
769 SkScalar width = this->width();
770 SkScalar height = this->height() / 8;
771
772 const std::u16string text1 =
773 u"A \u202ENAC\u202Cner, exceedingly \u202ENAC\u202Cny,\n"
774 "One morning remarked to his granny:\n"
775 "A \u202ENAC\u202Cner \u202ENAC\u202C \u202ENAC\u202C,\n"
776 "Anything that he \u202ENAC\u202C,\n"
777 "But a \u202ENAC\u202Cner \u202ENAC\u202C't \u202ENAC\u202C a \u202ENAC\u202C, "
778 "\u202ENAC\u202C he?";
779 bidi(canvas, width, height * 3, text1, u"", 5);
780 canvas->translate(0, height * 3);
781
782 bidi(canvas, width, height, u"\u2067DETALOSI\u2069", u"");
783 canvas->translate(0, height);
784
785 bidi(canvas, width, height, u"\u202BDEDDEBME\u202C", u"");
786 canvas->translate(0, height);
787
788 bidi(canvas, width, height, u"\u202EEDIRREVO\u202C", u"");
789 canvas->translate(0, height);
790
791 bidi(canvas, width, height, u"\u200FTICILPMI\u200E", u"");
792 canvas->translate(0, height);
793
794 bidi(canvas, width, height, u"123 456 7890 \u202EZYXWV UTS RQP ONM LKJ IHG FED CBA\u202C.",
795 u"", 2);
796 canvas->translate(0, height);
797
798 // bidi(canvas, width, height, u"", u"");
799 // canvas->translate(0, height);
800 }
801
802private:
803 typedef Sample INHERITED;
804};
805
806class ParagraphView6 : public Sample {
807protected:
808 bool onQuery(Sample::Event* evt) override {
809 if (Sample::TitleQ(*evt)) {
810 Sample::TitleR(evt, "Paragraph4");
811 return true;
812 }
813 return this->INHERITED::onQuery(evt);
814 }
815
816 void hangingS(SkCanvas* canvas, SkScalar w, SkScalar h, SkScalar fs = 60.0) {
817 auto ff = "HangingS";
818
819 canvas->drawColor(SK_ColorLTGRAY);
820
821 SkPaint black;
822 black.setAntiAlias(true);
823 black.setColor(SK_ColorBLACK);
824
825 SkPaint blue;
826 blue.setAntiAlias(true);
827 blue.setColor(SK_ColorBLUE);
828
829 SkPaint red;
830 red.setAntiAlias(true);
831 red.setColor(SK_ColorRED);
832
833 SkPaint green;
834 green.setAntiAlias(true);
835 green.setColor(SK_ColorGREEN);
836
837 SkPaint gray;
838 gray.setColor(SK_ColorCYAN);
839
840 SkPaint yellow;
841 yellow.setColor(SK_ColorYELLOW);
842
843 SkPaint magenta;
844 magenta.setAntiAlias(true);
845 magenta.setColor(SK_ColorMAGENTA);
846
847 SkFontStyle fontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
848 SkFontStyle::kItalic_Slant);
849
850 TextStyle style;
851 style.setFontFamilies({SkString(ff)});
852 style.setFontSize(fs);
853 style.setFontStyle(fontStyle);
854
855 TextStyle style0;
856 style0.setForegroundColor(black);
857 style0.setBackgroundColor(gray);
858 style0.setFontFamilies({SkString(ff)});
859 style0.setFontSize(fs);
860 style0.setFontStyle(fontStyle);
861
862 TextStyle style1;
863 style1.setForegroundColor(blue);
864 style1.setBackgroundColor(yellow);
865 style1.setFontFamilies({SkString(ff)});
866 style1.setFontSize(fs);
867 style1.setFontStyle(fontStyle);
868
869 TextStyle style2;
870 style2.setForegroundColor(red);
871 style2.setFontFamilies({SkString(ff)});
872 style2.setFontSize(fs);
873 style2.setFontStyle(fontStyle);
874
875 TextStyle style3;
876 style3.setForegroundColor(green);
877 style3.setFontFamilies({SkString(ff)});
878 style3.setFontSize(fs);
879 style3.setFontStyle(fontStyle);
880
881 TextStyle style4;
882 style4.setForegroundColor(magenta);
883 style4.setFontFamilies({SkString(ff)});
884 style4.setFontSize(fs);
885 style4.setFontStyle(fontStyle);
886
887 ParagraphStyle paraStyle;
888 paraStyle.setTextStyle(style);
889
890 const char* logo1 = "S";
891 const char* logo2 = "kia";
892 const char* logo3 = "Sk";
893 const char* logo4 = "ia";
894 const char* logo5 = "Ski";
895 const char* logo6 = "a";
896 {
897 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
898
899 builder.pushStyle(style0);
900 builder.addText(logo1);
901 builder.pop();
902 builder.pushStyle(style1);
903 builder.addText(logo2);
904 builder.pop();
905
906 builder.addText(" ");
907
908 builder.pushStyle(style0);
909 builder.addText(logo3);
910 builder.pop();
911 builder.pushStyle(style1);
912 builder.addText(logo4);
913 builder.pop();
914
915 builder.addText(" ");
916
917 builder.pushStyle(style0);
918 builder.addText(logo5);
919 builder.pop();
920 builder.pushStyle(style1);
921 builder.addText(logo6);
922 builder.pop();
923
924 auto paragraph = builder.Build();
925 paragraph->layout(w);
926 paragraph->paint(canvas, 40, 40);
927 canvas->translate(0, h);
928 }
929
930 const char* logo11 = "S";
931 const char* logo12 = "S";
932 const char* logo13 = "S";
933 const char* logo14 = "S";
934 const char* logo15 = "S";
935 const char* logo16 = "S";
936 {
937 ParagraphBuilderImpl builder(paraStyle, sk_make_sp<TestFontCollection>());
938
939 builder.pushStyle(style0);
940 builder.addText(logo11);
941 builder.pop();
942 builder.pushStyle(style1);
943 builder.addText(logo12);
944 builder.pop();
945
946 builder.addText(" ");
947
948 builder.pushStyle(style0);
949 builder.addText(logo13);
950 builder.pop();
951 builder.pushStyle(style1);
952 builder.addText(logo14);
953 builder.pop();
954
955 builder.addText(" ");
956
957 builder.pushStyle(style0);
958 builder.addText(logo15);
959 builder.pop();
960 builder.pushStyle(style1);
961 builder.addText(logo16);
962 builder.pop();
963
964 auto paragraph = builder.Build();
965 paragraph->layout(w);
966 paragraph->paint(canvas, 40, h);
967 canvas->translate(0, h);
968 }
969 }
970
971 void onDrawContent(SkCanvas* canvas) override {
972 canvas->drawColor(SK_ColorWHITE);
973 SkScalar width = this->width();
974 SkScalar height = this->height() / 4;
975
976 hangingS(canvas, width, height);
977 }
978
979private:
980 typedef Sample INHERITED;
981};
982
983class ParagraphView7 : public Sample {
984protected:
985 bool onQuery(Sample::Event* evt) override {
986 if (Sample::TitleQ(*evt)) {
987 Sample::TitleR(evt, "Paragraph7");
988 return true;
989 }
990 return this->INHERITED::onQuery(evt);
991 }
992
993 void drawText(SkCanvas* canvas, SkColor background, SkScalar letterSpace, SkScalar w,
994 SkScalar h) {
995 SkAutoCanvasRestore acr(canvas, true);
996 canvas->clipRect(SkRect::MakeWH(w, h));
997 canvas->drawColor(background);
998
999 const char* line =
1000 "World domination is such an ugly phrase - I prefer to call it world optimisation";
1001
1002 ParagraphStyle paragraphStyle;
1003 paragraphStyle.setTextAlign(TextAlign::kLeft);
1004 paragraphStyle.setMaxLines(10);
1005 paragraphStyle.turnHintingOff();
1006 TextStyle textStyle;
1007 textStyle.setFontFamilies({SkString("Roboto")});
1008 textStyle.setFontSize(30);
1009 textStyle.setLetterSpacing(letterSpace);
1010 textStyle.setColor(SK_ColorBLACK);
1011 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1012 SkFontStyle::kUpright_Slant));
1013
1014 ParagraphBuilderImpl builder(paragraphStyle, sk_make_sp<TestFontCollection>());
1015 builder.pushStyle(textStyle);
1016 builder.addText(line);
1017 builder.pop();
1018
1019 auto paragraph = builder.Build();
1020 paragraph->layout(w - 20);
1021 paragraph->paint(canvas, 10, 10);
1022 }
1023
1024 void onDrawContent(SkCanvas* canvas) override {
1025 canvas->drawColor(SK_ColorWHITE);
1026
1027 auto h = this->height() / 4;
1028 auto w = this->width() / 2;
1029
1030 drawText(canvas, SK_ColorGRAY, 1, w, h);
1031 canvas->translate(0, h);
1032
1033 drawText(canvas, SK_ColorLTGRAY, 2, w, h);
1034 canvas->translate(0, h);
1035
1036 drawText(canvas, SK_ColorCYAN, 3, w, h);
1037 canvas->translate(0, h);
1038
1039 drawText(canvas, SK_ColorGRAY, 4, w, h);
1040 canvas->translate(w, -3 * h);
1041
1042 drawText(canvas, SK_ColorYELLOW, 5, w, h);
1043 canvas->translate(0, h);
1044
1045 drawText(canvas, SK_ColorGREEN, 10, w, h);
1046 canvas->translate(0, h);
1047
1048 drawText(canvas, SK_ColorRED, 15, w, h);
1049 canvas->translate(0, h);
1050
1051 drawText(canvas, SK_ColorBLUE, 20, w, h);
1052 canvas->translate(0, h);
1053 }
1054
1055private:
1056 typedef Sample INHERITED;
1057};
1058
1059class ParagraphView8 : public Sample {
1060protected:
1061 bool onQuery(Sample::Event* evt) override {
1062 if (Sample::TitleQ(*evt)) {
1063 Sample::TitleR(evt, "Paragraph7");
1064 return true;
1065 }
1066 return this->INHERITED::onQuery(evt);
1067 }
1068
1069 void drawText(SkCanvas* canvas, SkColor background, SkScalar wordSpace, SkScalar w,
1070 SkScalar h) {
1071 SkAutoCanvasRestore acr(canvas, true);
1072 canvas->clipRect(SkRect::MakeWH(w, h));
1073 canvas->drawColor(background);
1074
1075 const char* line =
1076 "World domination is such an ugly phrase - I prefer to call it world optimisation";
1077
1078 ParagraphStyle paragraphStyle;
1079 paragraphStyle.setTextAlign(TextAlign::kLeft);
1080 paragraphStyle.setMaxLines(10);
1081 paragraphStyle.turnHintingOff();
1082 TextStyle textStyle;
1083 textStyle.setFontFamilies({SkString("Roboto")});
1084 textStyle.setFontSize(30);
1085 textStyle.setWordSpacing(wordSpace);
1086 textStyle.setColor(SK_ColorBLACK);
1087 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1088 SkFontStyle::kUpright_Slant));
1089
1090 ParagraphBuilderImpl builder(paragraphStyle, sk_make_sp<TestFontCollection>());
1091 builder.pushStyle(textStyle);
1092 builder.addText(line);
1093 builder.pop();
1094
1095 auto paragraph = builder.Build();
1096 paragraph->layout(w - 20);
1097 paragraph->paint(canvas, 10, 10);
1098 }
1099
1100 void onDrawContent(SkCanvas* canvas) override {
1101 canvas->drawColor(SK_ColorWHITE);
1102
1103 auto h = this->height() / 4;
1104 auto w = this->width() / 2;
1105
1106 drawText(canvas, SK_ColorGRAY, 1, w, h);
1107 canvas->translate(0, h);
1108
1109 drawText(canvas, SK_ColorLTGRAY, 2, w, h);
1110 canvas->translate(0, h);
1111
1112 drawText(canvas, SK_ColorCYAN, 3, w, h);
1113 canvas->translate(0, h);
1114
1115 drawText(canvas, SK_ColorGRAY, 4, w, h);
1116 canvas->translate(w, -3 * h);
1117
1118 drawText(canvas, SK_ColorYELLOW, 5, w, h);
1119 canvas->translate(0, h);
1120
1121 drawText(canvas, SK_ColorGREEN, 10, w, h);
1122 canvas->translate(0, h);
1123
1124 drawText(canvas, SK_ColorRED, 15, w, h);
1125 canvas->translate(0, h);
1126
1127 drawText(canvas, SK_ColorBLUE, 20, w, h);
1128 canvas->translate(0, h);
1129 }
1130
1131private:
1132 typedef Sample INHERITED;
1133};
1134
1135class ParagraphView9 : public Sample {
1136protected:
1137 bool onQuery(Sample::Event* evt) override {
1138 if (Sample::TitleQ(*evt)) {
1139 Sample::TitleR(evt, "Paragraph9");
1140 return true;
1141 }
1142
1143 SkUnichar uni;
1144 if (Sample::CharQ(*evt, &uni)) {
1145 switch (uni) {
1146 case 'w':
1147 ++wordSpacing;
1148 return true;
1149 case 'q':
1150 if (wordSpacing > 0) --wordSpacing;
1151 return true;
1152 case 'l':
1153 ++letterSpacing;
1154 return true;
1155 case 'k':
1156 if (letterSpacing > 0) --letterSpacing;
1157 return true;
1158 default:
1159 break;
1160 }
1161 }
1162
1163 return this->INHERITED::onQuery(evt);
1164 }
1165
1166 void drawText(SkCanvas* canvas, SkColor background, SkScalar w, SkScalar h) {
1167 SkAutoCanvasRestore acr(canvas, true);
1168 canvas->clipRect(SkRect::MakeWH(w, h));
1169 canvas->drawColor(background);
1170
1171 const char* text =
1172 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1173 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1174 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
1175
1176 ParagraphStyle paragraphStyle;
1177 paragraphStyle.setTextAlign(TextAlign::kLeft);
1178 paragraphStyle.setMaxLines(10);
1179 paragraphStyle.turnHintingOff();
1180 TextStyle textStyle;
1181 textStyle.setFontFamilies({SkString("Roboto")});
1182 textStyle.setFontSize(50);
1183 textStyle.setHeight(1.3f);
1184 textStyle.setColor(SK_ColorBLACK);
1185 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1186 SkFontStyle::kUpright_Slant));
1187
1188 ParagraphBuilderImpl builder(paragraphStyle, sk_make_sp<TestFontCollection>());
1189 builder.pushStyle(textStyle);
1190 builder.addText(text);
1191 builder.pop();
1192
1193 auto paragraph = builder.Build();
1194 paragraph->layout(550);
1195
1196 std::vector<size_t> sizes = {0, 1, 2, 8, 19, 21, 22, 30, 150};
1197
1198 std::vector<size_t> colors = {SK_ColorBLUE, SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGREEN,
1199 SK_ColorRED, SK_ColorWHITE, SK_ColorYELLOW, SK_ColorMAGENTA};
1200
1201 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
1202 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1203
1204 for (size_t i = 0; i < sizes.size() - 1; ++i) {
1205 size_t from = (i == 0 ? 0 : 1) + sizes[i];
1206 size_t to = sizes[i + 1];
1207 auto boxes = paragraph->getRectsForRange(from, to, rect_height_style, rect_width_style);
1208 if (boxes.empty()) {
1209 continue;
1210 }
1211 for (auto& box : boxes) {
1212 SkPaint paint;
1213 paint.setColor(colors[i % colors.size()]);
1214 paint.setShader(setgrad(box.rect, colors[i % colors.size()], SK_ColorWHITE));
1215 canvas->drawRect(box.rect, paint);
1216 }
1217 }
1218
1219 paragraph->paint(canvas, 0, 0);
1220 }
1221
1222 void onDrawContent(SkCanvas* canvas) override {
1223 canvas->drawColor(SK_ColorWHITE);
1224
1225 auto h = this->height();
1226 auto w = this->width();
1227
1228 drawText(canvas, SK_ColorGRAY, w, h);
1229 }
1230
1231private:
1232 typedef Sample INHERITED;
1233 SkScalar letterSpacing;
1234 SkScalar wordSpacing;
1235};
1236
1237class ParagraphView10 : public Sample {
1238protected:
1239 bool onQuery(Sample::Event* evt) override {
1240 if (Sample::TitleQ(*evt)) {
1241 Sample::TitleR(evt, "Paragraph10");
1242 return true;
1243 }
1244 return this->INHERITED::onQuery(evt);
1245 }
1246
1247 void onDrawContent(SkCanvas* canvas) override {
1248 canvas->drawColor(SK_ColorWHITE);
1249
1250 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
1251 ParagraphStyle paragraph_style;
1252 paragraph_style.turnHintingOff();
1253 ParagraphBuilderImpl builder(paragraph_style, sk_make_sp<TestFontCollection>());
1254
1255 TextStyle text_style;
1256 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji"),
1257 SkString("Source Han Serif CN")});
1258 text_style.setColor(SK_ColorRED);
1259 text_style.setFontSize(60);
1260 text_style.setLetterSpacing(0);
1261 text_style.setWordSpacing(0);
1262 text_style.setColor(SK_ColorBLACK);
1263 text_style.setHeight(1);
1264 builder.pushStyle(text_style);
1265 builder.addText(text);
1266 builder.pop();
1267
1268 auto paragraph = builder.Build();
1269 paragraph->layout(width());
1270
1271 paragraph->paint(canvas, 0, 0);
1272 SkDEBUGCODE(auto impl = reinterpret_cast<ParagraphImpl*>(paragraph.get()));
1273 SkASSERT(impl->runs().size() == 3);
1274 SkASSERT(impl->runs()[0].text().end() == impl->runs()[1].text().begin());
1275 SkASSERT(impl->runs()[1].text().end() == impl->runs()[2].text().begin());
1276 }
1277
1278private:
1279 typedef Sample INHERITED;
1280};
1281
1282class ParagraphView11 : public Sample {
1283protected:
1284 bool onQuery(Sample::Event* evt) override {
1285 if (Sample::TitleQ(*evt)) {
1286 Sample::TitleR(evt, "Paragraph11");
1287 return true;
1288 }
1289 return this->INHERITED::onQuery(evt);
1290 }
1291
1292 void onDrawContent(SkCanvas* canvas) override {
1293 canvas->drawColor(SK_ColorWHITE);
1294
1295 const char* text =
1296 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧"
1297 "‍"
1298 "👧"
1299 "💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝"
1300 "💦"
1301 "💧"
1302 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏"
1303 "🔑"
1304 "🔓"
1305 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳"
1306 "🇧"
1307 "🇴";
1308 text = "🍀\0‬";
1309 text = "qwerty ";
1310
1311 ParagraphStyle paragraph_style;
1312 paragraph_style.turnHintingOff();
1313 ParagraphBuilderImpl builder(paragraph_style, sk_make_sp<FontCollection>());
1314
1315 TextStyle text_style;
1316 text_style.setFontFamilies({SkString("???")});
1317 text_style.setFontStyle(SkFontStyle::Bold());
1318 text_style.setColor(SK_ColorBLACK);
1319 text_style.setFontSize(50);
1320 builder.pushStyle(text_style);
1321 builder.addText(text);
1322 builder.pop();
1323
1324 auto paragraph = builder.Build();
1325 paragraph->layout(1000);
1326 auto result = paragraph->getRectsForRange(6, 10, RectHeightStyle::kTight, RectWidthStyle::kTight);
1327 SkPaint paint;
1328 paint.setColor(SK_ColorLTGRAY);
1329 canvas->drawRect(result[0].rect, paint);
1330 paragraph->paint(canvas, 0, 0);
1331 }
1332
1333private:
1334 typedef Sample INHERITED;
1335};
1336//////////////////////////////////////////////////////////////////////////////
1337
1338DEF_SAMPLE(return new ParagraphView1();)
1339DEF_SAMPLE(return new ParagraphView2();)
1340DEF_SAMPLE(return new ParagraphView3();)
1341DEF_SAMPLE(return new ParagraphView4();)
1342DEF_SAMPLE(return new ParagraphView5();)
1343DEF_SAMPLE(return new ParagraphView6();)
1344DEF_SAMPLE(return new ParagraphView7();)
1345DEF_SAMPLE(return new ParagraphView8();)
1346DEF_SAMPLE(return new ParagraphView9();)
1347DEF_SAMPLE(return new ParagraphView10();)
1348DEF_SAMPLE(return new ParagraphView11();)