blob: 4add3b955b431e25c6fc447f5cd2d52303750cf1 [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002#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/SkBlurMaskFilter.h"
14#include "include/effects/SkGradientShader.h"
15#include "include/utils/SkRandom.h"
16#include "modules/skparagraph/include/Paragraph.h"
Julia Lavrova6e6333f2019-06-17 10:34:10 -040017#include "modules/skparagraph/include/TypefaceFontProvider.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040018#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
19#include "modules/skparagraph/src/ParagraphImpl.h"
Julia Lavrova9af5cc42019-06-19 13:32:01 -040020#include "modules/skparagraph/utils/TestFontCollection.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040021#include "samplecode/Sample.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040022#include "src/core/SkOSFile.h"
23#include "src/shaders/SkColorShader.h"
24#include "src/utils/SkUTF.h"
25#include "tools/Resources.h"
26
27using namespace skia::textlayout;
28namespace {
29
Mike Reed21a940d2019-07-23 10:11:03 -040030class ParagraphView_Base : public Sample {
31protected:
32 sk_sp<TestFontCollection> fFC;
33 void onOnceBeforeDraw() override {
34 fFC = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str());
35 }
36};
37
Julia Lavrovaa3552c52019-05-30 16:12:56 -040038sk_sp<SkShader> setgrad(const SkRect& r, SkColor c0, SkColor c1) {
39 SkColor colors[] = {c0, c1};
40 SkPoint pts[] = {{r.fLeft, r.fTop}, {r.fRight, r.fTop}};
41 return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
42}
Julia Lavrova5207f352019-06-21 12:22:32 -040043
44const char* gText =
45 "This is a very long sentence to test if the text will properly wrap "
46 "around and go to the next line. Sometimes, short sentence. Longer "
47 "sentences are okay too because they are nessecary. Very short. "
48 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
49 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
50 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
51 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
52 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
53 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
54 "mollit anim id est laborum. "
55 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
56 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
57 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
58 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
59 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
60 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
61 "mollit anim id est laborum.";
62
Julia Lavrovaa3552c52019-05-30 16:12:56 -040063} // namespace
64
Mike Reed21a940d2019-07-23 10:11:03 -040065class ParagraphView1 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -040066protected:
Hal Canary8a027312019-07-03 10:55:44 -040067 SkString name() override { return SkString("Paragraph1"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040068
69 void drawTest(SkCanvas* canvas, SkScalar w, SkScalar h, SkColor fg, SkColor bg) {
70 const std::vector<
71 std::tuple<std::string, bool, bool, int, SkColor, SkColor, bool, TextDecorationStyle>>
72 gParagraph = {{"monospace", true, false, 14, SK_ColorWHITE, SK_ColorRED, true,
73 TextDecorationStyle::kDashed},
74 {"Assyrian", false, false, 20, SK_ColorWHITE, SK_ColorBLUE, false,
75 TextDecorationStyle::kDotted},
76 {"serif", true, true, 10, SK_ColorWHITE, SK_ColorRED, true,
77 TextDecorationStyle::kDouble},
78 {"Arial", false, true, 16, SK_ColorGRAY, SK_ColorGREEN, true,
79 TextDecorationStyle::kSolid},
80 {"sans-serif", false, false, 8, SK_ColorWHITE, SK_ColorRED, false,
81 TextDecorationStyle::kWavy}};
82 SkAutoCanvasRestore acr(canvas, true);
83
84 canvas->clipRect(SkRect::MakeWH(w, h));
85 canvas->drawColor(SK_ColorWHITE);
86
87 SkScalar margin = 20;
88
89 SkPaint paint;
90 paint.setAntiAlias(true);
91 paint.setColor(fg);
92
93 SkPaint blue;
94 blue.setColor(SK_ColorBLUE);
95
96 TextStyle defaultStyle;
97 defaultStyle.setBackgroundColor(blue);
98 defaultStyle.setForegroundColor(paint);
99 ParagraphStyle paraStyle;
100
101 for (auto i = 1; i < 5; ++i) {
102 defaultStyle.setFontSize(24 * i);
103 paraStyle.setTextStyle(defaultStyle);
Julia Lavrova5207f352019-06-21 12:22:32 -0400104 auto fontCollection = sk_make_sp<FontCollection>();
105 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
106 ParagraphBuilderImpl builder(paraStyle, fontCollection);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400107 std::string name = "Paragraph: " + std::to_string(24 * i);
108 builder.addText(name.c_str());
109 for (auto para : gParagraph) {
110 TextStyle style;
111 style.setFontFamilies({SkString(std::get<0>(para).c_str())});
112 SkFontStyle fontStyle(std::get<1>(para) ? SkFontStyle::Weight::kBold_Weight
113 : SkFontStyle::Weight::kNormal_Weight,
114 SkFontStyle::Width::kNormal_Width,
115 std::get<2>(para) ? SkFontStyle::Slant::kItalic_Slant
116 : SkFontStyle::Slant::kUpright_Slant);
117 style.setFontStyle(fontStyle);
118 style.setFontSize(std::get<3>(para) * i);
119 SkPaint background;
120 background.setColor(std::get<4>(para));
121 style.setBackgroundColor(background);
122 SkPaint foreground;
123 foreground.setColor(std::get<5>(para));
124 foreground.setAntiAlias(true);
125 style.setForegroundColor(foreground);
126 if (std::get<6>(para)) {
127 style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(5, 5), 2));
128 }
129
130 auto decoration = (i % 4);
131 if (decoration == 3) {
132 decoration = 4;
133 }
134
135 bool test = (TextDecoration)decoration != TextDecoration::kNoDecoration;
136 std::string deco = std::to_string((int)decoration);
137 if (test) {
138 style.setDecoration((TextDecoration)decoration);
139 style.setDecorationStyle(std::get<7>(para));
140 style.setDecorationColor(std::get<5>(para));
141 }
142 builder.pushStyle(style);
143 std::string name = " " + std::get<0>(para) + " " +
144 (std::get<1>(para) ? ", bold" : "") +
145 (std::get<2>(para) ? ", italic" : "") + " " +
146 std::to_string(std::get<3>(para) * i) +
147 (std::get<4>(para) != bg ? ", background" : "") +
148 (std::get<5>(para) != fg ? ", foreground" : "") +
149 (std::get<6>(para) ? ", shadow" : "") +
150 (test ? ", decorations " + deco : "") + ";";
151 builder.addText(name.c_str());
152 builder.pop();
153 }
154
155 auto paragraph = builder.Build();
156 paragraph->layout(w - margin * 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400157 paragraph->paint(canvas, margin, margin);
158
159 canvas->translate(0, paragraph->getHeight());
160 }
161 }
162
163 void onDrawContent(SkCanvas* canvas) override {
164 drawTest(canvas, this->width(), this->height(), SK_ColorRED, SK_ColorWHITE);
165 }
166
167private:
168
169 typedef Sample INHERITED;
170};
171
Mike Reed21a940d2019-07-23 10:11:03 -0400172class ParagraphView2 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400173protected:
Hal Canary8a027312019-07-03 10:55:44 -0400174 SkString name() override { return SkString("Paragraph2"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400175
176 void drawCode(SkCanvas* canvas, SkScalar w, SkScalar h) {
177 SkPaint comment;
178 comment.setColor(SK_ColorGRAY);
179 SkPaint constant;
180 constant.setColor(SK_ColorMAGENTA);
181 SkPaint null;
182 null.setColor(SK_ColorMAGENTA);
183 SkPaint literal;
184 literal.setColor(SK_ColorGREEN);
185 SkPaint code;
186 code.setColor(SK_ColorDKGRAY);
187 SkPaint number;
188 number.setColor(SK_ColorBLUE);
189 SkPaint name;
190 name.setColor(SK_ColorRED);
191
192 SkPaint white;
193 white.setColor(SK_ColorWHITE);
194
195 TextStyle defaultStyle;
196 defaultStyle.setBackgroundColor(white);
197 defaultStyle.setForegroundColor(code);
198 defaultStyle.setFontFamilies({SkString("monospace")});
199 defaultStyle.setFontSize(30);
200 ParagraphStyle paraStyle;
201 paraStyle.setTextStyle(defaultStyle);
202
Julia Lavrova5207f352019-06-21 12:22:32 -0400203 auto fontCollection = sk_make_sp<FontCollection>();
204 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
205 ParagraphBuilderImpl builder(paraStyle, fontCollection);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400206
207 builder.pushStyle(style(name));
208 builder.addText("RaisedButton");
209 builder.pop();
210 builder.addText("(\n");
211 builder.addText(" child: ");
212 builder.pushStyle(style(constant));
213 builder.addText("const");
214 builder.pop();
215 builder.addText(" ");
216 builder.pushStyle(style(name));
217 builder.addText("Text");
218 builder.pop();
219 builder.addText("(");
220 builder.pushStyle(style(literal));
221 builder.addText("'BUTTON TITLE'");
222 builder.pop();
223 builder.addText("),\n");
224
225 auto paragraph = builder.Build();
226 paragraph->layout(w - 20);
227
228 paragraph->paint(canvas, 20, 20);
229 }
230
231 TextStyle style(SkPaint paint) {
232 TextStyle style;
233 paint.setAntiAlias(true);
234 style.setForegroundColor(paint);
235 style.setFontFamilies({SkString("monospace")});
236 style.setFontSize(30);
237
238 return style;
239 }
240
Julia Lavrova5207f352019-06-21 12:22:32 -0400241 void drawText(SkCanvas* canvas, SkScalar w, SkScalar h, std::vector<const char*>& text,
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400242 SkColor fg = SK_ColorDKGRAY, SkColor bg = SK_ColorWHITE,
243 const char* ff = "sans-serif", SkScalar fs = 24,
244 size_t lineLimit = 30,
245 const std::u16string& ellipsis = u"\u2026") {
246 SkAutoCanvasRestore acr(canvas, true);
247
248 canvas->clipRect(SkRect::MakeWH(w, h));
249 canvas->drawColor(bg);
250
251 SkScalar margin = 20;
252
253 SkPaint paint;
254 paint.setAntiAlias(true);
255 paint.setColor(fg);
256
257 SkPaint blue;
258 blue.setColor(SK_ColorBLUE);
259
260 SkPaint background;
261 background.setColor(bg);
262
263 TextStyle style;
264 style.setBackgroundColor(blue);
265 style.setForegroundColor(paint);
266 style.setFontFamilies({SkString(ff)});
267 style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight,
268 SkFontStyle::kNormal_Width,
269 SkFontStyle::kUpright_Slant));
270 style.setFontSize(fs);
271 ParagraphStyle paraStyle;
272 paraStyle.setTextStyle(style);
273 paraStyle.setMaxLines(lineLimit);
274
275 paraStyle.setEllipsis(ellipsis);
276 TextStyle defaultStyle;
277 defaultStyle.setFontSize(20);
278 paraStyle.setTextStyle(defaultStyle);
Mike Reed21a940d2019-07-23 10:11:03 -0400279 ParagraphBuilderImpl builder(paraStyle, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400280
281 SkPaint foreground;
282 foreground.setColor(fg);
283 style.setForegroundColor(foreground);
284 style.setBackgroundColor(background);
285
286 for (auto& part : text) {
287 builder.pushStyle(style);
Julia Lavrova5207f352019-06-21 12:22:32 -0400288 builder.addText(part);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400289 builder.pop();
290 }
291
292 auto paragraph = builder.Build();
293 paragraph->layout(w - margin * 2);
294 paragraph->paint(canvas, margin, margin);
295
296 canvas->translate(0, paragraph->getHeight() + margin);
297 }
298
299 void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
300 TextAlign align) {
301 SkAutoCanvasRestore acr(canvas, true);
302
303 canvas->clipRect(SkRect::MakeWH(w, h));
304 canvas->drawColor(SK_ColorWHITE);
305
306 SkScalar margin = 20;
307
308 SkPaint paint;
309 paint.setAntiAlias(true);
310 paint.setColor(SK_ColorBLUE);
311
312 SkPaint gray;
313 gray.setColor(SK_ColorLTGRAY);
314
315 TextStyle style;
316 style.setBackgroundColor(gray);
317 style.setForegroundColor(paint);
318 style.setFontFamilies({SkString("Arial")});
319 style.setFontSize(30);
320 ParagraphStyle paraStyle;
321 paraStyle.setTextStyle(style);
322 paraStyle.setTextAlign(align);
323
Julia Lavrova5207f352019-06-21 12:22:32 -0400324 auto fontCollection = sk_make_sp<FontCollection>();
325 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
326 ParagraphBuilderImpl builder(paraStyle, fontCollection);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400327 builder.addText(text.c_str());
328
329 auto paragraph = builder.Build();
330 paragraph->layout(w - margin * 2);
331 paragraph->layout(w - margin);
332 paragraph->paint(canvas, margin, margin);
333
334 canvas->translate(0, paragraph->getHeight() + margin);
335 }
336
337 void onDrawContent(SkCanvas* canvas) override {
Julia Lavrova5207f352019-06-21 12:22:32 -0400338 std::vector<const char*> cupertino = {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400339 "google_logogoogle_gsuper_g_logo 1 "
340 "google_logogoogle_gsuper_g_logo 12 "
341 "google_logogoogle_gsuper_g_logo 123 "
342 "google_logogoogle_gsuper_g_logo 1234 "
343 "google_logogoogle_gsuper_g_logo 12345 "
344 "google_logogoogle_gsuper_g_logo 123456 "
345 "google_logogoogle_gsuper_g_logo 1234567 "
346 "google_logogoogle_gsuper_g_logo 12345678 "
347 "google_logogoogle_gsuper_g_logo 123456789 "
348 "google_logogoogle_gsuper_g_logo 1234567890 "
349 "google_logogoogle_gsuper_g_logo 123456789 "
350 "google_logogoogle_gsuper_g_logo 12345678 "
351 "google_logogoogle_gsuper_g_logo 1234567 "
352 "google_logogoogle_gsuper_g_logo 123456 "
353 "google_logogoogle_gsuper_g_logo 12345 "
354 "google_logogoogle_gsuper_g_logo 1234 "
355 "google_logogoogle_gsuper_g_logo 123 "
356 "google_logogoogle_gsuper_g_logo 12 "
357 "google_logogoogle_gsuper_g_logo 1 "
358 "google_logogoogle_gsuper_g_logo "
359 "google_logogoogle_gsuper_g_logo "
360 "google_logogoogle_gsuper_g_logo "
361 "google_logogoogle_gsuper_g_logo "
362 "google_logogoogle_gsuper_g_logo "
363 "google_logogoogle_gsuper_g_logo"};
Julia Lavrova5207f352019-06-21 12:22:32 -0400364 std::vector<const char*> text = {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400365 "My neighbor came over to say,\n"
366 "Although not in a neighborly way,\n\n"
367 "That he'd knock me around,\n\n\n"
368 "If I didn't stop the sound,\n\n\n\n"
369 "Of the classical music I play."};
370
Julia Lavrova5207f352019-06-21 12:22:32 -0400371 std::vector<const char*> long_word = {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400372 "A_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
373 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
374 "very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_"
375 "very_very_very_very_very_very_very_long_text"};
376
Julia Lavrova5207f352019-06-21 12:22:32 -0400377 std::vector<const char*> very_long = {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400378 "A very very very very very very very very very very very very very very very very "
379 "very very very very very very very very very very very very very very very very "
380 "very very very very very very very very very very very very very very very very "
381 "very very very very very very very long text"};
382
Julia Lavrova5207f352019-06-21 12:22:32 -0400383 std::vector<const char*> very_word = {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400384 "A very_very_very_very_very_very_very_very_very_very "
385 "very_very_very_very_very_very_very_very_very_very very very very very very very "
386 "very very very very very very very very very very very very very very very very "
387 "very very very very very very very very very very very very very long text"};
388
389 SkScalar width = this->width() / 5;
390 SkScalar height = this->height();
391 drawText(canvas, width, height, long_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
392 canvas->translate(width, 0);
393 drawText(canvas, width, height, very_long, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
394 canvas->translate(width, 0);
395 drawText(canvas, width, height, very_word, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
396 canvas->translate(width, 0);
397
398 drawText(canvas, width, height / 2, text, SK_ColorBLACK, SK_ColorWHITE, "Roboto", 20, 100,
399 u"\u2026");
400 canvas->translate(0, height / 2);
401 drawCode(canvas, width, height / 2);
402 canvas->translate(width, -height / 2);
403
404 drawText(canvas, width, height, cupertino, SK_ColorBLACK, SK_ColorWHITE, "Google Sans", 30);
405 }
406
407private:
408 typedef Sample INHERITED;
409};
410
Mike Reed21a940d2019-07-23 10:11:03 -0400411class ParagraphView3 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400412protected:
Hal Canary8a027312019-07-03 10:55:44 -0400413 SkString name() override { return SkString("Paragraph3"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400414
415 void drawLine(SkCanvas* canvas, SkScalar w, SkScalar h, const std::string& text,
416 TextAlign align, size_t lineLimit = std::numeric_limits<size_t>::max(),
417 bool RTL = false, SkColor background = SK_ColorGRAY,
418 const std::u16string& ellipsis = u"\u2026") {
419 SkAutoCanvasRestore acr(canvas, true);
420
421 canvas->clipRect(SkRect::MakeWH(w, h));
422 canvas->drawColor(SK_ColorWHITE);
423
424 SkScalar margin = 20;
425
426 SkPaint paint;
427 paint.setAntiAlias(true);
428 paint.setColor(SK_ColorBLACK);
429
430 SkPaint gray;
431 gray.setColor(background);
432
433 SkPaint yellow;
434 yellow.setColor(SK_ColorYELLOW);
435
436 TextStyle style;
437 style.setBackgroundColor(gray);
438 style.setForegroundColor(paint);
439 style.setFontFamilies({SkString("sans-serif")});
440 style.setFontSize(30);
441 ParagraphStyle paraStyle;
442 paraStyle.setTextStyle(style);
443 paraStyle.setTextAlign(align);
444 paraStyle.setMaxLines(lineLimit);
445 paraStyle.setEllipsis(ellipsis);
446 // paraStyle.setTextDirection(RTL ? SkTextDirection::rtl : SkTextDirection::ltr);
447
Julia Lavrova5207f352019-06-21 12:22:32 -0400448 auto fontCollection = sk_make_sp<FontCollection>();
449 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
450 ParagraphBuilderImpl builder(paraStyle, fontCollection);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400451 if (RTL) {
452 builder.addText(mirror(text));
453 } else {
454 builder.addText(normal(text));
455 }
456
457 canvas->drawRect(SkRect::MakeXYWH(margin, margin, w - margin * 2, h - margin * 2), yellow);
458 auto paragraph = builder.Build();
459 paragraph->layout(w - margin * 2);
460 paragraph->paint(canvas, margin, margin);
461 }
462
463 std::u16string mirror(const std::string& text) {
464 std::u16string result;
465 result += u"\u202E";
466 // for (auto i = text.size(); i > 0; --i) {
467 // result += text[i - 1];
468 //}
469
470 for (auto i = text.size(); i > 0; --i) {
471 auto ch = text[i - 1];
472 if (ch == ',') {
473 result += u"!";
474 } else if (ch == '.') {
475 result += u"!";
476 } else {
477 result += ch;
478 }
479 }
480
481 result += u"\u202C";
482 return result;
483 }
484
485 std::u16string normal(const std::string& text) {
486 std::u16string result;
487 result += u"\u202D";
488 for (auto ch : text) {
489 result += ch;
490 }
491 result += u"\u202C";
492 return result;
493 }
494
495 void onDrawContent(SkCanvas* canvas) override {
496 const std::string options = // { "open-source open-source open-source open-source" };
497 {"Flutter is an open-source project to help developers "
498 "build high-performance, high-fidelity, mobile apps for "
499 "iOS and Android "
500 "from a single codebase. This design lab is a playground "
501 "and showcase of Flutter's many widgets, behaviors, "
502 "animations, layouts, and more."};
503
504 canvas->drawColor(SK_ColorDKGRAY);
505 SkScalar width = this->width() / 4;
506 SkScalar height = this->height() / 2;
507
508 const std::string line =
509 "World domination is such an ugly phrase - I prefer to call it world optimisation";
510
511 drawLine(canvas, width, height, line, TextAlign::kLeft, 1, false, SK_ColorLTGRAY);
512 canvas->translate(width, 0);
513 drawLine(canvas, width, height, line, TextAlign::kRight, 2, false, SK_ColorLTGRAY);
514 canvas->translate(width, 0);
515 drawLine(canvas, width, height, line, TextAlign::kCenter, 3, false, SK_ColorLTGRAY);
516 canvas->translate(width, 0);
517 drawLine(canvas, width, height, line, TextAlign::kJustify, 4, false, SK_ColorLTGRAY);
518 canvas->translate(-width * 3, height);
519
520 drawLine(canvas, width, height, line, TextAlign::kLeft, 1, true, SK_ColorLTGRAY);
521 canvas->translate(width, 0);
522 drawLine(canvas, width, height, line, TextAlign::kRight, 2, true, SK_ColorLTGRAY);
523 canvas->translate(width, 0);
524 drawLine(canvas, width, height, line, TextAlign::kCenter, 3, true, SK_ColorLTGRAY);
525 canvas->translate(width, 0);
526 drawLine(canvas, width, height, line, TextAlign::kJustify, 4, true, SK_ColorLTGRAY);
527 canvas->translate(width, 0);
528 }
529
530private:
531 typedef Sample INHERITED;
532};
533
Mike Reed21a940d2019-07-23 10:11:03 -0400534class ParagraphView4 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400535protected:
Hal Canary8a027312019-07-03 10:55:44 -0400536 SkString name() override { return SkString("Paragraph4"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400537
538 void drawFlutter(SkCanvas* canvas, SkScalar w, SkScalar h,
539 const char* ff = "Google Sans", SkScalar fs = 30,
540 size_t lineLimit = std::numeric_limits<size_t>::max(),
541 const std::u16string& ellipsis = u"\u2026") {
542 SkAutoCanvasRestore acr(canvas, true);
543
544 canvas->clipRect(SkRect::MakeWH(w, h));
545
546 SkScalar margin = 20;
547
548 SkPaint black;
549 black.setAntiAlias(true);
550 black.setColor(SK_ColorBLACK);
551
552 SkPaint blue;
553 blue.setAntiAlias(true);
554 blue.setColor(SK_ColorBLUE);
555
556 SkPaint red;
557 red.setAntiAlias(true);
558 red.setColor(SK_ColorRED);
559
560 SkPaint green;
561 green.setAntiAlias(true);
562 green.setColor(SK_ColorGREEN);
563
564 SkPaint gray;
565 gray.setColor(SK_ColorLTGRAY);
566
567 SkPaint yellow;
568 yellow.setColor(SK_ColorYELLOW);
569
570 SkPaint magenta;
571 magenta.setAntiAlias(true);
572 magenta.setColor(SK_ColorMAGENTA);
573
574 TextStyle style;
575 style.setFontFamilies({SkString(ff)});
576 style.setFontSize(fs);
577
578 TextStyle style0;
579 style0.setForegroundColor(black);
580 style0.setBackgroundColor(gray);
581 style0.setFontFamilies({SkString(ff)});
582 style0.setFontSize(fs);
583 style0.setDecoration(TextDecoration::kUnderline);
584 style0.setDecorationStyle(TextDecorationStyle::kDouble);
585 style0.setDecorationColor(SK_ColorBLACK);
586
587 TextStyle style1;
588 style1.setForegroundColor(blue);
589 style1.setBackgroundColor(yellow);
590 style1.setFontFamilies({SkString(ff)});
591 style1.setFontSize(fs);
592 style1.setDecoration(TextDecoration::kOverline);
593 style1.setDecorationStyle(TextDecorationStyle::kWavy);
594 style1.setDecorationColor(SK_ColorBLACK);
595
596 TextStyle style2;
597 style2.setForegroundColor(red);
598 style2.setFontFamilies({SkString(ff)});
599 style2.setFontSize(fs);
600
601 TextStyle style3;
602 style3.setForegroundColor(green);
603 style3.setFontFamilies({SkString(ff)});
604 style3.setFontSize(fs);
605
606 TextStyle style4;
607 style4.setForegroundColor(magenta);
608 style4.setFontFamilies({SkString(ff)});
609 style4.setFontSize(fs);
610
611 ParagraphStyle paraStyle;
612 paraStyle.setTextStyle(style);
613 paraStyle.setMaxLines(lineLimit);
614
615 paraStyle.setEllipsis(ellipsis);
616
617 const char* logo1 = "google_";
618 const char* logo2 = "logo";
619 const char* logo3 = "go";
620 const char* logo4 = "ogle_logo";
621 const char* logo5 = "google_lo";
622 const char* logo6 = "go";
623 {
Mike Reed21a940d2019-07-23 10:11:03 -0400624 ParagraphBuilderImpl builder(paraStyle, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400625
626 builder.pushStyle(style0);
627 builder.addText(logo1);
628 builder.pop();
629 builder.pushStyle(style1);
630 builder.addText(logo2);
631 builder.pop();
632
633 builder.addText(" ");
634
635 builder.pushStyle(style0);
636 builder.addText(logo3);
637 builder.pop();
638 builder.pushStyle(style1);
639 builder.addText(logo4);
640 builder.pop();
641
642 builder.addText(" ");
643
644 builder.pushStyle(style0);
645 builder.addText(logo5);
646 builder.pop();
647 builder.pushStyle(style1);
648 builder.addText(logo6);
649 builder.pop();
650
651 auto paragraph = builder.Build();
652 paragraph->layout(w - margin * 2);
653 paragraph->paint(canvas, margin, margin);
654 canvas->translate(0, h + margin);
655 }
656 }
657
658 void onDrawContent(SkCanvas* canvas) override {
659 canvas->drawColor(SK_ColorWHITE);
660 SkScalar width = this->width();
661 SkScalar height = this->height();
662
663 drawFlutter(canvas, width, height / 2);
664 }
665
666private:
667 typedef Sample INHERITED;
668};
669
Mike Reed21a940d2019-07-23 10:11:03 -0400670class ParagraphView5 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400671protected:
Julia Lavrova5207f352019-06-21 12:22:32 -0400672 SkString name() override { return SkString("Paragraph5"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400673
674 void bidi(SkCanvas* canvas, SkScalar w, SkScalar h, const std::u16string& text,
675 const std::u16string& expected, size_t lineLimit = std::numeric_limits<size_t>::max(),
676 const char* ff = "Roboto", SkScalar fs = 30,
677 const std::u16string& ellipsis = u"\u2026") {
678 SkAutoCanvasRestore acr(canvas, true);
679
680 canvas->clipRect(SkRect::MakeWH(w, h));
681
682 SkScalar margin = 20;
683
684 SkPaint black;
685 black.setColor(SK_ColorBLACK);
686 SkPaint gray;
687 gray.setColor(SK_ColorLTGRAY);
688
689 TextStyle style;
690 style.setForegroundColor(black);
691 style.setFontFamilies({SkString(ff)});
692 style.setFontSize(fs);
693
694 TextStyle style0;
695 style0.setForegroundColor(black);
696 style0.setFontFamilies({SkString(ff)});
697 style0.setFontSize(fs);
698 style0.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
699 SkFontStyle::kItalic_Slant));
700
701 TextStyle style1;
702 style1.setForegroundColor(gray);
703 style1.setFontFamilies({SkString(ff)});
704 style1.setFontSize(fs);
705 style1.setFontStyle(SkFontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
706 SkFontStyle::kUpright_Slant));
707
708 ParagraphStyle paraStyle;
709 paraStyle.setTextStyle(style);
710 paraStyle.setMaxLines(lineLimit);
711
712 paraStyle.setEllipsis(ellipsis);
713
Mike Reed21a940d2019-07-23 10:11:03 -0400714 ParagraphBuilderImpl builder(paraStyle, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400715
716 if (text.empty()) {
717 const std::u16string text0 = u"\u202Dabc";
718 const std::u16string text1 = u"\u202EFED";
719 const std::u16string text2 = u"\u202Dghi";
720 const std::u16string text3 = u"\u202ELKJ";
721 const std::u16string text4 = u"\u202Dmno";
722 builder.pushStyle(style0);
723 builder.addText(text0);
724 builder.pop();
725 builder.pushStyle(style1);
726 builder.addText(text1);
727 builder.pop();
728 builder.pushStyle(style0);
729 builder.addText(text2);
730 builder.pop();
731 builder.pushStyle(style1);
732 builder.addText(text3);
733 builder.pop();
734 builder.pushStyle(style0);
735 builder.addText(text4);
736 builder.pop();
737 } else {
738 // icu::UnicodeString unicode((UChar*) text.data(), SkToS32(text.size()));
739 // std::string str;
740 // unicode.toUTF8String(str);
741 // SkDebugf("Text: %s\n", str.c_str());
742 builder.addText(text + expected);
743 }
744
745 auto paragraph = builder.Build();
746 paragraph->layout(w - margin * 2);
747 paragraph->paint(canvas, margin, margin);
748 }
749
750 void onDrawContent(SkCanvas* canvas) override {
751 canvas->drawColor(SK_ColorWHITE);
752 SkScalar width = this->width();
753 SkScalar height = this->height() / 8;
754
755 const std::u16string text1 =
756 u"A \u202ENAC\u202Cner, exceedingly \u202ENAC\u202Cny,\n"
757 "One morning remarked to his granny:\n"
758 "A \u202ENAC\u202Cner \u202ENAC\u202C \u202ENAC\u202C,\n"
759 "Anything that he \u202ENAC\u202C,\n"
760 "But a \u202ENAC\u202Cner \u202ENAC\u202C't \u202ENAC\u202C a \u202ENAC\u202C, "
761 "\u202ENAC\u202C he?";
762 bidi(canvas, width, height * 3, text1, u"", 5);
763 canvas->translate(0, height * 3);
764
765 bidi(canvas, width, height, u"\u2067DETALOSI\u2069", u"");
766 canvas->translate(0, height);
767
768 bidi(canvas, width, height, u"\u202BDEDDEBME\u202C", u"");
769 canvas->translate(0, height);
770
771 bidi(canvas, width, height, u"\u202EEDIRREVO\u202C", u"");
772 canvas->translate(0, height);
773
774 bidi(canvas, width, height, u"\u200FTICILPMI\u200E", u"");
775 canvas->translate(0, height);
776
777 bidi(canvas, width, height, u"123 456 7890 \u202EZYXWV UTS RQP ONM LKJ IHG FED CBA\u202C.",
778 u"", 2);
779 canvas->translate(0, height);
780
781 // bidi(canvas, width, height, u"", u"");
782 // canvas->translate(0, height);
783 }
784
785private:
786 typedef Sample INHERITED;
787};
788
Mike Reed21a940d2019-07-23 10:11:03 -0400789class ParagraphView6 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400790protected:
Julia Lavrova5207f352019-06-21 12:22:32 -0400791 SkString name() override { return SkString("Paragraph6"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400792
793 void hangingS(SkCanvas* canvas, SkScalar w, SkScalar h, SkScalar fs = 60.0) {
794 auto ff = "HangingS";
795
796 canvas->drawColor(SK_ColorLTGRAY);
797
798 SkPaint black;
799 black.setAntiAlias(true);
800 black.setColor(SK_ColorBLACK);
801
802 SkPaint blue;
803 blue.setAntiAlias(true);
804 blue.setColor(SK_ColorBLUE);
805
806 SkPaint red;
807 red.setAntiAlias(true);
808 red.setColor(SK_ColorRED);
809
810 SkPaint green;
811 green.setAntiAlias(true);
812 green.setColor(SK_ColorGREEN);
813
814 SkPaint gray;
815 gray.setColor(SK_ColorCYAN);
816
817 SkPaint yellow;
818 yellow.setColor(SK_ColorYELLOW);
819
820 SkPaint magenta;
821 magenta.setAntiAlias(true);
822 magenta.setColor(SK_ColorMAGENTA);
823
824 SkFontStyle fontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
825 SkFontStyle::kItalic_Slant);
826
827 TextStyle style;
828 style.setFontFamilies({SkString(ff)});
829 style.setFontSize(fs);
830 style.setFontStyle(fontStyle);
831
832 TextStyle style0;
833 style0.setForegroundColor(black);
834 style0.setBackgroundColor(gray);
835 style0.setFontFamilies({SkString(ff)});
836 style0.setFontSize(fs);
837 style0.setFontStyle(fontStyle);
838
839 TextStyle style1;
840 style1.setForegroundColor(blue);
841 style1.setBackgroundColor(yellow);
842 style1.setFontFamilies({SkString(ff)});
843 style1.setFontSize(fs);
844 style1.setFontStyle(fontStyle);
845
846 TextStyle style2;
847 style2.setForegroundColor(red);
848 style2.setFontFamilies({SkString(ff)});
849 style2.setFontSize(fs);
850 style2.setFontStyle(fontStyle);
851
852 TextStyle style3;
853 style3.setForegroundColor(green);
854 style3.setFontFamilies({SkString(ff)});
855 style3.setFontSize(fs);
856 style3.setFontStyle(fontStyle);
857
858 TextStyle style4;
859 style4.setForegroundColor(magenta);
860 style4.setFontFamilies({SkString(ff)});
861 style4.setFontSize(fs);
862 style4.setFontStyle(fontStyle);
863
864 ParagraphStyle paraStyle;
865 paraStyle.setTextStyle(style);
866
867 const char* logo1 = "S";
868 const char* logo2 = "kia";
869 const char* logo3 = "Sk";
870 const char* logo4 = "ia";
871 const char* logo5 = "Ski";
872 const char* logo6 = "a";
873 {
Mike Reed21a940d2019-07-23 10:11:03 -0400874 ParagraphBuilderImpl builder(paraStyle, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400875
876 builder.pushStyle(style0);
877 builder.addText(logo1);
878 builder.pop();
879 builder.pushStyle(style1);
880 builder.addText(logo2);
881 builder.pop();
882
883 builder.addText(" ");
884
885 builder.pushStyle(style0);
886 builder.addText(logo3);
887 builder.pop();
888 builder.pushStyle(style1);
889 builder.addText(logo4);
890 builder.pop();
891
892 builder.addText(" ");
893
894 builder.pushStyle(style0);
895 builder.addText(logo5);
896 builder.pop();
897 builder.pushStyle(style1);
898 builder.addText(logo6);
899 builder.pop();
900
901 auto paragraph = builder.Build();
902 paragraph->layout(w);
903 paragraph->paint(canvas, 40, 40);
904 canvas->translate(0, h);
905 }
906
907 const char* logo11 = "S";
908 const char* logo12 = "S";
909 const char* logo13 = "S";
910 const char* logo14 = "S";
911 const char* logo15 = "S";
912 const char* logo16 = "S";
913 {
Mike Reed21a940d2019-07-23 10:11:03 -0400914 ParagraphBuilderImpl builder(paraStyle, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400915
916 builder.pushStyle(style0);
917 builder.addText(logo11);
918 builder.pop();
919 builder.pushStyle(style1);
920 builder.addText(logo12);
921 builder.pop();
922
923 builder.addText(" ");
924
925 builder.pushStyle(style0);
926 builder.addText(logo13);
927 builder.pop();
928 builder.pushStyle(style1);
929 builder.addText(logo14);
930 builder.pop();
931
932 builder.addText(" ");
933
934 builder.pushStyle(style0);
935 builder.addText(logo15);
936 builder.pop();
937 builder.pushStyle(style1);
938 builder.addText(logo16);
939 builder.pop();
940
941 auto paragraph = builder.Build();
942 paragraph->layout(w);
943 paragraph->paint(canvas, 40, h);
944 canvas->translate(0, h);
945 }
946 }
947
948 void onDrawContent(SkCanvas* canvas) override {
949 canvas->drawColor(SK_ColorWHITE);
950 SkScalar width = this->width();
951 SkScalar height = this->height() / 4;
952
953 hangingS(canvas, width, height);
954 }
955
956private:
957 typedef Sample INHERITED;
958};
959
Mike Reed21a940d2019-07-23 10:11:03 -0400960class ParagraphView7 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400961protected:
Hal Canary8a027312019-07-03 10:55:44 -0400962 SkString name() override { return SkString("Paragraph7"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400963
964 void drawText(SkCanvas* canvas, SkColor background, SkScalar letterSpace, SkScalar w,
965 SkScalar h) {
966 SkAutoCanvasRestore acr(canvas, true);
967 canvas->clipRect(SkRect::MakeWH(w, h));
968 canvas->drawColor(background);
969
970 const char* line =
971 "World domination is such an ugly phrase - I prefer to call it world optimisation";
972
973 ParagraphStyle paragraphStyle;
974 paragraphStyle.setTextAlign(TextAlign::kLeft);
975 paragraphStyle.setMaxLines(10);
976 paragraphStyle.turnHintingOff();
977 TextStyle textStyle;
978 textStyle.setFontFamilies({SkString("Roboto")});
979 textStyle.setFontSize(30);
980 textStyle.setLetterSpacing(letterSpace);
981 textStyle.setColor(SK_ColorBLACK);
982 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
983 SkFontStyle::kUpright_Slant));
984
Mike Reed21a940d2019-07-23 10:11:03 -0400985 ParagraphBuilderImpl builder(paragraphStyle, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400986 builder.pushStyle(textStyle);
987 builder.addText(line);
988 builder.pop();
989
990 auto paragraph = builder.Build();
991 paragraph->layout(w - 20);
992 paragraph->paint(canvas, 10, 10);
993 }
994
995 void onDrawContent(SkCanvas* canvas) override {
996 canvas->drawColor(SK_ColorWHITE);
997
998 auto h = this->height() / 4;
999 auto w = this->width() / 2;
1000
1001 drawText(canvas, SK_ColorGRAY, 1, w, h);
1002 canvas->translate(0, h);
1003
1004 drawText(canvas, SK_ColorLTGRAY, 2, w, h);
1005 canvas->translate(0, h);
1006
1007 drawText(canvas, SK_ColorCYAN, 3, w, h);
1008 canvas->translate(0, h);
1009
1010 drawText(canvas, SK_ColorGRAY, 4, w, h);
1011 canvas->translate(w, -3 * h);
1012
1013 drawText(canvas, SK_ColorYELLOW, 5, w, h);
1014 canvas->translate(0, h);
1015
1016 drawText(canvas, SK_ColorGREEN, 10, w, h);
1017 canvas->translate(0, h);
1018
1019 drawText(canvas, SK_ColorRED, 15, w, h);
1020 canvas->translate(0, h);
1021
1022 drawText(canvas, SK_ColorBLUE, 20, w, h);
1023 canvas->translate(0, h);
1024 }
1025
1026private:
1027 typedef Sample INHERITED;
1028};
1029
Mike Reed21a940d2019-07-23 10:11:03 -04001030class ParagraphView8 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001031protected:
Hal Canary8a027312019-07-03 10:55:44 -04001032 SkString name() override { return SkString("Paragraph7"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001033
1034 void drawText(SkCanvas* canvas, SkColor background, SkScalar wordSpace, SkScalar w,
1035 SkScalar h) {
1036 SkAutoCanvasRestore acr(canvas, true);
1037 canvas->clipRect(SkRect::MakeWH(w, h));
1038 canvas->drawColor(background);
1039
1040 const char* line =
1041 "World domination is such an ugly phrase - I prefer to call it world optimisation";
1042
1043 ParagraphStyle paragraphStyle;
1044 paragraphStyle.setTextAlign(TextAlign::kLeft);
1045 paragraphStyle.setMaxLines(10);
1046 paragraphStyle.turnHintingOff();
1047 TextStyle textStyle;
1048 textStyle.setFontFamilies({SkString("Roboto")});
1049 textStyle.setFontSize(30);
1050 textStyle.setWordSpacing(wordSpace);
1051 textStyle.setColor(SK_ColorBLACK);
1052 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1053 SkFontStyle::kUpright_Slant));
1054
Mike Reed21a940d2019-07-23 10:11:03 -04001055 ParagraphBuilderImpl builder(paragraphStyle, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001056 builder.pushStyle(textStyle);
1057 builder.addText(line);
1058 builder.pop();
1059
1060 auto paragraph = builder.Build();
1061 paragraph->layout(w - 20);
1062 paragraph->paint(canvas, 10, 10);
1063 }
1064
1065 void onDrawContent(SkCanvas* canvas) override {
1066 canvas->drawColor(SK_ColorWHITE);
1067
1068 auto h = this->height() / 4;
1069 auto w = this->width() / 2;
1070
1071 drawText(canvas, SK_ColorGRAY, 1, w, h);
1072 canvas->translate(0, h);
1073
1074 drawText(canvas, SK_ColorLTGRAY, 2, w, h);
1075 canvas->translate(0, h);
1076
1077 drawText(canvas, SK_ColorCYAN, 3, w, h);
1078 canvas->translate(0, h);
1079
1080 drawText(canvas, SK_ColorGRAY, 4, w, h);
1081 canvas->translate(w, -3 * h);
1082
1083 drawText(canvas, SK_ColorYELLOW, 5, w, h);
1084 canvas->translate(0, h);
1085
1086 drawText(canvas, SK_ColorGREEN, 10, w, h);
1087 canvas->translate(0, h);
1088
1089 drawText(canvas, SK_ColorRED, 15, w, h);
1090 canvas->translate(0, h);
1091
1092 drawText(canvas, SK_ColorBLUE, 20, w, h);
1093 canvas->translate(0, h);
1094 }
1095
1096private:
1097 typedef Sample INHERITED;
1098};
1099
Mike Reed21a940d2019-07-23 10:11:03 -04001100class ParagraphView9 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001101protected:
Hal Canary8a027312019-07-03 10:55:44 -04001102 SkString name() override { return SkString("Paragraph9"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001103
Hal Canary6cc65e12019-07-03 15:53:04 -04001104 bool onChar(SkUnichar uni) override {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001105 switch (uni) {
1106 case 'w':
1107 ++wordSpacing;
1108 return true;
1109 case 'q':
1110 if (wordSpacing > 0) --wordSpacing;
1111 return true;
1112 case 'l':
1113 ++letterSpacing;
1114 return true;
1115 case 'k':
1116 if (letterSpacing > 0) --letterSpacing;
1117 return true;
1118 default:
1119 break;
1120 }
Hal Canary6cc65e12019-07-03 15:53:04 -04001121 return false;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001122 }
1123
1124 void drawText(SkCanvas* canvas, SkColor background, SkScalar w, SkScalar h) {
1125 SkAutoCanvasRestore acr(canvas, true);
1126 canvas->clipRect(SkRect::MakeWH(w, h));
1127 canvas->drawColor(background);
1128
1129 const char* text =
1130 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1131 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
1132 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
1133
1134 ParagraphStyle paragraphStyle;
1135 paragraphStyle.setTextAlign(TextAlign::kLeft);
1136 paragraphStyle.setMaxLines(10);
1137 paragraphStyle.turnHintingOff();
1138 TextStyle textStyle;
1139 textStyle.setFontFamilies({SkString("Roboto")});
1140 textStyle.setFontSize(50);
1141 textStyle.setHeight(1.3f);
1142 textStyle.setColor(SK_ColorBLACK);
1143 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1144 SkFontStyle::kUpright_Slant));
1145
Mike Reed21a940d2019-07-23 10:11:03 -04001146 ParagraphBuilderImpl builder(paragraphStyle, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001147 builder.pushStyle(textStyle);
1148 builder.addText(text);
1149 builder.pop();
1150
1151 auto paragraph = builder.Build();
1152 paragraph->layout(550);
1153
1154 std::vector<size_t> sizes = {0, 1, 2, 8, 19, 21, 22, 30, 150};
1155
1156 std::vector<size_t> colors = {SK_ColorBLUE, SK_ColorCYAN, SK_ColorLTGRAY, SK_ColorGREEN,
1157 SK_ColorRED, SK_ColorWHITE, SK_ColorYELLOW, SK_ColorMAGENTA};
1158
1159 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
1160 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1161
1162 for (size_t i = 0; i < sizes.size() - 1; ++i) {
1163 size_t from = (i == 0 ? 0 : 1) + sizes[i];
1164 size_t to = sizes[i + 1];
1165 auto boxes = paragraph->getRectsForRange(from, to, rect_height_style, rect_width_style);
1166 if (boxes.empty()) {
1167 continue;
1168 }
1169 for (auto& box : boxes) {
1170 SkPaint paint;
1171 paint.setColor(colors[i % colors.size()]);
1172 paint.setShader(setgrad(box.rect, colors[i % colors.size()], SK_ColorWHITE));
1173 canvas->drawRect(box.rect, paint);
1174 }
1175 }
1176
1177 paragraph->paint(canvas, 0, 0);
1178 }
1179
1180 void onDrawContent(SkCanvas* canvas) override {
1181 canvas->drawColor(SK_ColorWHITE);
1182
1183 auto h = this->height();
1184 auto w = this->width();
1185
1186 drawText(canvas, SK_ColorGRAY, w, h);
1187 }
1188
1189private:
1190 typedef Sample INHERITED;
1191 SkScalar letterSpacing;
1192 SkScalar wordSpacing;
1193};
1194
Mike Reed21a940d2019-07-23 10:11:03 -04001195class ParagraphView10 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001196protected:
Hal Canary8a027312019-07-03 10:55:44 -04001197 SkString name() override { return SkString("Paragraph10"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001198
1199 void onDrawContent(SkCanvas* canvas) override {
1200 canvas->drawColor(SK_ColorWHITE);
1201
1202 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
1203 ParagraphStyle paragraph_style;
1204 paragraph_style.turnHintingOff();
Mike Reed21a940d2019-07-23 10:11:03 -04001205 ParagraphBuilderImpl builder(paragraph_style, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001206
1207 TextStyle text_style;
Julia Lavrova5207f352019-06-21 12:22:32 -04001208 text_style.setFontFamilies({SkString("Roboto"),
1209 SkString("Noto Color Emoji"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001210 SkString("Source Han Serif CN")});
1211 text_style.setColor(SK_ColorRED);
1212 text_style.setFontSize(60);
1213 text_style.setLetterSpacing(0);
1214 text_style.setWordSpacing(0);
1215 text_style.setColor(SK_ColorBLACK);
1216 text_style.setHeight(1);
1217 builder.pushStyle(text_style);
1218 builder.addText(text);
1219 builder.pop();
1220
1221 auto paragraph = builder.Build();
1222 paragraph->layout(width());
1223
1224 paragraph->paint(canvas, 0, 0);
1225 SkDEBUGCODE(auto impl = reinterpret_cast<ParagraphImpl*>(paragraph.get()));
1226 SkASSERT(impl->runs().size() == 3);
Julia Lavrova5207f352019-06-21 12:22:32 -04001227 SkASSERT(impl->runs()[0].textRange().end == impl->runs()[1].textRange().start);
1228 SkASSERT(impl->runs()[1].textRange().end == impl->runs()[2].textRange().start);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001229 }
1230
1231private:
1232 typedef Sample INHERITED;
1233};
1234
Mike Reed21a940d2019-07-23 10:11:03 -04001235class ParagraphView11 : public ParagraphView_Base {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001236protected:
Hal Canary8a027312019-07-03 10:55:44 -04001237 SkString name() override { return SkString("Paragraph11"); }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001238
1239 void onDrawContent(SkCanvas* canvas) override {
1240 canvas->drawColor(SK_ColorWHITE);
Julia Lavrova5207f352019-06-21 12:22:32 -04001241 const char* text = "The same text many times";
1242
1243 for (size_t i = 0; i < 10; i++) {
1244 ParagraphStyle paragraph_style;
Mike Reed21a940d2019-07-23 10:11:03 -04001245 ParagraphBuilderImpl builder(paragraph_style, fFC);
Julia Lavrova5207f352019-06-21 12:22:32 -04001246 TextStyle text_style;
1247 text_style.setFontFamilies({SkString("Roboto")});
1248 text_style.setColor(SK_ColorBLACK);
1249 text_style.setFontSize(10 + 2 * (i % 10));
1250 builder.pushStyle(text_style);
1251 builder.addText(text);
1252 builder.pop();
1253 auto paragraph = builder.Build();
1254 paragraph->layout(500);
Mike Reed21a940d2019-07-23 10:11:03 -04001255 paragraph->paint(canvas, 0, 40 * (i % 10));
Julia Lavrova5207f352019-06-21 12:22:32 -04001256 }
1257 }
1258
1259private:
1260 typedef Sample INHERITED;
1261};
1262
1263// Measure different stages of layout/paint
Mike Reed21a940d2019-07-23 10:11:03 -04001264class ParagraphView12 : public ParagraphView_Base {
Julia Lavrova5207f352019-06-21 12:22:32 -04001265protected:
1266 SkString name() override { return SkString("Paragraph12"); }
1267
1268 void onDrawContent(SkCanvas* canvas) override {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001269 ParagraphStyle paragraph_style;
Julia Lavrova5207f352019-06-21 12:22:32 -04001270 paragraph_style.setMaxLines(14);
1271 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001272 paragraph_style.turnHintingOff();
Mike Reed21a940d2019-07-23 10:11:03 -04001273 ParagraphBuilderImpl builder(paragraph_style, fFC);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001274
1275 TextStyle text_style;
Julia Lavrova5207f352019-06-21 12:22:32 -04001276 text_style.setFontFamilies({SkString("Roboto")});
1277 text_style.setFontSize(26);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001278 text_style.setColor(SK_ColorBLACK);
Julia Lavrova5207f352019-06-21 12:22:32 -04001279 text_style.setHeight(1);
1280 text_style.setDecoration(TextDecoration::kUnderline);
1281 text_style.setDecorationColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001282 builder.pushStyle(text_style);
Julia Lavrova5207f352019-06-21 12:22:32 -04001283 builder.addText(gText);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001284 builder.pop();
1285
1286 auto paragraph = builder.Build();
Julia Lavrova5207f352019-06-21 12:22:32 -04001287 auto impl = reinterpret_cast<ParagraphImpl*>(paragraph.get());
1288 impl->turnOnCache(false);
Julia Lavrova9af5cc42019-06-19 13:32:01 -04001289
Julia Lavrova5207f352019-06-21 12:22:32 -04001290 for (auto i = 0; i < 1000; ++i) {
1291 impl->setState(kUnknown);
1292 impl->shapeTextIntoEndlessLine();
1293 impl->setState(kShaped);
1294 }
1295
1296 for (auto i = 0; i < 1000; ++i) {
1297 impl->setState(kShaped);
1298 impl->buildClusterTable();
1299 impl->markLineBreaks();
1300 impl->setState(kMarked);
1301 }
1302
1303 for (auto i = 0; i < 1000; ++i) {
1304 impl->setState(kMarked);
1305 impl->breakShapedTextIntoLines(1000);
1306 impl->setState(kLineBroken);
1307 }
1308
1309 for (auto i = 0; i < 1000; ++i) {
1310 impl->setState(kLineBroken);
1311 impl->formatLines(1000);
1312 impl->setState(kFormatted);
1313 }
1314
1315 for (auto i = 0; i < 1000; ++i) {
1316 impl->setState(kFormatted);
1317 impl->paintLinesIntoPicture();
1318 impl->setState(kDrawn);
1319 }
1320
1321 auto picture = impl->getPicture();
1322 SkMatrix matrix = SkMatrix::MakeTrans(0, 0);
1323 for (auto i = 0; i < 1000; ++i) {
1324 canvas->drawPicture(picture, &matrix, nullptr);
1325 }
Julia Lavrova35f88222019-06-21 12:22:32 -04001326
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001327 }
1328
1329private:
1330 typedef Sample INHERITED;
1331};
1332//////////////////////////////////////////////////////////////////////////////
1333
1334DEF_SAMPLE(return new ParagraphView1();)
1335DEF_SAMPLE(return new ParagraphView2();)
1336DEF_SAMPLE(return new ParagraphView3();)
1337DEF_SAMPLE(return new ParagraphView4();)
1338DEF_SAMPLE(return new ParagraphView5();)
1339DEF_SAMPLE(return new ParagraphView6();)
1340DEF_SAMPLE(return new ParagraphView7();)
1341DEF_SAMPLE(return new ParagraphView8();)
1342DEF_SAMPLE(return new ParagraphView9();)
1343DEF_SAMPLE(return new ParagraphView10();)
1344DEF_SAMPLE(return new ParagraphView11();)
Julia Lavrova5207f352019-06-21 12:22:32 -04001345DEF_SAMPLE(return new ParagraphView12();)