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