blob: ba995c836805a98fea2e774523655e588affe22d [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002#include "src/core/SkFontMgrPriv.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 Lavrova2e30fde2019-10-09 09:43:02 -04007#include "modules/skparagraph/utils/TestFontCollection.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04008#include "src/core/SkOSFile.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -04009#include "src/utils/SkOSPath.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040010#include "src/utils/SkShaperJSONWriter.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040011#include "tests/CodecPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "tests/Test.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040013#include "tools/Resources.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040014#include "tools/ToolUtils.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040015
Julia Lavrovab30d4812019-11-08 14:51:16 -050016#include "third_party/icu/SkLoadICU.h"
17
Julia Lavrovaa3552c52019-05-30 16:12:56 -040018#define VeryLongCanvasWidth 1000000
19#define TestCanvasWidth 1000
20#define TestCanvasHeight 600
21
Julia Lavrova2e30fde2019-10-09 09:43:02 -040022#define DEF_TEST_DISABLED(name, reporter) \
23static void test_##name(skiatest::Reporter* reporter, const GrContextOptions&); \
24skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \
Herb Derby126d7a22019-11-27 11:38:16 -050025void test_##name(skiatest::Reporter* reporter, const GrContextOptions&) { /* SkDebugf("Disabled:"#name "\n"); */ } \
Julia Lavrova2e30fde2019-10-09 09:43:02 -040026void disabled_##name(skiatest::Reporter* reporter, const GrContextOptions&)
27
Julia Lavrovaa3552c52019-05-30 16:12:56 -040028using namespace skia::textlayout;
29namespace {
30
Julia Lavrovadb9f6692019-08-01 16:02:17 -040031SkScalar EPSILON100 = 0.01f;
32SkScalar EPSILON50 = 0.02f;
33SkScalar EPSILON20 = 0.05f;
Julia Lavrova916a9042019-08-08 16:51:27 -040034SkScalar EPSILON10 = 0.1f;
Julia Lavrovac2228562019-08-08 16:51:27 -040035SkScalar EPSILON5 = 0.20f;
36SkScalar EPSILON2 = 0.50f;
Julia Lavrovadb9f6692019-08-01 16:02:17 -040037
Julia Lavrova5207f352019-06-21 12:22:32 -040038bool equal(const char* base, TextRange a, const char* b) {
39 return std::strncmp(b, base + a.start, a.width()) == 0;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040040}
Julia Lavrova3281b962019-12-02 11:32:25 -050041
Julia Lavrova2e30fde2019-10-09 09:43:02 -040042class ResourceFontCollection : public FontCollection {
Julia Lavrovaa3552c52019-05-30 16:12:56 -040043public:
Julia Lavrova2e30fde2019-10-09 09:43:02 -040044 ResourceFontCollection(bool testOnly = false)
Julia Lavrovaa3552c52019-05-30 16:12:56 -040045 : fFontsFound(false)
46 , fResolvedFonts(0)
47 , fResourceDir(GetResourcePath("fonts").c_str())
48 , fFontProvider(sk_make_sp<TypefaceFontProvider>()) {
49 std::vector<SkString> fonts;
50 SkOSFile::Iter iter(fResourceDir.c_str());
Julia Lavrova2e30fde2019-10-09 09:43:02 -040051
Julia Lavrovab30d4812019-11-08 14:51:16 -050052 if (!SkLoadICU()) {
53 SkDebugf("ICU not loaded, skipping all the tests\n");
54 return;
55 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040056 SkString path;
57 while (iter.next(&path)) {
58 if (path.endsWith("Roboto-Italic.ttf")) {
59 fFontsFound = true;
60 }
61 fonts.emplace_back(path);
62 }
63
64 if (!fFontsFound) {
Herb Derby126d7a22019-11-27 11:38:16 -050065 // SkDebugf("Fonts not found, skipping all the tests\n");
Julia Lavrovaa3552c52019-05-30 16:12:56 -040066 return;
67 }
68 // Only register fonts if we have to
69 for (auto& font : fonts) {
70 SkString file_path;
71 file_path.printf("%s/%s", fResourceDir.c_str(), font.c_str());
72 fFontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
73 }
74
Julia Lavrova2e30fde2019-10-09 09:43:02 -040075 if (testOnly) {
76 this->setTestFontManager(std::move(fFontProvider));
77 } else {
78 this->setAssetFontManager(std::move(fFontProvider));
79 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040080 this->disableFontFallback();
Julia Lavrovaa3552c52019-05-30 16:12:56 -040081 }
82
Julia Lavrova2e30fde2019-10-09 09:43:02 -040083 ~ResourceFontCollection() = default;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040084
85 size_t resolvedFonts() const { return fResolvedFonts; }
86
87 // TODO: temp solution until we check in fonts
88 bool fontsFound() const { return fFontsFound; }
89
90private:
91 bool fFontsFound;
92 size_t fResolvedFonts;
93 std::string fResourceDir;
94 sk_sp<TypefaceFontProvider> fFontProvider;
95};
Julia Lavrovadb9f6692019-08-01 16:02:17 -040096
97class TestCanvas {
98public:
99 TestCanvas(const char* testName) : name(testName) {
100 bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight);
101 canvas = new SkCanvas(bits);
102 canvas->clear(SK_ColorWHITE);
103 }
104
105 ~TestCanvas() {
Julia Lavrovaaae845f2019-08-16 16:44:40 -0400106 SkString tmpDir = skiatest::GetTmpDir();
107 if (!tmpDir.isEmpty()) {
108 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
109 SkFILEWStream file(path.c_str());
110 if (!SkEncodeImage(&file, bits, SkEncodedImageFormat::kPNG, 100)) {
111 SkDebugf("Cannot write a picture %s\n", name);
112 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400113 }
114 delete canvas;
115 }
116
117 void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) {
118
119 SkPaint paint;
120 if (!fill) {
121 paint.setStyle(SkPaint::kStroke_Style);
122 paint.setAntiAlias(true);
123 paint.setStrokeWidth(1);
124 }
125 paint.setColor(color);
126 for (auto& r : result) {
127 canvas->drawRect(r.rect, paint);
128 }
129 }
130
131 void drawLine(SkColor color, SkRect rect, bool vertical = true) {
132
133 SkPaint paint;
134 paint.setStyle(SkPaint::kStroke_Style);
135 paint.setAntiAlias(true);
136 paint.setStrokeWidth(1);
137 paint.setColor(color);
138 if (vertical) {
139 canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
140 } else {
141 canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint);
142 }
143 }
144
145 void drawLines(SkColor color, std::vector<TextBox>& result) {
146
147 for (auto& r : result) {
148 drawLine(color, r.rect);
149 }
150 }
151
152 SkCanvas* get() { return canvas; }
153private:
154 SkBitmap bits;
155 SkCanvas* canvas;
156 const char* name;
157};
158
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400159} // namespace
160
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400161// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400162DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400163 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400164 if (!fontCollection->fontsFound()) return;
165 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400166 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400167
168 ParagraphStyle paragraph_style;
169 paragraph_style.turnHintingOff();
170 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
171
172 TextStyle text_style;
173 text_style.setFontFamilies({SkString("Roboto")});
174 text_style.setColor(SK_ColorBLACK);
175 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400176 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400177 builder.pop();
178
179 auto paragraph = builder.Build();
180 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500181 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400182
183 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
184 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
185 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400186 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400187
188 size_t index = 0;
189 for (auto& line : impl->lines()) {
190 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400191 [&index, reporter]
192 (TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400193 REPORTER_ASSERT(reporter, index == 0);
194 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorBLACK);
195 ++index;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400196 });
197 }
198}
199
Julia Lavrova916a9042019-08-08 16:51:27 -0400200DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400201 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400202 TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png");
203 if (!fontCollection->fontsFound()) return;
204
205 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400206 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400207
208 ParagraphStyle paragraph_style;
209 paragraph_style.turnHintingOff();
210 paragraph_style.setMaxLines(14);
211 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
212
213 TextStyle text_style;
214 text_style.setFontFamilies({SkString("Roboto")});
215 text_style.setColor(SK_ColorBLACK);
216 text_style.setFontSize(26);
217 text_style.setWordSpacing(5);
218 text_style.setLetterSpacing(1);
219 text_style.setDecoration(TextDecoration::kUnderline);
220 text_style.setDecorationColor(SK_ColorBLACK);
221 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400222 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400223
224 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
225 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400226 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400227 builder.addPlaceholder(placeholder1);
228
229 PlaceholderStyle placeholder2(5, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
230 builder.addPlaceholder(placeholder2);
231 builder.addPlaceholder(placeholder1);
232 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400233 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400234 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400235 builder.addText(text, len);
236 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400237 builder.addPlaceholder(placeholder2);
238 builder.addPlaceholder(placeholder2);
239 builder.addPlaceholder(placeholder2);
240 builder.addPlaceholder(placeholder2);
241 builder.addPlaceholder(placeholder2);
242 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400243 builder.addText(text, len);
244 builder.addText(text, len);
245 builder.addText(text, len);
246 builder.addText(text, len);
247 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400248 builder.addPlaceholder(placeholder2);
249 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400250 builder.addText(text, len);
251 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400252
253 builder.pop();
254
255 auto paragraph = builder.Build();
256 paragraph->layout(TestCanvasWidth);
257 paragraph->paint(canvas.get(), 0, 0);
258
259 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
260 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
261
262 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
263 canvas.drawRects(SK_ColorRED, boxes);
264 REPORTER_ASSERT(reporter, boxes.size() == 1);
265
266 boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
267 canvas.drawRects(SK_ColorGREEN, boxes);
268 REPORTER_ASSERT(reporter, boxes.size() == 1);
269
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400270 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400271 canvas.drawRects(SK_ColorRED, boxes);
272
273 boxes = paragraph->getRectsForRange(4, 17, rect_height_style, rect_width_style);
274 canvas.drawRects(SK_ColorBLUE, boxes);
275
276 REPORTER_ASSERT(reporter, boxes.size() == 7);
277
Julia Lavrovac028b422019-11-25 10:00:43 -0500278 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400279 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500280 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 90.921f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400281 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 100, EPSILON100));
282
Julia Lavrovac028b422019-11-25 10:00:43 -0500283 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.left(), 231.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.right(), 231.343f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.bottom(), 100, EPSILON100));
287
Julia Lavrovac028b422019-11-25 10:00:43 -0500288 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.left(), 281.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400289 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500290 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.right(), 281.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400291 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.bottom(), 50, EPSILON100));
292
Julia Lavrovac028b422019-11-25 10:00:43 -0500293 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.left(), 336.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.right(), 336.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400296 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100));
297}
298
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400299DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400300 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400301 TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png");
302 if (!fontCollection->fontsFound()) return;
303
304 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400305 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400306
307 ParagraphStyle paragraph_style;
308 paragraph_style.turnHintingOff();
309 paragraph_style.setMaxLines(14);
310 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
311
312 TextStyle text_style;
313 text_style.setFontFamilies({SkString("Roboto")});
314 text_style.setColor(SK_ColorBLACK);
315 text_style.setFontSize(26);
316 text_style.setWordSpacing(5);
317 text_style.setLetterSpacing(1);
318 text_style.setDecoration(TextDecoration::kUnderline);
319 text_style.setDecorationColor(SK_ColorBLACK);
320 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400321 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400322
323 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 38.347f);
324 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400325 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400326
327 builder.pop();
328
329 auto paragraph = builder.Build();
330 paragraph->layout(TestCanvasWidth);
331 paragraph->paint(canvas.get(), 0, 0);
332
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400333 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400334 canvas.drawRects(SK_ColorRED, boxes);
335
336 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500337 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400338 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
341
342 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
343 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
344
345 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
346 canvas.drawRects(SK_ColorBLUE, boxes);
347
348 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500349 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400350 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 14.226f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500351 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400353}
Julia Lavrova916a9042019-08-08 16:51:27 -0400354
Julia Lavrova916a9042019-08-08 16:51:27 -0400355DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400356 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400357 TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png");
358 if (!fontCollection->fontsFound()) return;
359
360 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400361 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400362
363 ParagraphStyle paragraph_style;
364 paragraph_style.turnHintingOff();
365 paragraph_style.setMaxLines(14);
366 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
367
368 TextStyle text_style;
369 text_style.setFontFamilies({SkString("Roboto")});
370 text_style.setColor(SK_ColorBLACK);
371 text_style.setFontSize(26);
372 text_style.setWordSpacing(5);
373 text_style.setLetterSpacing(1);
374 text_style.setDecoration(TextDecoration::kUnderline);
375 text_style.setDecorationColor(SK_ColorBLACK);
376 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400377 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400378
379 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kAboveBaseline, TextBaseline::kAlphabetic, 903129.129308f);
380 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400381 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400382
383 builder.pop();
384
385 auto paragraph = builder.Build();
386 paragraph->layout(TestCanvasWidth);
387 paragraph->paint(canvas.get(), 0, 0);
388
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400389 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400390 canvas.drawRects(SK_ColorRED, boxes);
391
392 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500393 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400394 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.347f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500395 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400396 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 49.652f, EPSILON100));
397
398 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
399 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
400
401 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
402 canvas.drawRects(SK_ColorBLUE, boxes);
403
404 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 25.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400409}
Julia Lavrova916a9042019-08-08 16:51:27 -0400410
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400411DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400412 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400413 TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png");
414 if (!fontCollection->fontsFound()) return;
415
416 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400417 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400418
419 ParagraphStyle paragraph_style;
420 paragraph_style.turnHintingOff();
421 paragraph_style.setMaxLines(14);
422 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
423
424 TextStyle text_style;
425 text_style.setFontFamilies({SkString("Roboto")});
426 text_style.setColor(SK_ColorBLACK);
427 text_style.setFontSize(26);
428 text_style.setWordSpacing(5);
429 text_style.setLetterSpacing(1);
430 text_style.setDecoration(TextDecoration::kUnderline);
431 text_style.setDecorationColor(SK_ColorBLACK);
432 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400433 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400434
435 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBelowBaseline, TextBaseline::kAlphabetic, 903129.129308f);
436 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400437 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400438
439 builder.pop();
440
441 auto paragraph = builder.Build();
442 paragraph->layout(TestCanvasWidth);
443 paragraph->paint(canvas.get(), 0, 0);
444
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400445 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400446 canvas.drawRects(SK_ColorRED, boxes);
447
448 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500449 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400450 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500451 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400452 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
453
454 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
455 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
456
457 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
458 canvas.drawRects(SK_ColorBLUE, boxes);
459
460 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500461 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400462 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.121f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500463 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400464 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400465}
Julia Lavrova916a9042019-08-08 16:51:27 -0400466
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400467DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400468 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400469 TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png");
470 if (!fontCollection->fontsFound()) return;
471
472 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400473 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400474
475 ParagraphStyle paragraph_style;
476 paragraph_style.turnHintingOff();
477 paragraph_style.setMaxLines(14);
478 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
479
480 TextStyle text_style;
481 text_style.setFontFamilies({SkString("Roboto")});
482 text_style.setColor(SK_ColorBLACK);
483 text_style.setFontSize(26);
484 text_style.setWordSpacing(5);
485 text_style.setLetterSpacing(1);
486 text_style.setDecoration(TextDecoration::kUnderline);
487 text_style.setDecorationColor(SK_ColorBLACK);
488 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400489 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400490
491 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBottom, TextBaseline::kAlphabetic, 0);
492 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400493 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400494
495 builder.pop();
496
497 auto paragraph = builder.Build();
498 paragraph->layout(TestCanvasWidth);
499 paragraph->paint(canvas.get(), 0, 0);
500
501 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
502 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
503
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400504 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400505 canvas.drawRects(SK_ColorRED, boxes);
506 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400508 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500509 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
511
512 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
513 canvas.drawRects(SK_ColorBLUE, boxes);
514 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 19.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400518 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400519}
Julia Lavrova916a9042019-08-08 16:51:27 -0400520
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400521DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400522 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400523 TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png");
524 if (!fontCollection->fontsFound()) return;
525
526 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400527 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400528
529 ParagraphStyle paragraph_style;
530 paragraph_style.turnHintingOff();
531 paragraph_style.setMaxLines(14);
532 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
533
534 TextStyle text_style;
535 text_style.setFontFamilies({SkString("Roboto")});
536 text_style.setColor(SK_ColorBLACK);
537 text_style.setFontSize(26);
538 text_style.setWordSpacing(5);
539 text_style.setLetterSpacing(1);
540 text_style.setDecoration(TextDecoration::kUnderline);
541 text_style.setDecorationColor(SK_ColorBLACK);
542 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400543 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400544
545 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kTop, TextBaseline::kAlphabetic, 0);
546 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400547 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400548
549 builder.pop();
550
551 auto paragraph = builder.Build();
552 paragraph->layout(TestCanvasWidth);
553 paragraph->paint(canvas.get(), 0, 0);
554
555 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
556 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
557
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400558 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400559 canvas.drawRects(SK_ColorRED, boxes);
560 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500561 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400562 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500563 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400564 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
565
566 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
567 canvas.drawRects(SK_ColorBLUE, boxes);
568 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500569 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400570 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500571 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400572 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400573}
Julia Lavrova916a9042019-08-08 16:51:27 -0400574
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400575DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400576 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400577 TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png");
578 if (!fontCollection->fontsFound()) return;
579
580 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400581 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400582
583 ParagraphStyle paragraph_style;
584 paragraph_style.turnHintingOff();
585 paragraph_style.setMaxLines(14);
586 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
587
588 TextStyle text_style;
589 text_style.setFontFamilies({SkString("Roboto")});
590 text_style.setColor(SK_ColorBLACK);
591 text_style.setFontSize(26);
592 text_style.setWordSpacing(5);
593 text_style.setLetterSpacing(1);
594 text_style.setDecoration(TextDecoration::kUnderline);
595 text_style.setDecorationColor(SK_ColorBLACK);
596 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400597 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400598
599 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kMiddle, TextBaseline::kAlphabetic, 0);
600 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400601 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400602
603 builder.pop();
604
605 auto paragraph = builder.Build();
606 paragraph->layout(TestCanvasWidth);
607 paragraph->paint(canvas.get(), 0, 0);
608
609 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
610 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
611
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400612 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400613 canvas.drawRects(SK_ColorRED, boxes);
614 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500615 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400616 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500617 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400618 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
619
620 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
621 canvas.drawRects(SK_ColorBLUE, boxes);
622 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500623 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 9.765f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500625 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400627}
Julia Lavrova916a9042019-08-08 16:51:27 -0400628
Julia Lavrova916a9042019-08-08 16:51:27 -0400629DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400630 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400631 TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png");
632 if (!fontCollection->fontsFound()) return;
633
634 const char* text = "給能上目秘使";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400635 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400636
637 ParagraphStyle paragraph_style;
638 paragraph_style.turnHintingOff();
639 paragraph_style.setMaxLines(14);
640 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
641
642 TextStyle text_style;
643 text_style.setFontFamilies({SkString("Source Han Serif CN")});
644 text_style.setColor(SK_ColorBLACK);
645 text_style.setFontSize(26);
646 text_style.setWordSpacing(5);
647 text_style.setLetterSpacing(1);
648 text_style.setDecoration(TextDecoration::kUnderline);
649 text_style.setDecorationColor(SK_ColorBLACK);
650 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400651 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400652 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kIdeographic, 38.347f);
653 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400654 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400655
656 builder.pop();
657
658 auto paragraph = builder.Build();
659 paragraph->layout(TestCanvasWidth);
660 paragraph->paint(canvas.get(), 0, 0);
661
662 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
663 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
664
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400665 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400666 canvas.drawRects(SK_ColorRED, boxes);
667 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500668 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400669 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500670 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400671 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
672
673 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
674 canvas.drawRects(SK_ColorBLUE, boxes);
675 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500676 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 135.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400677 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 4.703f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500678 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400679 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400680}
Julia Lavrova916a9042019-08-08 16:51:27 -0400681
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400682DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400683 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400684 TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png");
685 if (!fontCollection->fontsFound()) return;
686
687 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400688 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400689
690 ParagraphStyle paragraph_style;
691 paragraph_style.turnHintingOff();
692 paragraph_style.setMaxLines(14);
693 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
694
695 TextStyle text_style;
696 text_style.setFontFamilies({SkString("Roboto")});
697 text_style.setColor(SK_ColorBLACK);
698 text_style.setFontSize(26);
699 text_style.setWordSpacing(5);
700 text_style.setLetterSpacing(1);
701 text_style.setDecoration(TextDecoration::kUnderline);
702 text_style.setDecorationColor(SK_ColorBLACK);
703 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400704 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400705
706 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
707 PlaceholderStyle placeholder2(25, 25, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 12.5f);
708
709 builder.addPlaceholder(placeholder1);
710 builder.addPlaceholder(placeholder1);
711 builder.addPlaceholder(placeholder1);
712 builder.addPlaceholder(placeholder2);
713 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400714 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400715
716 builder.addPlaceholder(placeholder1);
717 builder.addPlaceholder(placeholder1);
718 builder.addPlaceholder(placeholder1);
719 builder.addPlaceholder(placeholder1);
720 builder.addPlaceholder(placeholder2); // 4 + 1
721 builder.addPlaceholder(placeholder1);
722 builder.addPlaceholder(placeholder1);
723 builder.addPlaceholder(placeholder1);
724 builder.addPlaceholder(placeholder1);
725 builder.addPlaceholder(placeholder1);
726 builder.addPlaceholder(placeholder1);
727 builder.addPlaceholder(placeholder2); // 6 + 1
728 builder.addPlaceholder(placeholder1);
729 builder.addPlaceholder(placeholder1);
730 builder.addPlaceholder(placeholder1);
731 builder.addPlaceholder(placeholder1);
732 builder.addPlaceholder(placeholder1);
733 builder.addPlaceholder(placeholder1);
734 builder.addPlaceholder(placeholder1);
735 builder.addPlaceholder(placeholder2); // 7 + 1
736
737 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400738 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400739 builder.addPlaceholder(placeholder1);
740 builder.addPlaceholder(placeholder2);
741
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400742 builder.addText(text, len);
743 builder.addText(text, len);
744 builder.addText(text, len);
745 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400746
747 builder.addPlaceholder(placeholder2);
748 builder.addPlaceholder(placeholder1);
749
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400750 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400751
752 builder.addPlaceholder(placeholder2);
753
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400754 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);
762 builder.addText(text, len);
763 builder.addText(text, len);
764 builder.addText(text, len);
765 builder.addText(text, len);
766 builder.addText(text, len);
767 builder.addText(text, len);
768 builder.addText(text, len);
769 builder.addText(text, len);
770 builder.addText(text, len);
771 builder.addText(text, len);
772 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400773
774 builder.pop();
775
776 auto paragraph = builder.Build();
777 paragraph->layout(TestCanvasWidth - 100);
778 paragraph->paint(canvas.get(), 0, 0);
779
780 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
781 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
782
783 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
784 canvas.drawRects(SK_ColorRED, boxes);
785 REPORTER_ASSERT(reporter, boxes.size() == 1);
786
787 boxes = paragraph->getRectsForRange(175, 176, rect_height_style, rect_width_style);
788 canvas.drawRects(SK_ColorGREEN, boxes);
789 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500790 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 31.695f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400791 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 218.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500792 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 47.292f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400793 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 249, EPSILON100));
794
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400795 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400796 canvas.drawRects(SK_ColorRED, boxes);
797
798 boxes = paragraph->getRectsForRange(4, 45, rect_height_style, rect_width_style);
799 canvas.drawRects(SK_ColorBLUE, boxes);
800 REPORTER_ASSERT(reporter, boxes.size() == 30);
Julia Lavrovac028b422019-11-25 10:00:43 -0500801 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 59.726f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400802 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.378f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500803 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400804 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56.847f, EPSILON100));
805
Julia Lavrovac028b422019-11-25 10:00:43 -0500806 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.left(), 606.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400807 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.top(), 38, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500808 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.right(), 631.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400809 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.bottom(), 63, EPSILON100));
810
Julia Lavrovac028b422019-11-25 10:00:43 -0500811 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400812 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.top(), 63.5f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500813 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.right(), 50.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400814 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400815}
Julia Lavrova916a9042019-08-08 16:51:27 -0400816
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400817DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400818 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400819 TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png");
820 if (!fontCollection->fontsFound()) return;
821
822 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400823 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400824
825 ParagraphStyle paragraph_style;
826 paragraph_style.turnHintingOff();
827 paragraph_style.setMaxLines(14);
828 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
829
830 TextStyle text_style;
831 text_style.setFontFamilies({SkString("Roboto")});
832 text_style.setColor(SK_ColorBLACK);
833 text_style.setFontSize(26);
834 text_style.setWordSpacing(5);
835 text_style.setLetterSpacing(1);
836 text_style.setDecoration(TextDecoration::kUnderline);
837 text_style.setDecorationColor(SK_ColorBLACK);
838 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400839 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400840
841 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
842 PlaceholderStyle placeholder2(5, 20, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 10);
843
844 builder.addPlaceholder(placeholder1);
845 builder.addPlaceholder(placeholder1);
846 builder.addPlaceholder(placeholder1);
847 builder.addPlaceholder(placeholder1);
848 builder.addPlaceholder(placeholder1);
849 builder.addPlaceholder(placeholder1);
850 builder.addPlaceholder(placeholder1);
851 builder.addPlaceholder(placeholder1);
852 builder.addPlaceholder(placeholder2); // 8 + 1
853 builder.addPlaceholder(placeholder1);
854 builder.addPlaceholder(placeholder1);
855 builder.addPlaceholder(placeholder1);
856 builder.addPlaceholder(placeholder1);
857 builder.addPlaceholder(placeholder1);
858 builder.addPlaceholder(placeholder2); // 5 + 1
859 builder.addPlaceholder(placeholder1);
860 builder.addPlaceholder(placeholder1);
861 builder.addPlaceholder(placeholder1);
862 builder.addPlaceholder(placeholder1);
863 builder.addPlaceholder(placeholder1);
864 builder.addPlaceholder(placeholder1);
865 builder.addPlaceholder(placeholder1);
866 builder.addPlaceholder(placeholder1); // 8 + 0
867
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400868 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400869
870 builder.addPlaceholder(placeholder1);
871 builder.addPlaceholder(placeholder2);
872 builder.addPlaceholder(placeholder2); // 1 + 2
873 builder.addPlaceholder(placeholder1);
874 builder.addPlaceholder(placeholder2);
875 builder.addPlaceholder(placeholder2); // 1 + 2
876
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400877 builder.addText(text, len);
878 builder.addText(text, len);
879 builder.addText(text, len);
880 builder.addText(text, len);
881 builder.addText(text, len);
882 builder.addText(text, len);
883 builder.addText(text, len);
884 builder.addText(text, len);
885 builder.addText(text, len);
886 builder.addText(text, len);
887 builder.addText(text, len); // 11
Julia Lavrova916a9042019-08-08 16:51:27 -0400888
889 builder.addPlaceholder(placeholder2);
890 builder.addPlaceholder(placeholder1);
891 builder.addPlaceholder(placeholder2);
892 builder.addPlaceholder(placeholder1);
893 builder.addPlaceholder(placeholder2);
894
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400895 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400896
897 builder.pop();
898
899 auto paragraph = builder.Build();
900 paragraph->layout(TestCanvasWidth);
901 paragraph->paint(canvas.get(), 0, 0);
902
903 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
904 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
905
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400906 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400907 canvas.drawRects(SK_ColorRED, boxes);
908
909 REPORTER_ASSERT(reporter, boxes.size() == 34);
Julia Lavrovac028b422019-11-25 10:00:43 -0500910 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400911 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500912 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 140.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400913 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
914
Julia Lavrovac028b422019-11-25 10:00:43 -0500915 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.left(), 800.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500917 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.right(), 850.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400918 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.bottom(), 50, EPSILON100));
919
Julia Lavrovac028b422019-11-25 10:00:43 -0500920 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.left(), 503.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400921 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.top(), 160, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500922 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.right(), 508.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400923 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.bottom(), 180, EPSILON100));
924
925 boxes = paragraph->getRectsForRange(30, 50, rect_height_style, rect_width_style);
926 canvas.drawRects(SK_ColorBLUE, boxes);
927
928 REPORTER_ASSERT(reporter, boxes.size() == 8);
Julia Lavrovac028b422019-11-25 10:00:43 -0500929 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 216.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400930 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500931 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 290.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400932 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 120, EPSILON100));
933
Julia Lavrovac028b422019-11-25 10:00:43 -0500934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 290.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 340.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 120, EPSILON100));
938
Julia Lavrovac028b422019-11-25 10:00:43 -0500939 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.left(), 340.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400940 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500941 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.right(), 345.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400942 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400943}
944
945// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400946DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400947 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400948 if (!fontCollection->fontsFound()) return;
949 const char* text = "I am RED";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400950 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400951
952 ParagraphStyle paragraph_style;
953 paragraph_style.turnHintingOff();
954 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
955
956 TextStyle text_style;
957 text_style.setFontFamilies({SkString("Roboto")});
958 text_style.setColor(SK_ColorRED);
959 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400960 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400961 builder.pop();
962
963 auto paragraph = builder.Build();
964 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500965 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400966
967 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
968 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
969 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400970 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400971
972 size_t index = 0;
973 for (auto& line : impl->lines()) {
974 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400975 [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
976 REPORTER_ASSERT(reporter, index == 0);
977 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED);
978 ++index;
979 return true;
980 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400981 }
982}
983
Julia Lavrovac2228562019-08-08 16:51:27 -0400984// Checked: DIFF+ (Space between 1 & 2 style blocks)
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400985DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400986 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400987 TestCanvas canvas("SkParagraph_RainbowParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400988 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400989 const char* text1 = "Red Roboto"; // [0:10)
990 const char* text2 = "big Greeen Default"; // [10:28)
991 const char* text3 = "Defcolor Homemade Apple"; // [28:51)
992 const char* text4 = "Small Blue Roboto"; // [51:68)
Julia Lavrovac2228562019-08-08 16:51:27 -0400993 const char* text41 = "Small Blue ";
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400994 const char* text5 =
995 "Continue Last Style With lots of words to check if it overlaps "
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400996 "properly or not"; // [68:)
997 const char* text42 =
998 "Roboto"
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400999 "Continue Last Style With lots of words to check if it overlaps "
1000 "properly or not";
1001
1002 ParagraphStyle paragraph_style;
1003 paragraph_style.turnHintingOff();
1004 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001005 paragraph_style.setMaxLines(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001006 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1007
1008 TextStyle text_style1;
1009 text_style1.setFontFamilies({SkString("Roboto")});
1010
1011 text_style1.setColor(SK_ColorRED);
1012 builder.pushStyle(text_style1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001013 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001014
1015 TextStyle text_style2;
1016 text_style2.setFontFamilies({SkString("Roboto")});
1017 text_style2.setFontSize(50);
1018 text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1019 SkFontStyle::kUpright_Slant));
1020 text_style2.setLetterSpacing(10);
1021 text_style2.setDecorationColor(SK_ColorBLACK);
1022 text_style2.setDecoration((TextDecoration)(
1023 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1024 text_style2.setWordSpacing(30);
1025 text_style2.setColor(SK_ColorGREEN);
1026 builder.pushStyle(text_style2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001027 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001028
1029 TextStyle text_style3;
1030 text_style3.setFontFamilies({SkString("Homemade Apple")});
Julia Lavrova526df262019-08-21 17:49:44 -04001031 text_style3.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001032 builder.pushStyle(text_style3);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001033 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001034
1035 TextStyle text_style4;
1036 text_style4.setFontFamilies({SkString("Roboto")});
1037 text_style4.setFontSize(14);
1038 text_style4.setDecorationColor(SK_ColorBLACK);
1039 text_style4.setDecoration((TextDecoration)(
1040 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1041 text_style4.setColor(SK_ColorBLUE);
1042 builder.pushStyle(text_style4);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001043 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001044
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001045 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001046 builder.pop();
1047
1048 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001049 paragraph->layout(1000);
1050 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001051
Julia Lavrova3281b962019-12-02 11:32:25 -05001052 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1053
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001054 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1055 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
1056 REPORTER_ASSERT(reporter, impl->styles().size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001057 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1058
1059 auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight);
1060 canvas.drawRects(SK_ColorMAGENTA, rects);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001061
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001062 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001063 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001064 StyleType::kAllAttributes,
1065 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001066 switch (index) {
1067 case 0:
1068 REPORTER_ASSERT(reporter, style.equals(text_style1));
Julia Lavrova526df262019-08-21 17:49:44 -04001069 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001070 break;
1071 case 1:
1072 REPORTER_ASSERT(reporter, style.equals(text_style2));
Julia Lavrova526df262019-08-21 17:49:44 -04001073 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001074 break;
1075 case 2:
1076 REPORTER_ASSERT(reporter, style.equals(text_style3));
Julia Lavrova526df262019-08-21 17:49:44 -04001077 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001078 break;
1079 case 3:
1080 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001081 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001082 break;
1083 default:
1084 REPORTER_ASSERT(reporter, false);
1085 break;
1086 }
1087 ++index;
1088 return true;
1089 });
1090 impl->lines()[1].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001091 StyleType::kAllAttributes,
1092 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001093 switch (index) {
1094 case 4:
1095 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001096 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001097 break;
1098 default:
1099 REPORTER_ASSERT(reporter, false);
1100 break;
1101 }
1102 ++index;
1103 return true;
1104 });
1105 REPORTER_ASSERT(reporter, index == 5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001106}
1107
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001108// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001109DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001110 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001111 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001112 TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001113 const char* text = "No TextStyle! Uh Oh!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001114 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001115
1116 ParagraphStyle paragraph_style;
1117 TextStyle defaultStyle;
1118 defaultStyle.setFontFamilies({SkString("Roboto")});
1119 paragraph_style.setTextStyle(defaultStyle);
1120 paragraph_style.turnHintingOff();
1121 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001122 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001123
1124 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001125 paragraph->layout(TestCanvasWidth);
1126 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001127
Julia Lavrova3281b962019-12-02 11:32:25 -05001128 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1129
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001130 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1131
1132 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1133 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1134 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1135
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001136 size_t index = 0;
1137 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001138 StyleType::kAllAttributes,
1139 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001140 REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle()));
Julia Lavrova526df262019-08-21 17:49:44 -04001141 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001142 ++index;
1143 return true;
1144 });
1145 REPORTER_ASSERT(reporter, index == 1);
1146}
1147
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001148// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001149DEF_TEST(SkParagraph_BoldParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001150 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001151 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001152 TestCanvas canvas("SkParagraph_BoldParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001153 const char* text = "This is Red max bold text!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001154 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001155
1156 ParagraphStyle paragraph_style;
1157 paragraph_style.turnHintingOff();
1158 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1159
1160 TextStyle text_style;
1161 text_style.setFontFamilies({SkString("Roboto")});
1162 text_style.setColor(SK_ColorRED);
1163 text_style.setFontSize(60);
1164 text_style.setLetterSpacing(0);
1165 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width,
1166 SkFontStyle::kUpright_Slant));
1167 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001168 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001169 builder.pop();
1170
1171 auto paragraph = builder.Build();
1172 paragraph->layout(VeryLongCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001173 paragraph->paint(canvas.get(), 10.0, 60.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001174
Julia Lavrova3281b962019-12-02 11:32:25 -05001175 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1176
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001177 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1178
1179 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1180 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1181 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1182
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001183 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001184 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001185 StyleType::kAllAttributes,
1186 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001187 REPORTER_ASSERT(reporter, style.equals(text_style));
Julia Lavrova526df262019-08-21 17:49:44 -04001188 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001189 ++index;
1190 return true;
1191 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001192 REPORTER_ASSERT(reporter, index == 1);
1193}
1194
Julia Lavrovac2228562019-08-08 16:51:27 -04001195// Checked: NO DIFF (line height rounding error)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001196DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001197 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04001198 if (!fontCollection->fontsFound()) return;
1199 TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png");
1200 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001201 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001202
Julia Lavrovac2228562019-08-08 16:51:27 -04001203 ParagraphStyle paragraph_style;
1204 paragraph_style.turnHintingOff();
1205 paragraph_style.setMaxLines(10);
1206 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001207
Julia Lavrovac2228562019-08-08 16:51:27 -04001208 TextStyle text_style;
1209 text_style.setFontFamilies({SkString("Roboto")});
1210 text_style.setFontSize(20);
1211 text_style.setColor(SK_ColorBLACK);
1212 text_style.setHeight(3.6345f);
1213 text_style.setHeightOverride(true);
1214 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001215 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04001216 builder.pop();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001217
Julia Lavrovac2228562019-08-08 16:51:27 -04001218 auto paragraph = builder.Build();
1219 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001220
Julia Lavrovac2228562019-08-08 16:51:27 -04001221 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001222 REPORTER_ASSERT(reporter, impl->runs().size() == 5);
Julia Lavrovac2228562019-08-08 16:51:27 -04001223 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
1224 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001225
Julia Lavrovac2228562019-08-08 16:51:27 -04001226 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001227
Julia Lavrovac2228562019-08-08 16:51:27 -04001228 SkPaint paint;
1229 paint.setStyle(SkPaint::kStroke_Style);
1230 paint.setAntiAlias(true);
1231 paint.setStrokeWidth(1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001232
Julia Lavrovac2228562019-08-08 16:51:27 -04001233 // Tests for GetRectsForRange()
1234 RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle;
1235 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1236 paint.setColor(SK_ColorRED);
1237 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
1238 canvas.drawRects(SK_ColorRED, boxes);
1239 REPORTER_ASSERT(reporter, boxes.size() == 0ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001240
Julia Lavrovac2228562019-08-08 16:51:27 -04001241 boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style);
1242 canvas.drawRects(SK_ColorBLUE, boxes);
1243 REPORTER_ASSERT(reporter, boxes.size() == 3ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001244
Julia Lavrovac2228562019-08-08 16:51:27 -04001245 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100));
1246 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5));
1247 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100));
1248 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001249}
1250
Julia Lavrovac2228562019-08-08 16:51:27 -04001251// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001252DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001253 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001254 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001255 TestCanvas canvas("SkParagraph_LeftAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001256 const char* text =
1257 "This is a very long sentence to test if the text will properly wrap "
1258 "around and go to the next line. Sometimes, short sentence. Longer "
1259 "sentences are okay too because they are nessecary. Very short. "
1260 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1261 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1262 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1263 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1264 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1265 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1266 "mollit anim id est laborum. "
1267 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1268 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1269 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1270 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1271 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1272 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1273 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001274 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001275
1276 ParagraphStyle paragraph_style;
1277 paragraph_style.setMaxLines(14);
1278 paragraph_style.setTextAlign(TextAlign::kLeft);
1279 paragraph_style.turnHintingOff();
1280 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1281
1282 TextStyle text_style;
1283 text_style.setFontFamilies({SkString("Roboto")});
1284 text_style.setFontSize(26);
1285 text_style.setLetterSpacing(1);
1286 text_style.setWordSpacing(5);
1287 text_style.setColor(SK_ColorBLACK);
1288 text_style.setHeight(1);
1289 text_style.setDecoration(TextDecoration::kUnderline);
1290 text_style.setDecorationColor(SK_ColorBLACK);
1291 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001292 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001293 builder.pop();
1294
1295 auto paragraph = builder.Build();
1296 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001297 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001298
1299 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001300
1301 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1302 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1303 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001304 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001305 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1306
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001307 double expected_y = 0;
1308 double epsilon = 0.01f;
1309 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1310 REPORTER_ASSERT(reporter,
1311 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1312 expected_y += 30;
1313 REPORTER_ASSERT(reporter,
1314 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1315 expected_y += 30;
1316 REPORTER_ASSERT(reporter,
1317 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1318 expected_y += 30;
1319 REPORTER_ASSERT(reporter,
1320 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1321 expected_y += 30 * 10;
1322 REPORTER_ASSERT(reporter,
1323 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1324
1325 REPORTER_ASSERT(reporter,
1326 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1327
1328 // Tests for GetGlyphPositionAtCoordinate()
1329 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0);
1330 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
1331 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
1332 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001333 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001334}
1335
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001336// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001337DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001338 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001339 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001340 TestCanvas canvas("SkParagraph_RightAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001341 const char* text =
1342 "This is a very long sentence to test if the text will properly wrap "
1343 "around and go to the next line. Sometimes, short sentence. Longer "
1344 "sentences are okay too because they are nessecary. Very short. "
1345 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1346 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1347 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1348 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1349 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1350 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1351 "mollit anim id est laborum. "
1352 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1353 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1354 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1355 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1356 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1357 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1358 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001359 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001360
1361 ParagraphStyle paragraph_style;
1362 paragraph_style.setMaxLines(14);
1363 paragraph_style.setTextAlign(TextAlign::kRight);
1364 paragraph_style.turnHintingOff();
1365 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1366
1367 TextStyle text_style;
1368 text_style.setFontFamilies({SkString("Roboto")});
1369 text_style.setFontSize(26);
1370 text_style.setLetterSpacing(1);
1371 text_style.setWordSpacing(5);
1372 text_style.setColor(SK_ColorBLACK);
1373 text_style.setHeight(1);
1374 text_style.setDecoration(TextDecoration::kUnderline);
1375 text_style.setDecorationColor(SK_ColorBLACK);
1376 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001377 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001378 builder.pop();
1379
1380 auto paragraph = builder.Build();
1381 paragraph->layout(TestCanvasWidth - 100);
1382
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001383 paragraph->paint(canvas.get(), 0, 0);
1384
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001385 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001386
1387 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1388 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001389 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001390 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1391
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001392 double expected_y = 0;
1393 double epsilon = 0.01f;
1394 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1395 REPORTER_ASSERT(reporter,
1396 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1397 expected_y += 30;
1398 REPORTER_ASSERT(reporter,
1399 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1400 expected_y += 30;
1401 REPORTER_ASSERT(reporter,
1402 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1403 expected_y += 30;
1404 REPORTER_ASSERT(reporter,
1405 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1406 expected_y += 30 * 10;
1407 REPORTER_ASSERT(reporter,
1408 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1409
1410 auto calculate = [](const TextLine& line) -> SkScalar {
1411 return TestCanvasWidth - 100 - line.offset().fX - line.width();
1412 };
1413
1414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1416 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1417 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1418 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1419
1420 REPORTER_ASSERT(reporter,
1421 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1422}
1423
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001424// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001425DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001426 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001427 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001428 TestCanvas canvas("SkParagraph_CenterAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001429 const char* text =
1430 "This is a very long sentence to test if the text will properly wrap "
1431 "around and go to the next line. Sometimes, short sentence. Longer "
1432 "sentences are okay too because they are nessecary. Very short. "
1433 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1434 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1435 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1436 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1437 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1438 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1439 "mollit anim id est laborum. "
1440 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1441 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1442 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1443 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1444 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1445 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1446 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001447 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001448
1449 ParagraphStyle paragraph_style;
1450 paragraph_style.setMaxLines(14);
1451 paragraph_style.setTextAlign(TextAlign::kCenter);
1452 paragraph_style.turnHintingOff();
1453 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1454
1455 TextStyle text_style;
1456 text_style.setFontFamilies({SkString("Roboto")});
1457 text_style.setFontSize(26);
1458 text_style.setLetterSpacing(1);
1459 text_style.setWordSpacing(5);
1460 text_style.setColor(SK_ColorBLACK);
1461 text_style.setHeight(1);
1462 text_style.setDecoration(TextDecoration::kUnderline);
1463 text_style.setDecorationColor(SK_ColorBLACK);
1464 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001465 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001466 builder.pop();
1467
1468 auto paragraph = builder.Build();
1469 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001470 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001471
1472 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001473
1474 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1475 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1476 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001477 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001478 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1479
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001480 double expected_y = 0;
1481 double epsilon = 0.01f;
1482 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1483 REPORTER_ASSERT(reporter,
1484 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1485 expected_y += 30;
1486 REPORTER_ASSERT(reporter,
1487 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1488 expected_y += 30;
1489 REPORTER_ASSERT(reporter,
1490 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1491 expected_y += 30;
1492 REPORTER_ASSERT(reporter,
1493 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1494 expected_y += 30 * 10;
1495 REPORTER_ASSERT(reporter,
1496 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1497
1498 auto calculate = [](const TextLine& line) -> SkScalar {
1499 return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width());
1500 };
1501
1502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1506 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1507
1508 REPORTER_ASSERT(reporter,
1509 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1510}
1511
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001512// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001513DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001514 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001515 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001516 TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001517 const char* text =
1518 "This is a very long sentence to test if the text will properly wrap "
1519 "around and go to the next line. Sometimes, short sentence. Longer "
1520 "sentences are okay too because they are nessecary. Very short. "
1521 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1522 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1523 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1524 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1525 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1526 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1527 "mollit anim id est laborum. "
1528 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1529 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1530 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1531 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1532 "velit esse cillum dolore eu fugiat.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001533 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001534
1535 ParagraphStyle paragraph_style;
1536 paragraph_style.setMaxLines(14);
1537 paragraph_style.setTextAlign(TextAlign::kJustify);
1538 paragraph_style.turnHintingOff();
1539 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1540
1541 TextStyle text_style;
1542 text_style.setFontFamilies({SkString("Roboto")});
1543 text_style.setFontSize(26);
1544 text_style.setLetterSpacing(0);
1545 text_style.setWordSpacing(5);
1546 text_style.setColor(SK_ColorBLACK);
1547 text_style.setHeight(1);
1548 text_style.setDecoration(TextDecoration::kUnderline);
1549 text_style.setDecorationColor(SK_ColorBLACK);
1550 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001551 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001552 builder.pop();
1553
1554 auto paragraph = builder.Build();
1555 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001556 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001557
Julia Lavrovac2228562019-08-08 16:51:27 -04001558 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1559 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1560 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1561 canvas.drawRects(SK_ColorRED, boxes);
1562
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001563 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001564
1565 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1566 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1567 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001568 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001569
1570 double expected_y = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001571 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001572 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001573 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001574 expected_y += 30;
1575 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001576 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001577 expected_y += 30;
1578 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001579 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001580 expected_y += 30;
1581 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001582 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001583 expected_y += 30 * 9;
1584 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001585 SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001586
1587 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001588 return line.offset().fX;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001589 };
1590
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001591 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100));
1592 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100));
1593 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100));
1594 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001595
1596 REPORTER_ASSERT(reporter,
1597 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1598}
1599
Julia Lavrovac2228562019-08-08 16:51:27 -04001600// Checked: DIFF (ghost spaces as a separate box in TxtLib)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001601DEF_TEST(SkParagraph_JustifyRTL, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001602 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001603 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001604 TestCanvas canvas("SkParagraph_JustifyRTL.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001605 const char* text =
1606 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1607 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1608 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001609 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001610
1611 ParagraphStyle paragraph_style;
1612 paragraph_style.setMaxLines(14);
1613 paragraph_style.setTextAlign(TextAlign::kJustify);
1614 paragraph_style.turnHintingOff();
1615 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1616
1617 TextStyle text_style;
1618 text_style.setFontFamilies({SkString("Ahem")});
1619 text_style.setFontSize(26);
1620 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001621 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001622 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001623 builder.pop();
1624
1625 auto paragraph = builder.Build();
1626 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001627 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001628
1629 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001630
1631 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001632 return TestCanvasWidth - 100 - line.width();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001633 };
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001634 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001635 if (&line == &impl->lines().back()) {
1636 REPORTER_ASSERT(reporter, calculate(line) > EPSILON100);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001637 } else {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001638 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001639 }
1640 }
1641
1642 // Just make sure the the text is actually RTL
1643 for (auto& run : impl->runs()) {
1644 REPORTER_ASSERT(reporter, !run.leftToRight());
1645 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001646
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001647 // Tests for GetRectsForRange()
1648 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1649 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1650 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1651 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001652 REPORTER_ASSERT(reporter, boxes.size() == 5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001653
1654 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1655 canvas.drawRects(SK_ColorBLUE, boxes);
1656 REPORTER_ASSERT(reporter, boxes.size() == 1);
1657
1658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100));
1659 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1660 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100));
1661 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1662}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001663
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001664DEF_TEST_DISABLED(SkParagraph_JustifyRTLNewLine, reporter) {
1665 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1666 if (!fontCollection->fontsFound()) return;
1667 TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png");
1668 const char* text =
1669 "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1670 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1671 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
1672
1673 auto icu_text = icu::UnicodeString::fromUTF8(text);
1674 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1675 const size_t len = strlen(text);
1676
1677 ParagraphStyle paragraph_style;
1678 paragraph_style.setMaxLines(14);
1679 paragraph_style.setTextAlign(TextAlign::kJustify);
1680 paragraph_style.setTextDirection(TextDirection::kRtl);
1681 paragraph_style.turnHintingOff();
1682 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1683
1684 TextStyle text_style;
1685 text_style.setFontFamilies({SkString("Ahem")});
1686 text_style.setFontSize(26);
1687 text_style.setColor(SK_ColorBLACK);
1688 builder.pushStyle(text_style);
1689 builder.addText(text, len);
1690 builder.pop();
1691
1692 auto paragraph = builder.Build();
1693 paragraph->layout(TestCanvasWidth - 100);
1694 paragraph->paint(canvas.get(), 0, 0);
1695
1696 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1697
1698 SkPaint paint;
1699 paint.setStyle(SkPaint::kStroke_Style);
1700 paint.setAntiAlias(true);
1701 paint.setStrokeWidth(1);
1702
1703 // Tests for GetRectsForRange()
1704 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1705 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1706 paint.setColor(SK_ColorRED);
1707 auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
1708 for (size_t i = 0; i < boxes.size(); ++i) {
1709 canvas.get()->drawRect(boxes[i].rect, paint);
1710 }
1711 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1712 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
1713 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
1714 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1715 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
1716
1717 paint.setColor(SK_ColorBLUE);
1718 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1719 for (size_t i = 0; i < boxes.size(); ++i) {
1720 canvas.get()->drawRect(boxes[i].rect, paint);
1721 }
1722 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
1723 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
1724 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1725 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
1726 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1727
1728 // All lines should be justified to the width of the
1729 // paragraph.
1730 for (auto& line : impl->lines()) {
1731 REPORTER_ASSERT(reporter,
1732 SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
1733 }
1734}
1735
1736DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
1737 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1738 if (!fontCollection->fontsFound()) return;
1739 TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
1740
1741 const char* text = " leading space";
1742
1743 auto icu_text = icu::UnicodeString::fromUTF8(text);
1744 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1745 const size_t len = strlen(text);
1746
1747 ParagraphStyle paragraph_style;
1748 paragraph_style.setMaxLines(14);
1749 paragraph_style.setTextAlign(TextAlign::kJustify);
1750 paragraph_style.setTextDirection(TextDirection::kRtl);
1751 paragraph_style.turnHintingOff();
1752 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1753
1754 TextStyle text_style;
1755 text_style.setFontFamilies({SkString("Ahem")});
1756 text_style.setFontSize(26);
1757 text_style.setColor(SK_ColorBLACK);
1758 builder.pushStyle(text_style);
1759 builder.addText(text, len);
1760 builder.pop();
1761
1762 auto paragraph = builder.Build();
1763 paragraph->layout(TestCanvasWidth - 100);
1764 paragraph->paint(canvas.get(), 0, 0);
1765
1766 SkPaint paint;
1767 paint.setStyle(SkPaint::kStroke_Style);
1768 paint.setAntiAlias(true);
1769 paint.setStrokeWidth(1);
1770
1771 // Tests for GetRectsForRange()
1772 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1773 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1774 paint.setColor(SK_ColorRED);
1775 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1776 for (size_t i = 0; i < boxes.size(); ++i) {
1777 canvas.get()->drawRect(boxes[i].rect, paint);
1778 }
1779 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1780}
1781
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001782// Checked: NO DIFF (some minor decoration differences, probably)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001783DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001784 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001785 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001786 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001787 const char* text1 = "This text should be";
1788 const char* text2 = " decorated even when";
1789 const char* text3 = " wrapped around to";
1790 const char* text4 = " the next line.";
1791 const char* text5 = " Otherwise, bad things happen.";
1792
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001793 ParagraphStyle paragraph_style;
1794 paragraph_style.setMaxLines(14);
1795 paragraph_style.setTextAlign(TextAlign::kLeft);
1796 paragraph_style.turnHintingOff();
1797 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1798
1799 TextStyle text_style;
1800 text_style.setFontFamilies({SkString("Roboto")});
1801 text_style.setFontSize(26);
1802 text_style.setLetterSpacing(0);
1803 text_style.setWordSpacing(5);
1804 text_style.setColor(SK_ColorBLACK);
1805 text_style.setHeight(2);
1806 text_style.setDecoration(TextDecoration::kUnderline);
1807 text_style.setDecorationColor(SK_ColorBLACK);
1808 text_style.setDecoration((TextDecoration)(
1809 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1810 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1811 text_style.setDecorationColor(SK_ColorBLACK);
1812 text_style.setDecorationThicknessMultiplier(2.0);
1813 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001814 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001815
1816 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1817 text_style.setDecorationColor(SK_ColorBLUE);
1818 text_style.setDecorationThicknessMultiplier(1.0);
1819 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001820 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001821
1822 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1823 text_style.setDecorationColor(SK_ColorBLACK);
1824 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001825 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001826
1827 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1828 text_style.setDecorationColor(SK_ColorBLACK);
1829 text_style.setDecorationThicknessMultiplier(3.0);
1830 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001831 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001832
1833 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1834 text_style.setDecorationColor(SK_ColorRED);
1835 text_style.setDecorationThicknessMultiplier(1.0);
1836 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001837 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001838 builder.pop();
1839
1840 auto paragraph = builder.Build();
1841 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001842 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001843
1844 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001845
1846 size_t index = 0;
1847 for (auto& line : impl->lines()) {
1848 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001849 StyleType::kDecorations,
1850 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001851 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1852 TextDecoration::kOverline |
1853 TextDecoration::kLineThrough);
1854 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1855 switch (index) {
1856 case 0:
1857 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1858 TextDecorationStyle::kSolid);
1859 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1860 REPORTER_ASSERT(reporter,
1861 style.getDecorationThicknessMultiplier() == 2.0);
1862 break;
1863 case 1: // The style appears on 2 lines so it has 2 pieces
1864 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1865 TextDecorationStyle::kDouble);
1866 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1867 REPORTER_ASSERT(reporter,
1868 style.getDecorationThicknessMultiplier() == 1.0);
1869 break;
1870 case 2:
1871 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1872 TextDecorationStyle::kDotted);
1873 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1874 REPORTER_ASSERT(reporter,
1875 style.getDecorationThicknessMultiplier() == 1.0);
1876 break;
1877 case 3:
1878 case 4:
1879 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1880 TextDecorationStyle::kDashed);
1881 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1882 REPORTER_ASSERT(reporter,
1883 style.getDecorationThicknessMultiplier() == 3.0);
1884 break;
1885 case 5:
1886 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1887 TextDecorationStyle::kWavy);
1888 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1889 REPORTER_ASSERT(reporter,
1890 style.getDecorationThicknessMultiplier() == 1.0);
1891 break;
1892 default:
1893 REPORTER_ASSERT(reporter, false);
1894 break;
1895 }
1896 ++index;
1897 return true;
1898 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001899 }
1900}
1901
Julia Lavrovac2228562019-08-08 16:51:27 -04001902DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001903 SkDebugf("TODO: Add test for wavy decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001904}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001905
1906// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001907DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001908 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001909 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001910 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001911 const char* text1 = "No italic ";
1912 const char* text2 = "Yes Italic ";
1913 const char* text3 = "No Italic again.";
1914
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001915 ParagraphStyle paragraph_style;
1916 paragraph_style.turnHintingOff();
1917 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1918
1919 TextStyle text_style;
1920 text_style.setFontFamilies({SkString("Roboto")});
1921 text_style.setFontSize(10);
1922 text_style.setColor(SK_ColorRED);
1923 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001924 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001925
1926 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1927 SkFontStyle::kItalic_Slant));
1928 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001929 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001930 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001931 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001932
1933 auto paragraph = builder.Build();
1934 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001935 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001936
1937 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001938
1939 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1940 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1941 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1942 auto& line = impl->lines()[0];
1943 size_t index = 0;
1944 line.scanStyles(
1945 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001946 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001947 switch (index) {
1948 case 0:
1949 REPORTER_ASSERT(
1950 reporter,
1951 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1952 break;
1953 case 1:
1954 REPORTER_ASSERT(reporter,
1955 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1956 break;
1957 case 2:
1958 REPORTER_ASSERT(
1959 reporter,
1960 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1961 break;
1962 default:
1963 REPORTER_ASSERT(reporter, false);
1964 break;
1965 }
1966 ++index;
1967 return true;
1968 });
1969}
1970
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001971// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001972DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001973 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001974 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001975 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001976 const char* text =
1977 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1978 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1979 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1980 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1981 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001982 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001983
1984 ParagraphStyle paragraph_style;
1985 paragraph_style.setMaxLines(14);
1986 paragraph_style.setTextAlign(TextAlign::kJustify);
1987 paragraph_style.turnHintingOff();
1988 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1989
1990 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
1991 TextDecoration::kLineThrough);
1992
1993 TextStyle text_style;
1994 text_style.setFontFamilies({SkString("Source Han Serif CN")});
1995 text_style.setFontSize(35);
1996 text_style.setColor(SK_ColorBLACK);
1997 text_style.setLetterSpacing(2);
1998 text_style.setHeight(1);
1999 text_style.setDecoration(decoration);
2000 text_style.setDecorationColor(SK_ColorBLACK);
2001 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2002 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002003 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002004 builder.pop();
2005
2006 auto paragraph = builder.Build();
2007 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002008 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002009
Julia Lavrova3281b962019-12-02 11:32:25 -05002010 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2011
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002012 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002013
2014 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2015 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
2016 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002017 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002018}
2019
Julia Lavrovac2228562019-08-08 16:51:27 -04002020// Checked: NO DIFF (disabled)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002021DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002022 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002023 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002024 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002025 const char* text =
2026 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2027 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002028 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002029
2030 ParagraphStyle paragraph_style;
2031 paragraph_style.setMaxLines(14);
2032 paragraph_style.setTextAlign(TextAlign::kJustify);
2033 paragraph_style.turnHintingOff();
2034 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2035
2036 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2037 TextDecoration::kLineThrough);
2038
2039 TextStyle text_style;
2040 text_style.setFontFamilies({SkString("Katibeh")});
2041 text_style.setFontSize(35);
2042 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002043 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002044 text_style.setDecoration(decoration);
2045 text_style.setDecorationColor(SK_ColorBLACK);
2046 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2047 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002048 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002049 builder.pop();
2050
2051 auto paragraph = builder.Build();
2052 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002053 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002054
Julia Lavrova3281b962019-12-02 11:32:25 -05002055 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2056
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002057 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002058
2059 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2060 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2061 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002062 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002063}
2064
Julia Lavrovac2228562019-08-08 16:51:27 -04002065// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002066DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
2067
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002068 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002069 if (!fontCollection->fontsFound()) return;
2070 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
2071 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002072 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002073
2074 ParagraphStyle paragraph_style;
2075 paragraph_style.turnHintingOff();
2076 paragraph_style.setMaxLines(14);
2077 paragraph_style.setTextAlign(TextAlign::kRight);
2078 paragraph_style.setTextDirection(TextDirection::kRtl);
2079 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2080
2081 TextStyle text_style;
2082 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2083 text_style.setFontSize(26);
2084 text_style.setWordSpacing(5);
2085 text_style.setColor(SK_ColorBLACK);
2086 text_style.setDecoration(TextDecoration::kUnderline);
2087 text_style.setDecorationColor(SK_ColorBLACK);
2088 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002089 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002090 builder.pop();
2091
2092 auto paragraph = builder.Build();
2093 paragraph->layout(TestCanvasWidth - 100);
2094
2095 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2096 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2097
2098 paragraph->paint(canvas.get(), 0, 0);
2099
2100 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2101 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2102 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
2103 canvas.drawRects(SK_ColorRED, boxes);
2104
Julia Lavrovac2228562019-08-08 16:51:27 -04002105 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002106
Julia Lavrovac2228562019-08-08 16:51:27 -04002107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
2108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
2110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002111}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002112
2113// Checked DIFF+
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002114// This test shows now 2 boxes for [36:40) range:
2115// [36:38) for arabic text and [38:39) for the last space
2116// that has default paragraph direction (LTR) and is placed at the end of the paragraph
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002117DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
2118
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002119 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002120 if (!fontCollection->fontsFound()) return;
2121 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
2122 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002123 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002124
2125 ParagraphStyle paragraph_style;
2126 paragraph_style.turnHintingOff();
2127 paragraph_style.setMaxLines(14);
2128 paragraph_style.setTextAlign(TextAlign::kLeft);
2129 paragraph_style.setTextDirection(TextDirection::kLtr);
2130 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2131
2132 TextStyle text_style;
2133 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2134 text_style.setFontSize(26);
2135 text_style.setWordSpacing(5);
2136 text_style.setColor(SK_ColorBLACK);
2137 text_style.setDecoration(TextDecoration::kUnderline);
2138 text_style.setDecorationColor(SK_ColorBLACK);
2139 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002140 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002141 builder.pop();
2142
2143 auto paragraph = builder.Build();
2144 paragraph->layout(TestCanvasWidth - 100);
2145
2146 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2147 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2148
2149 paragraph->paint(canvas.get(), 0, 0);
2150
2151 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2152 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002153 // There are 39 codepoints: [0:39); asking for [36:40) would give the same as for [36:39)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002154 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2155 canvas.drawRects(SK_ColorRED, boxes);
2156
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002157 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
2158 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.92f, EPSILON100)); // DIFF: 89.40625
2159 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2160 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 110.16f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002161 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002162}
2163
2164// Checked DIFF+
2165DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2166
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002167 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002168 if (!fontCollection->fontsFound()) return;
2169 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2170 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002171 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002172
2173 ParagraphStyle paragraph_style;
2174 paragraph_style.turnHintingOff();
2175 paragraph_style.setMaxLines(14);
2176 paragraph_style.setTextAlign(TextAlign::kRight);
2177 paragraph_style.setTextDirection(TextDirection::kLtr);
2178 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2179
2180 TextStyle text_style;
2181 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2182 text_style.setFontSize(26);
2183 text_style.setWordSpacing(5);
2184 text_style.setColor(SK_ColorBLACK);
2185 text_style.setDecoration(TextDecoration::kUnderline);
2186 text_style.setDecorationColor(SK_ColorBLACK);
2187 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002188 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002189 builder.pop();
2190
2191 auto paragraph = builder.Build();
2192 paragraph->layout(TestCanvasWidth - 100);
2193
2194 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2195 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2196
2197 paragraph->paint(canvas.get(), 0, 0);
2198
2199 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2200 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2201 std::vector<TextBox> boxes =
2202 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2203 canvas.drawRects(SK_ColorRED, boxes);
2204
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002205 REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF
2206 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.5f, EPSILON100)); // DIFF
2207 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2208 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 587.74f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002209 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002210}
2211
2212// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002213DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002214 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002215 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002216 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002217 const char* text =
2218 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2219 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002220 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002221
2222 ParagraphStyle paragraphStyle;
2223 paragraphStyle.setTextAlign(TextAlign::kLeft);
2224 paragraphStyle.setMaxLines(10);
2225 paragraphStyle.turnHintingOff();
2226 TextStyle textStyle;
2227 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002228 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2229 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002230 textStyle.setFontSize(50);
2231 textStyle.setLetterSpacing(1);
2232 textStyle.setWordSpacing(5);
2233 textStyle.setHeight(1);
2234 textStyle.setColor(SK_ColorBLACK);
2235
2236 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2237 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002238 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002239 builder.pop();
2240
2241 auto paragraph = builder.Build();
2242 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002243 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002244
2245 // Tests for getGlyphPositionAtCoordinate()
2246 // NOTE: resulting values can be a few off from their respective positions in
2247 // the original text because the final trailing whitespaces are sometimes not
2248 // drawn (namely, when using "justify" alignment) and therefore are not active
2249 // glyphs.
2250 REPORTER_ASSERT(reporter,
2251 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2252 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2253 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2254 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2255 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2256 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002257 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002258 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2259 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2260 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002261 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002262 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002263 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002264 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2265 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002266 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002267 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2268 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002269 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002270 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2271 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2272 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002273 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002274 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2275}
2276
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002277// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002278DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002279 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002280 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002281 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002282 const char* text =
2283 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2284 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002285 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002286
2287 ParagraphStyle paragraphStyle;
2288 paragraphStyle.setTextAlign(TextAlign::kLeft);
2289 paragraphStyle.setMaxLines(10);
2290 paragraphStyle.turnHintingOff();
2291 TextStyle textStyle;
2292 textStyle.setFontFamilies({SkString("Roboto")});
2293 textStyle.setFontSize(50);
2294 textStyle.setColor(SK_ColorBLACK);
2295 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2296 SkFontStyle::kUpright_Slant));
2297
2298 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2299 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002300 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002301 builder.pop();
2302
2303 auto paragraph = builder.Build();
2304 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002305 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002306
2307 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2308 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002309
2310 SkPaint paint;
2311 paint.setStyle(SkPaint::kStroke_Style);
2312 paint.setAntiAlias(true);
2313 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002314
2315 {
2316 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2317 REPORTER_ASSERT(reporter, result.empty());
2318 }
2319 {
2320 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002321 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002322 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002323 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2324 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2325 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2326 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002327 }
2328 {
2329 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002330 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002331 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2333 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2334 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2335 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002336 }
2337 {
2338 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002339 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002340 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002341 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2342 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2343 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2344 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002345 }
2346 {
2347 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002348 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002349 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002350 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2351 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2353 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2354 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2355 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2356 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2357 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002358 }
2359 {
2360 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002361 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002362 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002363 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002364 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002365 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002366 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002367 }
2368 {
2369 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2370 REPORTER_ASSERT(reporter, result.empty());
2371 }
2372}
2373
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002374// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002375DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002376 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002377 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002378 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002379 const char* text =
2380 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2381 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2382 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002383 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002384
2385 ParagraphStyle paragraphStyle;
2386 paragraphStyle.setTextAlign(TextAlign::kLeft);
2387 paragraphStyle.setMaxLines(10);
2388 paragraphStyle.turnHintingOff();
2389 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002390 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002391 textStyle.setFontSize(50);
2392 textStyle.setColor(SK_ColorBLACK);
2393 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2394 SkFontStyle::kUpright_Slant));
2395
2396 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2397 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002398 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002399 builder.pop();
2400
2401 auto paragraph = builder.Build();
2402 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002403 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002404
2405 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2406 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002407 {
2408 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2409 REPORTER_ASSERT(reporter, result.empty());
2410 }
2411 {
2412 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002413 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002414 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2416 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2417 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2418 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002419 }
2420 {
2421 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002422 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002423 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002424 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2425 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2426 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2427 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002428 }
2429 {
2430 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002431 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002432 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002433 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2434 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2435 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2436 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002437 }
2438}
2439
Julia Lavrovac2228562019-08-08 16:51:27 -04002440// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002441DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002442 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002443 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002444 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002445 const char* text =
2446 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2447 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2448 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002449 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002450
2451 ParagraphStyle paragraphStyle;
2452 paragraphStyle.setTextAlign(TextAlign::kLeft);
2453 paragraphStyle.setMaxLines(10);
2454 paragraphStyle.turnHintingOff();
2455 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002456 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002457 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002458 textStyle.setHeight(1.6f);
2459 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002460 textStyle.setColor(SK_ColorBLACK);
2461 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2462 SkFontStyle::kUpright_Slant));
2463
2464 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2465 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002466 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002467 builder.pop();
2468
2469 auto paragraph = builder.Build();
2470 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002471 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002472
2473 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002474 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002475 {
2476 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2477 REPORTER_ASSERT(reporter, result.empty());
2478 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002479
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002480 {
2481 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002482 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002483 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2486 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2487 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002488 }
2489 {
2490 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002491 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002492 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2496 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002497 }
2498 {
2499 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002500 canvas.drawRects(SK_ColorGREEN, result);
2501 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002506 }
2507 {
2508 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002509 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002510 REPORTER_ASSERT(reporter, result.size() == 8);
2511
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002512 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002513 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2514 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2516
2517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2518 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2519 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2520 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2521
2522 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2523 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002524 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002525 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2526
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002527 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002528 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2529 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2530 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2531
2532 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2536
2537 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2538 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2539 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2540 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002541 }
2542 {
2543 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002544 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002545 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002546 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002547 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002548 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002549 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2550
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002551 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002552 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2553 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2554 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002555 }
2556 {
2557 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2558 REPORTER_ASSERT(reporter, result.empty());
2559 }
2560}
2561
Julia Lavrovac2228562019-08-08 16:51:27 -04002562// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002563DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002564 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002565 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002566 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002567 const char* text =
2568 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2569 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2570 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002571 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002572
2573 ParagraphStyle paragraphStyle;
2574 paragraphStyle.setTextAlign(TextAlign::kLeft);
2575 paragraphStyle.setMaxLines(10);
2576 paragraphStyle.turnHintingOff();
2577 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002578 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002579 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002580 textStyle.setHeight(1.6f);
2581 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002582 textStyle.setColor(SK_ColorBLACK);
2583 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2584 SkFontStyle::kUpright_Slant));
2585
2586 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2587 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002588 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002589 builder.pop();
2590
2591 auto paragraph = builder.Build();
2592 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002593 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002594
2595 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002596 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002597 {
2598 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2599 REPORTER_ASSERT(reporter, result.empty());
2600 }
2601
2602 {
2603 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002604 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002605 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002606 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2607 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2608 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2609 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002610 }
2611 {
2612 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002613 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002614 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002615 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2616 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2617 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2618 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002619 }
2620 {
2621 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002622 canvas.drawRects(SK_ColorGREEN, result);
2623 REPORTER_ASSERT(reporter, result.size() == 1);
2624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2625 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2627 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002628 }
2629 {
2630 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002631 canvas.drawRects(SK_ColorMAGENTA, result);
2632 REPORTER_ASSERT(reporter, result.size() == 8);
2633
2634 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2635 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2636 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2637 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2638
2639 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2640 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2641 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2643
2644 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2645 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2646 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2648
2649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2651 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2653
2654 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2658
2659 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2660 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2661 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2662 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002663 }
2664 {
2665 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002666 canvas.drawRects(SK_ColorBLACK, result);
2667 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002668 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002669 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002670 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002671 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2672
2673 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2674 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2675 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2676 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002677 }
2678 {
2679 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2680 REPORTER_ASSERT(reporter, result.empty());
2681 }
2682}
2683
Julia Lavrovac2228562019-08-08 16:51:27 -04002684// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002685DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002686 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002687 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002688 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002689 const char* text =
2690 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2691 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2692 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002693 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002694
2695 ParagraphStyle paragraphStyle;
2696 paragraphStyle.setTextAlign(TextAlign::kLeft);
2697 paragraphStyle.setMaxLines(10);
2698 paragraphStyle.turnHintingOff();
2699 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002700 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002701 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002702 textStyle.setHeight(1.6f);
2703 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002704 textStyle.setColor(SK_ColorBLACK);
2705 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2706 SkFontStyle::kUpright_Slant));
2707
2708 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2709 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002710 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002711 builder.pop();
2712
2713 auto paragraph = builder.Build();
2714 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002715 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002716
2717 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002718 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002719 {
2720 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2721 REPORTER_ASSERT(reporter, result.empty());
2722 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002723
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002724 {
2725 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002726 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002727 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002728 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2729 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2730 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2731 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002732 }
2733 {
2734 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002735 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002736 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002737 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2738 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2739 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2740 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002741 }
2742 {
2743 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002744 canvas.drawRects(SK_ColorGREEN, result);
2745 REPORTER_ASSERT(reporter, result.size() == 1);
2746 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2747 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2748 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
2749 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002750 }
2751 {
2752 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002753 canvas.drawRects(SK_ColorMAGENTA, result);
2754 REPORTER_ASSERT(reporter, result.size() == 8);
2755
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002756 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002757 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2758 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2759 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2760
2761 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2762 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2763 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2764 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2765
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002766 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002767 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2768 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2769 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2770
2771 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2772 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2773 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2774 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2775
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002776 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002777 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2778 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2780
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002781 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002782 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2783 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2784 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002785 }
2786 {
2787 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002788 canvas.drawRects(SK_ColorBLACK, result);
2789 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002790 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002791 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002792 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002793 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2794
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002795 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002796 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2797 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2798 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002799 }
2800 {
2801 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2802 REPORTER_ASSERT(reporter, result.empty());
2803 }
2804}
2805
Julia Lavrovac2228562019-08-08 16:51:27 -04002806// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002807DEF_TEST(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002808 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002809 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002810 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002811 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002812 const size_t len = strlen(text);
2813
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002814 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002815 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002816 paragraphStyle.setMaxLines(10);
2817 paragraphStyle.turnHintingOff();
2818 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2819
2820 TextStyle textStyle;
2821 textStyle.setFontFamilies({SkString("Roboto")});
2822 textStyle.setFontSize(50);
2823 textStyle.setLetterSpacing(1);
2824 textStyle.setWordSpacing(5);
2825 textStyle.setHeight(1);
2826 textStyle.setColor(SK_ColorBLACK);
2827
2828 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002829 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002830 builder.pop();
2831
2832 auto paragraph = builder.Build();
2833 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002834 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002835
2836 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002837 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2838
2839 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2840 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2841 {
2842 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2843 REPORTER_ASSERT(reporter, result.empty());
2844 }
2845 {
2846 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2847 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2848 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002849 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2850 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002851 }
2852 {
2853 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2854 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2855 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002856 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2857 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002858 }
2859 {
2860 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2861 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2862 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2863 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002864 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002865 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002866 }
2867}
2868
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002869// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002870DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002871 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002872 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002873 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002874 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2875 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2876 // Any attempt to substitute one for another leads to errors
2877 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002878 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002879 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002880
2881 ParagraphStyle paragraphStyle;
2882 paragraphStyle.setTextAlign(TextAlign::kCenter);
2883 paragraphStyle.setMaxLines(10);
2884 paragraphStyle.turnHintingOff();
2885 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2886
2887 TextStyle textStyle;
2888 textStyle.setFontFamilies({SkString("Roboto")});
2889 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002890 textStyle.setHeight(1);
2891 textStyle.setColor(SK_ColorBLACK);
2892 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2893 SkFontStyle::kUpright_Slant));
2894
2895 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002896 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002897 builder.pop();
2898
2899 auto paragraph = builder.Build();
2900 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002901 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002902
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002903 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002904 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2905 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002906 {
2907 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2908 REPORTER_ASSERT(reporter, result.empty());
2909 }
2910
2911 {
2912 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002913 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002914 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002915 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2917 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2918 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002919 }
2920
2921 {
2922 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002923 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002924 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002925 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2926 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2927 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2928 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002929 }
2930
2931 {
2932 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002933 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002934 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2938 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002939 }
2940
2941 {
2942 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002943 canvas.drawRects(SK_ColorBLACK, result);
2944 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2945 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2946 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2947 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2948 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002949 }
2950
2951 {
2952 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002953 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002954 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002955 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2956 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2957 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2958 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002959 }
2960
2961 {
2962 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2963 REPORTER_ASSERT(reporter, result.empty());
2964 }
2965}
2966
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002967// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002968DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002969 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002970 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002971 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002972 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002973 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002974
2975 ParagraphStyle paragraphStyle;
2976 paragraphStyle.setTextAlign(TextAlign::kCenter);
2977 paragraphStyle.setMaxLines(10);
2978 paragraphStyle.turnHintingOff();
2979 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2980
2981 TextStyle textStyle;
2982 textStyle.setFontFamilies({SkString("Roboto")});
2983 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002984 textStyle.setHeight(1);
2985 textStyle.setColor(SK_ColorBLACK);
2986 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2987 SkFontStyle::kUpright_Slant));
2988
2989 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002990 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002991 builder.pop();
2992
2993 auto paragraph = builder.Build();
2994 paragraph->layout(550);
2995
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002996 paragraph->paint(canvas.get(), 0, 0);
2997
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002998 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002999 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3000
3001 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3002 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003003 {
3004 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3005 REPORTER_ASSERT(reporter, result.empty());
3006 }
3007
3008 {
3009 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04003010 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003011 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003012 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
3013 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
3014 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
3015 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003016 }
3017
3018 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003019 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3020 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003021 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003022 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3023 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3024 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3025 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003026 }
3027}
3028
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003029// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003030DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003031 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003032 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003033 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3034 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003035 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003036
3037 ParagraphStyle paragraphStyle;
3038 paragraphStyle.setTextAlign(TextAlign::kCenter);
3039 paragraphStyle.setMaxLines(10);
3040 paragraphStyle.turnHintingOff();
3041 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3042
3043 TextStyle textStyle;
3044 textStyle.setFontFamilies({SkString("Roboto")});
3045 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003046 textStyle.setHeight(1);
3047 textStyle.setColor(SK_ColorBLACK);
3048 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3049 SkFontStyle::kUpright_Slant));
3050
3051 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003052 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003053 builder.pop();
3054
3055 auto paragraph = builder.Build();
3056 paragraph->layout(550);
3057
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003058 paragraph->paint(canvas.get(), 0, 0);
3059
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003060 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003061
3062 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3063
3064 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3065 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3066 SkScalar epsilon = 0.01f;
3067 {
3068 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3069 REPORTER_ASSERT(reporter, result.empty());
3070 }
3071 {
3072 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003073 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003074 REPORTER_ASSERT(reporter, result.size() == 1);
3075 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3076 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3077 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3078 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3079 }
3080 {
3081 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003082 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003083 REPORTER_ASSERT(reporter, result.size() == 1);
3084 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3085 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3086 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3088 }
3089 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003090 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003091 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003092 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003093 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3094 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003095 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003096 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3097 }
3098 {
3099 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003100 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003101 REPORTER_ASSERT(reporter, result.size() == 1);
3102 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3103 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003104 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003105 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3106 }
3107 {
3108 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003109 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003110 REPORTER_ASSERT(reporter, result.size() == 1);
3111 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3112 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3113 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3114 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3115 }
3116 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003117 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003118 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003119 REPORTER_ASSERT(reporter, result.size() == 1);
3120 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3121 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003122 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003123 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3124 }
3125 {
3126 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3127 REPORTER_ASSERT(reporter, result.empty());
3128 }
3129}
3130
Julia Lavrovac2228562019-08-08 16:51:27 -04003131// Checked: DIFF (line height rounding error)
3132DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003133 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003134 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003135 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3136 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003137 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003138
3139 StrutStyle strutStyle;
3140 strutStyle.setStrutEnabled(true);
3141 strutStyle.setFontFamilies({SkString("Roboto")});
3142 strutStyle.setFontSize(14.0);
3143
3144 ParagraphStyle paragraphStyle;
3145 paragraphStyle.setStrutStyle(strutStyle);
3146
3147 TextStyle textStyle;
3148 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3149 textStyle.setFontSize(20);
3150 textStyle.setColor(SK_ColorBLACK);
3151
3152 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3153 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003154 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003155 builder.pop();
3156
3157 auto paragraph = builder.Build();
3158 paragraph->layout(550);
3159 paragraph->paint(canvas.get(), 0, 0);
3160
3161 {
3162 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3163 canvas.drawRects(SK_ColorGREEN, result);
3164 REPORTER_ASSERT(reporter, result.size() == 1);
3165 }
3166
3167 {
3168 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3169 canvas.drawRects(SK_ColorRED, result);
3170 REPORTER_ASSERT(reporter, result.size() == 1);
3171 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3172 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3173 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3174 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3175 }
3176}
3177
3178// Checked: NO DIFF
3179DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003180 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003181 if (!fontCollection->fontsFound()) return;
3182 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3183 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003184 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003185
3186 StrutStyle strutStyle;
3187 strutStyle.setStrutEnabled(false);
3188
3189 ParagraphStyle paragraphStyle;
3190 paragraphStyle.setStrutStyle(strutStyle);
3191
3192 TextStyle textStyle;
3193 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3194 textStyle.setFontSize(20);
3195 textStyle.setColor(SK_ColorBLACK);
3196
3197 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3198 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003199 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003200 builder.pop();
3201
3202 auto paragraph = builder.Build();
3203 paragraph->layout(550);
3204 paragraph->paint(canvas.get(), 0, 0);
3205
3206
3207 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3208 canvas.drawRects(SK_ColorGREEN, result1);
3209 REPORTER_ASSERT(reporter, result1.size() == 1);
3210
3211 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3212 canvas.drawRects(SK_ColorRED, result2);
3213 REPORTER_ASSERT(reporter, result2.size() == 1);
3214
3215 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3216}
3217
3218// Checked: DIFF (small in numbers)
3219DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003220 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003221 if (!fontCollection->fontsFound()) return;
3222 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003223 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3224 "67890 12345 67890 12345 67890 12345";
3225 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003226 ParagraphStyle paragraphStyle;
3227 paragraphStyle.setTextAlign(TextAlign::kLeft);
3228 paragraphStyle.setMaxLines(10);
3229 paragraphStyle.turnHintingOff();
3230 TextStyle textStyle;
3231 textStyle.setFontFamilies({SkString("Roboto")});
3232 textStyle.setFontSize(52);
3233 textStyle.setLetterSpacing(1.19039f);
3234 textStyle.setWordSpacing(5);
3235 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003236 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003237 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003238
3239 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3240 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003241 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003242 builder.pop();
3243
3244 auto paragraph = builder.Build();
3245 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003246 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003247
3248 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3249 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3250 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3251 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3252 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003253 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3254 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003255
3256 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003257 boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003258 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003259
Julia Lavrovac2228562019-08-08 16:51:27 -04003260 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003261 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003262 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003263
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003264 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3265 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3266 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3267 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3268 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3269 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3270 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3271 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3272
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003273 boxes = paragraph->getRectsForRange(12, 13, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003274 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003275 boxes = paragraph->getRectsForRange(13, 14, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003276 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003277 boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003278 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003279 boxes = paragraph->getRectsForRange(19, 20, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003280 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003281 boxes = paragraph->getRectsForRange(24, 25, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003282 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003283 boxes = paragraph->getRectsForRange(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003284 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003285 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003286 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003287 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003288 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003289
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003290 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3291 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003292}
3293
Julia Lavrovac2228562019-08-08 16:51:27 -04003294// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003295DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003296 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003297 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003298 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003299 ParagraphStyle paragraph_style;
3300 paragraph_style.setMaxLines(10);
3301 paragraph_style.setTextAlign(TextAlign::kLeft);
3302 paragraph_style.turnHintingOff();
3303 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3304
3305 TextStyle text_style;
3306 text_style.setFontFamilies({SkString("Roboto")});
3307 text_style.setFontSize(50);
3308 text_style.setLetterSpacing(20);
3309 text_style.setWordSpacing(0);
3310 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003311 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003312 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003313 builder.pop();
3314
3315 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003316 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003317 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003318 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003319 builder.pop();
3320
3321 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003322 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003323 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003324 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003325 builder.pop();
3326
3327 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003328 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003329 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003330 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003331 builder.pop();
3332
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003333 const char* hSpace = "H ";
3334 const size_t len = strlen(hSpace);
3335
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003336 text_style.setLetterSpacing(0);
3337 text_style.setWordSpacing(20);
3338 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003339 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003340 builder.pop();
3341
3342 text_style.setLetterSpacing(0);
3343 text_style.setWordSpacing(0);
3344 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003345 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003346 builder.pop();
3347
3348 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003349 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003350 text_style.setWordSpacing(20);
3351 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003352 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003353 builder.pop();
3354
3355 auto paragraph = builder.Build();
3356 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003357 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003358
3359 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3360 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3361 size_t index = 0;
3362 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003363 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3364 ++index;
3365 return true;
3366 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003367 REPORTER_ASSERT(reporter, index == 4);
3368 index = 0;
3369 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003370 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3371 ++index;
3372 return true;
3373 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003374 REPORTER_ASSERT(reporter, index == 4);
3375}
3376
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003377// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003378DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003379 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003380 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003381 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003382 const char* text =
3383 "A "
3384 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3385 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003386 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003387
3388 ParagraphStyle paragraph_style;
3389 paragraph_style.turnHintingOff();
3390 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3391
3392 TextStyle text_style;
3393 text_style.setFontFamilies({SkString("Roboto")});
3394 text_style.setColor(SK_ColorRED);
3395 text_style.setFontSize(31);
3396 text_style.setLetterSpacing(0);
3397 text_style.setWordSpacing(0);
3398 text_style.setColor(SK_ColorBLACK);
3399 text_style.setHeight(1);
3400 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003401 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003402 builder.pop();
3403
3404 auto paragraph = builder.Build();
3405 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003406 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003407
3408 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3409 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3410 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3411 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003412 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003413 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3414
3415 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3416 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3417 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3418}
3419
Julia Lavrovac2228562019-08-08 16:51:27 -04003420// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003421DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003422 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003423 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003424 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3425
3426 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3427 const char* text2 = " Dialog Text List lots of words to see "
3428 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003429 float scale = 3.0f;
3430 ParagraphStyle paragraph_style;
3431 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3432 TextStyle text_style;
3433 text_style.setFontFamilies({SkString("Droid Serif")});
3434 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003435 text_style.setColor(SK_ColorBLACK);
3436
3437 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003438 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003439 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003440 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003441 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003442 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003443 text_style.setFontSize(14 / scale);
3444 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003445 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003446 builder.pop();
3447
3448 auto paragraph = builder.Build();
3449 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003450 canvas.get()->scale(scale, scale);
3451 paragraph->paint(canvas.get(), 0, 0);
3452 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003453
3454 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003455
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003456 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003457 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003458 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3459 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3460 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3461 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3462 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3463 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003464}
3465
Julia Lavrovac2228562019-08-08 16:51:27 -04003466// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003467DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003468 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003469 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003470 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003471 const char* text =
3472 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3473 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003474 const size_t len = strlen(text);
3475
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003476 ParagraphStyle paragraph_style;
3477 paragraph_style.turnHintingOff();
3478 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3479
3480 TextStyle text_style;
3481 text_style.setFontFamilies({SkString("Roboto")});
3482 text_style.setColor(SK_ColorRED);
3483 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003484 text_style.setColor(SK_ColorBLACK);
3485 text_style.setHeight(1);
3486 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003487 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003488 builder.pop();
3489
3490 auto paragraph = builder.Build();
3491 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003492 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003493
3494 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3495 // Minikin does not count empty lines but SkParagraph does
3496 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3497
3498 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3499 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3500 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3501 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3502 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003503 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3504 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003505}
3506
Julia Lavrova526df262019-08-21 17:49:44 -04003507// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003508DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003509 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003510 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003511 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3512 const char* text =
3513 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3514 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3515 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3516 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003517 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003518
3519 ParagraphStyle paragraph_style;
3520 paragraph_style.turnHintingOff();
3521 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3522
3523 TextStyle text_style;
3524 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3525 text_style.setFontSize(50);
3526 text_style.setDecoration(TextDecoration::kUnderline);
3527 text_style.setColor(SK_ColorBLACK);
3528 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003529 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003530 builder.pop();
3531
3532 auto paragraph = builder.Build();
3533 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003534 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003535
Julia Lavrova3281b962019-12-02 11:32:25 -05003536 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3537
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003538 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003539
3540 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3541 for (auto& line : impl->lines()) {
3542 if (&line != impl->lines().end() - 1) {
3543 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3544 } else {
3545 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3546 }
3547 REPORTER_ASSERT(reporter, line.height() == 59);
3548 }
3549}
3550
Julia Lavrovac2228562019-08-08 16:51:27 -04003551// Checked: DIFF+
3552DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003553 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003554 if (!fontCollection->fontsFound()) return;
3555 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3556 const char* text =
3557 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3558 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3559 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3560 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3561 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3562 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003563 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003564
3565 ParagraphStyle paragraph_style;
3566 paragraph_style.turnHintingOff();
3567 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3568
3569 TextStyle text_style;
3570 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3571 text_style.setFontSize(50);
3572 text_style.setColor(SK_ColorBLACK);
3573 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003574 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003575 builder.pop();
3576
3577 auto paragraph = builder.Build();
3578 paragraph->layout(TestCanvasWidth - 300);
3579 paragraph->paint(canvas.get(), 0, 0);
3580
3581 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3582 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3583
3584 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3585 REPORTER_ASSERT(reporter, result.size() == 0);
3586
3587 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3588 REPORTER_ASSERT(reporter, result.size() == 2);
3589 canvas.drawRects(SK_ColorRED, result);
3590
3591 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003592 REPORTER_ASSERT(reporter, result.size() == 0); // There is no single glyph
Julia Lavrovac2228562019-08-08 16:51:27 -04003593 canvas.drawRects(SK_ColorBLUE, result);
3594
3595 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3596 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3597 REPORTER_ASSERT(reporter, result.size() == 2);
3598 canvas.drawRects(SK_ColorGREEN, result);
3599
3600 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3601 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3602 REPORTER_ASSERT(reporter, result.size() == 2);
3603 canvas.drawRects(SK_ColorGREEN, result);
3604
3605 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3606 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3607 REPORTER_ASSERT(reporter, result.size() == 2);
3608 canvas.drawRects(SK_ColorGREEN, result);
3609}
3610
Julia Lavrova916a9042019-08-08 16:51:27 -04003611DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3612 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3613}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003614
Julia Lavrovac2228562019-08-08 16:51:27 -04003615// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003616DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003617 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003618 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003619 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003620 const char* text =
3621 "Sentence to layout at diff widths to get diff line counts. short words "
3622 "short words short words short words short words short words short words "
3623 "short words short words short words short words short words short words "
3624 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003625 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003626
3627 ParagraphStyle paragraph_style;
3628 paragraph_style.turnHintingOff();
3629 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3630
3631 TextStyle text_style;
3632 text_style.setFontFamilies({SkString("Roboto")});
3633 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003634 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003635 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003636 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003637 builder.pop();
3638
3639 auto paragraph = builder.Build();
3640 paragraph->layout(300);
3641
3642 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3643 // Some of the formatting lazily done on paint
3644 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3645 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3646 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3647
3648 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003649 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003650 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3651 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3652 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3653}
3654
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003655// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003656DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003657 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003658 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003659 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003660 const char* text =
3661 "This is a very long sentence to test if the text will properly wrap "
3662 "around and go to the next line. Sometimes, short sentence. Longer "
3663 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003664 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003665
3666 ParagraphStyle paragraph_style;
3667 paragraph_style.setMaxLines(1);
3668 paragraph_style.setEllipsis(u"\u2026");
3669 paragraph_style.turnHintingOff();
3670 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3671
3672 TextStyle text_style;
3673 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003674 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003675 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003676 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003677 builder.pop();
3678
3679 auto paragraph = builder.Build();
3680 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003681 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003682
3683 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003684
3685 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3686 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3687
3688 auto& line = impl->lines()[0];
3689 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003690 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003691}
3692
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003693// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003694DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003695 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003696 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003697 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003698 const char* text1 = "fluttser ";
3699 const char* text2 = "mdje";
3700 const char* text3 = "fluttser mdje";
3701
3702 ParagraphStyle paragraph_style;
3703 paragraph_style.turnHintingOff();
3704 paragraph_style.setTextAlign(TextAlign::kLeft);
3705 paragraph_style.setMaxLines(2);
3706 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3707
3708 TextStyle text_style;
3709 text_style.setFontFamilies({SkString("Roboto")});
3710 text_style.setColor(SK_ColorBLACK);
3711 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003712 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003713 text_style.setDecoration(TextDecoration::kUnderline);
3714 text_style.setDecorationColor(SK_ColorBLACK);
3715 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003716 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003717 builder.pop();
3718
3719 auto paragraph = builder.Build();
3720 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003721 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003722
3723 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3724
3725 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3726 text_style.setDecoration(TextDecoration::kNoDecoration);
3727 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003728 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003729 builder1.pop();
3730
3731 auto paragraph1 = builder1.Build();
3732 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003733 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003734
3735 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3736
3737 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3738 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003739
3740 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3741 .front()
3742 .rect;
3743 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3744 .front()
3745 .rect;
3746 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3747 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3748
3749 for (size_t i = 0; i < 12; ++i) {
3750 auto r =
3751 paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
3752 .front()
3753 .rect;
3754 auto r1 =
3755 paragraph1
3756 ->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
3757 .front()
3758 .rect;
3759
3760 REPORTER_ASSERT(reporter, r.fLeft == r1.fLeft);
3761 REPORTER_ASSERT(reporter, r.fRight == r1.fRight);
3762 }
3763}
3764
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003765// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003766DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003767 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003768 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003769 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003770 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003771 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003772
3773 ParagraphStyle paragraph_style;
3774 paragraph_style.turnHintingOff();
3775 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3776
3777 TextStyle text_style;
3778 text_style.setFontFamilies({SkString("Roboto")});
3779 text_style.setColor(SK_ColorBLACK);
3780 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3781 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003782 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003783
3784 auto paragraph = builder.Build();
3785 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003786 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003787
3788 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3789
3790 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3791 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3792 size_t index = 0;
3793 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003794 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003795 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003796 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3797 ++index;
3798 return true;
3799 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003800 }
3801}
3802
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003803// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003804DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003805 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003806 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003807 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003808 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003809 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003810
3811 ParagraphStyle paragraph_style;
3812 paragraph_style.turnHintingOff();
3813 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3814
3815 TextStyle text_style;
3816 text_style.setFontFamilies({SkString("Roboto")});
3817 text_style.setColor(SK_ColorBLACK);
3818 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3819 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003820 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003821
3822 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3823 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3824 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003825 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003826 builder.pop();
3827
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003828 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003829
3830 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3831 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003832 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003833 builder.pop();
3834
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003835 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003836
3837 auto paragraph = builder.Build();
3838 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003839 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003840
3841 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3842
3843 size_t index = 0;
3844 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003845 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003846 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003847 ++index;
3848 switch (index) {
3849 case 1:
3850 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3851 break;
3852 case 2:
3853 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3854 break;
3855 case 3:
3856 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3857 break;
3858 case 4:
3859 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3860 REPORTER_ASSERT(reporter, style.equals(text_style));
3861 break;
3862 case 5:
3863 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3864 break;
3865 default:
3866 REPORTER_ASSERT(reporter, false);
3867 }
3868 return true;
3869 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003870 }
3871}
3872
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003873// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003874DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003875 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003876 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003877 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003878 const char* text =
3879 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3880 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003881 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003882
3883 ParagraphStyle paragraph_style;
3884 paragraph_style.turnHintingOff();
3885 paragraph_style.setMaxLines(14);
3886 paragraph_style.setTextAlign(TextAlign::kJustify);
3887 paragraph_style.setHeight(1.5);
3888 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3889
3890 TextStyle text_style;
3891 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3892 text_style.setColor(SK_ColorBLACK);
3893 text_style.setFontSize(55);
3894 text_style.setLetterSpacing(2);
3895 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3896 text_style.setDecorationColor(SK_ColorBLACK);
3897 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003898 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003899 builder.pop();
3900
3901 auto paragraph = builder.Build();
3902 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003903 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003904
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003905 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3906 paragraph->getMaxWidth(),
3907 paragraph->getIdeographicBaseline());
3908 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3909 paragraph->getMaxWidth(),
3910 paragraph->getAlphabeticBaseline());
3911 canvas.drawLine(SK_ColorRED, rect1, false);
3912 canvas.drawLine(SK_ColorGREEN, rect2, false);
3913
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003914 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003915 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003916 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003917 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003918}
3919
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003920// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003921DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003922 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003923 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003924 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003925
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003926 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3927 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3928 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003929
3930 ParagraphStyle paragraph_style;
3931 paragraph_style.turnHintingOff();
3932 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3933
3934 TextStyle text_style;
3935 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003936 SkString("Not a real font"),
3937 SkString("Also a fake font"),
3938 SkString("So fake it is obvious"),
3939 SkString("Next one should be a real font..."),
3940 SkString("Roboto"),
3941 SkString("another fake one in between"),
3942 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003943 });
3944 text_style.setColor(SK_ColorBLACK);
3945 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003946 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003947
3948 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003949 SkString("Not a real font"),
3950 SkString("Also a fake font"),
3951 SkString("So fake it is obvious"),
3952 SkString("Homemade Apple"),
3953 SkString("Next one should be a real font..."),
3954 SkString("Roboto"),
3955 SkString("another fake one in between"),
3956 SkString("Noto Sans CJK JP"),
3957 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003958 });
3959 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003960 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003961
3962 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003963 SkString("Not a real font"),
3964 SkString("Also a fake font"),
3965 SkString("So fake it is obvious"),
3966 SkString("Homemade Apple"),
3967 SkString("Next one should be a real font..."),
3968 SkString("Roboto"),
3969 SkString("another fake one in between"),
3970 SkString("Source Han Serif CN"),
3971 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003972 });
3973 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003974 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003975
3976 builder.pop();
3977
3978 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003979 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003980 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003981 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003982
Julia Lavrova3281b962019-12-02 11:32:25 -05003983 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
3984
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003985 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3986
3987 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3988 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3989 // [Apple + Noto] [Apple + Han]
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003990 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003991
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003992 auto robotoAdvance = impl->runs()[0].advance().fX +
3993 impl->runs()[1].advance().fX +
3994 impl->runs()[2].advance().fX;
3995 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
3996 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
3997 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
3998 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
3999 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004000
4001 // When a different font is resolved, then the metrics are different.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004002 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
4003 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004004}
4005
Julia Lavrovac2228562019-08-08 16:51:27 -04004006// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004007DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004008 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004009 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004010 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004011 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004012 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004013 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004014
4015 ParagraphStyle paragraph_style;
4016 paragraph_style.setMaxLines(10);
4017 paragraph_style.setTextAlign(TextAlign::kLeft);
4018 paragraph_style.turnHintingOff();
4019
4020 StrutStyle strut_style;
4021 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004022 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004023 strut_style.setFontSize(50);
4024 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004025 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004026 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004027 paragraph_style.setStrutStyle(strut_style);
4028
4029 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4030
4031 TextStyle text_style;
4032 text_style.setFontFamilies({SkString("Ahem")});
4033 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004034 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004035 text_style.setColor(SK_ColorBLACK);
4036 text_style.setHeight(0.5f);
4037 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004038 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004039 builder.pop();
4040
4041 auto paragraph = builder.Build();
4042 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004043 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004044
4045 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004046 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4047
4048 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4049 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4050 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004051 {
4052 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4053 REPORTER_ASSERT(reporter, boxes.empty());
4054 }
4055 {
4056 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004057 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004058 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004059 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4060 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4061 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4062 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004063 }
4064 {
4065 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004066 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004067 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004068 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4069 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4070 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4071 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004072 }
4073 {
4074 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004075 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004076 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004077 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4078 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004079 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004080 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004081 }
4082 {
4083 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004084 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004085 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004086 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004088 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004090 }
4091 {
4092 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004093 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004094 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004095 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4096 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 224.5f, EPSILON100));
4097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004099 }
4100 {
4101 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004102 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004103 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004104 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
4105 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 319.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004108 }
4109}
4110
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004111// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004112DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004113 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004114 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004115 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004116 // The chinese extra height should be absorbed by the strut.
4117 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004118 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004119
4120 ParagraphStyle paragraph_style;
4121 paragraph_style.setMaxLines(10);
4122 paragraph_style.setTextAlign(TextAlign::kLeft);
4123 paragraph_style.turnHintingOff();
4124
4125 StrutStyle strut_style;
4126
4127 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004128 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004129 strut_style.setFontSize(50);
4130 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004131 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004132 paragraph_style.setStrutStyle(strut_style);
4133
4134 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4135
4136 TextStyle text_style;
4137 text_style.setFontFamilies({SkString("Ahem")});
4138 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004139 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4140 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004141 text_style.setColor(SK_ColorBLACK);
4142 text_style.setHeight(1);
4143 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004144 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004145 builder.pop();
4146
4147 auto paragraph = builder.Build();
4148 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004149 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004150
4151 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4152 // Font is not resolved and the first line does not fit
4153 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4154
4155 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4156 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4157 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004158 {
4159 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4160 REPORTER_ASSERT(reporter, boxes.empty());
4161 }
4162 {
4163 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_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);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004166 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4167 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4168 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4169 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004170 }
4171 {
4172 auto boxes = paragraph->getRectsForRange(0, 1, 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);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004175 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4176 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4177 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4178 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004179 }
4180 {
4181 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004182 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004183 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004184 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4185 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4186 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4187 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004188 }
4189 {
4190 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004191 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004192 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004193 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4194 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4195 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4196 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004197 }
4198 {
4199 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004200 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004201 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004202 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4203 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 184, EPSILON100));
4204 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4205 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004206 }
4207 {
4208 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004209 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004210 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004211 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
4212 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 264, EPSILON100));
4213 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4214 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004215 }
4216}
4217
Julia Lavrovac2228562019-08-08 16:51:27 -04004218// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004219DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004220 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004221 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004222 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4223
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004224 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004225 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004226 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004227
4228 ParagraphStyle paragraph_style;
4229 paragraph_style.setMaxLines(10);
4230 paragraph_style.setTextAlign(TextAlign::kLeft);
4231 paragraph_style.turnHintingOff();
4232
4233 StrutStyle strut_style;
4234 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004235 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004236 strut_style.setFontSize(50);
4237 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004238 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004239 paragraph_style.setStrutStyle(strut_style);
4240
4241 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4242
4243 TextStyle text_style;
4244 text_style.setFontFamilies({SkString("Ahem")});
4245 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004246 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4247 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004248 text_style.setColor(SK_ColorBLACK);
4249 text_style.setHeight(1);
4250 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004251 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004252 builder.pop();
4253
4254 auto paragraph = builder.Build();
4255 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004256 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004257
4258 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4259 // Font is not resolved and the first line does not fit
4260 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4261
4262 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4263 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4264 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4265 SkScalar epsilon = 0.001f;
4266 {
4267 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4268 REPORTER_ASSERT(reporter, boxes.empty());
4269 }
4270 {
4271 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004272 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004273 REPORTER_ASSERT(reporter, boxes.size() == 1);
4274 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4275 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4276 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4277 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4278 }
4279 {
4280 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004281 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004282 REPORTER_ASSERT(reporter, boxes.size() == 1);
4283 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4287 }
4288 {
4289 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004290 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004291 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004292 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4293 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4296 }
4297 {
4298 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004299 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004300 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004301 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004302 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004303 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4305 }
4306 {
4307 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004308 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004309 REPORTER_ASSERT(reporter, boxes.size() == 1);
4310 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004311 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 128, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4313 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4314 }
4315 {
4316 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004317 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004318 REPORTER_ASSERT(reporter, boxes.size() == 1);
4319 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 188, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4323 }
4324}
4325
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004326// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004327DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004328 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004329 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004330 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004331 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004332 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004333
4334 ParagraphStyle paragraph_style;
4335 paragraph_style.setMaxLines(10);
4336 paragraph_style.setTextAlign(TextAlign::kLeft);
4337 paragraph_style.turnHintingOff();
4338
4339 StrutStyle strut_style;
4340 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004341 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004342 strut_style.setFontSize(50);
4343 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004344 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004345 strut_style.setLeading(0.1f);
4346 strut_style.setForceStrutHeight(true);
4347 paragraph_style.setStrutStyle(strut_style);
4348
4349 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4350
4351 TextStyle text_style;
4352 text_style.setFontFamilies({SkString("Ahem")});
4353 text_style.setFontSize(50);
4354 text_style.setLetterSpacing(0);
4355 text_style.setColor(SK_ColorBLACK);
4356 text_style.setHeight(1);
4357 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004358 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004359 builder.pop();
4360
4361 auto paragraph = builder.Build();
4362 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004363 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004364
4365 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4366 // Font is not resolved and the first line does not fit
4367 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4368
4369 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4370 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4371 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004372
4373 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4374 REPORTER_ASSERT(reporter, boxes1.empty());
4375
4376 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004377 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004378 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004379 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4380 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4381 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4382 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004383
4384 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004385 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004386 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004387 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
4388 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 22.5f, EPSILON100));
4389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004391
4392 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004393 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004394 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004395 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4396 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004399
4400 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004401 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004402 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004403 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
4404 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 22.5f, EPSILON100));
4405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004407
4408 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004409 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004410 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004411 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
4412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 182.5f, EPSILON100));
4413 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004415
4416 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004417 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004418 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004419 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
4420 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 262.5f, EPSILON100));
4421 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004423}
4424
Julia Lavrovac2228562019-08-08 16:51:27 -04004425// Checked: NO DIFF
4426DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004427 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004428 if (!fontCollection->fontsFound()) return;
4429 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4430
4431 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004432 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004433
4434 ParagraphStyle paragraph_style;
4435 paragraph_style.setMaxLines(10);
4436 paragraph_style.setTextAlign(TextAlign::kLeft);
4437 paragraph_style.turnHintingOff();
4438
4439 StrutStyle strut_style;
4440 strut_style.setStrutEnabled(true);
4441 strut_style.setFontFamilies({SkString("Ahem")});
4442 strut_style.setFontSize(50);
4443 strut_style.setHeight(1.5f);
4444 strut_style.setLeading(0.1f);
4445 strut_style.setForceStrutHeight(false);
4446 paragraph_style.setStrutStyle(strut_style);
4447
4448 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4449
4450 TextStyle text_style;
4451 text_style.setFontFamilies({SkString("Ahem")});
4452 text_style.setFontSize(20);
4453 text_style.setColor(SK_ColorBLACK);
4454 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004455 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004456 builder.pop();
4457
4458 auto paragraph = builder.Build();
4459 paragraph->layout(550);
4460 paragraph->paint(canvas.get(), 0, 0);
4461
4462 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4463 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4464 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4465 {
4466 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4467 REPORTER_ASSERT(reporter, boxes.empty());
4468 }
4469 {
4470 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4471 canvas.drawRects(SK_ColorRED, boxes);
4472 REPORTER_ASSERT(reporter, boxes.size() == 1);
4473 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4474 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4476 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4477 }
4478 {
4479 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4480 canvas.drawRects(SK_ColorRED, boxes);
4481 REPORTER_ASSERT(reporter, boxes.size() == 1);
4482 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4483 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4486 }
4487}
4488
Julia Lavrovac5313e62019-12-10 12:11:17 -05004489DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4490 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4491 if (!fontCollection->fontsFound()) return;
4492 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4493
4494 const char* text = "12ab\n";
4495
4496 ParagraphStyle paragraph_style;
4497 paragraph_style.turnHintingOff();
4498 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4499
4500 TextStyle text_style;
4501 text_style.setFontStyle(SkFontStyle::Italic());
4502 text_style.setFontFamilies({SkString("Roboto")});
4503 text_style.setColor(SK_ColorBLACK);
4504
4505 text_style.addFontFeature(SkString("tnum"), 1);
4506 builder.pushStyle(text_style);
4507 builder.addText(text);
4508
4509 text_style.resetFontFeatures();
4510 text_style.addFontFeature(SkString("tnum"), 0);
4511 text_style.addFontFeature(SkString("pnum"), 1);
4512 builder.pushStyle(text_style);
4513 builder.addText(text);
4514
4515 builder.pop();
4516 builder.pop();
4517
4518 auto paragraph = builder.Build();
4519 paragraph->layout(TestCanvasWidth);
4520
4521 paragraph->paint(canvas.get(), 10.0, 15.0);
4522
4523 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4524 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4525
4526 auto& tnum_line = impl->lines()[0];
4527 auto& pnum_line = impl->lines()[1];
4528
4529 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4530 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4531 // Tabular numbers should have equal widths.
4532 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4533 // Proportional numbers should have variable widths.
4534 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4535 // Alphabetic characters should be unaffected.
4536 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4537}
4538
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004539// Not in Minikin
4540DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004541 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004542 if (!fontCollection->fontsFound()) return;
4543 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004544 const size_t len = strlen(text);
4545
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004546 ParagraphStyle paragraph_style;
4547 paragraph_style.turnHintingOff();
4548 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4549
4550 TextStyle text_style;
4551 text_style.setFontFamilies(
4552 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4553 text_style.setFontSize(60);
4554 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004555 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004556 builder.pop();
4557
4558 auto paragraph = builder.Build();
4559 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004560
4561 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4562
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004563 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4564 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4565 auto first = impl->runs()[i].textRange();
4566 auto next = impl->runs()[i + 1].textRange();
4567 REPORTER_ASSERT(reporter, first.end == next.start);
4568 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004569}
4570
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004571DEF_TEST(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004572 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004573 if (!fontCollection->fontsFound()) return;
4574 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004575 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004576
4577 ParagraphStyle paragraph_style;
4578 paragraph_style.turnHintingOff();
4579 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4580
4581 TextStyle text_style;
4582 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4583 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004584 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004585 builder.pop();
4586
4587 auto paragraph = builder.Build();
4588 paragraph->layout(TestCanvasWidth);
4589
4590 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4591 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004592 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004593
4594 auto cluster = 0;
4595 SkShaperJSONWriter::VisualizeClusters(
4596 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4597 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4598 if (cluster == 0) {
4599 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4600 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4601 SkASSERT(glyph1to1.size() == 1);
4602 SkASSERT(*glyph1to1.begin() == 1611);
4603 }
4604 ++cluster;
4605 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004606 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004607}
4608
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004609DEF_TEST(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004610 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004611 if (!fontCollection->fontsFound()) return;
4612 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004613 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004614
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004615 ParagraphStyle paragraph_style;
4616 paragraph_style.turnHintingOff();
4617 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4618
4619 TextStyle text_style;
4620 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4621 text_style.setColor(SK_ColorBLACK);
4622 text_style.setFontSize(50);
4623 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004624 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004625 builder.pop();
4626
4627 auto paragraph = builder.Build();
4628 paragraph->layout(TestCanvasWidth);
4629
4630 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4631 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004632
4633 auto cluster = 0;
4634 for (auto& run : impl->runs()) {
4635 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004636 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4637 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004638 [&](int codePointCount, SkSpan<const char> utf1to1,
4639 SkSpan<const SkGlyphID> glyph1to1) {
4640 if (cluster == 0) {
4641 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4642 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4643 SkASSERT(glyph1to1.size() == 3);
4644 }
4645 ++cluster;
4646 });
4647 }
4648
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004649 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004650}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004651
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004652DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004653 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004654 cache.turnOn(true);
4655 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004656 if (!fontCollection->fontsFound()) return;
4657
4658 ParagraphStyle paragraph_style;
4659 paragraph_style.turnHintingOff();
4660
4661 TextStyle text_style;
4662 text_style.setFontFamilies({SkString("Roboto")});
4663 text_style.setColor(SK_ColorBLACK);
4664
4665 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4666 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4667 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004668 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004669 builder.pop();
4670 auto paragraph = builder.Build();
4671
4672 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4673 REPORTER_ASSERT(reporter, count == cache.count());
4674 auto found = cache.findParagraph(impl);
4675 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4676 auto added = cache.updateParagraph(impl);
4677 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4678 };
4679
4680 test("text1", 0, false);
4681 test("text1", 1, true);
4682 test("text2", 1, false);
4683 test("text2", 2, true);
4684 test("text3", 2, false);
4685}
4686
4687DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004688 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004689 cache.turnOn(true);
4690 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004691 if (!fontCollection->fontsFound()) return;
4692
4693 ParagraphStyle paragraph_style;
4694 paragraph_style.turnHintingOff();
4695
4696 TextStyle text_style;
4697 text_style.setColor(SK_ColorBLACK);
4698
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004699 const char* text = "text";
4700 const size_t len = strlen(text);
4701
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004702 auto test = [&](int count, bool expectedToBeFound) {
4703 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4704 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004705 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004706 builder.pop();
4707 auto paragraph = builder.Build();
4708 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4709
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004710 REPORTER_ASSERT(reporter, count == cache.count());
4711 auto found = cache.findParagraph(impl);
4712 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4713 auto added = cache.updateParagraph(impl);
4714 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4715 };
4716
4717 text_style.setFontFamilies({SkString("Roboto")});
4718 test(0, false);
4719 test(1, true);
4720 text_style.setFontFamilies({SkString("Homemade Apple")});
4721 test(1, false);
4722 test(2, true);
4723 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4724 test(2, false);
4725}
4726
4727DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004728 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004729 cache.turnOn(true);
4730 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004731 if (!fontCollection->fontsFound()) return;
4732
4733 ParagraphStyle paragraph_style;
4734 paragraph_style.turnHintingOff();
4735
4736 TextStyle text_style;
4737 text_style.setFontFamilies({SkString("Roboto")});
4738 text_style.setColor(SK_ColorBLACK);
4739
4740 auto test = [&](const char* text1,
4741 const char* text2,
4742 const char* font1,
4743 const char* font2,
4744 int count,
4745 bool expectedToBeFound) {
4746 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4747 text_style.setFontFamilies({SkString(font1)});
4748 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004749 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004750 builder.pop();
4751 text_style.setFontFamilies({SkString(font2)});
4752 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004753 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004754 builder.pop();
4755 auto paragraph = builder.Build();
4756 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4757
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004758 REPORTER_ASSERT(reporter, count == cache.count());
4759 auto found = cache.findParagraph(impl);
4760 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4761 auto added = cache.updateParagraph(impl);
4762 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4763 };
4764
4765 test("text", "", "Roboto", "Homemade Apple", 0, false);
4766 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4767 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4768 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4769 test("text", "", "Roboto", "Homemade Apple", 4, true);
4770}
4771
4772DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004773 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004774 cache.turnOn(true);
4775 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004776 if (!fontCollection->fontsFound()) return;
4777
4778 ParagraphStyle paragraph_style;
4779 paragraph_style.turnHintingOff();
4780
4781 TextStyle text_style;
4782 text_style.setFontFamilies({SkString("Roboto")});
4783 text_style.setColor(SK_ColorBLACK);
4784
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004785 const char* text = "text";
4786 const size_t len = strlen(text);
4787
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004788 auto test = [&](int count, bool expectedToBeFound) {
4789 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4790 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004791 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004792 builder.pop();
4793 auto paragraph = builder.Build();
4794 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4795
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004796 REPORTER_ASSERT(reporter, count == cache.count());
4797 auto found = cache.findParagraph(impl);
4798 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4799 auto added = cache.updateParagraph(impl);
4800 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4801 };
4802
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004803 test(0, false);
4804 test(1, true);
4805 text_style.setLetterSpacing(10);
4806 test(1, false);
4807 test(2, true);
4808 text_style.setWordSpacing(10);
4809 test(2, false);
4810}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004811
Julia Lavrova526df262019-08-21 17:49:44 -04004812DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004813 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004814 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004815 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4816 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004817
4818 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004819 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004820 text_style.setFontSize(16);
4821 text_style.setFontFamilies({SkString("Roboto")});
4822 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004823 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004824
4825 auto paragraph = builder.Build();
4826 paragraph->layout(TestCanvasWidth);
4827 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004828 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004829}
4830
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004831DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004832 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004833 if (!fontCollection->fontsFound()) return;
4834 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4835 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4836
4837 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4838
4839 ParagraphStyle paragraph_style;
4840 TextStyle text_style;
4841 text_style.setFontSize(16);
4842 text_style.setFontFamilies({SkString("Roboto")});
4843 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4844 builder.addText(text.c_str(), text.size());
4845
4846 auto paragraph = builder.Build();
4847 paragraph->layout(TestCanvasWidth);
4848 paragraph->paint(canvas.get(), 0, 0);
4849}
4850
Julia Lavrovaa40db422019-08-21 13:49:15 -04004851DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004852 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004853 if (!fontCollection->fontsFound()) return;
4854 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4855
4856 ParagraphStyle paragraph_style;
4857 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4858
Julia Lavrova526df262019-08-21 17:49:44 -04004859 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004860 builder.addPlaceholder(placeholder);
4861
4862 auto paragraph = builder.Build();
4863 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004864 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004865 paragraph->paint(canvas.get(), 0, 0);
4866}
4867
4868DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004869 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004870 if (!fontCollection->fontsFound()) return;
4871 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4872 TestCanvas canvas("SkParagraph_Fallbacks.png");
4873
4874 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004875 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004876
4877 const char* androidFonts[] = {
4878 "sans-serif",
4879 "sans-serif-condensed",
4880 "serif",
4881 "monospace",
4882 "serif-monospace",
4883 "casual",
4884 "cursive",
4885 "sans-serif-smallcaps",
4886 };
4887
4888 for (auto& font : androidFonts) {
4889
4890 ParagraphStyle paragraph_style;
4891 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4892
4893 TextStyle text_style;
4894 text_style.setColor(SK_ColorBLACK);
4895 text_style.setLocale(SkString("en_US"));
4896 text_style.setFontSize(20);
4897
4898 text_style.setFontFamilies({ SkString(font) });
4899 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004900 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004901
4902 builder.pop();
4903
4904 auto paragraph = builder.Build();
4905 paragraph->layout(TestCanvasWidth);
4906 paragraph->paint(canvas.get(), 0, 0);
4907 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4908 }
4909}
4910
4911DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004912 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004913 if (!fontCollection->fontsFound()) return;
4914 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004915 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004916 TestCanvas canvas("SkParagraph_Bidi1.png");
4917
4918 std::u16string abc = u"\u202Dabc";
4919 std::u16string DEF = u"\u202EDEF";
4920 std::u16string ghi = u"\u202Dghi";
4921 std::u16string JKL = u"\u202EJKL";
4922 std::u16string mno = u"\u202Dmno";
4923
4924 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4925
4926 ParagraphStyle paragraph_style;
4927 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4928
4929 TextStyle text_style;
4930 text_style.setFontFamilies({ SkString("sans-serif")});
4931 text_style.setFontSize(40);
4932
4933 text_style.setColor(SK_ColorCYAN);
4934 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4935 builder.pushStyle(text_style);
4936 builder.addText(abc);
4937
4938 text_style.setColor(SK_ColorGREEN);
4939 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4940 builder.pushStyle(text_style);
4941 builder.addText(DEF);
4942
4943 text_style.setColor(SK_ColorYELLOW);
4944 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4945 builder.pushStyle(text_style);
4946 builder.addText(ghi);
4947
4948 text_style.setColor(SK_ColorMAGENTA);
4949 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4950 builder.pushStyle(text_style);
4951 builder.addText(JKL);
4952
4953 text_style.setColor(SK_ColorBLUE);
4954 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4955 builder.pushStyle(text_style);
4956 builder.addText(mno);
4957
4958 auto paragraph = builder.Build();
4959 paragraph->layout(400);
4960 paragraph->paint(canvas.get(), 0, 0);
4961}
4962
4963DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004964 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004965 if (!fontCollection->fontsFound()) return;
4966 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004967 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004968 TestCanvas canvas("SkParagraph_Bidi2.png");
4969
4970 std::u16string abcD = u"\u202Dabc\u202ED";
4971 std::u16string EFgh = u"EF\u202Dgh";
4972 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4973
4974 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4975
4976 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004977 TextStyle text_style;
4978 text_style.setFontFamilies({ SkString("sans-serif")});
4979 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004980
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004981 {
4982 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4983 builder.pushStyle(text_style);
4984 builder.addText(abcD);
4985 builder.pushStyle(text_style);
4986 builder.addText(EFgh);
4987 builder.pushStyle(text_style);
4988 builder.addText(iJKLmno);
4989 auto paragraph = builder.Build();
4990 paragraph->layout(360);
4991 paragraph->paint(canvas.get(), 0, 0);
4992 }
4993 canvas.get()->translate(0, 400);
4994 {
4995 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4996 builder.pushStyle(text_style);
4997 builder.addText(abcDEFghiJKLmno);
4998 auto paragraph = builder.Build();
4999 paragraph->layout(360);
5000 paragraph->paint(canvas.get(), 0, 0);
5001 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04005002}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005003
5004DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005005 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005006 if (!fontCollection->fontsFound()) return;
5007 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5008 TestCanvas canvas("SkParagraph_Newline.png");
5009
5010 TextStyle text_style;
5011 text_style.setFontFamilies({SkString("Ahem")});
5012 text_style.setColor(SK_ColorBLACK);
5013 StrutStyle strut_style;
5014 strut_style.setStrutEnabled(false);
5015 ParagraphStyle paragraph_style;
5016 paragraph_style.setStrutStyle(strut_style);
5017 paragraph_style.setTextStyle(text_style);
5018 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5019 builder.addText("\n");
5020 auto paragraph = builder.Build();
5021 paragraph->layout(1000);
5022 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5023}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005024
Julia Lavrovab30d4812019-11-08 14:51:16 -05005025DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005026 TestCanvas canvas("SkParagraph_FontResolutions.png");
5027
5028 sk_sp<TestFontCollection> fontCollection =
5029 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5030 if (!fontCollection->fontsFound()) return;
5031
5032 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5033 return;
5034 }
5035 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5036 return;
5037 }
5038 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5039 return;
5040 }
5041
5042 TextStyle text_style;
5043 text_style.setFontFamilies({SkString("abc")});
5044 text_style.setFontSize(50);
5045
5046 ParagraphStyle paragraph_style;
5047 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5048
5049 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5050 text_style.setColor(SK_ColorBLUE);
5051 builder.pushStyle(text_style);
5052 builder.addText(u"a\u0300");
5053 text_style.setColor(SK_ColorMAGENTA);
5054 builder.pushStyle(text_style);
5055 builder.addText(u"à");
5056
5057 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5058
5059 text_style.setColor(SK_ColorRED);
5060 builder.pushStyle(text_style);
5061 builder.addText(u"a\u0300");
5062 text_style.setColor(SK_ColorGREEN);
5063 builder.pushStyle(text_style);
5064 builder.addText(u"à");
5065
5066 auto paragraph = builder.Build();
5067 paragraph->layout(TestCanvasWidth);
5068
5069 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5070 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5071
5072 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5073 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5074 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5075
5076 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5077 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5078
5079 paragraph->paint(canvas.get(), 100, 100);
5080}
5081
Julia Lavrovab30d4812019-11-08 14:51:16 -05005082DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005083 TestCanvas canvas("SkParagraph_FontStyle.png");
5084
5085 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5086 if (!fontCollection->fontsFound()) return;
5087
5088 TextStyle text_style;
5089 text_style.setFontFamilies({SkString("Roboto")});
5090 text_style.setColor(SK_ColorBLACK);
5091 text_style.setFontSize(20);
5092 SkFontStyle fs = SkFontStyle(
5093 SkFontStyle::Weight::kLight_Weight,
5094 SkFontStyle::Width::kNormal_Width,
5095 SkFontStyle::Slant::kUpright_Slant
5096 );
5097 text_style.setFontStyle(fs);
5098 ParagraphStyle paragraph_style;
5099 paragraph_style.setTextStyle(text_style);
5100 TextStyle boldItalic;
5101 boldItalic.setFontFamilies({SkString("Roboto")});
5102 boldItalic.setColor(SK_ColorRED);
5103 SkFontStyle bi = SkFontStyle(
5104 SkFontStyle::Weight::kBold_Weight,
5105 SkFontStyle::Width::kNormal_Width,
5106 SkFontStyle::Slant::kItalic_Slant
5107 );
5108 boldItalic.setFontStyle(bi);
5109 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5110 builder.addText("Default text\n");
5111 builder.pushStyle(boldItalic);
5112 builder.addText("Bold and Italic\n");
5113 builder.pop();
5114 builder.addText("back to normal");
5115 auto paragraph = builder.Build();
5116 paragraph->layout(250);
5117 paragraph->paint(canvas.get(), 0, 0);
5118}
5119
Julia Lavrovab30d4812019-11-08 14:51:16 -05005120DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005121 TestCanvas canvas("SkParagraph_Shaping.png");
5122
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005123 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5124 sk_sp<TestFontCollection> fontCollection =
5125 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5126 if (!fontCollection->fontsFound()) return;
5127
5128
5129 TextStyle text_style;
5130 text_style.setFontFamilies({SkString("Roboto")});
5131 text_style.setColor(SK_ColorGRAY);
5132 text_style.setFontSize(14);
5133 SkFontStyle b = SkFontStyle(
5134 SkFontStyle::Weight::kNormal_Weight,
5135 SkFontStyle::Width::kNormal_Width,
5136 SkFontStyle::Slant::kUpright_Slant
5137 );
5138 text_style.setFontStyle(b);
5139 ParagraphStyle paragraph_style;
5140 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5141 builder.pushStyle(text_style);
5142 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5143 auto paragraph = builder.Build();
5144 paragraph->layout(380);
5145 paragraph->paint(canvas.get(), 0, 0);
5146}
Julia Lavrovac028b422019-11-25 10:00:43 -05005147
5148DEF_TEST(SkParagraph_Ellipsis, reporter) {
5149 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5150 if (!fontCollection->fontsFound()) return;
5151 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5152 TestCanvas canvas("SkParagraph_Ellipsis.png");
5153
5154 const char* text = "This\n"
5155 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5156 TextStyle text_style;
5157 text_style.setFontFamilies({SkString("Ahem")});
5158 text_style.setColor(SK_ColorBLACK);
5159 text_style.setFontSize(10);
5160
5161 auto relayout = [&](size_t lines, bool ellipsis,
5162 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5163 ParagraphStyle paragraph_style;
5164 SkPaint paint;
5165 paint.setColor(bg);
5166 text_style.setForegroundColor(paint);
5167 paragraph_style.setTextStyle(text_style);
5168 paragraph_style.setMaxLines(lines);
5169 if (ellipsis) {
5170 paragraph_style.setEllipsis(u"\u2026");
5171 }
5172 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5173 builder.addText(text);
5174 auto paragraph = builder.Build();
5175 paragraph->layout(50);
5176 paragraph->paint(canvas.get(), 0, 0);
5177 canvas.get()->translate(50, paragraph->getHeight() + 10);
5178 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5179 SkPaint background;
5180 background.setColor(SK_ColorRED);
5181 background.setStyle(SkPaint::kStroke_Style);
5182 background.setAntiAlias(true);
5183 background.setStrokeWidth(1);
5184 canvas.get()->drawRect(result.front().rect, background);
5185
5186 SkASSERT(width == paragraph->getMaxWidth());
5187 SkASSERT(height == paragraph->getHeight());
5188 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5189 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5190 };
5191
5192 SkPaint paint;
5193 paint.setColor(SK_ColorLTGRAY);
5194 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5195
5196 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005197 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5198 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005199
5200 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005201 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005202 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5203
5204 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005205 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5206 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005207}