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/SkGraphics.h"
6 #include "include/core/SkPath.h"
7 #include "include/core/SkRegion.h"
8 #include "include/core/SkShader.h"
9 #include "include/core/SkStream.h"
10 #include "include/core/SkTextBlob.h"
11 #include "include/core/SkTime.h"
12 #include "include/core/SkTypeface.h"
13 #include "include/effects/SkGradientShader.h"
14 #include "include/utils/SkRandom.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/utils/TestFontCollection.h"
20 #include "samplecode/Sample.h"
21 #include "src/core/SkOSFile.h"
22 #include "src/shaders/SkColorShader.h"
23 #include "src/utils/SkOSPath.h"
24 #include "src/utils/SkUTF.h"
25 #include "tools/Resources.h"
26
27 using namespace skia::textlayout;
28 namespace {
29
30 class ParagraphView_Base : public Sample {
31 protected:
getFontCollection()32 sk_sp<TestFontCollection> getFontCollection() {
33 // If we reset font collection we need to reset paragraph cache
34 static sk_sp<TestFontCollection> fFC = nullptr;
35 if (fFC == nullptr) {
36 fFC = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
37 }
38 return fFC;
39 }
40 };
41
setgrad(const SkRect & r,SkColor c0,SkColor c1)42 sk_sp<SkShader> setgrad(const SkRect& r, SkColor c0, SkColor c1) {
43 SkColor colors[] = {c0, c1};
44 SkPoint pts[] = {{r.fLeft, r.fTop}, {r.fRight, r.fTop}};
45 return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
46 }
47 /*
48 void writeHtml(const char* name, Paragraph* paragraph) {
49 SkString tmpDir = skiatest::GetTmpDir();
50 if (!tmpDir.isEmpty()) {
51 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
52 SkFILEWStream file(path.c_str());
53 file.write(nullptr, 0);
54 }
55 }
56 */
57 } // namespace
58
59 class ParagraphView1 : public ParagraphView_Base {
60 protected:
name()61 SkString name() override { return SkString("Paragraph1"); }
62
drawTest(SkCanvas * canvas,SkScalar w,SkScalar h,SkColor fg,SkColor bg)63 void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) {
64 const std::vector<
65 std::tuple<std::string, bool, bool, int, SkColor, SkColor, bool, TextDecorationStyle>>
66 gParagraph = {{"monospace", true, false, 14, SK_ColorWHITE, SK_ColorRED, true,
67 TextDecorationStyle::kDashed},
68 {"Assyrian", false, false, 20, SK_ColorWHITE, SK_ColorBLUE, false,
69 TextDecorationStyle::kDotted},
70 {"serif", true, true, 10, SK_ColorWHITE, SK_ColorRED, true,
71 TextDecorationStyle::kDouble},
72 {"Arial", false, true, 16, SK_ColorGRAY, SK_ColorGREEN, true,
73 TextDecorationStyle::kSolid},
74 {"sans-serif", false, false, 8, SK_ColorWHITE, SK_ColorRED, false,
75 TextDecorationStyle::kWavy}};
76 SkAutoCanvasRestore acr(canvas, true);
77
78 canvas->clipRect(SkRect::MakeWH(w, h));
79 canvas->drawColor(SK_ColorWHITE);
80
81 SkScalar margin = 20;
82
83 SkPaint paint;
84 paint.setAntiAlias(true);
85 paint.setColor(fg);
86
87 SkPaint blue;
88 blue.setColor(SK_ColorBLUE);
89
90 TextStyle defaultStyle;
91 defaultStyle.setBackgroundColor(blue);
92 defaultStyle.setForegroundColor(paint);
93 ParagraphStyle paraStyle;
94
95 auto fontCollection = sk_make_sp<FontCollection>();
96 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
97 for (auto i = 1; i < 5; ++i) {
98 defaultStyle.setFontSize(24 * i);
99 paraStyle.setTextStyle(defaultStyle);
100 ParagraphBuilderImpl builder(paraStyle, fontCollection);
101 std::string name = "Paragraph: " + std::to_string(24 * i);
102 builder.addText(name.c_str(), name.length());
103 for (auto para : gParagraph) {
104 TextStyle style;
105 style.setFontFamilies({SkString(std::get<0>(para).c_str())});
106 SkFontStyle fontStyle(std::get<1>(para) ? SkFontStyle::Weight::kBold_Weight
107 : SkFontStyle::Weight::kNormal_Weight,
108 SkFontStyle::Width::kNormal_Width,
109 std::get<2>(para) ? SkFontStyle::Slant::kItalic_Slant
110 : SkFontStyle::Slant::kUpright_Slant);
111 style.setFontStyle(fontStyle);
112 style.setFontSize(std::get<3>(para) * i);
113 SkPaint background;
114 background.setColor(std::get<4>(para));
115 style.setBackgroundColor(background);
116 SkPaint foreground;
117 foreground.setColor(std::get<5>(para));
118 foreground.setAntiAlias(true);
119 style.setForegroundColor(foreground);
120 if (std::get<6>(para)) {
121 style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(5, 5), 2));
122 }
123
124 auto decoration = (i % 4);
125 if (decoration == 3) {
126 decoration = 4;
127 }
128
129 bool test = (TextDecoration)decoration != TextDecoration::kNoDecoration;
130 std::string deco = std::to_string((int)decoration);
131 if (test) {
132 style.setDecoration((TextDecoration)decoration);
133 style.setDecorationStyle(std::get<7>(para));
134 style.setDecorationColor(std::get<5>(para));
135 }
136 builder.pushStyle(style);
137 std::string name = " " + std::get<0>(para) + " " +
138 (std::get<1>(para) ? ", bold" : "") +
139 (std::get<2>(para) ? ", italic" : "") + " " +
140 std::to_string(std::get<3>(para) * i) +
141 (std::get<4>(para) != bg ? ", background" : "") +
142 (std::get<5>(para) != fg ? ", foreground" : "") +
143 (std::get<6>(para) ? ", shadow" : "") +
144 (test ? ", decorations " + deco : "") + ";";
145 builder.addText(name.c_str(), name.length());
146 builder.pop();
147 }
148
149 auto paragraph = builder.Build();
150 paragraph->layout(w - margin * 2);
151 paragraph->paint(canvas, margin, margin);
152
153 canvas->translate(0, paragraph->getHeight());
154 }
155 }
156
onDrawContent(SkCanvas * canvas)157 void onDrawContent(SkCanvas* canvas) override {
158 drawTest(canvas, this->width(), this->height(), SK_ColorRED, SK_ColorWHITE);
159 }
160
161 private:
162
163 typedef Sample INHERITED;
164 };
165
166 class ParagraphView2 : public ParagraphView_Base {
167 protected:
name()168 SkString name() override { return SkString("Paragraph2"); }
169
drawCode(SkCanvas * canvas,SkScalar w,SkScalar h)170 void drawCode(SkCanvas* canvas, SkScalar w, SkScalar h) {
171 SkPaint comment;
172 comment.setColor(SK_ColorGRAY);
173 SkPaint constant;
174 constant.setColor(SK_ColorMAGENTA);
175 SkPaint null;
176 null.setColor(SK_ColorMAGENTA);
177 SkPaint literal;
178 literal.setColor(SK_ColorGREEN);
179 SkPaint code;
180 code.setColor(SK_ColorDKGRAY);
181 SkPaint number;
182 number.setColor(SK_ColorBLUE);
183 SkPaint name;
184 name.setColor(SK_ColorRED);
185
186 SkPaint white;
187 white.setColor(SK_ColorWHITE);
188
189 TextStyle defaultStyle;
190 defaultStyle.setBackgroundColor(white);
191 defaultStyle.setForegroundColor(code);
192 defaultStyle.setFontFamilies({SkString("monospace")});
193 defaultStyle.setFontSize(30);
194 ParagraphStyle paraStyle;
195 paraStyle.setTextStyle(defaultStyle);
196
197 auto fontCollection = sk_make_sp<FontCollection>();
198 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
199 ParagraphBuilderImpl builder(paraStyle, fontCollection);
200
201 const char* text1 = "RaisedButton";
202 const char* text2 = "(\n";
203 const char* text3 = " child: ";
204 const char* text4 = "const";
205 const char* text5 = "Text";
206 const char* text6 = "'BUTTON TITLE'";
207 const char* text7 = "),\n";
208
209 builder.pushStyle(style(name));
210 builder.addText(text1, strlen(text1));
211 builder.pop();
212 builder.addText(text2, strlen(text2));
213 builder.addText(text3, strlen(text3));
214 builder.pushStyle(style(constant));
215 builder.addText(text4, strlen(text4));
216 builder.pop();
217 builder.addText(" ", 1);
218 builder.pushStyle(style(name));
219 builder.addText(text5, strlen(text5));
220 builder.pop();
221 builder.addText("(", 1);
222 builder.pushStyle(style(literal));
223 builder.addText(text6, strlen(text6));
224 builder.pop();
225 builder.addText(text7, strlen(text7));
226
227 auto paragraph = builder.Build();
228 paragraph->layout(w - 20);
229
230 paragraph->paint(canvas, 20, 20);
231 }
232
style(SkPaint paint)233 TextStyle style(SkPaint paint) {
234 TextStyle style;
235 paint.setAntiAlias(true);
236 style.setForegroundColor(paint);
237 style.setFontFamilies({SkString("monospace")});
238 style.setFontSize(30);
239
240 return style;
241 }
242
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")243 void drawText(SkCanvas* canvas, SkScalar w, SkScalar h, std::vector<const char*>& text,
244 SkColor fg = SK_ColorDKGRAY, SkColor bg = SK_ColorWHITE,
245 const char* ff = "sans-serif", SkScalar fs = 24,
246 size_t lineLimit = 30,
247 const std::u16string& ellipsis = u"\u2026") {
248 SkAutoCanvasRestore acr(canvas, true);
249
250 canvas->clipRect(SkRect::MakeWH(w, h));
251 canvas->drawColor(bg);
252
253 SkScalar margin = 20;
254
255 SkPaint paint;
256 paint.setAntiAlias(true);
257 paint.setColor(fg);
258
259 SkPaint blue;
260 blue.setColor(SK_ColorBLUE);
261
262 SkPaint background;
263 background.setColor(bg);
264
265 TextStyle style;
266 style.setBackgroundColor(blue);
267 style.setForegroundColor(paint);
268 style.setFontFamilies({SkString(ff)});
269 style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight,
270 SkFontStyle::kNormal_Width,
271 SkFontStyle::kUpright_Slant));
272 style.setFontSize(fs);
273 ParagraphStyle paraStyle;
274 paraStyle.setTextStyle(style);
275 paraStyle.setMaxLines(lineLimit);
276
277 paraStyle.setEllipsis(ellipsis);
278 TextStyle defaultStyle;
279 defaultStyle.setFontSize(20);
280 paraStyle.setTextStyle(defaultStyle);
281 ParagraphBuilderImpl builder(paraStyle, getFontCollection());
282
283 SkPaint foreground;
284 foreground.setColor(fg);
285 style.setForegroundColor(foreground);
286 style.setBackgroundColor(background);
287
288 for (auto& part : text) {
289 builder.pushStyle(style);
290 builder.addText(part, strlen(part));
291 builder.pop();
292 }
293
294 auto paragraph = builder.Build();
295 paragraph->layout(w - margin * 2);
296 paragraph->paint(canvas, margin, margin);
297
298 canvas->translate(0, paragraph->getHeight() + margin);
299 }
300
drawLine(SkCanvas * canvas,SkScalar w,SkScalar h,const std::string & text,TextAlign align)301 void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
302 TextAlign align) {
303 SkAutoCanvasRestore acr(canvas, true);
304
305 canvas->clipRect(SkRect::MakeWH(w, h));
306 canvas->drawColor(SK_ColorWHITE);
307
308 SkScalar margin = 20;
309
310 SkPaint paint;
311 paint.setAntiAlias(true);
312 paint.setColor(SK_ColorBLUE);
313
314 SkPaint gray;
315 gray.setColor(SK_ColorLTGRAY);
316
317 TextStyle style;
318 style.setBackgroundColor(gray);
319 style.setForegroundColor(paint);
320 style.setFontFamilies({SkString("Arial")});
321 style.setFontSize(30);
322 ParagraphStyle paraStyle;
323 paraStyle.setTextStyle(style);
324 paraStyle.setTextAlign(align);
325
326 auto fontCollection = sk_make_sp<FontCollection>();
327 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
328 ParagraphBuilderImpl builder(paraStyle, fontCollection);
329 builder.addText(text.c_str(), text.length());
330
331 auto paragraph = builder.Build();
332 paragraph->layout(w - margin * 2);
333 paragraph->layout(w - margin);
334 paragraph->paint(canvas, margin, margin);
335
336 canvas->translate(0, paragraph->getHeight() + margin);
337 }
338
onDrawContent(SkCanvas * canvas)339 void onDrawContent(SkCanvas* canvas) override {
340 std::vector<const char*> cupertino = {
341 "google_logogoogle_gsuper_g_logo 1 "
342 "google_logogoogle_gsuper_g_logo 12 "
343 "google_logogoogle_gsuper_g_logo 123 "
344 "google_logogoogle_gsuper_g_logo 1234 "
345 "google_logogoogle_gsuper_g_logo 12345 "
346 "google_logogoogle_gsuper_g_logo 123456 "
347 "google_logogoogle_gsuper_g_logo 1234567 "
348 "google_logogoogle_gsuper_g_logo 12345678 "
349 "google_logogoogle_gsuper_g_logo 123456789 "
350 "google_logogoogle_gsuper_g_logo 1234567890 "
351 "google_logogoogle_gsuper_g_logo 123456789 "
352 "google_logogoogle_gsuper_g_logo 12345678 "
353 "google_logogoogle_gsuper_g_logo 1234567 "
354 "google_logogoogle_gsuper_g_logo 123456 "
355 "google_logogoogle_gsuper_g_logo 12345 "
356 "google_logogoogle_gsuper_g_logo 1234 "
357 "google_logogoogle_gsuper_g_logo 123 "
358 "google_logogoogle_gsuper_g_logo 12 "
359 "google_logogoogle_gsuper_g_logo 1 "
360 "google_logogoogle_gsuper_g_logo "
361 "google_logogoogle_gsuper_g_logo "
362 "google_logogoogle_gsuper_g_logo "
363 "google_logogoogle_gsuper_g_logo "
364 "google_logogoogle_gsuper_g_logo "
365 "google_logogoogle_gsuper_g_logo"};
366 std::vector<const char*> text = {
367 "My neighbor came over to say,\n"
368 "Although not in a neighborly way,\n\n"
369 "That he'd knock me around,\n\n\n"
370 "If I didn't stop the sound,\n\n\n\n"
371 "Of the classical music I play."};
372
373 std::vector<const char*> long_word = {
374 "A_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
375 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
376 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
377 "very_very_very_very_very_very_very_long_text"};
378
379 std::vector<const char*> very_long = {
380 "A very very very very very very very very very very very very very very very very "
381 "very very very very very very very very very very very very very very very very "
382 "very very very very very very very very very very very very very very very very "
383 "very very very very very very very long text"};
384
385 std::vector<const char*> very_word = {
386 "A very_very_very_very_very_very_very_very_very_very "
387 "very_very_very_very_very_very_very_very_very_very very very very very very very "
388 "very very very very very very very very very very very very very very very very "
389 "very very very very very very very very very very very very very long text"};
390
391 SkScalar width = this->width() / 5;
392 SkScalar height = this->height();
393 drawText(canvas, width, height, long_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
394 canvas->translate(width, 0);
395 drawText(canvas, width, height, very_long, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
396 canvas->translate(width, 0);
397 drawText(canvas, width, height, very_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
398 canvas->translate(width, 0);
399 drawText(canvas, width, height / 2, text, SK_ColorBLACK, SK_ColorWHITE, "Roboto", 20, 100,
400 u"\u2026");
401 canvas->translate(0, height / 2);
402 drawCode(canvas, width, height / 2);
403 canvas->translate(width, -height / 2);
404
405 drawText(canvas, width, height, cupertino, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
406 }
407
408 private:
409 typedef Sample INHERITED;
410 };
411
412 class ParagraphView3 : public ParagraphView_Base {
413 protected:
name()414 SkString name() override { return SkString("Paragraph3"); }
415
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")416 void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
417 TextAlign align, size_t lineLimit = std::numeric_limits<size_t>::max(),
418 bool RTL = false, SkColor background = SK_ColorGRAY,
419 const std::u16string& ellipsis = u"\u2026") {
420 SkAutoCanvasRestore acr(canvas, true);
421
422 canvas->clipRect(SkRect::MakeWH(w, h));
423 canvas->drawColor(SK_ColorWHITE);
424
425 SkScalar margin = 20;
426
427 SkPaint paint;
428 paint.setAntiAlias(true);
429 paint.setColor(SK_ColorBLACK);
430
431 SkPaint gray;
432 gray.setColor(background);
433
434 SkPaint yellow;
435 yellow.setColor(SK_ColorYELLOW);
436
437 TextStyle style;
438 style.setBackgroundColor(gray);
439 style.setForegroundColor(paint);
440 style.setFontFamilies({SkString("sans-serif")});
441 style.setFontSize(30);
442 ParagraphStyle paraStyle;
443 paraStyle.setTextStyle(style);
444 paraStyle.setTextAlign(align);
445 paraStyle.setMaxLines(lineLimit);
446 paraStyle.setEllipsis(ellipsis);
447 // paraStyle.setTextDirection(RTL ? SkTextDirection::rtl : SkTextDirection::ltr);
448
449 auto fontCollection = sk_make_sp<FontCollection>();
450 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
451 ParagraphBuilderImpl builder(paraStyle, fontCollection);
452 if (RTL) {
453 builder.addText(mirror(text));
454 } else {
455 builder.addText(normal(text));
456 }
457
458 canvas->drawRect(SkRect::MakeXYWH(margin, margin, w - margin * 2, h - margin * 2), yellow);
459 auto paragraph = builder.Build();
460 paragraph->layout(w - margin * 2);
461 paragraph->paint(canvas, margin, margin);
462 }
463
mirror(const std::string & text)464 std::u16string mirror(const std::string& text) {
465 std::u16string result;
466 result += u"\u202E";
467 // for (auto i = text.size(); i > 0; --i) {
468 // result += text[i - 1];
469 //}
470
471 for (auto i = text.size(); i > 0; --i) {
472 auto ch = text[i - 1];
473 if (ch == ',') {
474 result += u"!";
475 } else if (ch == '.') {
476 result += u"!";
477 } else {
478 result += ch;
479 }
480 }
481
482 result += u"\u202C";
483 return result;
484 }
485
normal(const std::string & text)486 std::u16string normal(const std::string& text) {
487 std::u16string result;
488 result += u"\u202D";
489 for (auto ch : text) {
490 result += ch;
491 }
492 result += u"\u202C";
493 return result;
494 }
495
onDrawContent(SkCanvas * canvas)496 void onDrawContent(SkCanvas* canvas) override {
497 const std::string options = // { "open-source open-source open-source open-source" };
498 {"Flutter is an open-source project to help developers "
499 "build high-performance, high-fidelity, mobile apps for "
500 "iOS and Android "
501 "from a single codebase. This design lab is a playground "
502 "and showcase of Flutter's many widgets, behaviors, "
503 "animations, layouts, and more."};
504
505 canvas->drawColor(SK_ColorDKGRAY);
506 SkScalar width = this->width() / 4;
507 SkScalar height = this->height() / 2;
508
509 const std::string line =
510 "World domination is such an ugly phrase - I prefer to call it world optimisation";
511
512 drawLine(canvas, width, height, line, TextAlign::kLeft, 1, false, SK_ColorLTGRAY);
513 canvas->translate(width, 0);
514 drawLine(canvas, width, height, line, TextAlign::kRight, 2, false, SK_ColorLTGRAY);
515 canvas->translate(width, 0);
516 drawLine(canvas, width, height, line, TextAlign::kCenter, 3, false, SK_ColorLTGRAY);
517 canvas->translate(width, 0);
518 drawLine(canvas, width, height, line, TextAlign::kJustify, 4, false, SK_ColorLTGRAY);
519 canvas->translate(-width * 3, height);
520
521 drawLine(canvas, width, height, line, TextAlign::kLeft, 1, true, SK_ColorLTGRAY);
522 canvas->translate(width, 0);
523 drawLine(canvas, width, height, line, TextAlign::kRight, 2, true, SK_ColorLTGRAY);
524 canvas->translate(width, 0);
525 drawLine(canvas, width, height, line, TextAlign::kCenter, 3, true, SK_ColorLTGRAY);
526 canvas->translate(width, 0);
527 drawLine(canvas, width, height, line, TextAlign::kJustify, 4, true, SK_ColorLTGRAY);
528 canvas->translate(width, 0);
529 }
530
531 private:
532 typedef Sample INHERITED;
533 };
534
535 class ParagraphView4 : public ParagraphView_Base {
536 protected:
name()537 SkString name() override { return SkString("Paragraph4"); }
538
drawFlutter(SkCanvas * canvas,SkScalar w,SkScalar h,const char * ff="Google Sans",SkScalar fs=30,size_t lineLimit=std::numeric_limits<size_t>::max (),const std::u16string & ellipsis=u"\\u2026")539 void drawFlutter(SkCanvas* canvas, SkScalar w, SkScalar h,
540 const char* ff = "Google Sans", SkScalar fs = 30,
541 size_t lineLimit = std::numeric_limits<size_t>::max(),
542 const std::u16string& ellipsis = u"\u2026") {
543 SkAutoCanvasRestore acr(canvas, true);
544
545 canvas->clipRect(SkRect::MakeWH(w, h));
546
547 SkScalar margin = 20;
548
549 SkPaint black;
550 black.setAntiAlias(true);
551 black.setColor(SK_ColorBLACK);
552
553 SkPaint blue;
554 blue.setAntiAlias(true);
555 blue.setColor(SK_ColorBLUE);
556
557 SkPaint red;
558 red.setAntiAlias(true);
559 red.setColor(SK_ColorRED);
560
561 SkPaint green;
562 green.setAntiAlias(true);
563 green.setColor(SK_ColorGREEN);
564
565 SkPaint gray;
566 gray.setColor(SK_ColorLTGRAY);
567
568 SkPaint yellow;
569 yellow.setColor(SK_ColorYELLOW);
570
571 SkPaint magenta;
572 magenta.setAntiAlias(true);
573 magenta.setColor(SK_ColorMAGENTA);
574
575 TextStyle style;
576 style.setFontFamilies({SkString(ff)});
577 style.setFontSize(fs);
578
579 TextStyle style0;
580 style0.setForegroundColor(black);
581 style0.setBackgroundColor(gray);
582 style0.setFontFamilies({SkString(ff)});
583 style0.setFontSize(fs);
584 style0.setDecoration(TextDecoration::kUnderline);
585 style0.setDecorationStyle(TextDecorationStyle::kDouble);
586 style0.setDecorationColor(SK_ColorBLACK);
587
588 TextStyle style1;
589 style1.setForegroundColor(blue);
590 style1.setBackgroundColor(yellow);
591 style1.setFontFamilies({SkString(ff)});
592 style1.setFontSize(fs);
593 style1.setDecoration(TextDecoration::kOverline);
594 style1.setDecorationStyle(TextDecorationStyle::kWavy);
595 style1.setDecorationColor(SK_ColorBLACK);
596
597 TextStyle style2;
598 style2.setForegroundColor(red);
599 style2.setFontFamilies({SkString(ff)});
600 style2.setFontSize(fs);
601
602 TextStyle style3;
603 style3.setForegroundColor(green);
604 style3.setFontFamilies({SkString(ff)});
605 style3.setFontSize(fs);
606
607 TextStyle style4;
608 style4.setForegroundColor(magenta);
609 style4.setFontFamilies({SkString(ff)});
610 style4.setFontSize(fs);
611
612 ParagraphStyle paraStyle;
613 paraStyle.setTextStyle(style);
614 paraStyle.setMaxLines(lineLimit);
615
616 paraStyle.setEllipsis(ellipsis);
617
618 const char* logo1 = "google_";
619 const char* logo2 = "logo";
620 const char* logo3 = "go";
621 const char* logo4 = "ogle_logo";
622 const char* logo5 = "google_lo";
623 const char* logo6 = "go";
624 {
625 ParagraphBuilderImpl builder(paraStyle, getFontCollection());
626
627 builder.pushStyle(style0);
628 builder.addText(logo1, strlen(logo1));
629 builder.pop();
630 builder.pushStyle(style1);
631 builder.addText(logo2, strlen(logo2));
632 builder.pop();
633
634 builder.addText(" ", 1);
635
636 builder.pushStyle(style0);
637 builder.addText(logo3, strlen(logo3));
638 builder.pop();
639 builder.pushStyle(style1);
640 builder.addText(logo4, strlen(logo4));
641 builder.pop();
642
643 builder.addText(" ", 1);
644
645 builder.pushStyle(style0);
646 builder.addText(logo5, strlen(logo5));
647 builder.pop();
648 builder.pushStyle(style1);
649 builder.addText(logo6, strlen(logo6));
650 builder.pop();
651
652 auto paragraph = builder.Build();
653 paragraph->layout(w - margin * 2);
654 paragraph->paint(canvas, margin, margin);
655 canvas->translate(0, h + margin);
656 }
657 }
658
onDrawContent(SkCanvas * canvas)659 void onDrawContent(SkCanvas* canvas) override {
660 canvas->drawColor(SK_ColorWHITE);
661 SkScalar width = this->width();
662 SkScalar height = this->height();
663
664 drawFlutter(canvas, width, height / 2);
665 }
666
667 private:
668 typedef Sample INHERITED;
669 };
670
671 class ParagraphView5 : public ParagraphView_Base {
672 protected:
name()673 SkString name() override { return SkString("Paragraph5"); }
674
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")675 void bidi(SkCanvas* canvas, SkScalar w, SkScalar h, const std::u16string& text,
676 const std::u16string& expected, size_t lineLimit = std::numeric_limits<size_t>::max(),
677 const char* ff = "Roboto", SkScalar fs = 30,
678 const std::u16string& ellipsis = u"\u2026") {
679 SkAutoCanvasRestore acr(canvas, true);
680
681 canvas->clipRect(SkRect::MakeWH(w, h));
682
683 SkScalar margin = 20;
684
685 SkPaint black;
686 black.setColor(SK_ColorBLACK);
687 SkPaint gray;
688 gray.setColor(SK_ColorLTGRAY);
689
690 TextStyle style;
691 style.setForegroundColor(black);
692 style.setFontFamilies({SkString(ff)});
693 style.setFontSize(fs);
694
695 TextStyle style0;
696 style0.setForegroundColor(black);
697 style0.setFontFamilies({SkString(ff)});
698 style0.setFontSize(fs);
699 style0.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
700 SkFontStyle::kItalic_Slant));
701
702 TextStyle style1;
703 style1.setForegroundColor(gray);
704 style1.setFontFamilies({SkString(ff)});
705 style1.setFontSize(fs);
706 style1.setFontStyle(SkFontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
707 SkFontStyle::kUpright_Slant));
708
709 ParagraphStyle paraStyle;
710 paraStyle.setTextStyle(style);
711 paraStyle.setMaxLines(lineLimit);
712
713 paraStyle.setEllipsis(ellipsis);
714
715 ParagraphBuilderImpl builder(paraStyle, getFontCollection());
716
717 if (text.empty()) {
718 const std::u16string text0 = u"\u202Dabc";
719 const std::u16string text1 = u"\u202EFED";
720 const std::u16string text2 = u"\u202Dghi";
721 const std::u16string text3 = u"\u202ELKJ";
722 const std::u16string text4 = u"\u202Dmno";
723 builder.pushStyle(style0);
724 builder.addText(text0);
725 builder.pop();
726 builder.pushStyle(style1);
727 builder.addText(text1);
728 builder.pop();
729 builder.pushStyle(style0);
730 builder.addText(text2);
731 builder.pop();
732 builder.pushStyle(style1);
733 builder.addText(text3);
734 builder.pop();
735 builder.pushStyle(style0);
736 builder.addText(text4);
737 builder.pop();
738 } else {
739 // icu::UnicodeString unicode((UChar*) text.data(), SkToS32(text.size()));
740 // std::string str;
741 // unicode.toUTF8String(str);
742 // SkDebugf("Text: %s\n", str.c_str());
743 builder.addText(text + expected);
744 }
745
746 auto paragraph = builder.Build();
747 paragraph->layout(w - margin * 2);
748 paragraph->paint(canvas, margin, margin);
749 }
750
onDrawContent(SkCanvas * canvas)751 void onDrawContent(SkCanvas* canvas) override {
752 canvas->drawColor(SK_ColorWHITE);
753 SkScalar width = this->width();
754 SkScalar height = this->height() / 8;
755
756 const std::u16string text1 =
757 u"A \u202ENAC\u202Cner, exceedingly \u202ENAC\u202Cny,\n"
758 "One morning remarked to his granny:\n"
759 "A \u202ENAC\u202Cner \u202ENAC\u202C \u202ENAC\u202C,\n"
760 "Anything that he \u202ENAC\u202C,\n"
761 "But a \u202ENAC\u202Cner \u202ENAC\u202C't \u202ENAC\u202C a \u202ENAC\u202C, "
762 "\u202ENAC\u202C he?";
763 bidi(canvas, width, height * 3, text1, u"", 5);
764 canvas->translate(0, height * 3);
765
766 bidi(canvas, width, height, u"\u2067DETALOSI\u2069", u"");
767 canvas->translate(0, height);
768
769 bidi(canvas, width, height, u"\u202BDEDDEBME\u202C", u"");
770 canvas->translate(0, height);
771
772 bidi(canvas, width, height, u"\u202EEDIRREVO\u202C", u"");
773 canvas->translate(0, height);
774
775 bidi(canvas, width, height, u"\u200FTICILPMI\u200E", u"");
776 canvas->translate(0, height);
777
778 bidi(canvas, width, height, u"123 456 7890 \u202EZYXWV UTS RQP ONM LKJ IHG FED CBA\u202C.",
779 u"", 2);
780 canvas->translate(0, height);
781
782 // bidi(canvas, width, height, u"", u"");
783 // canvas->translate(0, height);
784 }
785
786 private:
787 typedef Sample INHERITED;
788 };
789
790 class ParagraphView6 : public ParagraphView_Base {
791 protected:
name()792 SkString name() override { return SkString("Paragraph6"); }
793
hangingS(SkCanvas * canvas,SkScalar w,SkScalar h,SkScalar fs=60.0)794 void hangingS(SkCanvas* canvas, SkScalar w, SkScalar h, SkScalar fs = 60.0) {
795 auto ff = "HangingS";
796
797 canvas->drawColor(SK_ColorLTGRAY);
798
799 SkPaint black;
800 black.setAntiAlias(true);
801 black.setColor(SK_ColorBLACK);
802
803 SkPaint blue;
804 blue.setAntiAlias(true);
805 blue.setColor(SK_ColorBLUE);
806
807 SkPaint red;
808 red.setAntiAlias(true);
809 red.setColor(SK_ColorRED);
810
811 SkPaint green;
812 green.setAntiAlias(true);
813 green.setColor(SK_ColorGREEN);
814
815 SkPaint gray;
816 gray.setColor(SK_ColorCYAN);
817
818 SkPaint yellow;
819 yellow.setColor(SK_ColorYELLOW);
820
821 SkPaint magenta;
822 magenta.setAntiAlias(true);
823 magenta.setColor(SK_ColorMAGENTA);
824
825 SkFontStyle fontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
826 SkFontStyle::kItalic_Slant);
827
828 TextStyle style;
829 style.setFontFamilies({SkString(ff)});
830 style.setFontSize(fs);
831 style.setFontStyle(fontStyle);
832
833 TextStyle style0;
834 style0.setForegroundColor(black);
835 style0.setBackgroundColor(gray);
836 style0.setFontFamilies({SkString(ff)});
837 style0.setFontSize(fs);
838 style0.setFontStyle(fontStyle);
839
840 TextStyle style1;
841 style1.setForegroundColor(blue);
842 style1.setBackgroundColor(yellow);
843 style1.setFontFamilies({SkString(ff)});
844 style1.setFontSize(fs);
845 style1.setFontStyle(fontStyle);
846
847 TextStyle style2;
848 style2.setForegroundColor(red);
849 style2.setFontFamilies({SkString(ff)});
850 style2.setFontSize(fs);
851 style2.setFontStyle(fontStyle);
852
853 TextStyle style3;
854 style3.setForegroundColor(green);
855 style3.setFontFamilies({SkString(ff)});
856 style3.setFontSize(fs);
857 style3.setFontStyle(fontStyle);
858
859 TextStyle style4;
860 style4.setForegroundColor(magenta);
861 style4.setFontFamilies({SkString(ff)});
862 style4.setFontSize(fs);
863 style4.setFontStyle(fontStyle);
864
865 ParagraphStyle paraStyle;
866 paraStyle.setTextStyle(style);
867
868 const char* logo1 = "S";
869 const char* logo2 = "kia";
870 const char* logo3 = "Sk";
871 const char* logo4 = "ia";
872 const char* logo5 = "Ski";
873 const char* logo6 = "a";
874 {
875 ParagraphBuilderImpl builder(paraStyle, getFontCollection());
876
877 builder.pushStyle(style0);
878 builder.addText(logo1, strlen(logo1));
879 builder.pop();
880 builder.pushStyle(style1);
881 builder.addText(logo2, strlen(logo2));
882 builder.pop();
883
884 builder.addText(" ", 3);
885
886 builder.pushStyle(style0);
887 builder.addText(logo3, strlen(logo3));
888 builder.pop();
889 builder.pushStyle(style1);
890 builder.addText(logo4, strlen(logo4));
891 builder.pop();
892
893 builder.addText(" ", 3);
894
895 builder.pushStyle(style0);
896 builder.addText(logo5, strlen(logo5));
897 builder.pop();
898 builder.pushStyle(style1);
899 builder.addText(logo6, strlen(logo6));
900 builder.pop();
901
902 auto paragraph = builder.Build();
903 paragraph->layout(w);
904 paragraph->paint(canvas, 40, 40);
905 canvas->translate(0, h);
906 }
907
908 const char* logo11 = "S";
909 const char* logo12 = "S";
910 const char* logo13 = "S";
911 const char* logo14 = "S";
912 const char* logo15 = "S";
913 const char* logo16 = "S";
914 {
915 ParagraphBuilderImpl builder(paraStyle, getFontCollection());
916
917 builder.pushStyle(style0);
918 builder.addText(logo11, strlen(logo1));
919 builder.pop();
920 builder.pushStyle(style1);
921 builder.addText(logo12, strlen(logo2));
922 builder.pop();
923
924 builder.addText(" ", 3);
925
926 builder.pushStyle(style0);
927 builder.addText(logo13, strlen(logo3));
928 builder.pop();
929 builder.pushStyle(style1);
930 builder.addText(logo14, strlen(logo4));
931 builder.pop();
932
933 builder.addText(" ", 3);
934
935 builder.pushStyle(style0);
936 builder.addText(logo15, strlen(logo5));
937 builder.pop();
938 builder.pushStyle(style1);
939 builder.addText(logo16, strlen(logo6));
940 builder.pop();
941
942 auto paragraph = builder.Build();
943 paragraph->layout(w);
944 paragraph->paint(canvas, 40, h);
945 canvas->translate(0, h);
946 }
947 }
948
onDrawContent(SkCanvas * canvas)949 void onDrawContent(SkCanvas* canvas) override {
950 canvas->drawColor(SK_ColorWHITE);
951 SkScalar width = this->width();
952 SkScalar height = this->height() / 4;
953
954 hangingS(canvas, width, height);
955 }
956
957 private:
958 typedef Sample INHERITED;
959 };
960
961 class ParagraphView7 : public ParagraphView_Base {
962 protected:
name()963 SkString name() override { return SkString("Paragraph7"); }
964
drawText(SkCanvas * canvas,SkColor background,SkScalar letterSpace,SkScalar w,SkScalar h)965 void drawText(SkCanvas* canvas, SkColor background, SkScalar letterSpace, SkScalar w,
966 SkScalar h) {
967 SkAutoCanvasRestore acr(canvas, true);
968 canvas->clipRect(SkRect::MakeWH(w, h));
969 canvas->drawColor(background);
970
971 const char* line =
972 "World domination is such an ugly phrase - I prefer to call it world optimisation.";
973
974 ParagraphStyle paragraphStyle;
975 paragraphStyle.setTextAlign(TextAlign::kLeft);
976 paragraphStyle.setMaxLines(10);
977 paragraphStyle.turnHintingOff();
978 TextStyle textStyle;
979 textStyle.setFontFamilies({SkString("Roboto")});
980 textStyle.setFontSize(30);
981 textStyle.setLetterSpacing(letterSpace);
982 textStyle.setColor(SK_ColorBLACK);
983 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
984 SkFontStyle::kUpright_Slant));
985
986 ParagraphBuilderImpl builder(paragraphStyle, getFontCollection());
987 builder.pushStyle(textStyle);
988 builder.addText(line, strlen(line));
989 builder.pop();
990
991 auto paragraph = builder.Build();
992 paragraph->layout(w - 20);
993 paragraph->paint(canvas, 10, 10);
994 }
995
onDrawContent(SkCanvas * canvas)996 void onDrawContent(SkCanvas* canvas) override {
997 canvas->drawColor(SK_ColorWHITE);
998
999 auto h = this->height() / 4;
1000 auto w = this->width() / 2;
1001
1002 drawText(canvas, SK_ColorGRAY, 1, w, h);
1003 canvas->translate(0, h);
1004
1005 drawText(canvas, SK_ColorLTGRAY, 2, w, h);
1006 canvas->translate(0, h);
1007
1008 drawText(canvas, SK_ColorCYAN, 3, w, h);
1009 canvas->translate(0, h);
1010
1011 drawText(canvas, SK_ColorGRAY, 4, w, h);
1012 canvas->translate(w, -3 * h);
1013
1014 drawText(canvas, SK_ColorYELLOW, 5, w, h);
1015 canvas->translate(0, h);
1016
1017 drawText(canvas, SK_ColorGREEN, 10, w, h);
1018 canvas->translate(0, h);
1019
1020 drawText(canvas, SK_ColorRED, 15, w, h);
1021 canvas->translate(0, h);
1022
1023 drawText(canvas, SK_ColorBLUE, 20, w, h);
1024 canvas->translate(0, h);
1025 }
1026
1027 private:
1028 typedef Sample INHERITED;
1029 };
1030
1031 class ParagraphView8 : public ParagraphView_Base {
1032 protected:
name()1033 SkString name() override { return SkString("Paragraph8"); }
1034
drawText(SkCanvas * canvas,SkColor background,SkScalar wordSpace,SkScalar w,SkScalar h)1035 void drawText(SkCanvas* canvas, SkColor background, SkScalar wordSpace, SkScalar w,
1036 SkScalar h) {
1037 SkAutoCanvasRestore acr(canvas, true);
1038 canvas->clipRect(SkRect::MakeWH(w, h));
1039 canvas->drawColor(background);
1040
1041 const char* line =
1042 "World domination is such an ugly phrase - I prefer to call it world optimisation.";
1043
1044 ParagraphStyle paragraphStyle;
1045 paragraphStyle.setTextAlign(TextAlign::kLeft);
1046 paragraphStyle.setMaxLines(10);
1047 paragraphStyle.turnHintingOff();
1048 TextStyle textStyle;
1049 textStyle.setFontFamilies({SkString("Roboto")});
1050 textStyle.setFontSize(30);
1051 textStyle.setWordSpacing(wordSpace);
1052 textStyle.setColor(SK_ColorBLACK);
1053 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1054 SkFontStyle::kUpright_Slant));
1055
1056 ParagraphBuilderImpl builder(paragraphStyle, getFontCollection());
1057 builder.pushStyle(textStyle);
1058 builder.addText(line, strlen(line));
1059 builder.pop();
1060
1061 auto paragraph = builder.Build();
1062 paragraph->layout(w - 20);
1063 paragraph->paint(canvas, 10, 10);
1064 }
1065
onDrawContent(SkCanvas * canvas)1066 void onDrawContent(SkCanvas* canvas) override {
1067 canvas->drawColor(SK_ColorWHITE);
1068
1069 auto h = this->height() / 4;
1070 auto w = this->width() / 2;
1071
1072 drawText(canvas, SK_ColorGRAY, 1, w, h);
1073 canvas->translate(0, h);
1074
1075 drawText(canvas, SK_ColorLTGRAY, 2, w, h);
1076 canvas->translate(0, h);
1077
1078 drawText(canvas, SK_ColorCYAN, 3, w, h);
1079 canvas->translate(0, h);
1080
1081 drawText(canvas, SK_ColorGRAY, 4, w, h);
1082 canvas->translate(w, -3 * h);
1083
1084 drawText(canvas, SK_ColorYELLOW, 5, w, h);
1085 canvas->translate(0, h);
1086
1087 drawText(canvas, SK_ColorGREEN, 10, w, h);
1088 canvas->translate(0, h);
1089
1090 drawText(canvas, SK_ColorRED, 15, w, h);
1091 canvas->translate(0, h);
1092
1093 drawText(canvas, SK_ColorBLUE, 20, w, h);
1094 canvas->translate(0, h);
1095 }
1096
1097 private:
1098 typedef Sample INHERITED;
1099 };
1100
1101 class ParagraphView9 : public ParagraphView_Base {
1102 protected:
name()1103 SkString name() override { return SkString("Paragraph9"); }
1104
onChar(SkUnichar uni)1105 bool onChar(SkUnichar uni) override {
1106 switch (uni) {
1107 case 'w':
1108 ++wordSpacing;
1109 return true;
1110 case 'q':
1111 if (wordSpacing > 0) --wordSpacing;
1112 return true;
1113 case 'l':
1114 ++letterSpacing;
1115 return true;
1116 case 'k':
1117 if (letterSpacing > 0) --letterSpacing;
1118 return true;
1119 default:
1120 break;
1121 }
1122 return false;
1123 }
1124
drawText(SkCanvas * canvas,SkColor background,SkScalar w,SkScalar h)1125 void drawText(SkCanvas* canvas, SkColor background, SkScalar w, SkScalar h) {
1126 SkAutoCanvasRestore acr(canvas, true);
1127 canvas->clipRect(SkRect::MakeWH(w, h));
1128 canvas->drawColor(background);
1129
1130 auto fontCollection = sk_make_sp<FontCollection>();
1131 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1132 fontCollection->enableFontFallback();
1133
1134 const char* text =
1135 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1136 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1137 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
1138 auto multiplier = 5.67;
1139 ParagraphStyle paragraphStyle;
1140 paragraphStyle.setTextAlign(TextAlign::kLeft);
1141 paragraphStyle.setMaxLines(10);
1142 paragraphStyle.turnHintingOff();
1143 TextStyle textStyle;
1144 textStyle.setFontFamilies({SkString("Roboto")});
1145 textStyle.setFontSize(5 * multiplier);
1146 textStyle.setHeight(1.3f);
1147 textStyle.setColor(SK_ColorBLACK);
1148 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1149 SkFontStyle::kUpright_Slant));
1150
1151 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
1152 builder.pushStyle(textStyle);
1153 builder.addText(text, strlen(text));
1154 builder.pop();
1155
1156 auto paragraph = builder.Build();
1157 paragraph->layout(200 * multiplier);
1158
1159 std::vector<size_t> sizes = {0, 1, 2, 8, 19, 21, 22, 30, 150};
1160
1161 std::vector<size_t> colors = {SK_ColorBLUE, SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGREEN,
1162 SK_ColorRED, SK_ColorWHITE, SK_ColorYELLOW, SK_ColorMAGENTA};
1163
1164 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
1165 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1166
1167 for (size_t i = 0; i < sizes.size() - 1; ++i) {
1168 size_t from = sizes[i];
1169 size_t to = sizes[i + 1];
1170 auto boxes = paragraph->getRectsForRange(from, to, rect_height_style, rect_width_style);
1171 if (boxes.empty()) {
1172 continue;
1173 }
1174 for (auto& box : boxes) {
1175 SkPaint paint;
1176 paint.setColor(colors[i % colors.size()]);
1177 paint.setShader(setgrad(box.rect, colors[i % colors.size()], SK_ColorWHITE));
1178 canvas->drawRect(box.rect, paint);
1179 }
1180 }
1181
1182 paragraph->paint(canvas, 0, 0);
1183 }
1184
onDrawContent(SkCanvas * canvas)1185 void onDrawContent(SkCanvas* canvas) override {
1186 canvas->drawColor(SK_ColorWHITE);
1187
1188 auto h = this->height();
1189 auto w = this->width();
1190
1191 drawText(canvas, SK_ColorGRAY, w, h);
1192 }
1193
1194 private:
1195 typedef Sample INHERITED;
1196 SkScalar letterSpacing;
1197 SkScalar wordSpacing;
1198 };
1199
1200 class ParagraphView10 : public ParagraphView_Base {
1201 protected:
name()1202 SkString name() override { return SkString("Paragraph10"); }
1203
onDrawContent(SkCanvas * canvas)1204 void onDrawContent(SkCanvas* canvas) override {
1205 canvas->drawColor(SK_ColorWHITE);
1206 auto multiplier = 5.67;
1207 const char* text = "English English 字典 字典 ";
1208
1209 auto fontCollection = sk_make_sp<FontCollection>();
1210 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1211 fontCollection->enableFontFallback();
1212
1213 ParagraphStyle paragraph_style;
1214 paragraph_style.turnHintingOff();
1215 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1216
1217 TextStyle text_style;
1218 text_style.setFontFamilies({SkString("Roboto"),
1219 SkString("Noto Color Emoji"),
1220 SkString("Noto Serif CJK JP")});
1221 text_style.setFontSize(10 * multiplier);
1222 text_style.setLetterSpacing(0);
1223 text_style.setWordSpacing(0);
1224 text_style.setColor(SK_ColorBLACK);
1225 text_style.setHeight(1);
1226 builder.pushStyle(text_style);
1227 builder.addText(text, strlen(text));
1228 builder.pop();
1229
1230 auto paragraph = builder.Build();
1231 paragraph->layout(width());
1232
1233 paragraph->paint(canvas, 0, 0);
1234 }
1235
1236 private:
1237 typedef Sample INHERITED;
1238 };
1239
1240 class ParagraphView11 : public ParagraphView_Base {
1241 protected:
name()1242 SkString name() override { return SkString("Paragraph11"); }
1243
onDrawContent(SkCanvas * canvas)1244 void onDrawContent(SkCanvas* canvas) override {
1245 canvas->drawColor(SK_ColorWHITE);
1246
1247 auto text = "\U0001f469\U0000200D\U0001f469\U0000200D\U0001f466\U0001f469\U0000200D\U0001f469\U0000200D\U0001f467\U0000200D\U0001f467\U0001f1fa\U0001f1f8";
1248
1249 TextStyle text_style;
1250 text_style.setFontFamilies({SkString("Ahem")});
1251 text_style.setColor(SK_ColorBLACK);
1252 text_style.setFontSize(60);
1253 text_style.setLetterSpacing(0);
1254 text_style.setWordSpacing(0);
1255 ParagraphStyle paragraph_style;
1256 paragraph_style.setTextStyle(text_style);
1257
1258 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), true, true);
1259 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1260 builder.addText(text, strlen(text));
1261 auto paragraph = builder.Build();
1262 paragraph->layout(1000);
1263 paragraph->paint(canvas, 0, 0);
1264
1265 struct pair {
1266 unsigned fX;
1267 unsigned fY;
1268 };
1269
1270 pair hit1[] =
1271 {{ 0, 8},{1, 33}, {2, 34}, { 3, 19}, {4, 20},
1272 { 5, 21}, { 6, 22 }, { 7, 23 }, {8, 24 }, { 9, 25},
1273 { 10, 26}, { 11, 27}, {12, 28}, { 13, 21}, {14, 22 },
1274 { 15, 23}, {16, 24}, {17, 21}, { 18, 22}, {19, 21},
1275 { 20, 24}, { 21, 23}, };
1276
1277 pair miss[] =
1278 {{ 0, 4},{1, 17}, {2, 18}, { 3, 11}, {4, 12},
1279 { 5, 13}, { 6, 14 }, { 7, 15 }, {8, 16 }, { 9, 17},
1280 { 10, 18}, { 11, 19}, {12, 20}, { 13, 17}, {14, 18 },
1281 { 15, 19}, {16, 20}, {17, 19}, { 18, 20},
1282 { 20, 22}, };
1283
1284 auto rects = paragraph->getRectsForRange(7, 9, RectHeightStyle::kTight, RectWidthStyle::kTight);
1285 SkPaint paint;
1286 paint.setColor(SK_ColorRED);
1287 paint.setStyle(SkPaint::kStroke_Style);
1288 paint.setAntiAlias(true);
1289 paint.setStrokeWidth(1);
1290 if (!rects.empty()) {
1291 canvas->drawRect(rects[0].rect, paint);
1292 }
1293
1294 for (auto& query : hit1) {
1295 auto rects = paragraph->getRectsForRange(query.fX, query.fY, RectHeightStyle::kTight, RectWidthStyle::kTight);
1296 if (rects.size() >= 1 && rects[0].rect.width() > 0) {
1297 } else {
1298 SkDebugf("+[%d:%d): Bad\n", query.fX, query.fY);
1299 }
1300 }
1301
1302 for (auto& query : miss) {
1303 auto miss = paragraph->getRectsForRange(query.fX, query.fY, RectHeightStyle::kTight, RectWidthStyle::kTight);
1304 if (miss.empty()) {
1305 } else {
1306 SkDebugf("-[%d:%d): Bad\n", query.fX, query.fY);
1307 }
1308 }
1309 }
1310
1311 private:
1312 typedef Sample INHERITED;
1313 };
1314
1315 class ParagraphView12 : public ParagraphView_Base {
1316 protected:
name()1317 SkString name() override { return SkString("Paragraph12"); }
1318
onDrawContent(SkCanvas * canvas)1319 void onDrawContent(SkCanvas* canvas) override {
1320 canvas->drawColor(SK_ColorWHITE);
1321
1322 const char* text = "Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges";
1323 TextStyle text_style;
1324 text_style.setFontFamilies({SkString("Ahem")});
1325 text_style.setColor(SK_ColorBLACK);
1326 text_style.setFontSize(16);
1327 //text_style.setLetterSpacing(-0.41);
1328 StrutStyle strut_style;
1329 strut_style.setStrutEnabled(false);
1330 ParagraphStyle paragraph_style;
1331 paragraph_style.setStrutStyle(strut_style);
1332 paragraph_style.setTextStyle(text_style);
1333 ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1334 builder.addText(text);
1335 auto paragraph = builder.Build();
1336 paragraph->layout(1095.000000);
1337 auto result = paragraph->getRectsForRange(65, 66, RectHeightStyle::kTight, RectWidthStyle::kTight);
1338 paragraph->paint(canvas, 0, 0);
1339
1340 SkPaint paint;
1341 paint.setColor(SK_ColorRED);
1342 paint.setStyle(SkPaint::kStroke_Style);
1343 paint.setAntiAlias(true);
1344 paint.setStrokeWidth(1);
1345 canvas->drawRect(result.front().rect, paint);
1346 }
1347
1348 private:
1349 typedef Sample INHERITED;
1350 };
1351
1352 class ParagraphView14 : public ParagraphView_Base {
1353 protected:
name()1354 SkString name() override { return SkString("Paragraph14"); }
1355
onDrawContent(SkCanvas * canvas)1356 void onDrawContent(SkCanvas* canvas) override {
1357 canvas->drawColor(SK_ColorWHITE);
1358 TextStyle text_style;
1359 text_style.setFontFamilies({SkString("Ahem")});
1360 text_style.setColor(SK_ColorBLACK);
1361 text_style.setFontSize(25);
1362 text_style.setDecoration((TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1363 text_style.setDecorationColor(SK_ColorBLUE);
1364 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1365 text_style.setDecorationThicknessMultiplier(4.0f);
1366 ParagraphStyle paragraph_style;
1367 paragraph_style.setTextStyle(text_style);
1368 paragraph_style.setTextDirection(TextDirection::kRtl);
1369 ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1370 builder.pushStyle(text_style);
1371 builder.addText("Hello, wor!\nabcd.");
1372 auto paragraph = builder.Build();
1373 paragraph->layout(300);
1374 paragraph->paint(canvas, 0, 0);
1375 SkPaint paint;
1376 paint.setColor(SK_ColorRED);
1377 paint.setStyle(SkPaint::kStroke_Style);
1378 paint.setAntiAlias(true);
1379 paint.setStrokeWidth(1);
1380 canvas->drawRect(SkRect::MakeXYWH(0, 0, 300, 100), paint);
1381 }
1382
1383 private:
1384 typedef Sample INHERITED;
1385 };
1386
1387 class ParagraphView15 : public ParagraphView_Base {
1388 protected:
name()1389 SkString name() override { return SkString("Paragraph15"); }
1390
onDrawContent(SkCanvas * canvas)1391 void onDrawContent(SkCanvas* canvas) override {
1392 canvas->drawColor(SK_ColorWHITE);
1393
1394 TextStyle text_style;
1395 text_style.setFontFamilies({SkString("abc.ttf")});
1396 text_style.setFontSize(50);
1397
1398 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
1399
1400 fontCollection->addFontFromFile("abc/abc.ttf", "abc");
1401 fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave");
1402 fontCollection->addFontFromFile("abc/abc+agrave.ttf", "abc+agrave");
1403
1404 ParagraphStyle paragraph_style;
1405 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1406
1407 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
1408 text_style.setColor(SK_ColorBLUE);
1409 builder.pushStyle(text_style);
1410 builder.addText(u"a\u0300");
1411 text_style.setColor(SK_ColorMAGENTA);
1412 builder.pushStyle(text_style);
1413 builder.addText(u"à");
1414
1415 text_style.setFontFamilies({SkString("abc"), SkString("abc+agrave")});
1416
1417 text_style.setColor(SK_ColorRED);
1418 builder.pushStyle(text_style);
1419 builder.addText(u"a\u0300");
1420 text_style.setColor(SK_ColorGREEN);
1421 builder.pushStyle(text_style);
1422 builder.addText(u"à");
1423
1424 auto paragraph = builder.Build();
1425 paragraph->layout(800);
1426 paragraph->paint(canvas, 50, 50);
1427
1428 }
1429
1430 private:
1431 typedef Sample INHERITED;
1432 };
1433
1434 class ParagraphView16 : public ParagraphView_Base {
1435 protected:
name()1436 SkString name() override { return SkString("Paragraph16"); }
1437
onDrawContent(SkCanvas * canvas)1438 void onDrawContent(SkCanvas* canvas) override {
1439 canvas->drawColor(SK_ColorWHITE);
1440
1441 const char* text = "content";
1442
1443 ParagraphStyle paragraph_style;
1444 paragraph_style.setMaxLines(1);
1445 paragraph_style.setEllipsis(u"\u2026");
1446 //auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1447 auto fontCollection = sk_make_sp<FontCollection>();
1448 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1449 fontCollection->enableFontFallback();
1450 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1451
1452 TextStyle text_style;
1453 text_style.setFontFamilies({SkString(".SF Pro Text")});
1454 text_style.setColor(SK_ColorBLACK);
1455 text_style.setFontSize(17.0f * 99.0f);
1456 text_style.setLetterSpacing(0.41f);
1457 builder.pushStyle(text_style);
1458 builder.addText(text);
1459
1460 auto paragraph = builder.Build();
1461 paragraph->layout(800);
1462 paragraph->paint(canvas, 0, 0);
1463 }
1464
1465 private:
1466 typedef Sample INHERITED;
1467 };
1468
1469 class ParagraphView17 : public ParagraphView_Base {
1470 protected:
name()1471 SkString name() override { return SkString("Paragraph17"); }
1472
onDrawContent(SkCanvas * canvas)1473 void onDrawContent(SkCanvas* canvas) override {
1474 canvas->drawColor(SK_ColorWHITE);
1475
1476 auto fontCollection = sk_make_sp<FontCollection>();
1477 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1478 fontCollection->enableFontFallback();
1479 auto navy = SkColorSetRGB(0, 0, 139);
1480 auto ltgray = SkColorSetRGB(211, 211, 211);
1481 auto multiplier = 5.67;
1482
1483 const char* text = ">Sͬ͑̀͐̈͒̈́̋̎ͮͩ̽̓ͬ̂̆̔͗́̓ͣͧ͊ͫ͛̉͌̐̑ͪ͗̚͝҉̴͉͢k̡̊̓ͫͭͩ͂͊ͨͪͬ̑ͫ̍̌̄͛̌̂̑̂̋̊̔ͫ͛̽̑ͨ̍ͭ̓̀ͪͪ̉͐͗̌̓̃̚͟͝҉̢͏̫̞̙͇͖̮͕̗̟͕͇͚̻͈̣̻̪͉̰̲̣̫ͅͅP̴̅̍͒̿͗͗̇ͩ̃͆͌̀̽͏̧̡͕͖̝̖̼̺̰̣̬͔͖͔̼͙̞̦̫͓̘͜a̸̴̸̴̢̢̨̨̫͍͓̥̼̭̼̻̤̯̙̤̻̠͚̍̌͋̂ͦͨ̽̇͌͌͆̀̽̎͒̄ͪ̐ͦ̈ͫ͐͗̓̚̚͜ͅr͐͐ͤͫ̐ͥ͂̈́̿́ͮ̃͗̓̏ͫ̀̿͏̸̵̧́͘̕͟͝͠͞͠҉̷̧͚͢͟a̓̽̎̄͗̔͛̄̐͊͛ͫ͂͌̂̂̈̈̓̔̅̅̄͊̉́ͪ̑̄͆ͬ̍͆ͭ͋̐ͬ͏̷̵̨̢̩̹̖͓̥̳̰͔̱̬͖̙͓̙͇̀̀̕͜͟͟͢͟͜͠͡g̨̅̇ͦ͋̂ͦͨͭ̓͐͆̏̂͛̉ͧ̑ͫ̐̒͛ͫ̍̒͛́̚҉̷̨̛̛̀͜͢͞҉̩̘̲͍͎̯̹̝̭̗̱͇͉̲̱͔̯̠̹̥̻͉̲̜̤̰̪̗̺̖̺r̷͌̓̇̅ͭ̀̐̃̃ͭ͑͗̉̈̇̈́ͥ̓ͣ́ͤ͂ͤ͂̏͌̆̚҉̴̸̧̢̢̛̫͉̦̥̤̙͈͉͈͉͓̙̗̟̳̜͈̗̺̟̠̠͖͓̖̪͕̠̕̕͝ͅả̸̴̡̡̧͠͞͡͞҉̛̕͟͏̷̘̪̱͈̲͉̞̠̞̪̫͎̲̬̖̀̀͟͝͞͞͠p̛͂̈͐̚͠҉̵̸̡̢̢̩̹͙̯͖̙̙̮̥̙͚̠͔̥̭̮̞̣̪̬̥̠̖̝̥̪͎́̀̕͜͡͡ͅͅh̵̷̵̡̛ͤ̂͌̐̓̐̋̋͊̒̆̽́̀̀̀͢͠͞͞҉̷̸̢̕҉͚̯͖̫̜̞̟̠̱͉̝̲̹̼͉̟͉̩̮͔̤͖̞̭̙̹̬ͅ<";
1484
1485 ParagraphStyle paragraph_style;
1486 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1487 SkPaint paint;
1488 paint.setColor(ltgray);
1489 TextStyle text_style;
1490 text_style.setBackgroundColor(paint);
1491 text_style.setColor(navy);
1492 text_style.setFontFamilies({SkString("Roboto")});
1493 text_style.setFontSize(20 * multiplier);
1494 builder.pushStyle(text_style);
1495 builder.addText(text);
1496 auto paragraph = builder.Build();
1497 paragraph->layout(10000);
1498 paragraph->paint(canvas, 0, 0);
1499 }
1500
1501 private:
1502 typedef Sample INHERITED;
1503 };
1504
1505 class Zalgo {
1506 private:
1507 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";
1508 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";
1509 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";
1510
randomMarks(std::u16string & combiningMarks)1511 std::u16string randomMarks(std::u16string& combiningMarks) {
1512 std::u16string result;
1513 auto num = std::rand() % (combiningMarks.size() / 1);
1514 for (size_t i = 0; i < num; ++i) {
1515 auto index = std::rand() % combiningMarks.size();
1516 result += combiningMarks[index];
1517 }
1518 return result;
1519 }
1520
1521 public:
zalgo(std::string victim)1522 std::u16string zalgo(std::string victim) {
1523 std::u16string result;
1524 for (auto& c : victim) {
1525 result += c;
1526 result += randomMarks(COMBINING_UP);
1527 result += randomMarks(COMBINING_MIDDLE);
1528 result += randomMarks(COMBINING_DOWN);
1529 }
1530 return result;
1531 }
1532 };
1533
1534 class ParagraphView18 : public ParagraphView_Base {
1535 protected:
name()1536 SkString name() override { return SkString("Paragraph18"); }
1537
onChar(SkUnichar uni)1538 bool onChar(SkUnichar uni) override {
1539 switch (uni) {
1540 case ' ':
1541 fLimit = 400;
1542 return true;
1543 case 's':
1544 fLimit += 10;
1545 return true;
1546 case 'f':
1547 if (fLimit > 10) {
1548 fLimit -= 10;
1549 }
1550 return true;
1551 default:
1552 break;
1553 }
1554 return false;
1555 }
1556
onAnimate(double nanos)1557 bool onAnimate(double nanos) override {
1558 if (++fIndex > fLimit) {
1559 fRedraw = true;
1560 fIndex = 0;
1561 } else {
1562 fRepeat = true;
1563 }
1564 return true;
1565 }
1566
onDrawContent(SkCanvas * canvas)1567 void onDrawContent(SkCanvas* canvas) override {
1568 canvas->drawColor(SK_ColorWHITE);
1569
1570 auto navy = SkColorSetRGB(0, 0, 139);
1571 auto ltgray = SkColorSetRGB(211, 211, 211);
1572
1573 auto multiplier = 5.67;
1574 auto fontCollection = sk_make_sp<FontCollection>();
1575 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1576 fontCollection->enableFontFallback();
1577
1578 ParagraphStyle paragraph_style;
1579 TextStyle text_style;
1580 text_style.setFontFamilies({SkString("Roboto")});
1581 text_style.setFontSize(20 * multiplier);
1582 text_style.setColor(navy);
1583 SkPaint paint;
1584 paint.setColor(ltgray);
1585 text_style.setBackgroundColor(paint);
1586
1587 Zalgo zalgo;
1588
1589 if (fRedraw || fRepeat) {
1590
1591 if (fRedraw || fParagraph.get() == nullptr) {
1592 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1593 builder.pushStyle(text_style);
1594 auto utf16text = zalgo.zalgo("SkParagraph");
1595 icu::UnicodeString unicode((UChar*)utf16text.data(), SkToS32(utf16text.size()));
1596 std::string str;
1597 unicode.toUTF8String(str);
1598 SkDebugf("Text:>%s<\n", str.data());
1599 builder.addText(utf16text);
1600 fParagraph = builder.Build();
1601 }
1602
1603 auto impl = static_cast<ParagraphImpl*>(fParagraph.get());
1604 impl->setState(InternalState::kUnknown);
1605 fParagraph->layout(1000);
1606 fParagraph->paint(canvas, 300, 200);
1607
1608 for (auto& run : impl->runs()) {
1609 SkString fontFamily("unresolved");
1610 if (run.font().getTypeface() != nullptr) {
1611 run.font().getTypeface()->getFamilyName(&fontFamily);
1612 }
1613 if (run.font().getTypeface() != nullptr) {
1614 for (size_t i = 0; i < run.size(); ++i) {
1615 auto glyph = run.glyphs().begin() + i;
1616 if (*glyph == 0) {
1617 SkDebugf("Run[%d] @pos=%d\n", run.index(), i);
1618 SkASSERT(false);
1619 }
1620 }
1621 } else {
1622 SkDebugf("Run[%d]: %s\n", run.index(), fontFamily.c_str());
1623 SkASSERT(false);
1624 }
1625 }
1626 fRedraw = false;
1627 fRepeat = false;
1628 }
1629 }
1630
1631 private:
1632 bool fRedraw = true;
1633 bool fRepeat = false;
1634 size_t fIndex = 0;
1635 size_t fLimit = 20;
1636 std::unique_ptr<Paragraph> fParagraph;
1637 typedef Sample INHERITED;
1638 };
1639
1640 class ParagraphView19 : public ParagraphView_Base {
1641 protected:
name()1642 SkString name() override { return SkString("Paragraph19"); }
1643
onDrawContent(SkCanvas * canvas)1644 void onDrawContent(SkCanvas* canvas) override {
1645 canvas->drawColor(SK_ColorWHITE);
1646
1647 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1648
1649 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";
1650 ParagraphStyle paragraph_style;
1651 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1652 TextStyle text_style;
1653 text_style.setColor(SK_ColorBLACK);
1654 text_style.setFontFamilies({SkString("Roboto")});
1655 text_style.setFontSize(20);
1656 builder.pushStyle(text_style);
1657 builder.addText(text);
1658 auto paragraph = builder.Build();
1659 paragraph->layout(this->width());
1660 paragraph->paint(canvas, 0, 0);
1661 }
1662
1663 private:
1664 typedef Sample INHERITED;
1665 };
1666
1667 class ParagraphView20 : public ParagraphView_Base {
1668 protected:
name()1669 SkString name() override { return SkString("Paragraph20"); }
1670
onDrawContent(SkCanvas * canvas)1671 void onDrawContent(SkCanvas* canvas) override {
1672 canvas->drawColor(SK_ColorWHITE);
1673
1674 auto fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
1675
1676 const char* text = "Manage your google account";
1677 ParagraphStyle paragraph_style;
1678 paragraph_style.setEllipsis(u"\u2026");
1679 paragraph_style.setMaxLines(1);
1680 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1681 TextStyle text_style;
1682 text_style.setColor(SK_ColorBLACK);
1683 text_style.setFontFamilies({SkString("Roboto")});
1684 text_style.setFontSize(50);
1685 builder.pushStyle(text_style);
1686 builder.addText(text);
1687 auto paragraph = builder.Build();
1688 paragraph->layout(this->width());
1689 paragraph->paint(canvas, 0, 0);
1690 }
1691
1692 private:
1693 typedef Sample INHERITED;
1694 };
1695
1696 class ParagraphView21 : public ParagraphView_Base {
1697 protected:
name()1698 SkString name() override { return SkString("Paragraph21"); }
1699
onDrawContent(SkCanvas * canvas)1700 void onDrawContent(SkCanvas* canvas) override {
1701 canvas->drawColor(SK_ColorWHITE);
1702
1703 const char* text = "Referral Code";
1704 ParagraphStyle paragraph_style;
1705 ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1706 TextStyle text_style;
1707 text_style.setColor(SK_ColorBLACK);
1708 text_style.setFontFamilies({SkString("Google Sans")});
1709 text_style.setFontSize(24);
1710 builder.pushStyle(text_style);
1711 builder.addText(text);
1712 auto paragraph = builder.Build();
1713 paragraph->layout(0);
1714 paragraph->paint(canvas, 0, 0);
1715 }
1716
1717 private:
1718 typedef Sample INHERITED;
1719 };
1720
1721 class ParagraphView22 : public ParagraphView_Base {
1722 protected:
name()1723 SkString name() override { return SkString("Paragraph22"); }
1724
onChar(SkUnichar uni)1725 bool onChar(SkUnichar uni) override {
1726 switch (uni) {
1727 case 'l':
1728 direction = true;
1729 return true;
1730 case 'r':
1731 direction = false;
1732 return true;
1733 default:
1734 break;
1735 }
1736 return false;
1737 }
1738
onDrawContent(SkCanvas * canvas)1739 void onDrawContent(SkCanvas* canvas) override {
1740
1741 canvas->drawColor(SK_ColorWHITE);
1742 ParagraphStyle paragraph_style;
1743 paragraph_style.setTextDirection(direction ? TextDirection::kLtr : TextDirection::kRtl);
1744 auto collection = getFontCollection();
1745 ParagraphBuilderImpl builder(paragraph_style, collection);
1746 collection->getParagraphCache()->reset();
1747 collection->getParagraphCache()->turnOn(false);
1748 TextStyle text_style;
1749 text_style.setColor(SK_ColorBLACK);
1750 text_style.setFontFamilies({SkString("Roboto")});
1751 text_style.setFontSize(12);
1752 builder.pushStyle(text_style);
1753 builder.addText("I have got a ");
1754 text_style.setFontStyle(SkFontStyle::Bold());
1755 builder.pushStyle(text_style);
1756 builder.addText("lovely bunch");
1757 text_style.setFontStyle(SkFontStyle::Normal());
1758 builder.pushStyle(text_style);
1759 builder.addText(" of coconuts.");
1760 auto paragraph = builder.Build();
1761 paragraph->layout(this->width());
1762 paragraph->paint(canvas, 0, 0);
1763 collection->getParagraphCache()->turnOn(true);
1764 }
1765
1766 private:
1767 typedef Sample INHERITED;
1768 bool direction;
1769 };
1770
1771 class ParagraphView23 : public ParagraphView_Base {
1772 protected:
name()1773 SkString name() override { return SkString("Paragraph23"); }
1774
onDrawContent(SkCanvas * canvas)1775 void onDrawContent(SkCanvas* canvas) override {
1776 canvas->drawColor(SK_ColorWHITE);
1777
1778 const char* text = "Text with shadow";
1779 ParagraphStyle paragraph_style;
1780 TextStyle text_style;
1781 text_style.setColor(SK_ColorBLACK);
1782 text_style.setFontFamilies({SkString("Google Sans")});
1783 text_style.setFontSize(24);
1784
1785 auto draw = [&](SkScalar h, SkScalar v, SkScalar b) {
1786 text_style.resetShadows();
1787 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(h, v), b));
1788 ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1789 builder.pushStyle(text_style);
1790 builder.addText(text);
1791 auto paragraph = builder.Build();
1792 paragraph->layout(300);
1793 paragraph->paint(canvas, 0, 0);
1794
1795 auto rect = SkRect::MakeXYWH(0, 0, paragraph->getMaxWidth(), paragraph->getHeight());
1796 SkPaint paint;
1797 paint.setColor(SK_ColorRED);
1798 paint.setStyle(SkPaint::kStroke_Style);
1799 paint.setAntiAlias(true);
1800 paint.setStrokeWidth(1);
1801 canvas->drawRect(rect, paint);
1802 };
1803
1804 draw(10, 10, 5);
1805 canvas->translate(0, 100);
1806
1807 draw(10, -10, 5);
1808 canvas->translate(0, 100);
1809
1810 draw(-10, -10, 5);
1811 canvas->translate(0, 100);
1812
1813 draw(-10, 10, 5);
1814 canvas->translate(0, 100);
1815 }
1816
1817 private:
1818 typedef Sample INHERITED;
1819 };
1820
1821 class ParagraphView24 : public ParagraphView_Base {
1822 protected:
name()1823 SkString name() override { return SkString("Paragraph24"); }
1824
onDrawContent(SkCanvas * canvas)1825 void onDrawContent(SkCanvas* canvas) override {
1826 canvas->drawColor(SK_ColorWHITE);
1827
1828 ParagraphStyle paragraph_style;
1829 paragraph_style.setTextDirection(TextDirection::kRtl);
1830 TextStyle text_style;
1831 text_style.setColor(SK_ColorBLACK);
1832 text_style.setFontFamilies({SkString("Google Sans")});
1833 text_style.setFontSize(24);
1834 {
1835 ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1836 builder.pushStyle(text_style);
1837 builder.addText("Right_to_left:");
1838 auto paragraph = builder.Build();
1839 paragraph->layout(this->width());
1840 paragraph->paint(canvas, 0, 0);
1841 }
1842 canvas->translate(0, 200);
1843 {
1844 ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1845 builder.pushStyle(text_style);
1846 builder.addText("Right_to_left+");
1847 auto paragraph = builder.Build();
1848 paragraph->layout(this->width());
1849 paragraph->paint(canvas, 0, 0);
1850 }
1851 canvas->translate(0, 200);
1852 {
1853 ParagraphBuilderImpl builder(paragraph_style, getFontCollection());
1854 builder.pushStyle(text_style);
1855 builder.addText("Right_to_left.");
1856 auto paragraph = builder.Build();
1857 paragraph->layout(this->width());
1858 paragraph->paint(canvas, 0, 0);
1859 }
1860 }
1861
1862 private:
1863 typedef Sample INHERITED;
1864 };
1865
1866 class ParagraphView25 : public ParagraphView_Base {
1867 protected:
name()1868 SkString name() override { return SkString("Paragraph25"); }
1869
onDrawContent(SkCanvas * canvas)1870 void onDrawContent(SkCanvas* canvas) override {
1871 canvas->drawColor(SK_ColorWHITE);
1872 /*
1873 * Shell: ParagraphStyle: 1.000000 1
1874 Shell: Strut enabled: 0 1.000000 14.000000 400 5 0
1875 Shell: Font Families: 0
1876 Shell: DefaultTextStyle: 16.000000 500 5 0
1877 Shell: Font Families: 1 Roboto
1878 Shell: Font Features: 0
1879 Shell: TextStyle#0: [0:22) 16.000000 500 5 0
1880 Shell: Font Families: 1 Roboto
1881 Shell: Font Features: 0
1882 Shell: TextStyle#1: [25:49) 16.000000 500 5 0
1883 Shell: Font Families: 1 Roboto
1884 Shell: Font Features: 0
1885 Shell: Placeholder#0: [22:25) 32.000000 32.000000 32.000000 0 5
1886 Shell: Placeholder#1: [49:52) 19.000000 41.000000 19.000000 0 4
1887 Shell: Placeholder#2: [52:52) 0.000000 0.000000 0.000000 0 5
1888 Shell: layout('Go to device settings  and set up a passcode. ', 280.000000): 280.000000 * 38.000000
1889 */
1890 auto fontCollection = getFontCollection();
1891 //fontCollection->getParagraphCache()->turnOn(false);
1892 const char* text1 = "Go to device settings ";
1893 const char* text2 = "and set up a passcode.";
1894 ParagraphStyle paragraph_style;
1895 StrutStyle strut_style;
1896 strut_style.setStrutEnabled(false);
1897 strut_style.setFontSize(14);
1898 strut_style.setForceStrutHeight(false);
1899 strut_style.setHeight(14);
1900 paragraph_style.setStrutStyle(strut_style);
1901 TextStyle text_style;
1902 text_style.setColor(SK_ColorBLACK);
1903 text_style.setFontFamilies({SkString("Roboto")});
1904 text_style.setFontSize(16);
1905 PlaceholderStyle placeholder_style;
1906 {
1907 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1908 builder.pushStyle(text_style);
1909 builder.addText(text1);
1910 placeholder_style.fHeight = 32;
1911 placeholder_style.fWidth = 32;
1912 placeholder_style.fBaselineOffset = 32;
1913 placeholder_style.fBaseline = TextBaseline::kAlphabetic;
1914 placeholder_style.fAlignment = PlaceholderAlignment::kMiddle;
1915 builder.addPlaceholder(placeholder_style);
1916 builder.addText(text2);
1917 placeholder_style.fHeight = 19;
1918 placeholder_style.fWidth = 41;
1919 placeholder_style.fBaselineOffset = 19;
1920 placeholder_style.fBaseline = TextBaseline::kAlphabetic;
1921 placeholder_style.fAlignment = PlaceholderAlignment::kTop;
1922 builder.addPlaceholder(placeholder_style);
1923 auto paragraph = builder.Build();
1924 paragraph->layout(280);
1925 paragraph->paint(canvas, 0, 0);
1926 }
1927 }
1928
1929 private:
1930 typedef Sample INHERITED;
1931 };
1932
1933 class ParagraphView26 : public ParagraphView_Base {
1934 protected:
name()1935 SkString name() override { return SkString("Paragraph26"); }
1936
onDrawContent(SkCanvas * canvas)1937 void onDrawContent(SkCanvas* canvas) override {
1938 auto fontCollection = sk_make_sp<FontCollection>();
1939 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1940 //fontCollection->enableFontFallback();
1941
1942 canvas->clear(SK_ColorWHITE);
1943
1944 SkPaint paint;
1945 paint.setAntiAlias(true);
1946 paint.setColor(SK_ColorBLACK);
1947
1948 TextStyle textStyle;
1949 textStyle.setForegroundColor(paint);
1950 textStyle.setFontFamilies({ SkString("Roboto") });
1951 textStyle.setFontSize(42.0f);
1952 textStyle.setLetterSpacing(-0.05f);
1953 textStyle.setHeightOverride(true);
1954
1955 ParagraphStyle paragraphStyle;
1956 paragraphStyle.setTextStyle(textStyle);
1957 paragraphStyle.setTextAlign(TextAlign::kLeft);
1958
1959 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
1960 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");
1961
1962 auto paragraph = builder.Build();
1963 paragraph->layout(this->width() / 2);
1964
1965 std::vector<LineMetrics> lines;
1966 paragraph->getLineMetrics(lines); // <-- error happens here
1967
1968 canvas->translate(10, 10);
1969 paragraph->paint(canvas, 0, 0);
1970 }
1971
1972 private:
1973 typedef Sample INHERITED;
1974 };
1975
1976 class ParagraphView27 : public ParagraphView_Base {
1977 protected:
name()1978 SkString name() override { return SkString("Paragraph27"); }
1979
onDrawContent(SkCanvas * canvas)1980 void onDrawContent(SkCanvas* canvas) override {
1981 auto fontCollection = sk_make_sp<FontCollection>();
1982 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
1983 fontCollection->enableFontFallback();
1984 fontCollection->getParagraphCache()->turnOn(false);
1985
1986 SkPaint red;
1987 red.setColor(SK_ColorRED);
1988 red.setStyle(SkPaint::kStroke_Style);
1989 red.setAntiAlias(true);
1990 red.setStrokeWidth(1);
1991
1992 SkPaint blue;
1993 blue.setColor(SK_ColorRED);
1994 blue.setStyle(SkPaint::kStroke_Style);
1995 blue.setAntiAlias(true);
1996 blue.setStrokeWidth(1);
1997
1998 SkPaint black;
1999 black.setColor(SK_ColorBLACK);
2000 black.setStyle(SkPaint::kStroke_Style);
2001 black.setAntiAlias(true);
2002 black.setStrokeWidth(1);
2003
2004 SkPaint whiteSpaces;
2005 whiteSpaces.setColor(SK_ColorLTGRAY);
2006
2007 SkPaint breakingSpace;
2008 breakingSpace.setColor(SK_ColorYELLOW);
2009
2010 SkPaint text;
2011 text.setColor(SK_ColorWHITE);
2012
2013 ParagraphStyle paragraph_style;
2014 paragraph_style.setTextAlign(TextAlign::kRight);
2015 TextStyle text_style;
2016 text_style.setColor(SK_ColorBLACK);
2017 text_style.setFontFamilies({SkString("Roboto")});
2018
2019 // RTL + right align + arabic
2020 // RTL + right align + latin
2021 // LTR + right align + arabic
2022 // LTR + right align + latin
2023 // RTL + left align + arabic
2024 // RTL + left align + latin
2025 // arabic and latin should not differ at all
2026 // check: line breaking and trailing spaces
2027
2028 canvas->drawColor(SK_ColorWHITE);
2029 auto h = 60;
2030 auto w = 300;
2031
2032 auto draw = [&](SkScalar width, SkScalar height, TextDirection td, TextAlign ta, const char* t) {
2033 SkDebugf("draw '%s' dir:%s align:%s\n", t,
2034 td == TextDirection::kLtr ? "left" : "right",
2035 ta == TextAlign::kLeft ? "left" : "right");
2036 paragraph_style.setTextDirection(td);
2037 paragraph_style.setTextAlign(ta);
2038 text_style.setFontSize(20);
2039 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2040 text_style.setBackgroundColor(whiteSpaces);
2041 builder.pushStyle(text_style);
2042 builder.addText(" ");
2043 text_style.setBackgroundColor(text);
2044 builder.pushStyle(text_style);
2045 builder.addText(t);
2046 text_style.setBackgroundColor(breakingSpace);
2047 builder.pushStyle(text_style);
2048 builder.addText(" ");
2049 text_style.setBackgroundColor(text);
2050 builder.pushStyle(text_style);
2051 builder.addText(t);
2052 text_style.setBackgroundColor(whiteSpaces);
2053 builder.pushStyle(text_style);
2054 builder.addText(" ");
2055 auto paragraph = builder.Build();
2056 paragraph->layout(width);
2057 paragraph->paint(canvas, 0, 0);
2058 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2059 for (auto& line : impl->lines()) {
2060 SkDebugf("line[%d]: %f + %f\n", &line - impl->lines().begin(), line.offset().fX, line.shift());
2061 line.iterateThroughVisualRuns(true,
2062 [&](const Run* run, SkScalar runOffset, TextRange textRange, SkScalar* width) {
2063 *width = line.measureTextInsideOneRun(textRange, run, runOffset, 0, true, false).clip.width();
2064 SkDebugf("%d[%d: %d) @%f + %f %s\n", run->index(),
2065 textRange.start, textRange.end, runOffset, *width, run->leftToRight() ? "left" : "right");
2066 return true;
2067 });
2068 }
2069 auto boxes = paragraph->getRectsForRange(0, 100, RectHeightStyle::kTight, RectWidthStyle::kTight);
2070 bool even = true;
2071 for (auto& box : boxes) {
2072 SkDebugf("[%f:%f,%f:%f] %s\n",
2073 box.rect.fLeft, box.rect.fRight, box.rect.fTop, box.rect.fBottom,
2074 box.direction == TextDirection::kLtr ? "left" : "right");
2075 canvas->drawRect(box.rect, even ? red : blue);
2076 even = !even;
2077 }
2078 canvas->translate(0, height);
2079 };
2080
2081 canvas->drawRect(SkRect::MakeXYWH(0, 0, w, h * 8), black);
2082
2083 draw(w, h, TextDirection::kRtl, TextAlign::kRight, "RTL+RIGHT#1234567890");
2084 draw(w, h, TextDirection::kRtl, TextAlign::kRight, "قففغغغغقففغغغغقففغغغ");
2085
2086 draw(w, h, TextDirection::kLtr, TextAlign::kRight, "LTR+RIGHT#1234567890");
2087 draw(w, h, TextDirection::kLtr, TextAlign::kRight, "قففغغغغقففغغغغقففغغغ");
2088
2089 draw(w, h, TextDirection::kRtl, TextAlign::kLeft, "RTL+LEFT##1234567890");
2090 draw(w, h, TextDirection::kRtl, TextAlign::kLeft, "قففغغغغقففغغغغقففغغغ");
2091
2092 draw(w, h, TextDirection::kLtr, TextAlign::kLeft, "LTR+LEFT##1234567890");
2093 draw(w, h, TextDirection::kLtr, TextAlign::kLeft, "قففغغغغقففغغغغقففغغغ");
2094 }
2095
2096 private:
2097 typedef Sample INHERITED;
2098 };
2099
2100 class ParagraphView28 : public ParagraphView_Base {
2101 protected:
name()2102 SkString name() override { return SkString("Paragraph28"); }
2103
onDrawContent(SkCanvas * canvas)2104 void onDrawContent(SkCanvas* canvas) override {
2105
2106 const char* text = "AAAAA BBBBB CCCCC DDDDD EEEEE FFFFF GGGGG HHHHH IIIII JJJJJ KKKKK LLLLL MMMMM NNNNN OOOOO PPPPP QQQQQ";
2107
2108 canvas->drawColor(SK_ColorWHITE);
2109 ParagraphStyle paragraph_style;
2110 paragraph_style.setTextAlign(TextAlign::kJustify);
2111 auto collection = getFontCollection();
2112 ParagraphBuilderImpl builder(paragraph_style, collection);
2113 TextStyle text_style;
2114 text_style.setColor(SK_ColorBLACK);
2115 text_style.setFontFamilies({SkString("Roboto")});
2116 text_style.setFontSize(40);
2117 builder.pushStyle(text_style);
2118 builder.addText(text);
2119 auto paragraph = builder.Build();
2120 auto s = 186;
2121 paragraph->layout(360 - s);
2122 paragraph->paint(canvas, 0, 0);
2123 /*
2124 paragraph->layout(360);
2125 paragraph->paint(canvas, 0, 0);
2126 canvas->translate(0, 400);
2127 paragraph->layout(354.333);
2128 paragraph->paint(canvas, 0, 0);
2129 */
2130 }
2131
2132 private:
2133 typedef Sample INHERITED;
2134 };
2135
2136 class ParagraphView29 : public ParagraphView_Base {
2137 protected:
name()2138 SkString name() override { return SkString("Paragraph29"); }
2139
onDrawContent(SkCanvas * canvas)2140 void onDrawContent(SkCanvas* canvas) override {
2141
2142 const char* text = "ffi";
2143 canvas->drawColor(SK_ColorWHITE);
2144
2145 auto collection = getFontCollection();
2146
2147 ParagraphStyle paragraph_style;
2148 ParagraphBuilderImpl builder(paragraph_style, collection);
2149 TextStyle text_style;
2150 text_style.setColor(SK_ColorBLACK);
2151 text_style.setFontFamilies({SkString("Roboto")});
2152 text_style.setFontSize(60);
2153 builder.pushStyle(text_style);
2154 builder.addText(text);
2155 auto paragraph = builder.Build();
2156 paragraph->layout(width());
2157 paragraph->paint(canvas, 0, 0);
2158 auto width = paragraph->getLongestLine();
2159 auto height = paragraph->getHeight();
2160
2161 auto f1 = paragraph->getGlyphPositionAtCoordinate(width/6, height/2);
2162 auto f2 = paragraph->getGlyphPositionAtCoordinate(width/2, height/2);
2163 auto i = paragraph->getGlyphPositionAtCoordinate(width*5/6, height/2);
2164
2165 SkDebugf("%d(%s) %d(%s) %d(%s)\n",
2166 f1.position, f1.affinity == Affinity::kUpstream ? "up" : "down",
2167 f2.position, f2.affinity == Affinity::kUpstream ? "up" : "down",
2168 i.position, i.affinity == Affinity::kUpstream ? "up" : "down");
2169
2170 auto rf1 = paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight, RectWidthStyle::kTight)[0];
2171 auto rf2 = paragraph->getRectsForRange(1, 2, RectHeightStyle::kTight, RectWidthStyle::kTight)[0];
2172 auto rfi = paragraph->getRectsForRange(2, 3, RectHeightStyle::kTight, RectWidthStyle::kTight)[0];
2173
2174 SkDebugf("f1: [%f:%f] %s\n",
2175 rf1.rect.fLeft, rf1.rect.fRight, rf1.direction == TextDirection::kRtl ? "rtl" : "ltr");
2176 SkDebugf("f2: [%f:%f] %s\n",
2177 rf2.rect.fLeft, rf2.rect.fRight, rf2.direction == TextDirection::kRtl ? "rtl" : "ltr");
2178 SkDebugf("i: [%f:%f] %s\n",
2179 rfi.rect.fLeft, rfi.rect.fRight, rfi.direction == TextDirection::kRtl ? "rtl" : "ltr");
2180 }
2181
2182 private:
2183 typedef Sample INHERITED;
2184 };
2185
2186 class ParagraphView30 : public ParagraphView_Base {
2187 protected:
name()2188 SkString name() override { return SkString("Paragraph30"); }
2189
onDrawContent(SkCanvas * canvas)2190 void onDrawContent(SkCanvas* canvas) override {
2191
2192 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";
2193 canvas->drawColor(SK_ColorWHITE);
2194
2195 auto fontCollection = sk_make_sp<FontCollection>();
2196 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2197 fontCollection->enableFontFallback();
2198
2199 ParagraphStyle paragraph_style;
2200 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2201 TextStyle text_style;
2202 text_style.setColor(SK_ColorBLACK);
2203 text_style.setFontFamilies({SkString("Noto Color Emoji")});
2204 text_style.setFontSize(60);
2205 builder.pushStyle(text_style);
2206 builder.addText(text);
2207 auto paragraph = builder.Build();
2208 paragraph->layout(width());
2209
2210
2211 SkColor colors[] = {
2212 SK_ColorRED,
2213 SK_ColorGREEN,
2214 SK_ColorBLUE,
2215 SK_ColorMAGENTA,
2216 SK_ColorYELLOW
2217 };
2218 SkPaint paint;
2219 size_t color = 0;
2220 for (size_t i = 0; i < text.size(); ++i) {
2221 auto result = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kTight, RectWidthStyle::kTight);
2222 if (result.empty()) {
2223 SkDebugf("empty [%d:%d)\n", i, i + 1);
2224 continue;
2225 }
2226 auto rect = result[0].rect;
2227 paint.setColor(colors[color++ % 5]);
2228 canvas->drawRect(rect, paint);
2229 SkDebugf("rect [%d:%d): %f:%f\n", i, i + 1, rect.fLeft, rect.fRight);
2230 }
2231 paragraph->paint(canvas, 0, 0);
2232 }
2233
2234 private:
2235 typedef Sample INHERITED;
2236 };
2237
2238 class ParagraphView31 : public ParagraphView_Base {
2239 protected:
name()2240 SkString name() override { return SkString("Paragraph31"); }
2241
onDrawContent(SkCanvas * canvas)2242 void onDrawContent(SkCanvas* canvas) override {
2243
2244 canvas->drawColor(SK_ColorWHITE);
2245
2246 auto fontCollection = sk_make_sp<FontCollection>();
2247 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2248 fontCollection->enableFontFallback();
2249
2250 ParagraphStyle paragraph_style;
2251 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2252 TextStyle text_style;
2253 text_style.setColor(SK_ColorBLACK);
2254 text_style.setFontFamilies({SkString("Roboto")});
2255 text_style.setFontSize(40);
2256 builder.pushStyle(text_style);
2257 auto s = u"েن েূথ";
2258 builder.addText(s);
2259 auto paragraph = builder.Build();
2260 paragraph->layout(width());
2261 paragraph->paint(canvas, 0, 0);
2262 }
2263
2264 private:
2265 typedef Sample INHERITED;
2266 };
2267
2268 class ParagraphView32 : public ParagraphView_Base {
2269 protected:
name()2270 SkString name() override { return SkString("Paragraph32"); }
2271
onDrawContent(SkCanvas * canvas)2272 void onDrawContent(SkCanvas* canvas) override {
2273
2274 canvas->drawColor(SK_ColorWHITE);
2275
2276 auto fontCollection = sk_make_sp<FontCollection>();
2277 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2278 fontCollection->enableFontFallback();
2279
2280 ParagraphStyle paragraph_style;
2281 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2282 TextStyle text_style;
2283 text_style.setColor(SK_ColorBLACK);
2284 text_style.setFontFamilies({SkString("Roboto")});
2285 text_style.setFontSize(40);
2286 text_style.setLocale(SkString("ko"));
2287 builder.pushStyle(text_style);
2288 builder.addText(u"\u904d ko ");
2289 text_style.setLocale(SkString("zh_Hant"));
2290 builder.pushStyle(text_style);
2291 builder.addText(u"\u904d zh-Hant ");
2292 text_style.setLocale(SkString("zh_Hans"));
2293 builder.pushStyle(text_style);
2294 builder.addText(u"\u904d zh-Hans ");
2295 text_style.setLocale(SkString("zh_HK"));
2296 builder.pushStyle(text_style);
2297 builder.addText(u"\u904d zh-HK ");
2298 auto paragraph = builder.Build();
2299 paragraph->layout(width());
2300 paragraph->paint(canvas, 0, 0);
2301 }
2302
2303 private:
2304 typedef Sample INHERITED;
2305 };
2306
2307 class ParagraphView33 : public ParagraphView_Base {
2308 protected:
name()2309 SkString name() override { return SkString("Paragraph33"); }
2310
onDrawContent(SkCanvas * canvas)2311 void onDrawContent(SkCanvas* canvas) override {
2312
2313 canvas->drawColor(SK_ColorWHITE);
2314
2315 auto fontCollection = sk_make_sp<FontCollection>();
2316 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2317 fontCollection->enableFontFallback();
2318
2319 ParagraphStyle paragraph_style;
2320 paragraph_style.setTextAlign(TextAlign::kJustify);
2321 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2322 TextStyle text_style;
2323 text_style.setColor(SK_ColorBLACK);
2324 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2325 text_style.setFontSize(36);
2326 builder.pushStyle(text_style);
2327 builder.addText(u"AAAAA \U0001f600 BBBBB CCCCC DDDDD EEEEE");
2328 auto paragraph = builder.Build();
2329 paragraph->layout(width() / 2);
2330 SkPaint paint;
2331 paint.setColor(SK_ColorLTGRAY);
2332 canvas->drawRect(SkRect::MakeXYWH(0, 0, width()/2, paragraph->getHeight()), paint);
2333 paragraph->paint(canvas, 0, 0);
2334 }
2335
2336 private:
2337 typedef Sample INHERITED;
2338 };
2339
2340 class ParagraphView34 : public ParagraphView_Base {
2341 protected:
name()2342 SkString name() override { return SkString("Paragraph34"); }
2343
onDrawContent(SkCanvas * canvas)2344 void onDrawContent(SkCanvas* canvas) override {
2345
2346 canvas->drawColor(SK_ColorWHITE);
2347 auto text = "ضخمة ص ،ضضض ؤ،،شسي،ؤرى،ببب،ثيلااتن";
2348 //auto text = "ى،بب";
2349 //auto text1 = "World domination is such an ugly phrase - I prefer to call it world optimisation";
2350 auto fontCollection = sk_make_sp<FontCollection>();
2351 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2352 fontCollection->enableFontFallback();
2353
2354 ParagraphStyle paragraph_style;
2355 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2356 TextStyle text_style;
2357 text_style.setColor(SK_ColorBLACK);
2358 text_style.setFontFamilies({SkString("Noto Color Emoji")});
2359 text_style.setFontSize(50);
2360 builder.pushStyle(text_style);
2361 builder.addText(text);
2362 auto paragraph = builder.Build();
2363 paragraph->layout(1041); // 1041
2364
2365 SkColor colors[] = {SK_ColorBLUE, SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGREEN,
2366 SK_ColorRED, SK_ColorWHITE, SK_ColorYELLOW, SK_ColorMAGENTA };
2367 SkPaint paint;
2368 size_t wordPos = 0;
2369 size_t index = 0;
2370 while (wordPos < 72) {
2371 auto res2 = paragraph->getWordBoundary(wordPos);
2372 if (res2.width() == 0) {
2373 break;
2374 }
2375 wordPos = res2.end;
2376 auto res3 = paragraph->getRectsForRange(
2377 res2.start, res2.end,
2378 RectHeightStyle::kTight, RectWidthStyle::kTight);
2379 paint.setColor(colors[index % 8]);
2380 ++index;
2381 if (!res3.empty()) {
2382 canvas->drawRect(res3[0].rect, paint);
2383 }
2384 }
2385 paragraph->paint(canvas, 0, 0);
2386 }
2387
2388 private:
2389 typedef Sample INHERITED;
2390 };
2391
2392 class ParagraphView35 : public ParagraphView_Base {
2393 protected:
name()2394 SkString name() override { return SkString("Paragraph35"); }
2395
onFindClickHandler(SkScalar x,SkScalar y,skui::ModifierKey modi)2396 Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
2397 return new Click;
2398 }
2399
onClick(Click * click)2400 bool onClick(Click* click) override {
2401 fPoint = click->fCurr;
2402 return true;
2403 }
2404
onDrawContent(SkCanvas * canvas)2405 void onDrawContent(SkCanvas* canvas) override {
2406
2407 canvas->drawColor(SK_ColorWHITE);
2408
2409 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";
2410 auto fontCollection = sk_make_sp<FontCollection>();
2411 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2412 fontCollection->enableFontFallback();
2413
2414 ParagraphStyle paragraph_style;
2415 //paragraph_style.setTextAlign(TextAlign::kJustify);
2416 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2417 TextStyle text_style;
2418 text_style.setColor(SK_ColorBLACK);
2419 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
2420 text_style.setFontSize(40);
2421 builder.pushStyle(text_style);
2422 builder.addText(text);
2423 auto paragraph = builder.Build();
2424 paragraph->layout(width());//758
2425
2426 //auto res1 = paragraph->getGlyphPositionAtCoordinate(line.width() + line.spacesWidth() / 2, line.offset().fY + 10);
2427 //auto res2 = paragraph->getWordBoundary(res1.position);
2428 auto res1 = paragraph->getRectsForRange(360, 361, RectHeightStyle::kTight, RectWidthStyle::kTight);
2429 auto res2 = paragraph->getRectsForRange(359, 360, RectHeightStyle::kTight, RectWidthStyle::kTight);
2430 auto res3 = paragraph->getRectsForRange(358, 359, RectHeightStyle::kTight, RectWidthStyle::kTight);
2431
2432 auto draw = [&](std::vector<TextBox> res, SkColor color) {
2433 SkPaint paint;
2434 paint.setColor(color);
2435 for (auto& r : res) {
2436 canvas->drawRect(r.rect, paint);
2437 }
2438 };
2439
2440 draw(res1, SK_ColorRED);
2441 draw(res2, SK_ColorGREEN);
2442 draw(res3, SK_ColorBLUE);
2443
2444 paragraph->paint(canvas, 0, 0);
2445 }
2446
2447 private:
2448 typedef Sample INHERITED;
2449 SkPoint fPoint;
2450 };
2451
2452 class ParagraphView36 : public ParagraphView_Base {
2453 protected:
name()2454 SkString name() override { return SkString("Paragraph36"); }
2455
onDrawContent(SkCanvas * canvas)2456 void onDrawContent(SkCanvas* canvas) override {
2457
2458 canvas->drawColor(SK_ColorWHITE);
2459
2460 auto text = "其实就是要 English 却又无法预览 English 功能强大起来 English 了我觉得自己也 English 可以的时候我们";
2461 auto fontCollection = sk_make_sp<FontCollection>();
2462 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2463 fontCollection->enableFontFallback();
2464
2465 ParagraphStyle paragraph_style;
2466 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2467 TextStyle text_style;
2468 text_style.setColor(SK_ColorBLACK);
2469 text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Serif CJK JP")});
2470 text_style.setFontSize(10);
2471 builder.pushStyle(text_style);
2472 builder.addText(text);
2473 auto paragraph = builder.Build();
2474 paragraph->layout(width());
2475
2476 auto res1 = paragraph->getRectsForRange(63, 64, RectHeightStyle::kTight, RectWidthStyle::kTight);
2477 auto rect = res1[0].rect;
2478 auto res2 = paragraph->getGlyphPositionAtCoordinate(rect.fLeft + rect.width() / 2, rect.height());
2479 auto res3 = paragraph->getWordBoundary(res2.position);
2480 SkDebugf("[%d:%d)\n", res3.start, res3.end);
2481
2482 paragraph->paint(canvas, 0, 0);
2483 }
2484
2485 private:
2486 typedef Sample INHERITED;
2487 };
2488
2489 class ParagraphView37 : public ParagraphView_Base {
2490 protected:
name()2491 SkString name() override { return SkString("Paragraph37"); }
2492
onDrawContent(SkCanvas * canvas)2493 void onDrawContent(SkCanvas* canvas) override {
2494 const char* text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaয়ৠঝোণ৺ঢ়মৈবৗৗঘথফড়৭২খসঢ়ৃঢ়ঁ৷থডঈঽলবনদ২ৢৃঀজঝ৩ঠ৪৫৯০ঌয়্মওৗ৲গখদ৹ঈ৴৹ঢ়ৄএৡফণহলঈ৲থজোৱে ঀকৰঀষজঝঃাখশঽএমংি";
2495 //"ৎৣ়ৎঽতঃ৳্ৱব৴ৣঈ৷ূঁঢঢ়শটডৎ৵৵ৰৃ্দংঊাথৗদঊউদ৯ঐৃধা৬হওধি়৭ঽম৯স০ঢফৈঢ়কষঁছফীআে৶ৰ৶ঌৌঊ্ঊঝএঀঃদঞ৮তব৬ৄঊঙঢ়ৡগ৶৹৹ঌড়ঘৄ৷লপ১ভড়৶েঢ়৯ৎকনংট২ংএঢৌৌঐনো০টঽুৠগআ৷৭৩৬তো৻ঈ০ূসষঅঝআমণঔা১ণৈো৵চঽ৩বমৎঙঘ২ঠৠৈী৫তঌণচ৲ঔী৮ঘৰঔ";
2496 canvas->drawColor(SK_ColorWHITE);
2497
2498 auto fontCollection = sk_make_sp<FontCollection>();
2499 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
2500 fontCollection->enableFontFallback();
2501
2502 ParagraphStyle paragraph_style;
2503 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2504 TextStyle text_style;
2505 text_style.setColor(SK_ColorBLACK);
2506 text_style.setFontFamilies({SkString("Roboto")});
2507 text_style.setFontSize(20);
2508 builder.pushStyle(text_style);
2509 builder.addText(text);
2510 auto paragraph = builder.Build();
2511 auto w = width() / 2;
2512 paragraph->layout(w);
2513 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2514
2515 auto clusters = impl->clusters();
2516 size_t c = 0;
2517 SkDebugf("clusters\n");
2518 for (auto& cluster: clusters) {
2519 SkDebugf(""
2520 "%d: [%d:%d) %s\n", c++,
2521 cluster.textRange().start, cluster.textRange().end,
2522 cluster.isSoftBreak() ? "soft" :
2523 cluster.isHardBreak() ? "hard" :
2524 cluster.isWhitespaces() ? "spaces" : ""
2525 );
2526 }
2527 auto lines = impl->lines();
2528 size_t i = 0;
2529 SkDebugf("lines\n");
2530 for (auto& line : lines) {
2531 SkDebugf("%d: [%d:%d)\n", i++, line.trimmedText().start, line.trimmedText().end);
2532 }
2533
2534 paragraph->paint(canvas, 0, 0);
2535 }
2536
2537 private:
2538 typedef Sample INHERITED;
2539 };
2540
2541 //////////////////////////////////////////////////////////////////////////////
2542 DEF_SAMPLE(return new ParagraphView1();)
2543 DEF_SAMPLE(return new ParagraphView2();)
2544 DEF_SAMPLE(return new ParagraphView3();)
2545 DEF_SAMPLE(return new ParagraphView4();)
2546 DEF_SAMPLE(return new ParagraphView5();)
2547 DEF_SAMPLE(return new ParagraphView6();)
2548 DEF_SAMPLE(return new ParagraphView7();)
2549 DEF_SAMPLE(return new ParagraphView8();)
2550 DEF_SAMPLE(return new ParagraphView9();)
2551 DEF_SAMPLE(return new ParagraphView10();)
2552 DEF_SAMPLE(return new ParagraphView11();)
2553 DEF_SAMPLE(return new ParagraphView12();)
2554 DEF_SAMPLE(return new ParagraphView14();)
2555 DEF_SAMPLE(return new ParagraphView15();)
2556 DEF_SAMPLE(return new ParagraphView16();)
2557 DEF_SAMPLE(return new ParagraphView17();)
2558 DEF_SAMPLE(return new ParagraphView18();)
2559 DEF_SAMPLE(return new ParagraphView19();)
2560 DEF_SAMPLE(return new ParagraphView20();)
2561 DEF_SAMPLE(return new ParagraphView21();)
2562 DEF_SAMPLE(return new ParagraphView22();)
2563 DEF_SAMPLE(return new ParagraphView23();)
2564 DEF_SAMPLE(return new ParagraphView24();)
2565 DEF_SAMPLE(return new ParagraphView25();)
2566 DEF_SAMPLE(return new ParagraphView26();)
2567 DEF_SAMPLE(return new ParagraphView27();)
2568 DEF_SAMPLE(return new ParagraphView28();)
2569 DEF_SAMPLE(return new ParagraphView29();)
2570 DEF_SAMPLE(return new ParagraphView30();)
2571 DEF_SAMPLE(return new ParagraphView31();)
2572 DEF_SAMPLE(return new ParagraphView32();)
2573 DEF_SAMPLE(return new ParagraphView33();)
2574 DEF_SAMPLE(return new ParagraphView34();)
2575 DEF_SAMPLE(return new ParagraphView35();)
2576 DEF_SAMPLE(return new ParagraphView36();)
2577 DEF_SAMPLE(return new ParagraphView37();)
2578