blob: 5cee73cbc94e092dd9e7224f7494c6e491e3510e [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002#include "src/utils/SkOSPath.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003#include <sstream>
Julia Lavrova6e6333f2019-06-17 10:34:10 -04004#include "modules/skparagraph/include/TypefaceFontProvider.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04005#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
6#include "modules/skparagraph/src/ParagraphImpl.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04007#include "src/core/SkOSFile.h"
8#include "src/utils/SkShaperJSONWriter.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -04009#include "tests/CodecPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040010#include "tests/Test.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040011#include "tools/Resources.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040012#include "tools/ToolUtils.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040013
14#define VeryLongCanvasWidth 1000000
15#define TestCanvasWidth 1000
16#define TestCanvasHeight 600
17
18using namespace skia::textlayout;
19namespace {
20
Julia Lavrovadb9f6692019-08-01 16:02:17 -040021SkScalar EPSILON100 = 0.01f;
22SkScalar EPSILON50 = 0.02f;
23SkScalar EPSILON20 = 0.05f;
Julia Lavrova916a9042019-08-08 16:51:27 -040024SkScalar EPSILON10 = 0.1f;
Julia Lavrovac2228562019-08-08 16:51:27 -040025SkScalar EPSILON5 = 0.20f;
26SkScalar EPSILON2 = 0.50f;
Julia Lavrovadb9f6692019-08-01 16:02:17 -040027
Julia Lavrova5207f352019-06-21 12:22:32 -040028bool equal(const char* base, TextRange a, const char* b) {
29 return std::strncmp(b, base + a.start, a.width()) == 0;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040030}
31class TestFontCollection : public FontCollection {
32public:
33 TestFontCollection()
34 : fFontsFound(false)
35 , fResolvedFonts(0)
36 , fResourceDir(GetResourcePath("fonts").c_str())
37 , fFontProvider(sk_make_sp<TypefaceFontProvider>()) {
38 std::vector<SkString> fonts;
39 SkOSFile::Iter iter(fResourceDir.c_str());
40 SkString path;
41 while (iter.next(&path)) {
42 if (path.endsWith("Roboto-Italic.ttf")) {
43 fFontsFound = true;
44 }
45 fonts.emplace_back(path);
46 }
47
48 if (!fFontsFound) {
49 return;
50 }
51 // Only register fonts if we have to
52 for (auto& font : fonts) {
53 SkString file_path;
54 file_path.printf("%s/%s", fResourceDir.c_str(), font.c_str());
55 fFontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
56 }
57
58 this->setTestFontManager(std::move(fFontProvider));
59 this->disableFontFallback();
60
61 if (!fFontsFound) SkDebugf("Fonts not found, skipping all the tests\n");
62 }
63
64 ~TestFontCollection() = default;
65
66 size_t resolvedFonts() const { return fResolvedFonts; }
67
68 // TODO: temp solution until we check in fonts
69 bool fontsFound() const { return fFontsFound; }
70
71private:
72 bool fFontsFound;
73 size_t fResolvedFonts;
74 std::string fResourceDir;
75 sk_sp<TypefaceFontProvider> fFontProvider;
76};
Julia Lavrovadb9f6692019-08-01 16:02:17 -040077
78class TestCanvas {
79public:
80 TestCanvas(const char* testName) : name(testName) {
81 bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight);
82 canvas = new SkCanvas(bits);
83 canvas->clear(SK_ColorWHITE);
84 }
85
86 ~TestCanvas() {
Julia Lavrovaaae845f2019-08-16 16:44:40 -040087 SkString tmpDir = skiatest::GetTmpDir();
88 if (!tmpDir.isEmpty()) {
89 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
90 SkFILEWStream file(path.c_str());
91 if (!SkEncodeImage(&file, bits, SkEncodedImageFormat::kPNG, 100)) {
92 SkDebugf("Cannot write a picture %s\n", name);
93 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -040094 }
95 delete canvas;
96 }
97
98 void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) {
99
100 SkPaint paint;
101 if (!fill) {
102 paint.setStyle(SkPaint::kStroke_Style);
103 paint.setAntiAlias(true);
104 paint.setStrokeWidth(1);
105 }
106 paint.setColor(color);
107 for (auto& r : result) {
108 canvas->drawRect(r.rect, paint);
109 }
110 }
111
112 void drawLine(SkColor color, SkRect rect, bool vertical = true) {
113
114 SkPaint paint;
115 paint.setStyle(SkPaint::kStroke_Style);
116 paint.setAntiAlias(true);
117 paint.setStrokeWidth(1);
118 paint.setColor(color);
119 if (vertical) {
120 canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
121 } else {
122 canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint);
123 }
124 }
125
126 void drawLines(SkColor color, std::vector<TextBox>& result) {
127
128 for (auto& r : result) {
129 drawLine(color, r.rect);
130 }
131 }
132
133 SkCanvas* get() { return canvas; }
134private:
135 SkBitmap bits;
136 SkCanvas* canvas;
137 const char* name;
138};
139
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400140} // namespace
141
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400142// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400143DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
144 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
145 if (!fontCollection->fontsFound()) return;
146 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400147 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400148
149 ParagraphStyle paragraph_style;
150 paragraph_style.turnHintingOff();
151 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
152
153 TextStyle text_style;
154 text_style.setFontFamilies({SkString("Roboto")});
155 text_style.setColor(SK_ColorBLACK);
156 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400157 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400158 builder.pop();
159
160 auto paragraph = builder.Build();
161 paragraph->layout(TestCanvasWidth);
162
163 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
164 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
165 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400166 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400167
168 size_t index = 0;
169 for (auto& line : impl->lines()) {
170 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400171 [&index, reporter]
172 (TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400173 REPORTER_ASSERT(reporter, index == 0);
174 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorBLACK);
175 ++index;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400176 });
177 }
178}
179
Julia Lavrova526df262019-08-21 17:49:44 -0400180// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrova916a9042019-08-08 16:51:27 -0400181DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
182 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
183 TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png");
184 if (!fontCollection->fontsFound()) return;
185
186 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400187 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400188
189 ParagraphStyle paragraph_style;
190 paragraph_style.turnHintingOff();
191 paragraph_style.setMaxLines(14);
192 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
193
194 TextStyle text_style;
195 text_style.setFontFamilies({SkString("Roboto")});
196 text_style.setColor(SK_ColorBLACK);
197 text_style.setFontSize(26);
198 text_style.setWordSpacing(5);
199 text_style.setLetterSpacing(1);
200 text_style.setDecoration(TextDecoration::kUnderline);
201 text_style.setDecorationColor(SK_ColorBLACK);
202 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400203 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400204
205 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
206 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400207 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400208 builder.addPlaceholder(placeholder1);
209
210 PlaceholderStyle placeholder2(5, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
211 builder.addPlaceholder(placeholder2);
212 builder.addPlaceholder(placeholder1);
213 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400214 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400215 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400216 builder.addText(text, len);
217 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400218 builder.addPlaceholder(placeholder2);
219 builder.addPlaceholder(placeholder2);
220 builder.addPlaceholder(placeholder2);
221 builder.addPlaceholder(placeholder2);
222 builder.addPlaceholder(placeholder2);
223 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400224 builder.addText(text, len);
225 builder.addText(text, len);
226 builder.addText(text, len);
227 builder.addText(text, len);
228 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400229 builder.addPlaceholder(placeholder2);
230 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400231 builder.addText(text, len);
232 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400233
234 builder.pop();
235
236 auto paragraph = builder.Build();
237 paragraph->layout(TestCanvasWidth);
238 paragraph->paint(canvas.get(), 0, 0);
239
240 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
241 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
242
243 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
244 canvas.drawRects(SK_ColorRED, boxes);
245 REPORTER_ASSERT(reporter, boxes.size() == 1);
246
247 boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
248 canvas.drawRects(SK_ColorGREEN, boxes);
249 REPORTER_ASSERT(reporter, boxes.size() == 1);
250
251 boxes = paragraph->GetRectsForPlaceholders();
252 canvas.drawRects(SK_ColorRED, boxes);
253
254 boxes = paragraph->getRectsForRange(4, 17, rect_height_style, rect_width_style);
255 canvas.drawRects(SK_ColorBLUE, boxes);
256
257 REPORTER_ASSERT(reporter, boxes.size() == 7);
258
259 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 90.921f - 0.5f, EPSILON2));
260 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 50, EPSILON100));
261 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 90.921f + 50 - 0.5f, EPSILON2));
262 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 100, EPSILON100));
263
264 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.left(), 231.343f - 0.5f, EPSILON2));
265 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.top(), 50, EPSILON100));
266 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.right(), 231.343f + 50 - 0.5f, EPSILON2));
267 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.bottom(), 100, EPSILON100));
268
269 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.left(), 281.343f - 0.5f, EPSILON2));
270 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.top(), 0, EPSILON100));
271 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.right(), 281.343f + 5 - 0.5f, EPSILON2));
272 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.bottom(), 50, EPSILON100));
273
274 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.left(), 336.343f - 0.5f, EPSILON2));
275 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.top(), 0, EPSILON100));
276 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.right(), 336.343f + 5 - 0.5f, EPSILON2));
277 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100));
278}
279
Julia Lavrova526df262019-08-21 17:49:44 -0400280// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400281DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
Julia Lavrova916a9042019-08-08 16:51:27 -0400282 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
283 TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png");
284 if (!fontCollection->fontsFound()) return;
285
286 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400287 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400288
289 ParagraphStyle paragraph_style;
290 paragraph_style.turnHintingOff();
291 paragraph_style.setMaxLines(14);
292 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
293
294 TextStyle text_style;
295 text_style.setFontFamilies({SkString("Roboto")});
296 text_style.setColor(SK_ColorBLACK);
297 text_style.setFontSize(26);
298 text_style.setWordSpacing(5);
299 text_style.setLetterSpacing(1);
300 text_style.setDecoration(TextDecoration::kUnderline);
301 text_style.setDecorationColor(SK_ColorBLACK);
302 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400303 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400304
305 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 38.347f);
306 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400307 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400308
309 builder.pop();
310
311 auto paragraph = builder.Build();
312 paragraph->layout(TestCanvasWidth);
313 paragraph->paint(canvas.get(), 0, 0);
314
315 auto boxes = paragraph->GetRectsForPlaceholders();
316 canvas.drawRects(SK_ColorRED, boxes);
317
318 REPORTER_ASSERT(reporter, boxes.size() == 1);
319 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f - 0.5f, EPSILON2));
320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55 - 0.5f, EPSILON2));
322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
323
324 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
325 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
326
327 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
328 canvas.drawRects(SK_ColorBLUE, boxes);
329
330 REPORTER_ASSERT(reporter, boxes.size() == 1);
331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f - 0.5f, EPSILON2));
332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 14.226f, EPSILON100));
333 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f - 0.5f, EPSILON2));
334 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400335}
Julia Lavrova916a9042019-08-08 16:51:27 -0400336
Julia Lavrova526df262019-08-21 17:49:44 -0400337// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrova916a9042019-08-08 16:51:27 -0400338DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
339 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
340 TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png");
341 if (!fontCollection->fontsFound()) return;
342
343 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400344 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400345
346 ParagraphStyle paragraph_style;
347 paragraph_style.turnHintingOff();
348 paragraph_style.setMaxLines(14);
349 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
350
351 TextStyle text_style;
352 text_style.setFontFamilies({SkString("Roboto")});
353 text_style.setColor(SK_ColorBLACK);
354 text_style.setFontSize(26);
355 text_style.setWordSpacing(5);
356 text_style.setLetterSpacing(1);
357 text_style.setDecoration(TextDecoration::kUnderline);
358 text_style.setDecorationColor(SK_ColorBLACK);
359 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400360 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400361
362 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kAboveBaseline, TextBaseline::kAlphabetic, 903129.129308f);
363 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400364 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400365
366 builder.pop();
367
368 auto paragraph = builder.Build();
369 paragraph->layout(TestCanvasWidth);
370 paragraph->paint(canvas.get(), 0, 0);
371
372 auto boxes = paragraph->GetRectsForPlaceholders();
373 canvas.drawRects(SK_ColorRED, boxes);
374
375 REPORTER_ASSERT(reporter, boxes.size() == 1);
376 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f - 0.5f, EPSILON2));
377 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.347f, EPSILON100));
378 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55 - 0.5f, EPSILON2));
379 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 49.652f, EPSILON100));
380
381 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
382 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
383
384 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
385 canvas.drawRects(SK_ColorBLUE, boxes);
386
387 REPORTER_ASSERT(reporter, boxes.size() == 1);
388 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f - 0.5f, EPSILON2));
389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 25.531f, EPSILON100));
390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f - 0.5f, EPSILON2));
391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400392}
Julia Lavrova916a9042019-08-08 16:51:27 -0400393
Julia Lavrova526df262019-08-21 17:49:44 -0400394// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400395DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
Julia Lavrova916a9042019-08-08 16:51:27 -0400396 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
397 TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png");
398 if (!fontCollection->fontsFound()) return;
399
400 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400401 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400402
403 ParagraphStyle paragraph_style;
404 paragraph_style.turnHintingOff();
405 paragraph_style.setMaxLines(14);
406 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
407
408 TextStyle text_style;
409 text_style.setFontFamilies({SkString("Roboto")});
410 text_style.setColor(SK_ColorBLACK);
411 text_style.setFontSize(26);
412 text_style.setWordSpacing(5);
413 text_style.setLetterSpacing(1);
414 text_style.setDecoration(TextDecoration::kUnderline);
415 text_style.setDecorationColor(SK_ColorBLACK);
416 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400417 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400418
419 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBelowBaseline, TextBaseline::kAlphabetic, 903129.129308f);
420 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400421 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400422
423 builder.pop();
424
425 auto paragraph = builder.Build();
426 paragraph->layout(TestCanvasWidth);
427 paragraph->paint(canvas.get(), 0, 0);
428
429 auto boxes = paragraph->GetRectsForPlaceholders();
430 canvas.drawRects(SK_ColorRED, boxes);
431
432 REPORTER_ASSERT(reporter, boxes.size() == 1);
433 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f - 0.5f, EPSILON2));
434 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
435 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55 - 0.5f, EPSILON2));
436 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
437
438 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
439 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
440
441 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
442 canvas.drawRects(SK_ColorBLUE, boxes);
443
444 REPORTER_ASSERT(reporter, boxes.size() == 1);
445 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f - 0.5f, EPSILON2));
446 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.121f, EPSILON100));
447 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f - 0.5f, EPSILON2));
448 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400449}
Julia Lavrova916a9042019-08-08 16:51:27 -0400450
Julia Lavrova526df262019-08-21 17:49:44 -0400451// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400452DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
Julia Lavrova916a9042019-08-08 16:51:27 -0400453 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
454 TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png");
455 if (!fontCollection->fontsFound()) return;
456
457 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400458 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400459
460 ParagraphStyle paragraph_style;
461 paragraph_style.turnHintingOff();
462 paragraph_style.setMaxLines(14);
463 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
464
465 TextStyle text_style;
466 text_style.setFontFamilies({SkString("Roboto")});
467 text_style.setColor(SK_ColorBLACK);
468 text_style.setFontSize(26);
469 text_style.setWordSpacing(5);
470 text_style.setLetterSpacing(1);
471 text_style.setDecoration(TextDecoration::kUnderline);
472 text_style.setDecorationColor(SK_ColorBLACK);
473 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400474 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400475
476 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBottom, TextBaseline::kAlphabetic, 0);
477 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400478 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400479
480 builder.pop();
481
482 auto paragraph = builder.Build();
483 paragraph->layout(TestCanvasWidth);
484 paragraph->paint(canvas.get(), 0, 0);
485
486 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
487 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
488
489 auto boxes = paragraph->GetRectsForPlaceholders();
490 canvas.drawRects(SK_ColorRED, boxes);
491 REPORTER_ASSERT(reporter, boxes.size() == 1);
492 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f - 0.5f, EPSILON50));
493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55 - 0.5f, EPSILON50));
495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
496
497 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
498 canvas.drawRects(SK_ColorBLUE, boxes);
499 REPORTER_ASSERT(reporter, boxes.size() == 1);
500 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f - 0.5f, EPSILON50));
501 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 19.531f, EPSILON100));
502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f - 0.5f, EPSILON50));
503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400504}
Julia Lavrova916a9042019-08-08 16:51:27 -0400505
Julia Lavrova526df262019-08-21 17:49:44 -0400506// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400507DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
Julia Lavrova916a9042019-08-08 16:51:27 -0400508 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
509 TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png");
510 if (!fontCollection->fontsFound()) return;
511
512 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400513 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400514
515 ParagraphStyle paragraph_style;
516 paragraph_style.turnHintingOff();
517 paragraph_style.setMaxLines(14);
518 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
519
520 TextStyle text_style;
521 text_style.setFontFamilies({SkString("Roboto")});
522 text_style.setColor(SK_ColorBLACK);
523 text_style.setFontSize(26);
524 text_style.setWordSpacing(5);
525 text_style.setLetterSpacing(1);
526 text_style.setDecoration(TextDecoration::kUnderline);
527 text_style.setDecorationColor(SK_ColorBLACK);
528 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400529 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400530
531 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kTop, TextBaseline::kAlphabetic, 0);
532 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400533 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400534
535 builder.pop();
536
537 auto paragraph = builder.Build();
538 paragraph->layout(TestCanvasWidth);
539 paragraph->paint(canvas.get(), 0, 0);
540
541 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
542 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
543
544 auto boxes = paragraph->GetRectsForPlaceholders();
545 canvas.drawRects(SK_ColorRED, boxes);
546 REPORTER_ASSERT(reporter, boxes.size() == 1);
547 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f - 0.5f, EPSILON50));
548 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
549 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55 - 0.5f, EPSILON50));
550 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
551
552 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
553 canvas.drawRects(SK_ColorBLUE, boxes);
554 REPORTER_ASSERT(reporter, boxes.size() == 1);
555 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f - 0.5f, EPSILON50));
556 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
557 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f - 0.5f, EPSILON50));
558 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400559}
Julia Lavrova916a9042019-08-08 16:51:27 -0400560
Julia Lavrova526df262019-08-21 17:49:44 -0400561// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400562DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
Julia Lavrova916a9042019-08-08 16:51:27 -0400563 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
564 TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png");
565 if (!fontCollection->fontsFound()) return;
566
567 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400568 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400569
570 ParagraphStyle paragraph_style;
571 paragraph_style.turnHintingOff();
572 paragraph_style.setMaxLines(14);
573 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
574
575 TextStyle text_style;
576 text_style.setFontFamilies({SkString("Roboto")});
577 text_style.setColor(SK_ColorBLACK);
578 text_style.setFontSize(26);
579 text_style.setWordSpacing(5);
580 text_style.setLetterSpacing(1);
581 text_style.setDecoration(TextDecoration::kUnderline);
582 text_style.setDecorationColor(SK_ColorBLACK);
583 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400584 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400585
586 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kMiddle, TextBaseline::kAlphabetic, 0);
587 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400588 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400589
590 builder.pop();
591
592 auto paragraph = builder.Build();
593 paragraph->layout(TestCanvasWidth);
594 paragraph->paint(canvas.get(), 0, 0);
595
596 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
597 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
598
599 auto boxes = paragraph->GetRectsForPlaceholders();
600 canvas.drawRects(SK_ColorRED, boxes);
601 REPORTER_ASSERT(reporter, boxes.size() == 1);
602 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f - 0.5f, EPSILON50));
603 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
604 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55 - 0.5f, EPSILON50));
605 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
606
607 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
608 canvas.drawRects(SK_ColorBLUE, boxes);
609 REPORTER_ASSERT(reporter, boxes.size() == 1);
610 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f - 0.5f, EPSILON50));
611 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 9.765f, EPSILON100));
612 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f - 0.5f, EPSILON50));
613 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400614}
Julia Lavrova916a9042019-08-08 16:51:27 -0400615
Julia Lavrova526df262019-08-21 17:49:44 -0400616// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrova916a9042019-08-08 16:51:27 -0400617DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
618 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
619 TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png");
620 if (!fontCollection->fontsFound()) return;
621
622 const char* text = "給能上目秘使";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400623 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400624
625 ParagraphStyle paragraph_style;
626 paragraph_style.turnHintingOff();
627 paragraph_style.setMaxLines(14);
628 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
629
630 TextStyle text_style;
631 text_style.setFontFamilies({SkString("Source Han Serif CN")});
632 text_style.setColor(SK_ColorBLACK);
633 text_style.setFontSize(26);
634 text_style.setWordSpacing(5);
635 text_style.setLetterSpacing(1);
636 text_style.setDecoration(TextDecoration::kUnderline);
637 text_style.setDecorationColor(SK_ColorBLACK);
638 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400639 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400640 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kIdeographic, 38.347f);
641 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400642 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400643
644 builder.pop();
645
646 auto paragraph = builder.Build();
647 paragraph->layout(TestCanvasWidth);
648 paragraph->paint(canvas.get(), 0, 0);
649
650 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
651 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
652
653 auto boxes = paragraph->GetRectsForPlaceholders();
654 canvas.drawRects(SK_ColorRED, boxes);
655 REPORTER_ASSERT(reporter, boxes.size() == 1);
656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 162.5f - 0.5f, EPSILON50));
657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f + 55 - 0.5f, EPSILON50));
659 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
660
661 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
662 canvas.drawRects(SK_ColorBLUE, boxes);
663 REPORTER_ASSERT(reporter, boxes.size() == 1);
664 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 135.5f - 0.5f, EPSILON50));
665 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 4.703f, EPSILON100));
666 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f - 0.5f, EPSILON50));
667 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400668}
Julia Lavrova916a9042019-08-08 16:51:27 -0400669
Julia Lavrova526df262019-08-21 17:49:44 -0400670// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400671DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
Julia Lavrova916a9042019-08-08 16:51:27 -0400672 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
673 TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png");
674 if (!fontCollection->fontsFound()) return;
675
676 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400677 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400678
679 ParagraphStyle paragraph_style;
680 paragraph_style.turnHintingOff();
681 paragraph_style.setMaxLines(14);
682 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
683
684 TextStyle text_style;
685 text_style.setFontFamilies({SkString("Roboto")});
686 text_style.setColor(SK_ColorBLACK);
687 text_style.setFontSize(26);
688 text_style.setWordSpacing(5);
689 text_style.setLetterSpacing(1);
690 text_style.setDecoration(TextDecoration::kUnderline);
691 text_style.setDecorationColor(SK_ColorBLACK);
692 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400693 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400694
695 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
696 PlaceholderStyle placeholder2(25, 25, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 12.5f);
697
698 builder.addPlaceholder(placeholder1);
699 builder.addPlaceholder(placeholder1);
700 builder.addPlaceholder(placeholder1);
701 builder.addPlaceholder(placeholder2);
702 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400703 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400704
705 builder.addPlaceholder(placeholder1);
706 builder.addPlaceholder(placeholder1);
707 builder.addPlaceholder(placeholder1);
708 builder.addPlaceholder(placeholder1);
709 builder.addPlaceholder(placeholder2); // 4 + 1
710 builder.addPlaceholder(placeholder1);
711 builder.addPlaceholder(placeholder1);
712 builder.addPlaceholder(placeholder1);
713 builder.addPlaceholder(placeholder1);
714 builder.addPlaceholder(placeholder1);
715 builder.addPlaceholder(placeholder1);
716 builder.addPlaceholder(placeholder2); // 6 + 1
717 builder.addPlaceholder(placeholder1);
718 builder.addPlaceholder(placeholder1);
719 builder.addPlaceholder(placeholder1);
720 builder.addPlaceholder(placeholder1);
721 builder.addPlaceholder(placeholder1);
722 builder.addPlaceholder(placeholder1);
723 builder.addPlaceholder(placeholder1);
724 builder.addPlaceholder(placeholder2); // 7 + 1
725
726 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400727 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400728 builder.addPlaceholder(placeholder1);
729 builder.addPlaceholder(placeholder2);
730
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400731 builder.addText(text, len);
732 builder.addText(text, len);
733 builder.addText(text, len);
734 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400735
736 builder.addPlaceholder(placeholder2);
737 builder.addPlaceholder(placeholder1);
738
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400739 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400740
741 builder.addPlaceholder(placeholder2);
742
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400743 builder.addText(text, len);
744 builder.addText(text, len);
745 builder.addText(text, len);
746 builder.addText(text, len);
747 builder.addText(text, len);
748 builder.addText(text, len);
749 builder.addText(text, len);
750 builder.addText(text, len);
751 builder.addText(text, len);
752 builder.addText(text, len);
753 builder.addText(text, len);
754 builder.addText(text, len);
755 builder.addText(text, len);
756 builder.addText(text, len);
757 builder.addText(text, len);
758 builder.addText(text, len);
759 builder.addText(text, len);
760 builder.addText(text, len);
761 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400762
763 builder.pop();
764
765 auto paragraph = builder.Build();
766 paragraph->layout(TestCanvasWidth - 100);
767 paragraph->paint(canvas.get(), 0, 0);
768
769 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
770 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
771
772 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
773 canvas.drawRects(SK_ColorRED, boxes);
774 REPORTER_ASSERT(reporter, boxes.size() == 1);
775
776 boxes = paragraph->getRectsForRange(175, 176, rect_height_style, rect_width_style);
777 canvas.drawRects(SK_ColorGREEN, boxes);
778 REPORTER_ASSERT(reporter, boxes.size() == 1);
779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 31.695f - 0.5f, EPSILON50));
780 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 218.531f, EPSILON100));
781 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 47.292f - 0.5f, EPSILON50));
782 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 249, EPSILON100));
783
784 boxes = paragraph->GetRectsForPlaceholders();
785 canvas.drawRects(SK_ColorRED, boxes);
786
787 boxes = paragraph->getRectsForRange(4, 45, rect_height_style, rect_width_style);
788 canvas.drawRects(SK_ColorBLUE, boxes);
789 REPORTER_ASSERT(reporter, boxes.size() == 30);
790 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 59.726f - 0.5f, EPSILON50));
791 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.378f, EPSILON100));
792 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f - 0.5f, EPSILON50));
793 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56.847f, EPSILON100));
794
795 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.left(), 606.343f - 0.5f, EPSILON20));
796 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.top(), 38, EPSILON100));
797 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.right(), 631.343f - 0.5f, EPSILON20));
798 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.bottom(), 63, EPSILON100));
799
800 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.left(), 0.5f - 0.5f, EPSILON50));
801 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.top(), 63.5f, EPSILON100));
802 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.right(), 50.5f - 0.5f, EPSILON50));
803 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400804}
Julia Lavrova916a9042019-08-08 16:51:27 -0400805
Julia Lavrova526df262019-08-21 17:49:44 -0400806// Checked: DIFF+ (half of the letter spacing before the text???)
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400807DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
Julia Lavrova916a9042019-08-08 16:51:27 -0400808 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
809 TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png");
810 if (!fontCollection->fontsFound()) return;
811
812 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400813 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400814
815 ParagraphStyle paragraph_style;
816 paragraph_style.turnHintingOff();
817 paragraph_style.setMaxLines(14);
818 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
819
820 TextStyle text_style;
821 text_style.setFontFamilies({SkString("Roboto")});
822 text_style.setColor(SK_ColorBLACK);
823 text_style.setFontSize(26);
824 text_style.setWordSpacing(5);
825 text_style.setLetterSpacing(1);
826 text_style.setDecoration(TextDecoration::kUnderline);
827 text_style.setDecorationColor(SK_ColorBLACK);
828 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400829 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400830
831 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
832 PlaceholderStyle placeholder2(5, 20, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 10);
833
834 builder.addPlaceholder(placeholder1);
835 builder.addPlaceholder(placeholder1);
836 builder.addPlaceholder(placeholder1);
837 builder.addPlaceholder(placeholder1);
838 builder.addPlaceholder(placeholder1);
839 builder.addPlaceholder(placeholder1);
840 builder.addPlaceholder(placeholder1);
841 builder.addPlaceholder(placeholder1);
842 builder.addPlaceholder(placeholder2); // 8 + 1
843 builder.addPlaceholder(placeholder1);
844 builder.addPlaceholder(placeholder1);
845 builder.addPlaceholder(placeholder1);
846 builder.addPlaceholder(placeholder1);
847 builder.addPlaceholder(placeholder1);
848 builder.addPlaceholder(placeholder2); // 5 + 1
849 builder.addPlaceholder(placeholder1);
850 builder.addPlaceholder(placeholder1);
851 builder.addPlaceholder(placeholder1);
852 builder.addPlaceholder(placeholder1);
853 builder.addPlaceholder(placeholder1);
854 builder.addPlaceholder(placeholder1);
855 builder.addPlaceholder(placeholder1);
856 builder.addPlaceholder(placeholder1); // 8 + 0
857
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400858 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400859
860 builder.addPlaceholder(placeholder1);
861 builder.addPlaceholder(placeholder2);
862 builder.addPlaceholder(placeholder2); // 1 + 2
863 builder.addPlaceholder(placeholder1);
864 builder.addPlaceholder(placeholder2);
865 builder.addPlaceholder(placeholder2); // 1 + 2
866
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400867 builder.addText(text, len);
868 builder.addText(text, len);
869 builder.addText(text, len);
870 builder.addText(text, len);
871 builder.addText(text, len);
872 builder.addText(text, len);
873 builder.addText(text, len);
874 builder.addText(text, len);
875 builder.addText(text, len);
876 builder.addText(text, len);
877 builder.addText(text, len); // 11
Julia Lavrova916a9042019-08-08 16:51:27 -0400878
879 builder.addPlaceholder(placeholder2);
880 builder.addPlaceholder(placeholder1);
881 builder.addPlaceholder(placeholder2);
882 builder.addPlaceholder(placeholder1);
883 builder.addPlaceholder(placeholder2);
884
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400885 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400886
887 builder.pop();
888
889 auto paragraph = builder.Build();
890 paragraph->layout(TestCanvasWidth);
891 paragraph->paint(canvas.get(), 0, 0);
892
893 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
894 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
895
896 auto boxes = paragraph->GetRectsForPlaceholders();
897 canvas.drawRects(SK_ColorRED, boxes);
898
899 REPORTER_ASSERT(reporter, boxes.size() == 34);
900 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f - 0.5f, EPSILON50));
901 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
902 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 140.921f - 0.5f, EPSILON50));
903 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
904
905 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.left(), 800.921f - 0.5f, EPSILON20));
906 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.top(), 0, EPSILON100));
907 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.right(), 850.921f - 0.5f, EPSILON20));
908 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.bottom(), 50, EPSILON100));
909
910 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.left(), 503.382f - 0.5f, EPSILON10));
911 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.top(), 160, EPSILON100));
912 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.right(), 508.382f - 0.5f, EPSILON10));
913 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.bottom(), 180, EPSILON100));
914
915 boxes = paragraph->getRectsForRange(30, 50, rect_height_style, rect_width_style);
916 canvas.drawRects(SK_ColorBLUE, boxes);
917
918 REPORTER_ASSERT(reporter, boxes.size() == 8);
919 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 216.097f - 0.5f, EPSILON50));
920 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 60, EPSILON100));
921 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 290.921f - 0.5f, EPSILON50));
922 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 120, EPSILON100));
923
924 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 290.921f - 0.5f, EPSILON20));
925 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 60, EPSILON100));
926 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 340.921f - 0.5f, EPSILON20));
927 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 120, EPSILON100));
928
929 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.left(), 340.921f - 0.5f, EPSILON50));
930 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top(), 60, EPSILON100));
931 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.right(), 345.921f - 0.5f, EPSILON50));
932 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400933}
934
935// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400936DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
937 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
938 if (!fontCollection->fontsFound()) return;
939 const char* text = "I am RED";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400940 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400941
942 ParagraphStyle paragraph_style;
943 paragraph_style.turnHintingOff();
944 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
945
946 TextStyle text_style;
947 text_style.setFontFamilies({SkString("Roboto")});
948 text_style.setColor(SK_ColorRED);
949 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400950 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400951 builder.pop();
952
953 auto paragraph = builder.Build();
954 paragraph->layout(TestCanvasWidth);
955
956 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
957 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
958 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400959 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400960
961 size_t index = 0;
962 for (auto& line : impl->lines()) {
963 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400964 [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
965 REPORTER_ASSERT(reporter, index == 0);
966 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED);
967 ++index;
968 return true;
969 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400970 }
971}
972
Julia Lavrovac2228562019-08-08 16:51:27 -0400973// Checked: DIFF+ (Space between 1 & 2 style blocks)
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400974DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
975 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400976 TestCanvas canvas("SkParagraph_RainbowParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400977 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400978 const char* text1 = "Red Roboto"; // [0:10)
979 const char* text2 = "big Greeen Default"; // [10:28)
980 const char* text3 = "Defcolor Homemade Apple"; // [28:51)
981 const char* text4 = "Small Blue Roboto"; // [51:68)
Julia Lavrovac2228562019-08-08 16:51:27 -0400982 const char* text41 = "Small Blue ";
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400983 const char* text5 =
984 "Continue Last Style With lots of words to check if it overlaps "
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400985 "properly or not"; // [68:)
986 const char* text42 =
987 "Roboto"
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400988 "Continue Last Style With lots of words to check if it overlaps "
989 "properly or not";
990
991 ParagraphStyle paragraph_style;
992 paragraph_style.turnHintingOff();
993 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400994 paragraph_style.setMaxLines(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400995 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
996
997 TextStyle text_style1;
998 text_style1.setFontFamilies({SkString("Roboto")});
999
1000 text_style1.setColor(SK_ColorRED);
1001 builder.pushStyle(text_style1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001002 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001003
1004 TextStyle text_style2;
1005 text_style2.setFontFamilies({SkString("Roboto")});
1006 text_style2.setFontSize(50);
1007 text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1008 SkFontStyle::kUpright_Slant));
1009 text_style2.setLetterSpacing(10);
1010 text_style2.setDecorationColor(SK_ColorBLACK);
1011 text_style2.setDecoration((TextDecoration)(
1012 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1013 text_style2.setWordSpacing(30);
1014 text_style2.setColor(SK_ColorGREEN);
1015 builder.pushStyle(text_style2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001016 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001017
1018 TextStyle text_style3;
1019 text_style3.setFontFamilies({SkString("Homemade Apple")});
Julia Lavrova526df262019-08-21 17:49:44 -04001020 text_style3.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001021 builder.pushStyle(text_style3);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001022 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001023
1024 TextStyle text_style4;
1025 text_style4.setFontFamilies({SkString("Roboto")});
1026 text_style4.setFontSize(14);
1027 text_style4.setDecorationColor(SK_ColorBLACK);
1028 text_style4.setDecoration((TextDecoration)(
1029 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1030 text_style4.setColor(SK_ColorBLUE);
1031 builder.pushStyle(text_style4);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001032 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001033
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001034 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001035 builder.pop();
1036
1037 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001038 paragraph->layout(1000);
1039 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001040
1041 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1042 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
1043 REPORTER_ASSERT(reporter, impl->styles().size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001044 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1045
1046 auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight);
1047 canvas.drawRects(SK_ColorMAGENTA, rects);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001048
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001049 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001050 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001051 StyleType::kAllAttributes,
1052 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001053 switch (index) {
1054 case 0:
1055 REPORTER_ASSERT(reporter, style.equals(text_style1));
Julia Lavrova526df262019-08-21 17:49:44 -04001056 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001057 break;
1058 case 1:
1059 REPORTER_ASSERT(reporter, style.equals(text_style2));
Julia Lavrova526df262019-08-21 17:49:44 -04001060 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001061 break;
1062 case 2:
1063 REPORTER_ASSERT(reporter, style.equals(text_style3));
Julia Lavrova526df262019-08-21 17:49:44 -04001064 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001065 break;
1066 case 3:
1067 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001068 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001069 break;
1070 default:
1071 REPORTER_ASSERT(reporter, false);
1072 break;
1073 }
1074 ++index;
1075 return true;
1076 });
1077 impl->lines()[1].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001078 StyleType::kAllAttributes,
1079 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001080 switch (index) {
1081 case 4:
1082 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001083 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001084 break;
1085 default:
1086 REPORTER_ASSERT(reporter, false);
1087 break;
1088 }
1089 ++index;
1090 return true;
1091 });
1092 REPORTER_ASSERT(reporter, index == 5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001093}
1094
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001095// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001096DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
1097 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1098 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001099 TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001100 const char* text = "No TextStyle! Uh Oh!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001101 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001102
1103 ParagraphStyle paragraph_style;
1104 TextStyle defaultStyle;
1105 defaultStyle.setFontFamilies({SkString("Roboto")});
1106 paragraph_style.setTextStyle(defaultStyle);
1107 paragraph_style.turnHintingOff();
1108 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001109 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001110
1111 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001112 paragraph->layout(TestCanvasWidth);
1113 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001114
1115 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1116
1117 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1118 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1119 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1120
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001121 size_t index = 0;
1122 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001123 StyleType::kAllAttributes,
1124 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001125 REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle()));
Julia Lavrova526df262019-08-21 17:49:44 -04001126 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001127 ++index;
1128 return true;
1129 });
1130 REPORTER_ASSERT(reporter, index == 1);
1131}
1132
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001133// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001134DEF_TEST(SkParagraph_BoldParagraph, reporter) {
1135 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1136 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001137 TestCanvas canvas("SkParagraph_BoldParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001138 const char* text = "This is Red max bold text!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001139 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001140
1141 ParagraphStyle paragraph_style;
1142 paragraph_style.turnHintingOff();
1143 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1144
1145 TextStyle text_style;
1146 text_style.setFontFamilies({SkString("Roboto")});
1147 text_style.setColor(SK_ColorRED);
1148 text_style.setFontSize(60);
1149 text_style.setLetterSpacing(0);
1150 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width,
1151 SkFontStyle::kUpright_Slant));
1152 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001153 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001154 builder.pop();
1155
1156 auto paragraph = builder.Build();
1157 paragraph->layout(VeryLongCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001158 paragraph->paint(canvas.get(), 10.0, 60.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001159
1160 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1161
1162 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1163 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1164 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1165
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001166 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001167 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001168 StyleType::kAllAttributes,
1169 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001170 REPORTER_ASSERT(reporter, style.equals(text_style));
Julia Lavrova526df262019-08-21 17:49:44 -04001171 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001172 ++index;
1173 return true;
1174 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001175 REPORTER_ASSERT(reporter, index == 1);
1176}
1177
Julia Lavrovac2228562019-08-08 16:51:27 -04001178// Checked: NO DIFF (line height rounding error)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001179DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
Julia Lavrovac2228562019-08-08 16:51:27 -04001180 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1181 if (!fontCollection->fontsFound()) return;
1182 TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png");
1183 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001184 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001185
Julia Lavrovac2228562019-08-08 16:51:27 -04001186 ParagraphStyle paragraph_style;
1187 paragraph_style.turnHintingOff();
1188 paragraph_style.setMaxLines(10);
1189 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001190
Julia Lavrovac2228562019-08-08 16:51:27 -04001191 TextStyle text_style;
1192 text_style.setFontFamilies({SkString("Roboto")});
1193 text_style.setFontSize(20);
1194 text_style.setColor(SK_ColorBLACK);
1195 text_style.setHeight(3.6345f);
1196 text_style.setHeightOverride(true);
1197 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001198 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04001199 builder.pop();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001200
Julia Lavrovac2228562019-08-08 16:51:27 -04001201 auto paragraph = builder.Build();
1202 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001203
Julia Lavrovac2228562019-08-08 16:51:27 -04001204 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1205 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1206 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
1207 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001208
Julia Lavrovac2228562019-08-08 16:51:27 -04001209 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001210
Julia Lavrovac2228562019-08-08 16:51:27 -04001211 SkPaint paint;
1212 paint.setStyle(SkPaint::kStroke_Style);
1213 paint.setAntiAlias(true);
1214 paint.setStrokeWidth(1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001215
Julia Lavrovac2228562019-08-08 16:51:27 -04001216 // Tests for GetRectsForRange()
1217 RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle;
1218 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1219 paint.setColor(SK_ColorRED);
1220 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
1221 canvas.drawRects(SK_ColorRED, boxes);
1222 REPORTER_ASSERT(reporter, boxes.size() == 0ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001223
Julia Lavrovac2228562019-08-08 16:51:27 -04001224 boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style);
1225 canvas.drawRects(SK_ColorBLUE, boxes);
1226 REPORTER_ASSERT(reporter, boxes.size() == 3ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001227
Julia Lavrovac2228562019-08-08 16:51:27 -04001228 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100));
1229 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5));
1230 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100));
1231 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001232}
1233
Julia Lavrovac2228562019-08-08 16:51:27 -04001234// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001235DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
1236 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1237 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001238 TestCanvas canvas("SkParagraph_LeftAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001239 const char* text =
1240 "This is a very long sentence to test if the text will properly wrap "
1241 "around and go to the next line. Sometimes, short sentence. Longer "
1242 "sentences are okay too because they are nessecary. Very short. "
1243 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1244 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1245 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1246 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1247 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1248 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1249 "mollit anim id est laborum. "
1250 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1251 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1252 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1253 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1254 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1255 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1256 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001257 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001258
1259 ParagraphStyle paragraph_style;
1260 paragraph_style.setMaxLines(14);
1261 paragraph_style.setTextAlign(TextAlign::kLeft);
1262 paragraph_style.turnHintingOff();
1263 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1264
1265 TextStyle text_style;
1266 text_style.setFontFamilies({SkString("Roboto")});
1267 text_style.setFontSize(26);
1268 text_style.setLetterSpacing(1);
1269 text_style.setWordSpacing(5);
1270 text_style.setColor(SK_ColorBLACK);
1271 text_style.setHeight(1);
1272 text_style.setDecoration(TextDecoration::kUnderline);
1273 text_style.setDecorationColor(SK_ColorBLACK);
1274 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001275 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001276 builder.pop();
1277
1278 auto paragraph = builder.Build();
1279 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001280 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001281
1282 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001283
1284 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1285 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1286 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001287 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001288 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1289
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001290 double expected_y = 0;
1291 double epsilon = 0.01f;
1292 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1293 REPORTER_ASSERT(reporter,
1294 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1295 expected_y += 30;
1296 REPORTER_ASSERT(reporter,
1297 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1298 expected_y += 30;
1299 REPORTER_ASSERT(reporter,
1300 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1301 expected_y += 30;
1302 REPORTER_ASSERT(reporter,
1303 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1304 expected_y += 30 * 10;
1305 REPORTER_ASSERT(reporter,
1306 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1307
1308 REPORTER_ASSERT(reporter,
1309 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1310
1311 // Tests for GetGlyphPositionAtCoordinate()
1312 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0);
1313 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
1314 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
1315 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
1316 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);
1317}
1318
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001319// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001320DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
1321 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1322 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001323 TestCanvas canvas("SkParagraph_RightAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001324 const char* text =
1325 "This is a very long sentence to test if the text will properly wrap "
1326 "around and go to the next line. Sometimes, short sentence. Longer "
1327 "sentences are okay too because they are nessecary. Very short. "
1328 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1329 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1330 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1331 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1332 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1333 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1334 "mollit anim id est laborum. "
1335 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1336 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1337 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1338 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1339 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1340 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1341 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001342 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001343
1344 ParagraphStyle paragraph_style;
1345 paragraph_style.setMaxLines(14);
1346 paragraph_style.setTextAlign(TextAlign::kRight);
1347 paragraph_style.turnHintingOff();
1348 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1349
1350 TextStyle text_style;
1351 text_style.setFontFamilies({SkString("Roboto")});
1352 text_style.setFontSize(26);
1353 text_style.setLetterSpacing(1);
1354 text_style.setWordSpacing(5);
1355 text_style.setColor(SK_ColorBLACK);
1356 text_style.setHeight(1);
1357 text_style.setDecoration(TextDecoration::kUnderline);
1358 text_style.setDecorationColor(SK_ColorBLACK);
1359 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001360 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001361 builder.pop();
1362
1363 auto paragraph = builder.Build();
1364 paragraph->layout(TestCanvasWidth - 100);
1365
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001366 paragraph->paint(canvas.get(), 0, 0);
1367
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001368 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001369
1370 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1371 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001372 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001373 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1374
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001375 double expected_y = 0;
1376 double epsilon = 0.01f;
1377 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1378 REPORTER_ASSERT(reporter,
1379 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1380 expected_y += 30;
1381 REPORTER_ASSERT(reporter,
1382 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1383 expected_y += 30;
1384 REPORTER_ASSERT(reporter,
1385 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1386 expected_y += 30;
1387 REPORTER_ASSERT(reporter,
1388 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1389 expected_y += 30 * 10;
1390 REPORTER_ASSERT(reporter,
1391 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1392
1393 auto calculate = [](const TextLine& line) -> SkScalar {
1394 return TestCanvasWidth - 100 - line.offset().fX - line.width();
1395 };
1396
1397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1401 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1402
1403 REPORTER_ASSERT(reporter,
1404 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1405}
1406
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001407// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001408DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
1409 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1410 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001411 TestCanvas canvas("SkParagraph_CenterAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001412 const char* text =
1413 "This is a very long sentence to test if the text will properly wrap "
1414 "around and go to the next line. Sometimes, short sentence. Longer "
1415 "sentences are okay too because they are nessecary. Very short. "
1416 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1417 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1418 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1419 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1420 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1421 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1422 "mollit anim id est laborum. "
1423 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1424 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1425 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1426 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1427 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1428 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1429 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001430 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001431
1432 ParagraphStyle paragraph_style;
1433 paragraph_style.setMaxLines(14);
1434 paragraph_style.setTextAlign(TextAlign::kCenter);
1435 paragraph_style.turnHintingOff();
1436 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1437
1438 TextStyle text_style;
1439 text_style.setFontFamilies({SkString("Roboto")});
1440 text_style.setFontSize(26);
1441 text_style.setLetterSpacing(1);
1442 text_style.setWordSpacing(5);
1443 text_style.setColor(SK_ColorBLACK);
1444 text_style.setHeight(1);
1445 text_style.setDecoration(TextDecoration::kUnderline);
1446 text_style.setDecorationColor(SK_ColorBLACK);
1447 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001448 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001449 builder.pop();
1450
1451 auto paragraph = builder.Build();
1452 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001453 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001454
1455 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001456
1457 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1458 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1459 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001460 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001461 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1462
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001463 double expected_y = 0;
1464 double epsilon = 0.01f;
1465 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1466 REPORTER_ASSERT(reporter,
1467 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1468 expected_y += 30;
1469 REPORTER_ASSERT(reporter,
1470 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1471 expected_y += 30;
1472 REPORTER_ASSERT(reporter,
1473 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1474 expected_y += 30;
1475 REPORTER_ASSERT(reporter,
1476 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1477 expected_y += 30 * 10;
1478 REPORTER_ASSERT(reporter,
1479 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1480
1481 auto calculate = [](const TextLine& line) -> SkScalar {
1482 return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width());
1483 };
1484
1485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1486 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1487 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1488 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1489 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1490
1491 REPORTER_ASSERT(reporter,
1492 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1493}
1494
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001495// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001496DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
1497 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1498 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001499 TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001500 const char* text =
1501 "This is a very long sentence to test if the text will properly wrap "
1502 "around and go to the next line. Sometimes, short sentence. Longer "
1503 "sentences are okay too because they are nessecary. Very short. "
1504 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1505 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1506 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1507 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1508 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1509 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1510 "mollit anim id est laborum. "
1511 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1512 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1513 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1514 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1515 "velit esse cillum dolore eu fugiat.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001516 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001517
1518 ParagraphStyle paragraph_style;
1519 paragraph_style.setMaxLines(14);
1520 paragraph_style.setTextAlign(TextAlign::kJustify);
1521 paragraph_style.turnHintingOff();
1522 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1523
1524 TextStyle text_style;
1525 text_style.setFontFamilies({SkString("Roboto")});
1526 text_style.setFontSize(26);
1527 text_style.setLetterSpacing(0);
1528 text_style.setWordSpacing(5);
1529 text_style.setColor(SK_ColorBLACK);
1530 text_style.setHeight(1);
1531 text_style.setDecoration(TextDecoration::kUnderline);
1532 text_style.setDecorationColor(SK_ColorBLACK);
1533 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001534 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001535 builder.pop();
1536
1537 auto paragraph = builder.Build();
1538 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001539 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001540
Julia Lavrovac2228562019-08-08 16:51:27 -04001541 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1542 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1543 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1544 canvas.drawRects(SK_ColorRED, boxes);
1545
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001546 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001547
1548 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1549 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1550 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001551 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001552
1553 double expected_y = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001554 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001555 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001556 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001557 expected_y += 30;
1558 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001559 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001560 expected_y += 30;
1561 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001562 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001563 expected_y += 30;
1564 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001565 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001566 expected_y += 30 * 9;
1567 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001568 SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001569
1570 auto calculate = [](const TextLine& line) -> SkScalar {
1571 return TestCanvasWidth - 100 - (line.offset().fX + line.width());
1572 };
1573
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001574 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100));
1575 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100));
1576 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100));
1577 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100));
1578 REPORTER_ASSERT(reporter, calculate(impl->lines()[13]) > 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001579
1580 REPORTER_ASSERT(reporter,
1581 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1582}
1583
Julia Lavrovac2228562019-08-08 16:51:27 -04001584// Checked: DIFF (ghost spaces as a separate box in TxtLib)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001585DEF_TEST(SkParagraph_JustifyRTL, reporter) {
1586 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1587 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001588 TestCanvas canvas("SkParagraph_JustifyRTL.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001589 const char* text =
1590 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1591 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1592 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001593 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001594
1595 ParagraphStyle paragraph_style;
1596 paragraph_style.setMaxLines(14);
1597 paragraph_style.setTextAlign(TextAlign::kJustify);
1598 paragraph_style.turnHintingOff();
1599 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1600
1601 TextStyle text_style;
1602 text_style.setFontFamilies({SkString("Ahem")});
1603 text_style.setFontSize(26);
1604 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001605 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001606 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001607 builder.pop();
1608
1609 auto paragraph = builder.Build();
1610 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001611 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001612
1613 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001614
1615 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001616 return TestCanvasWidth - 100 - line.width();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001617 };
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001618 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001619 if (&line == &impl->lines().back()) {
1620 REPORTER_ASSERT(reporter, calculate(line) > EPSILON100);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001621 } else {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001622 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001623 }
1624 }
1625
1626 // Just make sure the the text is actually RTL
1627 for (auto& run : impl->runs()) {
1628 REPORTER_ASSERT(reporter, !run.leftToRight());
1629 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001630
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001631 // Tests for GetRectsForRange()
1632 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1633 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1634 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1635 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04001636 REPORTER_ASSERT(reporter, boxes.size() == 3); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001637
1638 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1639 canvas.drawRects(SK_ColorBLUE, boxes);
1640 REPORTER_ASSERT(reporter, boxes.size() == 1);
1641
1642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100));
1643 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1644 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100));
1645 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1646}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001647
1648// Checked: NO DIFF (some minor decoration differences, probably)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001649DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
1650 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1651 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001652 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001653 const char* text1 = "This text should be";
1654 const char* text2 = " decorated even when";
1655 const char* text3 = " wrapped around to";
1656 const char* text4 = " the next line.";
1657 const char* text5 = " Otherwise, bad things happen.";
1658
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001659 ParagraphStyle paragraph_style;
1660 paragraph_style.setMaxLines(14);
1661 paragraph_style.setTextAlign(TextAlign::kLeft);
1662 paragraph_style.turnHintingOff();
1663 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1664
1665 TextStyle text_style;
1666 text_style.setFontFamilies({SkString("Roboto")});
1667 text_style.setFontSize(26);
1668 text_style.setLetterSpacing(0);
1669 text_style.setWordSpacing(5);
1670 text_style.setColor(SK_ColorBLACK);
1671 text_style.setHeight(2);
1672 text_style.setDecoration(TextDecoration::kUnderline);
1673 text_style.setDecorationColor(SK_ColorBLACK);
1674 text_style.setDecoration((TextDecoration)(
1675 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1676 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1677 text_style.setDecorationColor(SK_ColorBLACK);
1678 text_style.setDecorationThicknessMultiplier(2.0);
1679 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001680 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001681
1682 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1683 text_style.setDecorationColor(SK_ColorBLUE);
1684 text_style.setDecorationThicknessMultiplier(1.0);
1685 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001686 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001687
1688 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1689 text_style.setDecorationColor(SK_ColorBLACK);
1690 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001691 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001692
1693 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1694 text_style.setDecorationColor(SK_ColorBLACK);
1695 text_style.setDecorationThicknessMultiplier(3.0);
1696 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001697 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001698
1699 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1700 text_style.setDecorationColor(SK_ColorRED);
1701 text_style.setDecorationThicknessMultiplier(1.0);
1702 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001703 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001704 builder.pop();
1705
1706 auto paragraph = builder.Build();
1707 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001708 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001709
1710 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001711
1712 size_t index = 0;
1713 for (auto& line : impl->lines()) {
1714 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001715 StyleType::kDecorations,
1716 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001717 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1718 TextDecoration::kOverline |
1719 TextDecoration::kLineThrough);
1720 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1721 switch (index) {
1722 case 0:
1723 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1724 TextDecorationStyle::kSolid);
1725 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1726 REPORTER_ASSERT(reporter,
1727 style.getDecorationThicknessMultiplier() == 2.0);
1728 break;
1729 case 1: // The style appears on 2 lines so it has 2 pieces
1730 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1731 TextDecorationStyle::kDouble);
1732 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1733 REPORTER_ASSERT(reporter,
1734 style.getDecorationThicknessMultiplier() == 1.0);
1735 break;
1736 case 2:
1737 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1738 TextDecorationStyle::kDotted);
1739 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1740 REPORTER_ASSERT(reporter,
1741 style.getDecorationThicknessMultiplier() == 1.0);
1742 break;
1743 case 3:
1744 case 4:
1745 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1746 TextDecorationStyle::kDashed);
1747 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1748 REPORTER_ASSERT(reporter,
1749 style.getDecorationThicknessMultiplier() == 3.0);
1750 break;
1751 case 5:
1752 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1753 TextDecorationStyle::kWavy);
1754 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1755 REPORTER_ASSERT(reporter,
1756 style.getDecorationThicknessMultiplier() == 1.0);
1757 break;
1758 default:
1759 REPORTER_ASSERT(reporter, false);
1760 break;
1761 }
1762 ++index;
1763 return true;
1764 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001765 }
1766}
1767
Julia Lavrovac2228562019-08-08 16:51:27 -04001768DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova916a9042019-08-08 16:51:27 -04001769 SkDebugf("TODO: Fix decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001770}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001771
1772// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001773DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
1774 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1775 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001776 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001777 const char* text1 = "No italic ";
1778 const char* text2 = "Yes Italic ";
1779 const char* text3 = "No Italic again.";
1780
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001781 ParagraphStyle paragraph_style;
1782 paragraph_style.turnHintingOff();
1783 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1784
1785 TextStyle text_style;
1786 text_style.setFontFamilies({SkString("Roboto")});
1787 text_style.setFontSize(10);
1788 text_style.setColor(SK_ColorRED);
1789 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001790 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001791
1792 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1793 SkFontStyle::kItalic_Slant));
1794 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001795 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001796 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001797 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001798
1799 auto paragraph = builder.Build();
1800 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001801 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001802
1803 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001804
1805 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1806 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1807 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1808 auto& line = impl->lines()[0];
1809 size_t index = 0;
1810 line.scanStyles(
1811 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001812 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001813 switch (index) {
1814 case 0:
1815 REPORTER_ASSERT(
1816 reporter,
1817 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1818 break;
1819 case 1:
1820 REPORTER_ASSERT(reporter,
1821 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1822 break;
1823 case 2:
1824 REPORTER_ASSERT(
1825 reporter,
1826 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1827 break;
1828 default:
1829 REPORTER_ASSERT(reporter, false);
1830 break;
1831 }
1832 ++index;
1833 return true;
1834 });
1835}
1836
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001837// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001838DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
1839 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1840 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001841 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001842 const char* text =
1843 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1844 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1845 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1846 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1847 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001848 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001849
1850 ParagraphStyle paragraph_style;
1851 paragraph_style.setMaxLines(14);
1852 paragraph_style.setTextAlign(TextAlign::kJustify);
1853 paragraph_style.turnHintingOff();
1854 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1855
1856 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
1857 TextDecoration::kLineThrough);
1858
1859 TextStyle text_style;
1860 text_style.setFontFamilies({SkString("Source Han Serif CN")});
1861 text_style.setFontSize(35);
1862 text_style.setColor(SK_ColorBLACK);
1863 text_style.setLetterSpacing(2);
1864 text_style.setHeight(1);
1865 text_style.setDecoration(decoration);
1866 text_style.setDecorationColor(SK_ColorBLACK);
1867 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1868 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001869 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001870 builder.pop();
1871
1872 auto paragraph = builder.Build();
1873 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001874 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001875
1876 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001877
1878 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1879 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
1880 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001881 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001882}
1883
Julia Lavrovac2228562019-08-08 16:51:27 -04001884// Checked: NO DIFF (disabled)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001885DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
1886 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1887 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001888 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001889 const char* text =
1890 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
1891 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001892 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001893
1894 ParagraphStyle paragraph_style;
1895 paragraph_style.setMaxLines(14);
1896 paragraph_style.setTextAlign(TextAlign::kJustify);
1897 paragraph_style.turnHintingOff();
1898 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1899
1900 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
1901 TextDecoration::kLineThrough);
1902
1903 TextStyle text_style;
1904 text_style.setFontFamilies({SkString("Katibeh")});
1905 text_style.setFontSize(35);
1906 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001907 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001908 text_style.setDecoration(decoration);
1909 text_style.setDecorationColor(SK_ColorBLACK);
1910 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1911 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001912 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001913 builder.pop();
1914
1915 auto paragraph = builder.Build();
1916 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001917 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001918
1919 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001920
1921 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1922 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1923 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001924 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001925}
1926
Julia Lavrovac2228562019-08-08 16:51:27 -04001927// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001928DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
1929
1930 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1931 if (!fontCollection->fontsFound()) return;
1932 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
1933 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001934 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001935
1936 ParagraphStyle paragraph_style;
1937 paragraph_style.turnHintingOff();
1938 paragraph_style.setMaxLines(14);
1939 paragraph_style.setTextAlign(TextAlign::kRight);
1940 paragraph_style.setTextDirection(TextDirection::kRtl);
1941 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1942
1943 TextStyle text_style;
1944 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
1945 text_style.setFontSize(26);
1946 text_style.setWordSpacing(5);
1947 text_style.setColor(SK_ColorBLACK);
1948 text_style.setDecoration(TextDecoration::kUnderline);
1949 text_style.setDecorationColor(SK_ColorBLACK);
1950 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001951 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001952 builder.pop();
1953
1954 auto paragraph = builder.Build();
1955 paragraph->layout(TestCanvasWidth - 100);
1956
1957 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1958 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1959
1960 paragraph->paint(canvas.get(), 0, 0);
1961
1962 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1963 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1964 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1965 canvas.drawRects(SK_ColorRED, boxes);
1966
Julia Lavrovac2228562019-08-08 16:51:27 -04001967 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001968
Julia Lavrovac2228562019-08-08 16:51:27 -04001969 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
1970 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001971 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1972 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001973}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001974
1975// Checked DIFF+
1976DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
1977
1978 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
1979 if (!fontCollection->fontsFound()) return;
1980 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
1981 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001982 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001983
1984 ParagraphStyle paragraph_style;
1985 paragraph_style.turnHintingOff();
1986 paragraph_style.setMaxLines(14);
1987 paragraph_style.setTextAlign(TextAlign::kLeft);
1988 paragraph_style.setTextDirection(TextDirection::kLtr);
1989 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1990
1991 TextStyle text_style;
1992 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
1993 text_style.setFontSize(26);
1994 text_style.setWordSpacing(5);
1995 text_style.setColor(SK_ColorBLACK);
1996 text_style.setDecoration(TextDecoration::kUnderline);
1997 text_style.setDecorationColor(SK_ColorBLACK);
1998 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001999 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002000 builder.pop();
2001
2002 auto paragraph = builder.Build();
2003 paragraph->layout(TestCanvasWidth - 100);
2004
2005 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2006 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2007
2008 paragraph->paint(canvas.get(), 0, 0);
2009
2010 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2011 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2012 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2013 canvas.drawRects(SK_ColorRED, boxes);
2014
Julia Lavrova526df262019-08-21 17:49:44 -04002015 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovac2228562019-08-08 16:51:27 -04002016 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.916f, EPSILON100)); // DIFF: 89.40625
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002017 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrova526df262019-08-21 17:49:44 -04002018 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 115.893f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002019 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002020}
2021
2022// Checked DIFF+
2023DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2024
2025 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2026 if (!fontCollection->fontsFound()) return;
2027 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2028 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002029 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002030
2031 ParagraphStyle paragraph_style;
2032 paragraph_style.turnHintingOff();
2033 paragraph_style.setMaxLines(14);
2034 paragraph_style.setTextAlign(TextAlign::kRight);
2035 paragraph_style.setTextDirection(TextDirection::kLtr);
2036 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2037
2038 TextStyle text_style;
2039 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2040 text_style.setFontSize(26);
2041 text_style.setWordSpacing(5);
2042 text_style.setColor(SK_ColorBLACK);
2043 text_style.setDecoration(TextDecoration::kUnderline);
2044 text_style.setDecorationColor(SK_ColorBLACK);
2045 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002046 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002047 builder.pop();
2048
2049 auto paragraph = builder.Build();
2050 paragraph->layout(TestCanvasWidth - 100);
2051
2052 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2053 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2054
2055 paragraph->paint(canvas.get(), 0, 0);
2056
2057 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2058 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2059 std::vector<TextBox> boxes =
2060 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2061 canvas.drawRects(SK_ColorRED, boxes);
2062
Julia Lavrova526df262019-08-21 17:49:44 -04002063 REPORTER_ASSERT(reporter, boxes.size() == 1ull); // DIFF
Julia Lavrovac2228562019-08-08 16:51:27 -04002064 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.501f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002065 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrova526df262019-08-21 17:49:44 -04002066 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 593.479f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002067 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002068}
2069
2070// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002071DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
2072 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2073 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002074 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002075 const char* text =
2076 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2077 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002078 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002079
2080 ParagraphStyle paragraphStyle;
2081 paragraphStyle.setTextAlign(TextAlign::kLeft);
2082 paragraphStyle.setMaxLines(10);
2083 paragraphStyle.turnHintingOff();
2084 TextStyle textStyle;
2085 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002086 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2087 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002088 textStyle.setFontSize(50);
2089 textStyle.setLetterSpacing(1);
2090 textStyle.setWordSpacing(5);
2091 textStyle.setHeight(1);
2092 textStyle.setColor(SK_ColorBLACK);
2093
2094 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2095 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002096 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002097 builder.pop();
2098
2099 auto paragraph = builder.Build();
2100 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002101 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002102
2103 // Tests for getGlyphPositionAtCoordinate()
2104 // NOTE: resulting values can be a few off from their respective positions in
2105 // the original text because the final trailing whitespaces are sometimes not
2106 // drawn (namely, when using "justify" alignment) and therefore are not active
2107 // glyphs.
2108 REPORTER_ASSERT(reporter,
2109 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2110 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2111 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2112 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2113 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2114 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002115 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002116 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2117 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2118 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002119 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002120 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002121 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002122 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2123 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002124 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002125 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2126 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002127 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002128 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2129 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2130 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
2131 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);
2132 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2133}
2134
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002135// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002136DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
2137 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2138 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002139 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002140 const char* text =
2141 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2142 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002143 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002144
2145 ParagraphStyle paragraphStyle;
2146 paragraphStyle.setTextAlign(TextAlign::kLeft);
2147 paragraphStyle.setMaxLines(10);
2148 paragraphStyle.turnHintingOff();
2149 TextStyle textStyle;
2150 textStyle.setFontFamilies({SkString("Roboto")});
2151 textStyle.setFontSize(50);
2152 textStyle.setColor(SK_ColorBLACK);
2153 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2154 SkFontStyle::kUpright_Slant));
2155
2156 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2157 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002158 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002159 builder.pop();
2160
2161 auto paragraph = builder.Build();
2162 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002163 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002164
2165 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2166 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002167
2168 SkPaint paint;
2169 paint.setStyle(SkPaint::kStroke_Style);
2170 paint.setAntiAlias(true);
2171 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002172
2173 {
2174 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2175 REPORTER_ASSERT(reporter, result.empty());
2176 }
2177 {
2178 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002179 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002180 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002181 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2182 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2183 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2184 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002185 }
2186 {
2187 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002188 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002189 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002190 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2191 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2192 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2193 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002194 }
2195 {
2196 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002197 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002198 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002199 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2200 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2201 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2202 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002203 }
2204 {
2205 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002206 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002207 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002208 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2209 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2210 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2211 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2212 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2213 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2214 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2215 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002216 }
2217 {
2218 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002219 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002220 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002221 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON100));
2222 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2223 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON100));
2224 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002225 }
2226 {
2227 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2228 REPORTER_ASSERT(reporter, result.empty());
2229 }
2230}
2231
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002232// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002233DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
2234 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2235 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002236 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002237 const char* text =
2238 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2239 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2240 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002241 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002242
2243 ParagraphStyle paragraphStyle;
2244 paragraphStyle.setTextAlign(TextAlign::kLeft);
2245 paragraphStyle.setMaxLines(10);
2246 paragraphStyle.turnHintingOff();
2247 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002248 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002249 textStyle.setFontSize(50);
2250 textStyle.setColor(SK_ColorBLACK);
2251 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2252 SkFontStyle::kUpright_Slant));
2253
2254 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2255 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002256 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002257 builder.pop();
2258
2259 auto paragraph = builder.Build();
2260 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002261 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002262
2263 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2264 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002265 {
2266 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2267 REPORTER_ASSERT(reporter, result.empty());
2268 }
2269 {
2270 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002271 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002272 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002273 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2274 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2275 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2276 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002277 }
2278 {
2279 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002280 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002281 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002282 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2283 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002286 }
2287 {
2288 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002289 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002290 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002291 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2292 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2293 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002295 }
2296}
2297
Julia Lavrovac2228562019-08-08 16:51:27 -04002298// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002299DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
2300 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2301 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002302 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002303 const char* text =
2304 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2305 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2306 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002307 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002308
2309 ParagraphStyle paragraphStyle;
2310 paragraphStyle.setTextAlign(TextAlign::kLeft);
2311 paragraphStyle.setMaxLines(10);
2312 paragraphStyle.turnHintingOff();
2313 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002314 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002315 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002316 textStyle.setHeight(1.6f);
2317 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002318 textStyle.setColor(SK_ColorBLACK);
2319 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2320 SkFontStyle::kUpright_Slant));
2321
2322 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2323 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002324 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002325 builder.pop();
2326
2327 auto paragraph = builder.Build();
2328 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002329 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002330
2331 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002332 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002333 {
2334 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2335 REPORTER_ASSERT(reporter, result.empty());
2336 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002337
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002338 {
2339 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002340 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002341 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002342 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2343 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2344 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2345 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002346 }
2347 {
2348 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002349 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002350 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002351 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2353 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2354 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002355 }
2356 {
2357 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002358 canvas.drawRects(SK_ColorGREEN, result);
2359 REPORTER_ASSERT(reporter, result.size() == 1);
2360 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2361 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2362 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2363 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002364 }
2365 {
2366 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002367 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002368 REPORTER_ASSERT(reporter, result.size() == 8);
2369
2370 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2371 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2372 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2373 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2374
2375 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2376 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2377 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2378 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2379
2380 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2381 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
2382 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON50));
2383 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2384
2385 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON50));
2386 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2387 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2388 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2389
2390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2392 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2393 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2394
2395 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2396 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002399 }
2400 {
2401 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002402 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002403 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
2404 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON50));
2405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON50));
2407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2408
2409 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2410 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2411 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002413 }
2414 {
2415 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2416 REPORTER_ASSERT(reporter, result.empty());
2417 }
2418}
2419
Julia Lavrovac2228562019-08-08 16:51:27 -04002420// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002421DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
2422 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2423 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002424 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002425 const char* text =
2426 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2427 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2428 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002429 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002430
2431 ParagraphStyle paragraphStyle;
2432 paragraphStyle.setTextAlign(TextAlign::kLeft);
2433 paragraphStyle.setMaxLines(10);
2434 paragraphStyle.turnHintingOff();
2435 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002436 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002437 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002438 textStyle.setHeight(1.6f);
2439 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002440 textStyle.setColor(SK_ColorBLACK);
2441 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2442 SkFontStyle::kUpright_Slant));
2443
2444 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2445 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002446 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002447 builder.pop();
2448
2449 auto paragraph = builder.Build();
2450 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002451 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002452
2453 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002454 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002455 {
2456 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2457 REPORTER_ASSERT(reporter, result.empty());
2458 }
2459
2460 {
2461 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002462 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002463 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002464 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2465 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2466 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2467 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002468 }
2469 {
2470 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002471 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002472 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002473 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2474 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2476 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002477 }
2478 {
2479 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002480 canvas.drawRects(SK_ColorGREEN, result);
2481 REPORTER_ASSERT(reporter, result.size() == 1);
2482 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2483 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002486 }
2487 {
2488 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002489 canvas.drawRects(SK_ColorMAGENTA, result);
2490 REPORTER_ASSERT(reporter, result.size() == 8);
2491
2492 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2496
2497 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2498 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2499 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2500 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2501
2502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2506
2507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2508 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2509 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2511
2512 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2513 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2514 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2516
2517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2518 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2519 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2520 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002521 }
2522 {
2523 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002524 canvas.drawRects(SK_ColorBLACK, result);
2525 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
2526 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON50));
2527 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2528 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON50));
2529 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2530
2531 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2532 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002535 }
2536 {
2537 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2538 REPORTER_ASSERT(reporter, result.empty());
2539 }
2540}
2541
Julia Lavrovac2228562019-08-08 16:51:27 -04002542// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002543DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
2544 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2545 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002546 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002547 const char* text =
2548 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2549 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2550 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002551 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002552
2553 ParagraphStyle paragraphStyle;
2554 paragraphStyle.setTextAlign(TextAlign::kLeft);
2555 paragraphStyle.setMaxLines(10);
2556 paragraphStyle.turnHintingOff();
2557 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002558 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002559 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002560 textStyle.setHeight(1.6f);
2561 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002562 textStyle.setColor(SK_ColorBLACK);
2563 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2564 SkFontStyle::kUpright_Slant));
2565
2566 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2567 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002568 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002569 builder.pop();
2570
2571 auto paragraph = builder.Build();
2572 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002573 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002574
2575 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002576 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002577 {
2578 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2579 REPORTER_ASSERT(reporter, result.empty());
2580 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002581
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002582 {
2583 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002584 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002585 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002586 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2587 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2588 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2589 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002590 }
2591 {
2592 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002593 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002594 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002595 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2596 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2597 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2598 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002599 }
2600 {
2601 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002602 canvas.drawRects(SK_ColorGREEN, result);
2603 REPORTER_ASSERT(reporter, result.size() == 1);
2604 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2605 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2606 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
2607 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002608 }
2609 {
2610 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002611 canvas.drawRects(SK_ColorMAGENTA, result);
2612 REPORTER_ASSERT(reporter, result.size() == 8);
2613
2614 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2615 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2616 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2617 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2618
2619 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2620 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2621 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2622 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2623
2624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2625 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2627 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2628
2629 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2630 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2631 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2632 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2633
2634 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2635 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2636 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2637 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2638
2639 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2640 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2641 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002643 }
2644 {
2645 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002646 canvas.drawRects(SK_ColorBLACK, result);
2647 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
2648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON50));
2649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON50));
2651 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2652
2653 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON50));
2654 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002657 }
2658 {
2659 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2660 REPORTER_ASSERT(reporter, result.empty());
2661 }
2662}
2663
Julia Lavrovac2228562019-08-08 16:51:27 -04002664// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002665DEF_TEST(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
2666 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2667 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002668 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002669 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002670 const size_t len = strlen(text);
2671
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002672 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002673 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002674 paragraphStyle.setMaxLines(10);
2675 paragraphStyle.turnHintingOff();
2676 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2677
2678 TextStyle textStyle;
2679 textStyle.setFontFamilies({SkString("Roboto")});
2680 textStyle.setFontSize(50);
2681 textStyle.setLetterSpacing(1);
2682 textStyle.setWordSpacing(5);
2683 textStyle.setHeight(1);
2684 textStyle.setColor(SK_ColorBLACK);
2685
2686 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002687 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002688 builder.pop();
2689
2690 auto paragraph = builder.Build();
2691 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002692 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002693
2694 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002695 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2696
2697 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2698 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2699 {
2700 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2701 REPORTER_ASSERT(reporter, result.empty());
2702 }
2703 {
2704 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2705 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2706 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002707 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2708 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002709 }
2710 {
2711 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2712 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2713 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002714 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2715 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002716 }
2717 {
2718 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2719 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2720 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2721 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002722 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 &&
2723 third.size() == 1 && last.size() == 1);
2724 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002725 }
2726}
2727
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002728// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002729DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
2730 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2731 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002732 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002733 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2734 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2735 // Any attempt to substitute one for another leads to errors
2736 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002737 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002738 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002739
2740 ParagraphStyle paragraphStyle;
2741 paragraphStyle.setTextAlign(TextAlign::kCenter);
2742 paragraphStyle.setMaxLines(10);
2743 paragraphStyle.turnHintingOff();
2744 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2745
2746 TextStyle textStyle;
2747 textStyle.setFontFamilies({SkString("Roboto")});
2748 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002749 textStyle.setHeight(1);
2750 textStyle.setColor(SK_ColorBLACK);
2751 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2752 SkFontStyle::kUpright_Slant));
2753
2754 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002755 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002756 builder.pop();
2757
2758 auto paragraph = builder.Build();
2759 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002760 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002761
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002762 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002763 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2764 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002765 {
2766 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2767 REPORTER_ASSERT(reporter, result.empty());
2768 }
2769
2770 {
2771 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002772 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002773 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002774 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2775 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2776 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2777 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002778 }
2779
2780 {
2781 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002782 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002783 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002784 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2785 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2786 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2787 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002788 }
2789
2790 {
2791 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002792 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002793 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002794 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2795 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2796 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2797 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002798 }
2799
2800 {
2801 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002802 canvas.drawRects(SK_ColorBLACK, result);
2803 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2804 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2805 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2806 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2807 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002808 }
2809
2810 {
2811 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002812 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002813 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002814 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2815 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2816 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2817 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002818 }
2819
2820 {
2821 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2822 REPORTER_ASSERT(reporter, result.empty());
2823 }
2824}
2825
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002826// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002827DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
2828 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2829 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002830 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002831 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002832 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002833
2834 ParagraphStyle paragraphStyle;
2835 paragraphStyle.setTextAlign(TextAlign::kCenter);
2836 paragraphStyle.setMaxLines(10);
2837 paragraphStyle.turnHintingOff();
2838 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2839
2840 TextStyle textStyle;
2841 textStyle.setFontFamilies({SkString("Roboto")});
2842 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002843 textStyle.setHeight(1);
2844 textStyle.setColor(SK_ColorBLACK);
2845 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2846 SkFontStyle::kUpright_Slant));
2847
2848 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002849 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002850 builder.pop();
2851
2852 auto paragraph = builder.Build();
2853 paragraph->layout(550);
2854
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002855 paragraph->paint(canvas.get(), 0, 0);
2856
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002857 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002858 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2859
2860 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2861 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002862 {
2863 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2864 REPORTER_ASSERT(reporter, result.empty());
2865 }
2866
2867 {
2868 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04002869 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002870 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002871 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2872 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2873 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2874 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002875 }
2876
2877 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002878 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
2879 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002880 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002881 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
2882 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
2883 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
2884 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002885 }
2886}
2887
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002888// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002889DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
2890 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2891 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002892 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
2893 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002894 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002895
2896 ParagraphStyle paragraphStyle;
2897 paragraphStyle.setTextAlign(TextAlign::kCenter);
2898 paragraphStyle.setMaxLines(10);
2899 paragraphStyle.turnHintingOff();
2900 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2901
2902 TextStyle textStyle;
2903 textStyle.setFontFamilies({SkString("Roboto")});
2904 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002905 textStyle.setHeight(1);
2906 textStyle.setColor(SK_ColorBLACK);
2907 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2908 SkFontStyle::kUpright_Slant));
2909
2910 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002911 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002912 builder.pop();
2913
2914 auto paragraph = builder.Build();
2915 paragraph->layout(550);
2916
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002917 paragraph->paint(canvas.get(), 0, 0);
2918
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002919 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002920
2921 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2922
2923 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2924 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2925 SkScalar epsilon = 0.01f;
2926 {
2927 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2928 REPORTER_ASSERT(reporter, result.empty());
2929 }
2930 {
2931 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002932 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002933 REPORTER_ASSERT(reporter, result.size() == 1);
2934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
2935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
2936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
2937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
2938 }
2939 {
2940 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002941 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002942 REPORTER_ASSERT(reporter, result.size() == 1);
2943 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
2944 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
2945 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
2946 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
2947 }
2948 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002949 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002950 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04002951 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002952 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
2953 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04002954 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002955 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
2956 }
2957 {
2958 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002959 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002960 REPORTER_ASSERT(reporter, result.size() == 1);
2961 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
2962 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002963 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002964 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
2965 }
2966 {
2967 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002968 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002969 REPORTER_ASSERT(reporter, result.size() == 1);
2970 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
2971 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
2972 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
2973 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
2974 }
2975 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002976 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002977 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002978 REPORTER_ASSERT(reporter, result.size() == 1);
2979 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
2980 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002981 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002982 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
2983 }
2984 {
2985 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2986 REPORTER_ASSERT(reporter, result.empty());
2987 }
2988}
2989
Julia Lavrovac2228562019-08-08 16:51:27 -04002990// Checked: DIFF (line height rounding error)
2991DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002992 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
2993 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04002994 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
2995 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002996 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04002997
2998 StrutStyle strutStyle;
2999 strutStyle.setStrutEnabled(true);
3000 strutStyle.setFontFamilies({SkString("Roboto")});
3001 strutStyle.setFontSize(14.0);
3002
3003 ParagraphStyle paragraphStyle;
3004 paragraphStyle.setStrutStyle(strutStyle);
3005
3006 TextStyle textStyle;
3007 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3008 textStyle.setFontSize(20);
3009 textStyle.setColor(SK_ColorBLACK);
3010
3011 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3012 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003013 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003014 builder.pop();
3015
3016 auto paragraph = builder.Build();
3017 paragraph->layout(550);
3018 paragraph->paint(canvas.get(), 0, 0);
3019
3020 {
3021 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3022 canvas.drawRects(SK_ColorGREEN, result);
3023 REPORTER_ASSERT(reporter, result.size() == 1);
3024 }
3025
3026 {
3027 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3028 canvas.drawRects(SK_ColorRED, result);
3029 REPORTER_ASSERT(reporter, result.size() == 1);
3030 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3031 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3032 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3033 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3034 }
3035}
3036
3037// Checked: NO DIFF
3038DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
3039 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3040 if (!fontCollection->fontsFound()) return;
3041 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3042 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003043 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003044
3045 StrutStyle strutStyle;
3046 strutStyle.setStrutEnabled(false);
3047
3048 ParagraphStyle paragraphStyle;
3049 paragraphStyle.setStrutStyle(strutStyle);
3050
3051 TextStyle textStyle;
3052 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3053 textStyle.setFontSize(20);
3054 textStyle.setColor(SK_ColorBLACK);
3055
3056 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3057 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003058 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003059 builder.pop();
3060
3061 auto paragraph = builder.Build();
3062 paragraph->layout(550);
3063 paragraph->paint(canvas.get(), 0, 0);
3064
3065
3066 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3067 canvas.drawRects(SK_ColorGREEN, result1);
3068 REPORTER_ASSERT(reporter, result1.size() == 1);
3069
3070 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3071 canvas.drawRects(SK_ColorRED, result2);
3072 REPORTER_ASSERT(reporter, result2.size() == 1);
3073
3074 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3075}
3076
3077// Checked: DIFF (small in numbers)
3078DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
3079 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3080 if (!fontCollection->fontsFound()) return;
3081 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003082 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3083 "67890 12345 67890 12345 67890 12345";
3084 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003085 ParagraphStyle paragraphStyle;
3086 paragraphStyle.setTextAlign(TextAlign::kLeft);
3087 paragraphStyle.setMaxLines(10);
3088 paragraphStyle.turnHintingOff();
3089 TextStyle textStyle;
3090 textStyle.setFontFamilies({SkString("Roboto")});
3091 textStyle.setFontSize(52);
3092 textStyle.setLetterSpacing(1.19039f);
3093 textStyle.setWordSpacing(5);
3094 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003095 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003096 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003097
3098 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3099 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003100 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003101 builder.pop();
3102
3103 auto paragraph = builder.Build();
3104 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003105 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003106
3107 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3108 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3109 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3110 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3111 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003112 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3113 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003114
3115 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003116 boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003117 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003118
Julia Lavrovac2228562019-08-08 16:51:27 -04003119 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003120 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003121 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003122
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003123 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3124 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3125 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3126 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3127 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3128 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3129 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3130 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3131
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003132 boxes = paragraph->getRectsForRange(12, 13, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003133 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003134 boxes = paragraph->getRectsForRange(13, 14, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003135 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003136 boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003137 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003138 boxes = paragraph->getRectsForRange(19, 20, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003139 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003140 boxes = paragraph->getRectsForRange(24, 25, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003141 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003142 boxes = paragraph->getRectsForRange(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003143 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003144 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003145 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003146 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003147 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003148
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003149 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3150 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003151}
3152
Julia Lavrovac2228562019-08-08 16:51:27 -04003153// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003154DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
3155 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3156 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003157 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003158 ParagraphStyle paragraph_style;
3159 paragraph_style.setMaxLines(10);
3160 paragraph_style.setTextAlign(TextAlign::kLeft);
3161 paragraph_style.turnHintingOff();
3162 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3163
3164 TextStyle text_style;
3165 text_style.setFontFamilies({SkString("Roboto")});
3166 text_style.setFontSize(50);
3167 text_style.setLetterSpacing(20);
3168 text_style.setWordSpacing(0);
3169 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003170 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003171 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003172 builder.pop();
3173
3174 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003175 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003176 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003177 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003178 builder.pop();
3179
3180 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003181 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003182 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003183 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003184 builder.pop();
3185
3186 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003187 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003188 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003189 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003190 builder.pop();
3191
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003192 const char* hSpace = "H ";
3193 const size_t len = strlen(hSpace);
3194
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003195 text_style.setLetterSpacing(0);
3196 text_style.setWordSpacing(20);
3197 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003198 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003199 builder.pop();
3200
3201 text_style.setLetterSpacing(0);
3202 text_style.setWordSpacing(0);
3203 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003204 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003205 builder.pop();
3206
3207 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003208 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003209 text_style.setWordSpacing(20);
3210 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003211 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003212 builder.pop();
3213
3214 auto paragraph = builder.Build();
3215 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003216 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003217
3218 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3219 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3220 size_t index = 0;
3221 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003222 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3223 ++index;
3224 return true;
3225 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003226 REPORTER_ASSERT(reporter, index == 4);
3227 index = 0;
3228 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003229 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3230 ++index;
3231 return true;
3232 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003233 REPORTER_ASSERT(reporter, index == 4);
3234}
3235
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003236// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003237DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
3238 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3239 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003240 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003241 const char* text =
3242 "A "
3243 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3244 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003245 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003246
3247 ParagraphStyle paragraph_style;
3248 paragraph_style.turnHintingOff();
3249 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3250
3251 TextStyle text_style;
3252 text_style.setFontFamilies({SkString("Roboto")});
3253 text_style.setColor(SK_ColorRED);
3254 text_style.setFontSize(31);
3255 text_style.setLetterSpacing(0);
3256 text_style.setWordSpacing(0);
3257 text_style.setColor(SK_ColorBLACK);
3258 text_style.setHeight(1);
3259 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003260 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003261 builder.pop();
3262
3263 auto paragraph = builder.Build();
3264 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003265 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003266
3267 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3268 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3269 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3270 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003271 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003272 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3273
3274 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3275 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3276 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3277}
3278
Julia Lavrovac2228562019-08-08 16:51:27 -04003279// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003280DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
3281 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3282 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003283 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3284
3285 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3286 const char* text2 = " Dialog Text List lots of words to see "
3287 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003288 float scale = 3.0f;
3289 ParagraphStyle paragraph_style;
3290 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3291 TextStyle text_style;
3292 text_style.setFontFamilies({SkString("Droid Serif")});
3293 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003294 text_style.setColor(SK_ColorBLACK);
3295
3296 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003297 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003298 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003299 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003300 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003301 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003302 text_style.setFontSize(14 / scale);
3303 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003304 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003305 builder.pop();
3306
3307 auto paragraph = builder.Build();
3308 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003309 canvas.get()->scale(scale, scale);
3310 paragraph->paint(canvas.get(), 0, 0);
3311 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003312
3313 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003314
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003315 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003316 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003317 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3318 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3319 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003323}
3324
Julia Lavrovac2228562019-08-08 16:51:27 -04003325// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003326DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
3327 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3328 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003329 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003330 const char* text =
3331 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3332 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003333 const size_t len = strlen(text);
3334
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003335 ParagraphStyle paragraph_style;
3336 paragraph_style.turnHintingOff();
3337 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3338
3339 TextStyle text_style;
3340 text_style.setFontFamilies({SkString("Roboto")});
3341 text_style.setColor(SK_ColorRED);
3342 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003343 text_style.setColor(SK_ColorBLACK);
3344 text_style.setHeight(1);
3345 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003346 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003347 builder.pop();
3348
3349 auto paragraph = builder.Build();
3350 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003351 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003352
3353 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3354 // Minikin does not count empty lines but SkParagraph does
3355 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3356
3357 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3358 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3359 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3360 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3361 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
3362 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 350);
3363 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 420);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003364}
3365
Julia Lavrova526df262019-08-21 17:49:44 -04003366// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003367DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
3368 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3369 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003370 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3371 const char* text =
3372 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3373 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3374 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3375 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003376 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003377
3378 ParagraphStyle paragraph_style;
3379 paragraph_style.turnHintingOff();
3380 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3381
3382 TextStyle text_style;
3383 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3384 text_style.setFontSize(50);
3385 text_style.setDecoration(TextDecoration::kUnderline);
3386 text_style.setColor(SK_ColorBLACK);
3387 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003388 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003389 builder.pop();
3390
3391 auto paragraph = builder.Build();
3392 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003393 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003394
3395 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003396
3397 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3398 for (auto& line : impl->lines()) {
3399 if (&line != impl->lines().end() - 1) {
3400 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3401 } else {
3402 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3403 }
3404 REPORTER_ASSERT(reporter, line.height() == 59);
3405 }
3406}
3407
Julia Lavrovac2228562019-08-08 16:51:27 -04003408// Checked: DIFF+
3409DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
3410 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3411 if (!fontCollection->fontsFound()) return;
3412 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3413 const char* text =
3414 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3415 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3416 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3417 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3418 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3419 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003420 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003421
3422 ParagraphStyle paragraph_style;
3423 paragraph_style.turnHintingOff();
3424 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3425
3426 TextStyle text_style;
3427 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3428 text_style.setFontSize(50);
3429 text_style.setColor(SK_ColorBLACK);
3430 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003431 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003432 builder.pop();
3433
3434 auto paragraph = builder.Build();
3435 paragraph->layout(TestCanvasWidth - 300);
3436 paragraph->paint(canvas.get(), 0, 0);
3437
3438 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3439 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3440
3441 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3442 REPORTER_ASSERT(reporter, result.size() == 0);
3443
3444 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3445 REPORTER_ASSERT(reporter, result.size() == 2);
3446 canvas.drawRects(SK_ColorRED, result);
3447
3448 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
3449 REPORTER_ASSERT(reporter, result.size() == 1);
3450 canvas.drawRects(SK_ColorBLUE, result);
3451
3452 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3453 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3454 REPORTER_ASSERT(reporter, result.size() == 2);
3455 canvas.drawRects(SK_ColorGREEN, result);
3456
3457 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3458 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3459 REPORTER_ASSERT(reporter, result.size() == 2);
3460 canvas.drawRects(SK_ColorGREEN, result);
3461
3462 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3463 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3464 REPORTER_ASSERT(reporter, result.size() == 2);
3465 canvas.drawRects(SK_ColorGREEN, result);
3466}
3467
Julia Lavrova916a9042019-08-08 16:51:27 -04003468DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3469 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3470}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003471
Julia Lavrovac2228562019-08-08 16:51:27 -04003472// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003473DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
3474 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3475 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003476 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003477 const char* text =
3478 "Sentence to layout at diff widths to get diff line counts. short words "
3479 "short words short words short words short words short words short words "
3480 "short words short words short words short words short words short words "
3481 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003482 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003483
3484 ParagraphStyle paragraph_style;
3485 paragraph_style.turnHintingOff();
3486 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3487
3488 TextStyle text_style;
3489 text_style.setFontFamilies({SkString("Roboto")});
3490 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003491 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003492 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003493 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003494 builder.pop();
3495
3496 auto paragraph = builder.Build();
3497 paragraph->layout(300);
3498
3499 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3500 // Some of the formatting lazily done on paint
3501 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3502 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3503 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3504
3505 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003506 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003507 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3508 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3509 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3510}
3511
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003512// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003513DEF_TEST(SkParagraph_Ellipsize, reporter) {
3514 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3515 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003516 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003517 const char* text =
3518 "This is a very long sentence to test if the text will properly wrap "
3519 "around and go to the next line. Sometimes, short sentence. Longer "
3520 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003521 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003522
3523 ParagraphStyle paragraph_style;
3524 paragraph_style.setMaxLines(1);
3525 paragraph_style.setEllipsis(u"\u2026");
3526 paragraph_style.turnHintingOff();
3527 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3528
3529 TextStyle text_style;
3530 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003531 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003532 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003533 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003534 builder.pop();
3535
3536 auto paragraph = builder.Build();
3537 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003538 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003539
3540 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003541
3542 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3543 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3544
3545 auto& line = impl->lines()[0];
3546 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003547 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003548}
3549
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003550// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003551DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
3552 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3553 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003554 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003555 const char* text1 = "fluttser ";
3556 const char* text2 = "mdje";
3557 const char* text3 = "fluttser mdje";
3558
3559 ParagraphStyle paragraph_style;
3560 paragraph_style.turnHintingOff();
3561 paragraph_style.setTextAlign(TextAlign::kLeft);
3562 paragraph_style.setMaxLines(2);
3563 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3564
3565 TextStyle text_style;
3566 text_style.setFontFamilies({SkString("Roboto")});
3567 text_style.setColor(SK_ColorBLACK);
3568 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003569 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003570 text_style.setDecoration(TextDecoration::kUnderline);
3571 text_style.setDecorationColor(SK_ColorBLACK);
3572 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003573 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003574 builder.pop();
3575
3576 auto paragraph = builder.Build();
3577 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003578 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003579
3580 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3581
3582 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3583 text_style.setDecoration(TextDecoration::kNoDecoration);
3584 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003585 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003586 builder1.pop();
3587
3588 auto paragraph1 = builder1.Build();
3589 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003590 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003591
3592 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3593
3594 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3595 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003596
3597 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3598 .front()
3599 .rect;
3600 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3601 .front()
3602 .rect;
3603 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3604 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3605
3606 for (size_t i = 0; i < 12; ++i) {
3607 auto r =
3608 paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
3609 .front()
3610 .rect;
3611 auto r1 =
3612 paragraph1
3613 ->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
3614 .front()
3615 .rect;
3616
3617 REPORTER_ASSERT(reporter, r.fLeft == r1.fLeft);
3618 REPORTER_ASSERT(reporter, r.fRight == r1.fRight);
3619 }
3620}
3621
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003622// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003623DEF_TEST(SkParagraph_SimpleShadow, reporter) {
3624 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3625 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003626 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003627 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003628 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003629
3630 ParagraphStyle paragraph_style;
3631 paragraph_style.turnHintingOff();
3632 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3633
3634 TextStyle text_style;
3635 text_style.setFontFamilies({SkString("Roboto")});
3636 text_style.setColor(SK_ColorBLACK);
3637 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3638 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003639 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003640
3641 auto paragraph = builder.Build();
3642 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003643 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003644
3645 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3646
3647 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3648 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3649 size_t index = 0;
3650 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003651 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003652 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003653 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3654 ++index;
3655 return true;
3656 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003657 }
3658}
3659
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003660// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003661DEF_TEST(SkParagraph_ComplexShadow, reporter) {
3662 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3663 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003664 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003665 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003666 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003667
3668 ParagraphStyle paragraph_style;
3669 paragraph_style.turnHintingOff();
3670 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3671
3672 TextStyle text_style;
3673 text_style.setFontFamilies({SkString("Roboto")});
3674 text_style.setColor(SK_ColorBLACK);
3675 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3676 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003677 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003678
3679 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3680 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3681 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003682 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003683 builder.pop();
3684
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003685 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003686
3687 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3688 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003689 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003690 builder.pop();
3691
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003692 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003693
3694 auto paragraph = builder.Build();
3695 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003696 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003697
3698 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3699
3700 size_t index = 0;
3701 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003702 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003703 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003704 ++index;
3705 switch (index) {
3706 case 1:
3707 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3708 break;
3709 case 2:
3710 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3711 break;
3712 case 3:
3713 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3714 break;
3715 case 4:
3716 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3717 REPORTER_ASSERT(reporter, style.equals(text_style));
3718 break;
3719 case 5:
3720 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3721 break;
3722 default:
3723 REPORTER_ASSERT(reporter, false);
3724 }
3725 return true;
3726 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003727 }
3728}
3729
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003730// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003731DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
3732 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3733 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003734 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003735 const char* text =
3736 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3737 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003738 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003739
3740 ParagraphStyle paragraph_style;
3741 paragraph_style.turnHintingOff();
3742 paragraph_style.setMaxLines(14);
3743 paragraph_style.setTextAlign(TextAlign::kJustify);
3744 paragraph_style.setHeight(1.5);
3745 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3746
3747 TextStyle text_style;
3748 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3749 text_style.setColor(SK_ColorBLACK);
3750 text_style.setFontSize(55);
3751 text_style.setLetterSpacing(2);
3752 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3753 text_style.setDecorationColor(SK_ColorBLACK);
3754 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003755 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003756 builder.pop();
3757
3758 auto paragraph = builder.Build();
3759 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003760 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003761
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003762 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3763 paragraph->getMaxWidth(),
3764 paragraph->getIdeographicBaseline());
3765 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3766 paragraph->getMaxWidth(),
3767 paragraph->getAlphabeticBaseline());
3768 canvas.drawLine(SK_ColorRED, rect1, false);
3769 canvas.drawLine(SK_ColorGREEN, rect2, false);
3770
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003771 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003772 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003773 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003774 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003775}
3776
Julia Lavrovac2228562019-08-08 16:51:27 -04003777// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003778DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
3779 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3780 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003781 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003782
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003783 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3784 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3785 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003786
3787 ParagraphStyle paragraph_style;
3788 paragraph_style.turnHintingOff();
3789 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3790
3791 TextStyle text_style;
3792 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003793 SkString("Not a real font"),
3794 SkString("Also a fake font"),
3795 SkString("So fake it is obvious"),
3796 SkString("Next one should be a real font..."),
3797 SkString("Roboto"),
3798 SkString("another fake one in between"),
3799 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003800 });
3801 text_style.setColor(SK_ColorBLACK);
3802 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003803 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003804
3805 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003806 SkString("Not a real font"),
3807 SkString("Also a fake font"),
3808 SkString("So fake it is obvious"),
3809 SkString("Homemade Apple"),
3810 SkString("Next one should be a real font..."),
3811 SkString("Roboto"),
3812 SkString("another fake one in between"),
3813 SkString("Noto Sans CJK JP"),
3814 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003815 });
3816 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003817 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003818
3819 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003820 SkString("Not a real font"),
3821 SkString("Also a fake font"),
3822 SkString("So fake it is obvious"),
3823 SkString("Homemade Apple"),
3824 SkString("Next one should be a real font..."),
3825 SkString("Roboto"),
3826 SkString("another fake one in between"),
3827 SkString("Source Han Serif CN"),
3828 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003829 });
3830 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003831 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003832
3833 builder.pop();
3834
3835 auto paragraph = builder.Build();
3836 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003837 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003838
3839 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3840
3841 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3842 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3843 // [Apple + Noto] [Apple + Han]
3844 REPORTER_ASSERT(reporter, impl->runs().size() == 6);
3845
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003846 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[0].advance().fX, 48.330f, EPSILON100));
3847 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[1].advance().fX, 15.879f, EPSILON100));
3848 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[2].advance().fX, 139.125f, EPSILON100));
3849 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 27.999f, EPSILON100));
3850 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 62.248f, EPSILON100));
3851 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003852
3853 // When a different font is resolved, then the metrics are different.
Julia Lavrovac2228562019-08-08 16:51:27 -04003854 REPORTER_ASSERT(reporter, impl->runs()[1].correctAscent() != impl->runs()[3].correctAscent());
3855 REPORTER_ASSERT(reporter, impl->runs()[1].correctDescent() != impl->runs()[3].correctDescent());
3856 REPORTER_ASSERT(reporter, impl->runs()[3].correctAscent() != impl->runs()[5].correctAscent());
3857 REPORTER_ASSERT(reporter, impl->runs()[3].correctDescent() != impl->runs()[5].correctDescent());
3858 REPORTER_ASSERT(reporter, impl->runs()[1].correctAscent() != impl->runs()[5].correctAscent());
3859 REPORTER_ASSERT(reporter, impl->runs()[1].correctDescent() != impl->runs()[5].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003860}
3861
Julia Lavrovac2228562019-08-08 16:51:27 -04003862// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003863DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
3864 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3865 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003866 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003867 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003868 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003869 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003870
3871 ParagraphStyle paragraph_style;
3872 paragraph_style.setMaxLines(10);
3873 paragraph_style.setTextAlign(TextAlign::kLeft);
3874 paragraph_style.turnHintingOff();
3875
3876 StrutStyle strut_style;
3877 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003878 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003879 strut_style.setFontSize(50);
3880 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003881 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003882 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003883 paragraph_style.setStrutStyle(strut_style);
3884
3885 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3886
3887 TextStyle text_style;
3888 text_style.setFontFamilies({SkString("Ahem")});
3889 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003890 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003891 text_style.setColor(SK_ColorBLACK);
3892 text_style.setHeight(0.5f);
3893 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003894 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003895 builder.pop();
3896
3897 auto paragraph = builder.Build();
3898 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003899 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003900
3901 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003902 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3903
3904 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3905 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
3906 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003907 {
3908 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3909 REPORTER_ASSERT(reporter, boxes.empty());
3910 }
3911 {
3912 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003913 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003914 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003915 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
3916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
3917 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
3918 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003919 }
3920 {
3921 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003922 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003923 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003924 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
3925 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
3926 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
3927 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003928 }
3929 {
3930 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003931 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04003932 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003933 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
3934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04003935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003937 }
3938 {
3939 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003940 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04003941 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003942 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
3943 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04003944 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003945 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003946 }
3947 {
3948 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003949 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003950 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003951 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
3952 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 224.5f, EPSILON100));
3953 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
3954 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003955 }
3956 {
3957 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003958 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04003959 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003960 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
3961 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 319.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04003962 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003963 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003964 }
3965}
3966
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003967// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003968DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
3969 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
3970 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04003971 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003972 // The chinese extra height should be absorbed by the strut.
3973 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003974 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003975
3976 ParagraphStyle paragraph_style;
3977 paragraph_style.setMaxLines(10);
3978 paragraph_style.setTextAlign(TextAlign::kLeft);
3979 paragraph_style.turnHintingOff();
3980
3981 StrutStyle strut_style;
3982
3983 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003984 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003985 strut_style.setFontSize(50);
3986 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003987 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003988 paragraph_style.setStrutStyle(strut_style);
3989
3990 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3991
3992 TextStyle text_style;
3993 text_style.setFontFamilies({SkString("Ahem")});
3994 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003995 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3996 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003997 text_style.setColor(SK_ColorBLACK);
3998 text_style.setHeight(1);
3999 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004000 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004001 builder.pop();
4002
4003 auto paragraph = builder.Build();
4004 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004005 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004006
4007 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4008 // Font is not resolved and the first line does not fit
4009 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4010
4011 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4012 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4013 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004014 {
4015 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4016 REPORTER_ASSERT(reporter, boxes.empty());
4017 }
4018 {
4019 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004020 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004021 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004022 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4023 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4024 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4025 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004026 }
4027 {
4028 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004029 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004030 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004031 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4032 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4033 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4034 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004035 }
4036 {
4037 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004038 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004039 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004040 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4041 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4042 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4043 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004044 }
4045 {
4046 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004047 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004048 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004049 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4050 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4051 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4052 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004053 }
4054 {
4055 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004056 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004057 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004058 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4059 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 184, EPSILON100));
4060 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4061 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004062 }
4063 {
4064 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004065 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004066 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004067 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
4068 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 264, EPSILON100));
4069 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4070 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004071 }
4072}
4073
Julia Lavrovac2228562019-08-08 16:51:27 -04004074// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004075DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
4076 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4077 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004078 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4079
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004080 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004081 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004082 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004083
4084 ParagraphStyle paragraph_style;
4085 paragraph_style.setMaxLines(10);
4086 paragraph_style.setTextAlign(TextAlign::kLeft);
4087 paragraph_style.turnHintingOff();
4088
4089 StrutStyle strut_style;
4090 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004091 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004092 strut_style.setFontSize(50);
4093 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004094 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004095 paragraph_style.setStrutStyle(strut_style);
4096
4097 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4098
4099 TextStyle text_style;
4100 text_style.setFontFamilies({SkString("Ahem")});
4101 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004102 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4103 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004104 text_style.setColor(SK_ColorBLACK);
4105 text_style.setHeight(1);
4106 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004107 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004108 builder.pop();
4109
4110 auto paragraph = builder.Build();
4111 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004112 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004113
4114 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4115 // Font is not resolved and the first line does not fit
4116 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4117
4118 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4119 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4120 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4121 SkScalar epsilon = 0.001f;
4122 {
4123 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4124 REPORTER_ASSERT(reporter, boxes.empty());
4125 }
4126 {
4127 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004128 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004129 REPORTER_ASSERT(reporter, boxes.size() == 1);
4130 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4131 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4132 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4133 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4134 }
4135 {
4136 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004137 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004138 REPORTER_ASSERT(reporter, boxes.size() == 1);
4139 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004140 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004141 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4142 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4143 }
4144 {
4145 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004146 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004147 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004148 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4149 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004150 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004151 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4152 }
4153 {
4154 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004155 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004156 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004157 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004158 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004159 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004160 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4161 }
4162 {
4163 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004164 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004165 REPORTER_ASSERT(reporter, boxes.size() == 1);
4166 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004167 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 128, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004168 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4169 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4170 }
4171 {
4172 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004173 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004174 REPORTER_ASSERT(reporter, boxes.size() == 1);
4175 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004176 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 188, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004177 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4178 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4179 }
4180}
4181
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004182// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004183DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
4184 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4185 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004186 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004187 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004188 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004189
4190 ParagraphStyle paragraph_style;
4191 paragraph_style.setMaxLines(10);
4192 paragraph_style.setTextAlign(TextAlign::kLeft);
4193 paragraph_style.turnHintingOff();
4194
4195 StrutStyle strut_style;
4196 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004197 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004198 strut_style.setFontSize(50);
4199 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004200 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004201 strut_style.setLeading(0.1f);
4202 strut_style.setForceStrutHeight(true);
4203 paragraph_style.setStrutStyle(strut_style);
4204
4205 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4206
4207 TextStyle text_style;
4208 text_style.setFontFamilies({SkString("Ahem")});
4209 text_style.setFontSize(50);
4210 text_style.setLetterSpacing(0);
4211 text_style.setColor(SK_ColorBLACK);
4212 text_style.setHeight(1);
4213 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004214 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004215 builder.pop();
4216
4217 auto paragraph = builder.Build();
4218 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004219 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004220
4221 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4222 // Font is not resolved and the first line does not fit
4223 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4224
4225 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4226 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4227 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004228
4229 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4230 REPORTER_ASSERT(reporter, boxes1.empty());
4231
4232 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004233 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004234 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004235 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4236 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4237 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4238 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004239
4240 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004241 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004242 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004243 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
4244 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 22.5f, EPSILON100));
4245 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4246 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004247
4248 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004249 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004250 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004251 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4252 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4253 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4254 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004255
4256 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004257 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004258 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004259 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
4260 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 22.5f, EPSILON100));
4261 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4262 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004263
4264 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004265 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004266 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004267 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
4268 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 182.5f, EPSILON100));
4269 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4270 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004271
4272 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004273 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004274 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004275 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
4276 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 262.5f, EPSILON100));
4277 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4278 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004279}
4280
Julia Lavrovac2228562019-08-08 16:51:27 -04004281// Checked: NO DIFF
4282DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
4283 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4284 if (!fontCollection->fontsFound()) return;
4285 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4286
4287 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004288 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004289
4290 ParagraphStyle paragraph_style;
4291 paragraph_style.setMaxLines(10);
4292 paragraph_style.setTextAlign(TextAlign::kLeft);
4293 paragraph_style.turnHintingOff();
4294
4295 StrutStyle strut_style;
4296 strut_style.setStrutEnabled(true);
4297 strut_style.setFontFamilies({SkString("Ahem")});
4298 strut_style.setFontSize(50);
4299 strut_style.setHeight(1.5f);
4300 strut_style.setLeading(0.1f);
4301 strut_style.setForceStrutHeight(false);
4302 paragraph_style.setStrutStyle(strut_style);
4303
4304 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4305
4306 TextStyle text_style;
4307 text_style.setFontFamilies({SkString("Ahem")});
4308 text_style.setFontSize(20);
4309 text_style.setColor(SK_ColorBLACK);
4310 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004311 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004312 builder.pop();
4313
4314 auto paragraph = builder.Build();
4315 paragraph->layout(550);
4316 paragraph->paint(canvas.get(), 0, 0);
4317
4318 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4319 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4320 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4321 {
4322 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4323 REPORTER_ASSERT(reporter, boxes.empty());
4324 }
4325 {
4326 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4327 canvas.drawRects(SK_ColorRED, boxes);
4328 REPORTER_ASSERT(reporter, boxes.size() == 1);
4329 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4330 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4333 }
4334 {
4335 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4336 canvas.drawRects(SK_ColorRED, boxes);
4337 REPORTER_ASSERT(reporter, boxes.size() == 1);
4338 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4341 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4342 }
4343}
4344
4345// TODO: Implement font features
Julia Lavrova916a9042019-08-08 16:51:27 -04004346DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4347 SkDebugf("TODO: Font features\n");
4348}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004349
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004350// Not in Minikin
4351DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
4352 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4353 if (!fontCollection->fontsFound()) return;
4354 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004355 const size_t len = strlen(text);
4356
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004357 ParagraphStyle paragraph_style;
4358 paragraph_style.turnHintingOff();
4359 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4360
4361 TextStyle text_style;
4362 text_style.setFontFamilies(
4363 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4364 text_style.setFontSize(60);
4365 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004366 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004367 builder.pop();
4368
4369 auto paragraph = builder.Build();
4370 paragraph->layout(TestCanvasWidth);
4371
4372 SkDEBUGCODE(auto impl = static_cast<ParagraphImpl*>(paragraph.get());)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004373 SkASSERT(impl->runs().size() == 3);
Julia Lavrova5207f352019-06-21 12:22:32 -04004374 SkASSERT(impl->runs()[0].textRange().end == impl->runs()[1].textRange().start);
4375 SkASSERT(impl->runs()[1].textRange().end == impl->runs()[2].textRange().start);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004376}
4377
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004378DEF_TEST(SkParagraph_JSON1, reporter) {
4379 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4380 if (!fontCollection->fontsFound()) return;
4381 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004382 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004383
4384 ParagraphStyle paragraph_style;
4385 paragraph_style.turnHintingOff();
4386 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4387
4388 TextStyle text_style;
4389 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4390 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004391 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004392 builder.pop();
4393
4394 auto paragraph = builder.Build();
4395 paragraph->layout(TestCanvasWidth);
4396
4397 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4398 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
4399 auto run = impl->runs().front();
4400
4401 auto cluster = 0;
4402 SkShaperJSONWriter::VisualizeClusters(
4403 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4404 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4405 if (cluster == 0) {
4406 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4407 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4408 SkASSERT(glyph1to1.size() == 1);
4409 SkASSERT(*glyph1to1.begin() == 1611);
4410 }
4411 ++cluster;
4412 });
4413 SkASSERT(cluster <= 2);
4414}
4415
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004416DEF_TEST(SkParagraph_JSON2, reporter) {
4417 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4418 if (!fontCollection->fontsFound()) return;
4419 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004420 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004421
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004422 ParagraphStyle paragraph_style;
4423 paragraph_style.turnHintingOff();
4424 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4425
4426 TextStyle text_style;
4427 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4428 text_style.setColor(SK_ColorBLACK);
4429 text_style.setFontSize(50);
4430 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004431 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004432 builder.pop();
4433
4434 auto paragraph = builder.Build();
4435 paragraph->layout(TestCanvasWidth);
4436
4437 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4438 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
4439 auto run = impl->runs().front();
4440
4441 auto cluster = 0;
4442 for (auto& run : impl->runs()) {
4443 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004444 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4445 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004446 [&](int codePointCount, SkSpan<const char> utf1to1,
4447 SkSpan<const SkGlyphID> glyph1to1) {
4448 if (cluster == 0) {
4449 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4450 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4451 SkASSERT(glyph1to1.size() == 3);
4452 }
4453 ++cluster;
4454 });
4455 }
4456
4457 SkASSERT(cluster <= 2);
4458}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004459
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004460DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004461 ParagraphCache cache;
4462 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4463 if (!fontCollection->fontsFound()) return;
4464
4465 ParagraphStyle paragraph_style;
4466 paragraph_style.turnHintingOff();
4467
4468 TextStyle text_style;
4469 text_style.setFontFamilies({SkString("Roboto")});
4470 text_style.setColor(SK_ColorBLACK);
4471
4472 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4473 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4474 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004475 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004476 builder.pop();
4477 auto paragraph = builder.Build();
4478
4479 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4480 REPORTER_ASSERT(reporter, count == cache.count());
4481 auto found = cache.findParagraph(impl);
4482 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4483 auto added = cache.updateParagraph(impl);
4484 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4485 };
4486
4487 test("text1", 0, false);
4488 test("text1", 1, true);
4489 test("text2", 1, false);
4490 test("text2", 2, true);
4491 test("text3", 2, false);
4492}
4493
4494DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004495 ParagraphCache cache;
4496 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4497 if (!fontCollection->fontsFound()) return;
4498
4499 ParagraphStyle paragraph_style;
4500 paragraph_style.turnHintingOff();
4501
4502 TextStyle text_style;
4503 text_style.setColor(SK_ColorBLACK);
4504
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004505 const char* text = "text";
4506 const size_t len = strlen(text);
4507
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004508 auto test = [&](int count, bool expectedToBeFound) {
4509 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4510 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004511 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004512 builder.pop();
4513 auto paragraph = builder.Build();
4514 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4515
4516 impl->getResolver().findAllFontsForAllStyledBlocks(impl);
4517
4518 REPORTER_ASSERT(reporter, count == cache.count());
4519 auto found = cache.findParagraph(impl);
4520 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4521 auto added = cache.updateParagraph(impl);
4522 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4523 };
4524
4525 text_style.setFontFamilies({SkString("Roboto")});
4526 test(0, false);
4527 test(1, true);
4528 text_style.setFontFamilies({SkString("Homemade Apple")});
4529 test(1, false);
4530 test(2, true);
4531 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4532 test(2, false);
4533}
4534
4535DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004536 ParagraphCache cache;
4537 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4538 if (!fontCollection->fontsFound()) return;
4539
4540 ParagraphStyle paragraph_style;
4541 paragraph_style.turnHintingOff();
4542
4543 TextStyle text_style;
4544 text_style.setFontFamilies({SkString("Roboto")});
4545 text_style.setColor(SK_ColorBLACK);
4546
4547 auto test = [&](const char* text1,
4548 const char* text2,
4549 const char* font1,
4550 const char* font2,
4551 int count,
4552 bool expectedToBeFound) {
4553 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4554 text_style.setFontFamilies({SkString(font1)});
4555 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004556 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004557 builder.pop();
4558 text_style.setFontFamilies({SkString(font2)});
4559 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004560 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004561 builder.pop();
4562 auto paragraph = builder.Build();
4563 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4564
4565 impl->getResolver().findAllFontsForAllStyledBlocks(impl);
4566
4567 REPORTER_ASSERT(reporter, count == cache.count());
4568 auto found = cache.findParagraph(impl);
4569 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4570 auto added = cache.updateParagraph(impl);
4571 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4572 };
4573
4574 test("text", "", "Roboto", "Homemade Apple", 0, false);
4575 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4576 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4577 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4578 test("text", "", "Roboto", "Homemade Apple", 4, true);
4579}
4580
4581DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004582 ParagraphCache cache;
4583 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4584 if (!fontCollection->fontsFound()) return;
4585
4586 ParagraphStyle paragraph_style;
4587 paragraph_style.turnHintingOff();
4588
4589 TextStyle text_style;
4590 text_style.setFontFamilies({SkString("Roboto")});
4591 text_style.setColor(SK_ColorBLACK);
4592
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004593 const char* text = "text";
4594 const size_t len = strlen(text);
4595
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004596 auto test = [&](int count, bool expectedToBeFound) {
4597 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4598 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004599 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004600 builder.pop();
4601 auto paragraph = builder.Build();
4602 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4603
4604 impl->getResolver().findAllFontsForAllStyledBlocks(impl);
4605
4606 REPORTER_ASSERT(reporter, count == cache.count());
4607 auto found = cache.findParagraph(impl);
4608 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4609 auto added = cache.updateParagraph(impl);
4610 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4611 };
4612
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004613 test(0, false);
4614 test(1, true);
4615 text_style.setLetterSpacing(10);
4616 test(1, false);
4617 test(2, true);
4618 text_style.setWordSpacing(10);
4619 test(2, false);
4620}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004621
Julia Lavrova526df262019-08-21 17:49:44 -04004622DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrovaa40db422019-08-21 13:49:15 -04004623 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4624 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004625 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4626 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004627
4628 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004629 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004630 text_style.setFontSize(16);
4631 text_style.setFontFamilies({SkString("Roboto")});
4632 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004633 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004634
4635 auto paragraph = builder.Build();
4636 paragraph->layout(TestCanvasWidth);
4637 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrova526df262019-08-21 17:49:44 -04004638 auto result = paragraph->GetRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004639}
4640
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004641DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
4642 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4643 if (!fontCollection->fontsFound()) return;
4644 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4645 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4646
4647 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4648
4649 ParagraphStyle paragraph_style;
4650 TextStyle text_style;
4651 text_style.setFontSize(16);
4652 text_style.setFontFamilies({SkString("Roboto")});
4653 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4654 builder.addText(text.c_str(), text.size());
4655
4656 auto paragraph = builder.Build();
4657 paragraph->layout(TestCanvasWidth);
4658 paragraph->paint(canvas.get(), 0, 0);
4659}
4660
Julia Lavrovaa40db422019-08-21 13:49:15 -04004661DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
4662 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4663 if (!fontCollection->fontsFound()) return;
4664 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4665
4666 ParagraphStyle paragraph_style;
4667 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4668
Julia Lavrova526df262019-08-21 17:49:44 -04004669 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004670 builder.addPlaceholder(placeholder);
4671
4672 auto paragraph = builder.Build();
4673 paragraph->layout(TestCanvasWidth);
Julia Lavrova526df262019-08-21 17:49:44 -04004674 auto result = paragraph->GetRectsForPlaceholders();
4675 paragraph->paint(canvas.get(), 0, 0);
4676}
4677
4678DEF_TEST(SkParagraph_Fallbacks, reporter) {
4679 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4680 if (!fontCollection->fontsFound()) return;
4681 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4682 TestCanvas canvas("SkParagraph_Fallbacks.png");
4683
4684 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004685 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004686
4687 const char* androidFonts[] = {
4688 "sans-serif",
4689 "sans-serif-condensed",
4690 "serif",
4691 "monospace",
4692 "serif-monospace",
4693 "casual",
4694 "cursive",
4695 "sans-serif-smallcaps",
4696 };
4697
4698 for (auto& font : androidFonts) {
4699
4700 ParagraphStyle paragraph_style;
4701 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4702
4703 TextStyle text_style;
4704 text_style.setColor(SK_ColorBLACK);
4705 text_style.setLocale(SkString("en_US"));
4706 text_style.setFontSize(20);
4707
4708 text_style.setFontFamilies({ SkString(font) });
4709 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004710 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004711
4712 builder.pop();
4713
4714 auto paragraph = builder.Build();
4715 paragraph->layout(TestCanvasWidth);
4716 paragraph->paint(canvas.get(), 0, 0);
4717 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4718 }
4719}
4720
4721DEF_TEST(SkParagraph_Bidi1, reporter) {
4722 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4723 if (!fontCollection->fontsFound()) return;
4724 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4725 TestCanvas canvas("SkParagraph_Bidi1.png");
4726
4727 std::u16string abc = u"\u202Dabc";
4728 std::u16string DEF = u"\u202EDEF";
4729 std::u16string ghi = u"\u202Dghi";
4730 std::u16string JKL = u"\u202EJKL";
4731 std::u16string mno = u"\u202Dmno";
4732
4733 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4734
4735 ParagraphStyle paragraph_style;
4736 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4737
4738 TextStyle text_style;
4739 text_style.setFontFamilies({ SkString("sans-serif")});
4740 text_style.setFontSize(40);
4741
4742 text_style.setColor(SK_ColorCYAN);
4743 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4744 builder.pushStyle(text_style);
4745 builder.addText(abc);
4746
4747 text_style.setColor(SK_ColorGREEN);
4748 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4749 builder.pushStyle(text_style);
4750 builder.addText(DEF);
4751
4752 text_style.setColor(SK_ColorYELLOW);
4753 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4754 builder.pushStyle(text_style);
4755 builder.addText(ghi);
4756
4757 text_style.setColor(SK_ColorMAGENTA);
4758 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4759 builder.pushStyle(text_style);
4760 builder.addText(JKL);
4761
4762 text_style.setColor(SK_ColorBLUE);
4763 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4764 builder.pushStyle(text_style);
4765 builder.addText(mno);
4766
4767 auto paragraph = builder.Build();
4768 paragraph->layout(400);
4769 paragraph->paint(canvas.get(), 0, 0);
4770}
4771
4772DEF_TEST(SkParagraph_Bidi2, reporter) {
4773 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>();
4774 if (!fontCollection->fontsFound()) return;
4775 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4776 TestCanvas canvas("SkParagraph_Bidi2.png");
4777
4778 std::u16string abcD = u"\u202Dabc\u202ED";
4779 std::u16string EFgh = u"EF\u202Dgh";
4780 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4781
4782 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4783
4784 ParagraphStyle paragraph_style;
4785 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4786
4787 TextStyle text_style;
4788 text_style.setFontFamilies({ SkString("sans-serif")});
4789 text_style.setFontSize(40);
4790 text_style.setColor(SK_ColorBLACK);
4791
4792 text_style.setColor(SK_ColorYELLOW);
4793 text_style.setFontSize(40);
4794 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4795 builder.pushStyle(text_style);
4796 builder.addText(abcD);
4797
4798 text_style.setColor(SK_ColorRED);
4799 text_style.setFontSize(50);
4800 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4801 builder.pushStyle(text_style);
4802 builder.addText(EFgh);
4803
4804 text_style.setColor(SK_ColorMAGENTA);
4805 text_style.setFontSize(60);
4806 text_style.setFontStyle(SkFontStyle(SkFontStyle::kExtraBold_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4807 builder.pushStyle(text_style);
4808 builder.addText(iJKLmno);
4809
4810 auto paragraph = builder.Build();
4811 paragraph->layout(360);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004812 paragraph->paint(canvas.get(), 0, 0);
4813}