blob: 68c28d5ced6c23f950deb1baef387cdc85107cca [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#include <sstream>
Julia Lavrovadb543f62020-01-29 11:43:41 -05003#include <thread>
Julia Lavrovacd2d4e42020-03-27 15:40:37 -04004#include "include/core/SkFontMgr.h"
Julia Lavrova6e6333f2019-06-17 10:34:10 -04005#include "modules/skparagraph/include/TypefaceFontProvider.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04006#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
7#include "modules/skparagraph/src/ParagraphImpl.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -04008#include "modules/skparagraph/utils/TestFontCollection.h"
Julia Lavrovadb543f62020-01-29 11:43:41 -05009#include "src/core/SkFontMgrPriv.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040010#include "src/core/SkOSFile.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -040011#include "src/utils/SkOSPath.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040012#include "src/utils/SkShaperJSONWriter.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040013#include "tests/CodecPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040014#include "tests/Test.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040015#include "tools/Resources.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040016#include "tools/ToolUtils.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040017
18#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 Lavrovaa3552c52019-05-30 16:12:56 -040052 SkString path;
53 while (iter.next(&path)) {
54 if (path.endsWith("Roboto-Italic.ttf")) {
55 fFontsFound = true;
56 }
57 fonts.emplace_back(path);
58 }
59
60 if (!fFontsFound) {
Herb Derby126d7a22019-11-27 11:38:16 -050061 // SkDebugf("Fonts not found, skipping all the tests\n");
Julia Lavrovaa3552c52019-05-30 16:12:56 -040062 return;
63 }
64 // Only register fonts if we have to
65 for (auto& font : fonts) {
66 SkString file_path;
67 file_path.printf("%s/%s", fResourceDir.c_str(), font.c_str());
68 fFontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
69 }
70
Julia Lavrova2e30fde2019-10-09 09:43:02 -040071 if (testOnly) {
72 this->setTestFontManager(std::move(fFontProvider));
73 } else {
74 this->setAssetFontManager(std::move(fFontProvider));
75 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040076 this->disableFontFallback();
Julia Lavrovaa3552c52019-05-30 16:12:56 -040077 }
78
Julia Lavrova2e30fde2019-10-09 09:43:02 -040079 ~ResourceFontCollection() = default;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040080
81 size_t resolvedFonts() const { return fResolvedFonts; }
82
83 // TODO: temp solution until we check in fonts
84 bool fontsFound() const { return fFontsFound; }
85
86private:
87 bool fFontsFound;
88 size_t fResolvedFonts;
89 std::string fResourceDir;
90 sk_sp<TypefaceFontProvider> fFontProvider;
91};
Julia Lavrovadb9f6692019-08-01 16:02:17 -040092
93class TestCanvas {
94public:
95 TestCanvas(const char* testName) : name(testName) {
96 bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight);
97 canvas = new SkCanvas(bits);
98 canvas->clear(SK_ColorWHITE);
99 }
100
101 ~TestCanvas() {
Julia Lavrovaaae845f2019-08-16 16:44:40 -0400102 SkString tmpDir = skiatest::GetTmpDir();
103 if (!tmpDir.isEmpty()) {
104 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
105 SkFILEWStream file(path.c_str());
106 if (!SkEncodeImage(&file, bits, SkEncodedImageFormat::kPNG, 100)) {
107 SkDebugf("Cannot write a picture %s\n", name);
108 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400109 }
110 delete canvas;
111 }
112
113 void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) {
114
115 SkPaint paint;
116 if (!fill) {
117 paint.setStyle(SkPaint::kStroke_Style);
118 paint.setAntiAlias(true);
119 paint.setStrokeWidth(1);
120 }
121 paint.setColor(color);
122 for (auto& r : result) {
123 canvas->drawRect(r.rect, paint);
124 }
125 }
126
127 void drawLine(SkColor color, SkRect rect, bool vertical = true) {
128
129 SkPaint paint;
130 paint.setStyle(SkPaint::kStroke_Style);
131 paint.setAntiAlias(true);
132 paint.setStrokeWidth(1);
133 paint.setColor(color);
134 if (vertical) {
135 canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
136 } else {
137 canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint);
138 }
139 }
140
141 void drawLines(SkColor color, std::vector<TextBox>& result) {
142
143 for (auto& r : result) {
144 drawLine(color, r.rect);
145 }
146 }
147
148 SkCanvas* get() { return canvas; }
149private:
150 SkBitmap bits;
151 SkCanvas* canvas;
152 const char* name;
153};
154
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400155} // namespace
156
157DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400158 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400159 if (!fontCollection->fontsFound()) return;
160 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400161 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400162
163 ParagraphStyle paragraph_style;
164 paragraph_style.turnHintingOff();
165 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
166
167 TextStyle text_style;
168 text_style.setFontFamilies({SkString("Roboto")});
169 text_style.setColor(SK_ColorBLACK);
170 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400171 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400172 builder.pop();
173
174 auto paragraph = builder.Build();
175 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500176 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400177
178 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
179 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
180 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400181 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400182
183 size_t index = 0;
184 for (auto& line : impl->lines()) {
185 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400186 [&index, reporter]
187 (TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400188 REPORTER_ASSERT(reporter, index == 0);
189 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorBLACK);
190 ++index;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400191 });
192 }
193}
194
Julia Lavrova916a9042019-08-08 16:51:27 -0400195DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400196 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400197 TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png");
198 if (!fontCollection->fontsFound()) return;
199
200 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400201 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400202
203 ParagraphStyle paragraph_style;
204 paragraph_style.turnHintingOff();
205 paragraph_style.setMaxLines(14);
206 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
207
208 TextStyle text_style;
209 text_style.setFontFamilies({SkString("Roboto")});
210 text_style.setColor(SK_ColorBLACK);
211 text_style.setFontSize(26);
212 text_style.setWordSpacing(5);
213 text_style.setLetterSpacing(1);
214 text_style.setDecoration(TextDecoration::kUnderline);
215 text_style.setDecorationColor(SK_ColorBLACK);
216 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400217 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400218
219 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
220 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400221 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400222 builder.addPlaceholder(placeholder1);
223
224 PlaceholderStyle placeholder2(5, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
225 builder.addPlaceholder(placeholder2);
226 builder.addPlaceholder(placeholder1);
227 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400228 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400229 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400230 builder.addText(text, len);
231 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400232 builder.addPlaceholder(placeholder2);
233 builder.addPlaceholder(placeholder2);
234 builder.addPlaceholder(placeholder2);
235 builder.addPlaceholder(placeholder2);
236 builder.addPlaceholder(placeholder2);
237 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400238 builder.addText(text, len);
239 builder.addText(text, len);
240 builder.addText(text, len);
241 builder.addText(text, len);
242 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400243 builder.addPlaceholder(placeholder2);
244 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400245 builder.addText(text, len);
246 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400247
248 builder.pop();
249
250 auto paragraph = builder.Build();
251 paragraph->layout(TestCanvasWidth);
252 paragraph->paint(canvas.get(), 0, 0);
253
254 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
255 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
256
257 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
258 canvas.drawRects(SK_ColorRED, boxes);
259 REPORTER_ASSERT(reporter, boxes.size() == 1);
260
261 boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
262 canvas.drawRects(SK_ColorGREEN, boxes);
263 REPORTER_ASSERT(reporter, boxes.size() == 1);
264
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400265 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400266 canvas.drawRects(SK_ColorRED, boxes);
267
268 boxes = paragraph->getRectsForRange(4, 17, rect_height_style, rect_width_style);
269 canvas.drawRects(SK_ColorBLUE, boxes);
270
271 REPORTER_ASSERT(reporter, boxes.size() == 7);
272
Julia Lavrovac028b422019-11-25 10:00:43 -0500273 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400274 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500275 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 90.921f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400276 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 100, EPSILON100));
277
Julia Lavrovac028b422019-11-25 10:00:43 -0500278 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.left(), 231.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400279 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500280 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.right(), 231.343f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400281 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.bottom(), 100, EPSILON100));
282
Julia Lavrovac028b422019-11-25 10:00:43 -0500283 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.left(), 281.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.right(), 281.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.bottom(), 50, EPSILON100));
287
Julia Lavrovac028b422019-11-25 10:00:43 -0500288 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.left(), 336.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400289 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500290 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.right(), 336.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400291 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100));
292}
293
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400294DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400295 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400296 TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png");
297 if (!fontCollection->fontsFound()) return;
298
299 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400300 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400301
302 ParagraphStyle paragraph_style;
303 paragraph_style.turnHintingOff();
304 paragraph_style.setMaxLines(14);
305 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
306
307 TextStyle text_style;
308 text_style.setFontFamilies({SkString("Roboto")});
309 text_style.setColor(SK_ColorBLACK);
310 text_style.setFontSize(26);
311 text_style.setWordSpacing(5);
312 text_style.setLetterSpacing(1);
313 text_style.setDecoration(TextDecoration::kUnderline);
314 text_style.setDecorationColor(SK_ColorBLACK);
315 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400316 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400317
318 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 38.347f);
319 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400320 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400321
322 builder.pop();
323
324 auto paragraph = builder.Build();
325 paragraph->layout(TestCanvasWidth);
326 paragraph->paint(canvas.get(), 0, 0);
327
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400328 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400329 canvas.drawRects(SK_ColorRED, boxes);
330
331 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400333 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500334 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400335 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
336
337 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
338 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
339
340 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
341 canvas.drawRects(SK_ColorBLUE, boxes);
342
343 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500344 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400345 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 14.226f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500346 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400347 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400348}
Julia Lavrova916a9042019-08-08 16:51:27 -0400349
Julia Lavrova916a9042019-08-08 16:51:27 -0400350DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400351 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400352 TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png");
353 if (!fontCollection->fontsFound()) return;
354
355 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400356 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400357
358 ParagraphStyle paragraph_style;
359 paragraph_style.turnHintingOff();
360 paragraph_style.setMaxLines(14);
361 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
362
363 TextStyle text_style;
364 text_style.setFontFamilies({SkString("Roboto")});
365 text_style.setColor(SK_ColorBLACK);
366 text_style.setFontSize(26);
367 text_style.setWordSpacing(5);
368 text_style.setLetterSpacing(1);
369 text_style.setDecoration(TextDecoration::kUnderline);
370 text_style.setDecorationColor(SK_ColorBLACK);
371 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400372 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400373
374 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kAboveBaseline, TextBaseline::kAlphabetic, 903129.129308f);
375 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400376 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400377
378 builder.pop();
379
380 auto paragraph = builder.Build();
381 paragraph->layout(TestCanvasWidth);
382 paragraph->paint(canvas.get(), 0, 0);
383
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400384 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400385 canvas.drawRects(SK_ColorRED, boxes);
386
387 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500388 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.347f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 49.652f, EPSILON100));
392
393 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
394 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
395
396 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
397 canvas.drawRects(SK_ColorBLUE, boxes);
398
399 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400401 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 25.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500402 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400403 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400404}
Julia Lavrova916a9042019-08-08 16:51:27 -0400405
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400406DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400407 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400408 TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png");
409 if (!fontCollection->fontsFound()) return;
410
411 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400412 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400413
414 ParagraphStyle paragraph_style;
415 paragraph_style.turnHintingOff();
416 paragraph_style.setMaxLines(14);
417 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
418
419 TextStyle text_style;
420 text_style.setFontFamilies({SkString("Roboto")});
421 text_style.setColor(SK_ColorBLACK);
422 text_style.setFontSize(26);
423 text_style.setWordSpacing(5);
424 text_style.setLetterSpacing(1);
425 text_style.setDecoration(TextDecoration::kUnderline);
426 text_style.setDecorationColor(SK_ColorBLACK);
427 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400428 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400429
430 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBelowBaseline, TextBaseline::kAlphabetic, 903129.129308f);
431 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400432 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400433
434 builder.pop();
435
436 auto paragraph = builder.Build();
437 paragraph->layout(TestCanvasWidth);
438 paragraph->paint(canvas.get(), 0, 0);
439
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400440 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400441 canvas.drawRects(SK_ColorRED, boxes);
442
443 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500444 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400445 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500446 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400447 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
448
449 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
450 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
451
452 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
453 canvas.drawRects(SK_ColorBLUE, boxes);
454
455 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500456 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400457 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.121f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500458 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400459 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400460}
Julia Lavrova916a9042019-08-08 16:51:27 -0400461
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400462DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400463 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400464 TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png");
465 if (!fontCollection->fontsFound()) return;
466
467 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400468 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400469
470 ParagraphStyle paragraph_style;
471 paragraph_style.turnHintingOff();
472 paragraph_style.setMaxLines(14);
473 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
474
475 TextStyle text_style;
476 text_style.setFontFamilies({SkString("Roboto")});
477 text_style.setColor(SK_ColorBLACK);
478 text_style.setFontSize(26);
479 text_style.setWordSpacing(5);
480 text_style.setLetterSpacing(1);
481 text_style.setDecoration(TextDecoration::kUnderline);
482 text_style.setDecorationColor(SK_ColorBLACK);
483 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400484 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400485
486 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBottom, TextBaseline::kAlphabetic, 0);
487 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400488 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400489
490 builder.pop();
491
492 auto paragraph = builder.Build();
493 paragraph->layout(TestCanvasWidth);
494 paragraph->paint(canvas.get(), 0, 0);
495
496 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
497 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
498
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400499 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400500 canvas.drawRects(SK_ColorRED, boxes);
501 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
506
507 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
508 canvas.drawRects(SK_ColorBLUE, boxes);
509 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400511 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 19.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500512 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400513 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400514}
Julia Lavrova916a9042019-08-08 16:51:27 -0400515
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400516DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400517 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400518 TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png");
519 if (!fontCollection->fontsFound()) return;
520
521 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400522 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400523
524 ParagraphStyle paragraph_style;
525 paragraph_style.turnHintingOff();
526 paragraph_style.setMaxLines(14);
527 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
528
529 TextStyle text_style;
530 text_style.setFontFamilies({SkString("Roboto")});
531 text_style.setColor(SK_ColorBLACK);
532 text_style.setFontSize(26);
533 text_style.setWordSpacing(5);
534 text_style.setLetterSpacing(1);
535 text_style.setDecoration(TextDecoration::kUnderline);
536 text_style.setDecorationColor(SK_ColorBLACK);
537 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400538 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400539
540 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kTop, TextBaseline::kAlphabetic, 0);
541 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400542 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400543
544 builder.pop();
545
546 auto paragraph = builder.Build();
547 paragraph->layout(TestCanvasWidth);
548 paragraph->paint(canvas.get(), 0, 0);
549
550 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
551 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
552
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400553 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400554 canvas.drawRects(SK_ColorRED, boxes);
555 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500556 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400557 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500558 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400559 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
560
561 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
562 canvas.drawRects(SK_ColorBLUE, boxes);
563 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500564 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400565 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500566 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400567 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400568}
Julia Lavrova916a9042019-08-08 16:51:27 -0400569
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400570DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400571 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400572 TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png");
573 if (!fontCollection->fontsFound()) return;
574
575 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400576 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400577
578 ParagraphStyle paragraph_style;
579 paragraph_style.turnHintingOff();
580 paragraph_style.setMaxLines(14);
581 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
582
583 TextStyle text_style;
584 text_style.setFontFamilies({SkString("Roboto")});
585 text_style.setColor(SK_ColorBLACK);
586 text_style.setFontSize(26);
587 text_style.setWordSpacing(5);
588 text_style.setLetterSpacing(1);
589 text_style.setDecoration(TextDecoration::kUnderline);
590 text_style.setDecorationColor(SK_ColorBLACK);
591 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400592 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400593
594 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kMiddle, TextBaseline::kAlphabetic, 0);
595 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400596 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400597
598 builder.pop();
599
600 auto paragraph = builder.Build();
601 paragraph->layout(TestCanvasWidth);
602 paragraph->paint(canvas.get(), 0, 0);
603
604 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
605 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
606
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400607 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400608 canvas.drawRects(SK_ColorRED, boxes);
609 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500610 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400611 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500612 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400613 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
614
615 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
616 canvas.drawRects(SK_ColorBLUE, boxes);
617 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500618 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400619 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 9.765f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500620 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400621 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400622}
Julia Lavrova916a9042019-08-08 16:51:27 -0400623
Julia Lavrova916a9042019-08-08 16:51:27 -0400624DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400625 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400626 TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png");
627 if (!fontCollection->fontsFound()) return;
628
629 const char* text = "給能上目秘使";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400630 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400631
632 ParagraphStyle paragraph_style;
633 paragraph_style.turnHintingOff();
634 paragraph_style.setMaxLines(14);
635 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
636
637 TextStyle text_style;
638 text_style.setFontFamilies({SkString("Source Han Serif CN")});
639 text_style.setColor(SK_ColorBLACK);
640 text_style.setFontSize(26);
641 text_style.setWordSpacing(5);
642 text_style.setLetterSpacing(1);
643 text_style.setDecoration(TextDecoration::kUnderline);
644 text_style.setDecorationColor(SK_ColorBLACK);
645 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400646 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400647 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kIdeographic, 38.347f);
648 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400649 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400650
651 builder.pop();
652
653 auto paragraph = builder.Build();
654 paragraph->layout(TestCanvasWidth);
655 paragraph->paint(canvas.get(), 0, 0);
656
657 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
658 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
659
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400660 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400661 canvas.drawRects(SK_ColorRED, boxes);
662 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500663 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400664 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500665 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400666 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
667
668 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
669 canvas.drawRects(SK_ColorBLUE, boxes);
670 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500671 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 135.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400672 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 4.703f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500673 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400674 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400675}
Julia Lavrova916a9042019-08-08 16:51:27 -0400676
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400677DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400678 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400679 TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png");
680 if (!fontCollection->fontsFound()) return;
681
682 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400683 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400684
685 ParagraphStyle paragraph_style;
686 paragraph_style.turnHintingOff();
687 paragraph_style.setMaxLines(14);
688 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
689
690 TextStyle text_style;
691 text_style.setFontFamilies({SkString("Roboto")});
692 text_style.setColor(SK_ColorBLACK);
693 text_style.setFontSize(26);
694 text_style.setWordSpacing(5);
695 text_style.setLetterSpacing(1);
696 text_style.setDecoration(TextDecoration::kUnderline);
697 text_style.setDecorationColor(SK_ColorBLACK);
698 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400699 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400700
701 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
702 PlaceholderStyle placeholder2(25, 25, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 12.5f);
703
704 builder.addPlaceholder(placeholder1);
705 builder.addPlaceholder(placeholder1);
706 builder.addPlaceholder(placeholder1);
707 builder.addPlaceholder(placeholder2);
708 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400709 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400710
711 builder.addPlaceholder(placeholder1);
712 builder.addPlaceholder(placeholder1);
713 builder.addPlaceholder(placeholder1);
714 builder.addPlaceholder(placeholder1);
715 builder.addPlaceholder(placeholder2); // 4 + 1
716 builder.addPlaceholder(placeholder1);
717 builder.addPlaceholder(placeholder1);
718 builder.addPlaceholder(placeholder1);
719 builder.addPlaceholder(placeholder1);
720 builder.addPlaceholder(placeholder1);
721 builder.addPlaceholder(placeholder1);
722 builder.addPlaceholder(placeholder2); // 6 + 1
723 builder.addPlaceholder(placeholder1);
724 builder.addPlaceholder(placeholder1);
725 builder.addPlaceholder(placeholder1);
726 builder.addPlaceholder(placeholder1);
727 builder.addPlaceholder(placeholder1);
728 builder.addPlaceholder(placeholder1);
729 builder.addPlaceholder(placeholder1);
730 builder.addPlaceholder(placeholder2); // 7 + 1
731
732 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400733 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400734 builder.addPlaceholder(placeholder1);
735 builder.addPlaceholder(placeholder2);
736
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400737 builder.addText(text, len);
738 builder.addText(text, len);
739 builder.addText(text, len);
740 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400741
742 builder.addPlaceholder(placeholder2);
743 builder.addPlaceholder(placeholder1);
744
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400745 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400746
747 builder.addPlaceholder(placeholder2);
748
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400749 builder.addText(text, len);
750 builder.addText(text, len);
751 builder.addText(text, len);
752 builder.addText(text, len);
753 builder.addText(text, len);
754 builder.addText(text, len);
755 builder.addText(text, len);
756 builder.addText(text, len);
757 builder.addText(text, len);
758 builder.addText(text, len);
759 builder.addText(text, len);
760 builder.addText(text, len);
761 builder.addText(text, len);
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);
Julia Lavrova916a9042019-08-08 16:51:27 -0400768
769 builder.pop();
770
771 auto paragraph = builder.Build();
772 paragraph->layout(TestCanvasWidth - 100);
773 paragraph->paint(canvas.get(), 0, 0);
774
775 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
776 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
777
778 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
779 canvas.drawRects(SK_ColorRED, boxes);
780 REPORTER_ASSERT(reporter, boxes.size() == 1);
781
782 boxes = paragraph->getRectsForRange(175, 176, rect_height_style, rect_width_style);
783 canvas.drawRects(SK_ColorGREEN, boxes);
784 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500785 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 31.695f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400786 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 218.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500787 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 47.292f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400788 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 249, EPSILON100));
789
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400790 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400791 canvas.drawRects(SK_ColorRED, boxes);
792
793 boxes = paragraph->getRectsForRange(4, 45, rect_height_style, rect_width_style);
794 canvas.drawRects(SK_ColorBLUE, boxes);
795 REPORTER_ASSERT(reporter, boxes.size() == 30);
Julia Lavrovac028b422019-11-25 10:00:43 -0500796 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 59.726f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400797 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.378f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500798 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400799 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56.847f, EPSILON100));
800
Julia Lavrovac028b422019-11-25 10:00:43 -0500801 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.left(), 606.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400802 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.top(), 38, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500803 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.right(), 631.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400804 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.bottom(), 63, EPSILON100));
805
Julia Lavrovac028b422019-11-25 10:00:43 -0500806 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400807 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.top(), 63.5f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500808 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.right(), 50.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400809 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400810}
Julia Lavrova916a9042019-08-08 16:51:27 -0400811
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400812DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400813 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400814 TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png");
815 if (!fontCollection->fontsFound()) return;
816
817 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400818 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400819
820 ParagraphStyle paragraph_style;
821 paragraph_style.turnHintingOff();
822 paragraph_style.setMaxLines(14);
823 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
824
825 TextStyle text_style;
826 text_style.setFontFamilies({SkString("Roboto")});
827 text_style.setColor(SK_ColorBLACK);
828 text_style.setFontSize(26);
829 text_style.setWordSpacing(5);
830 text_style.setLetterSpacing(1);
831 text_style.setDecoration(TextDecoration::kUnderline);
832 text_style.setDecorationColor(SK_ColorBLACK);
833 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400834 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400835
836 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
837 PlaceholderStyle placeholder2(5, 20, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 10);
838
839 builder.addPlaceholder(placeholder1);
840 builder.addPlaceholder(placeholder1);
841 builder.addPlaceholder(placeholder1);
842 builder.addPlaceholder(placeholder1);
843 builder.addPlaceholder(placeholder1);
844 builder.addPlaceholder(placeholder1);
845 builder.addPlaceholder(placeholder1);
846 builder.addPlaceholder(placeholder1);
847 builder.addPlaceholder(placeholder2); // 8 + 1
848 builder.addPlaceholder(placeholder1);
849 builder.addPlaceholder(placeholder1);
850 builder.addPlaceholder(placeholder1);
851 builder.addPlaceholder(placeholder1);
852 builder.addPlaceholder(placeholder1);
853 builder.addPlaceholder(placeholder2); // 5 + 1
854 builder.addPlaceholder(placeholder1);
855 builder.addPlaceholder(placeholder1);
856 builder.addPlaceholder(placeholder1);
857 builder.addPlaceholder(placeholder1);
858 builder.addPlaceholder(placeholder1);
859 builder.addPlaceholder(placeholder1);
860 builder.addPlaceholder(placeholder1);
861 builder.addPlaceholder(placeholder1); // 8 + 0
862
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400863 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400864
865 builder.addPlaceholder(placeholder1);
866 builder.addPlaceholder(placeholder2);
867 builder.addPlaceholder(placeholder2); // 1 + 2
868 builder.addPlaceholder(placeholder1);
869 builder.addPlaceholder(placeholder2);
870 builder.addPlaceholder(placeholder2); // 1 + 2
871
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400872 builder.addText(text, len);
873 builder.addText(text, len);
874 builder.addText(text, len);
875 builder.addText(text, len);
876 builder.addText(text, len);
877 builder.addText(text, len);
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); // 11
Julia Lavrova916a9042019-08-08 16:51:27 -0400883
884 builder.addPlaceholder(placeholder2);
885 builder.addPlaceholder(placeholder1);
886 builder.addPlaceholder(placeholder2);
887 builder.addPlaceholder(placeholder1);
888 builder.addPlaceholder(placeholder2);
889
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400890 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400891
892 builder.pop();
893
894 auto paragraph = builder.Build();
895 paragraph->layout(TestCanvasWidth);
896 paragraph->paint(canvas.get(), 0, 0);
897
898 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
899 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
900
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400901 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400902 canvas.drawRects(SK_ColorRED, boxes);
903
904 REPORTER_ASSERT(reporter, boxes.size() == 34);
Julia Lavrovac028b422019-11-25 10:00:43 -0500905 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400906 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500907 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 140.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400908 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
909
Julia Lavrovac028b422019-11-25 10:00:43 -0500910 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.left(), 800.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400911 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500912 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.right(), 850.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400913 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.bottom(), 50, EPSILON100));
914
Julia Lavrovac028b422019-11-25 10:00:43 -0500915 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.left(), 503.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.top(), 160, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500917 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.right(), 508.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400918 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.bottom(), 180, EPSILON100));
919
920 boxes = paragraph->getRectsForRange(30, 50, rect_height_style, rect_width_style);
921 canvas.drawRects(SK_ColorBLUE, boxes);
922
923 REPORTER_ASSERT(reporter, boxes.size() == 8);
Julia Lavrovac028b422019-11-25 10:00:43 -0500924 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 216.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400925 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500926 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 290.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400927 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 120, EPSILON100));
928
Julia Lavrovac028b422019-11-25 10:00:43 -0500929 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 290.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400930 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500931 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 340.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400932 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 120, EPSILON100));
933
Julia Lavrovac028b422019-11-25 10:00:43 -0500934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.left(), 340.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.right(), 345.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400938}
939
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400940DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400941 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400942 if (!fontCollection->fontsFound()) return;
943 const char* text = "I am RED";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400944 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400945
946 ParagraphStyle paragraph_style;
947 paragraph_style.turnHintingOff();
948 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
949
950 TextStyle text_style;
951 text_style.setFontFamilies({SkString("Roboto")});
952 text_style.setColor(SK_ColorRED);
953 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400954 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400955 builder.pop();
956
957 auto paragraph = builder.Build();
958 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500959 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400960
961 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
962 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
963 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400964 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400965
966 size_t index = 0;
967 for (auto& line : impl->lines()) {
968 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400969 [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
970 REPORTER_ASSERT(reporter, index == 0);
971 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED);
972 ++index;
973 return true;
974 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400975 }
976}
977
Julia Lavrovac2228562019-08-08 16:51:27 -0400978// Checked: DIFF+ (Space between 1 & 2 style blocks)
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400979DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400980 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400981 TestCanvas canvas("SkParagraph_RainbowParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400982 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400983 const char* text1 = "Red Roboto"; // [0:10)
984 const char* text2 = "big Greeen Default"; // [10:28)
985 const char* text3 = "Defcolor Homemade Apple"; // [28:51)
986 const char* text4 = "Small Blue Roboto"; // [51:68)
Julia Lavrovac2228562019-08-08 16:51:27 -0400987 const char* text41 = "Small Blue ";
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400988 const char* text5 =
989 "Continue Last Style With lots of words to check if it overlaps "
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400990 "properly or not"; // [68:)
991 const char* text42 =
992 "Roboto"
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400993 "Continue Last Style With lots of words to check if it overlaps "
994 "properly or not";
995
996 ParagraphStyle paragraph_style;
997 paragraph_style.turnHintingOff();
998 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400999 paragraph_style.setMaxLines(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001000 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1001
1002 TextStyle text_style1;
1003 text_style1.setFontFamilies({SkString("Roboto")});
1004
1005 text_style1.setColor(SK_ColorRED);
1006 builder.pushStyle(text_style1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001007 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001008
1009 TextStyle text_style2;
1010 text_style2.setFontFamilies({SkString("Roboto")});
1011 text_style2.setFontSize(50);
1012 text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1013 SkFontStyle::kUpright_Slant));
1014 text_style2.setLetterSpacing(10);
1015 text_style2.setDecorationColor(SK_ColorBLACK);
1016 text_style2.setDecoration((TextDecoration)(
1017 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1018 text_style2.setWordSpacing(30);
1019 text_style2.setColor(SK_ColorGREEN);
1020 builder.pushStyle(text_style2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001021 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001022
1023 TextStyle text_style3;
1024 text_style3.setFontFamilies({SkString("Homemade Apple")});
Julia Lavrova526df262019-08-21 17:49:44 -04001025 text_style3.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001026 builder.pushStyle(text_style3);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001027 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001028
1029 TextStyle text_style4;
1030 text_style4.setFontFamilies({SkString("Roboto")});
1031 text_style4.setFontSize(14);
1032 text_style4.setDecorationColor(SK_ColorBLACK);
1033 text_style4.setDecoration((TextDecoration)(
1034 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1035 text_style4.setColor(SK_ColorBLUE);
1036 builder.pushStyle(text_style4);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001037 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001038
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001039 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001040 builder.pop();
1041
1042 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001043 paragraph->layout(1000);
1044 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001045
Julia Lavrova3281b962019-12-02 11:32:25 -05001046 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1047
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001048 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1049 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
1050 REPORTER_ASSERT(reporter, impl->styles().size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001051 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1052
1053 auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight);
1054 canvas.drawRects(SK_ColorMAGENTA, rects);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001055
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001056 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001057 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001058 StyleType::kAllAttributes,
1059 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001060 switch (index) {
1061 case 0:
1062 REPORTER_ASSERT(reporter, style.equals(text_style1));
Julia Lavrova526df262019-08-21 17:49:44 -04001063 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001064 break;
1065 case 1:
1066 REPORTER_ASSERT(reporter, style.equals(text_style2));
Julia Lavrova526df262019-08-21 17:49:44 -04001067 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001068 break;
1069 case 2:
1070 REPORTER_ASSERT(reporter, style.equals(text_style3));
Julia Lavrova526df262019-08-21 17:49:44 -04001071 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001072 break;
1073 case 3:
1074 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001075 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001076 break;
1077 default:
1078 REPORTER_ASSERT(reporter, false);
1079 break;
1080 }
1081 ++index;
1082 return true;
1083 });
1084 impl->lines()[1].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001085 StyleType::kAllAttributes,
1086 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001087 switch (index) {
1088 case 4:
1089 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001090 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001091 break;
1092 default:
1093 REPORTER_ASSERT(reporter, false);
1094 break;
1095 }
1096 ++index;
1097 return true;
1098 });
1099 REPORTER_ASSERT(reporter, index == 5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001100}
1101
1102DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001103 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001104 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001105 TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001106 const char* text = "No TextStyle! Uh Oh!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001107 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001108
1109 ParagraphStyle paragraph_style;
1110 TextStyle defaultStyle;
1111 defaultStyle.setFontFamilies({SkString("Roboto")});
1112 paragraph_style.setTextStyle(defaultStyle);
1113 paragraph_style.turnHintingOff();
1114 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001115 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001116
1117 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001118 paragraph->layout(TestCanvasWidth);
1119 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001120
Julia Lavrova3281b962019-12-02 11:32:25 -05001121 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1122
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001123 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1124
1125 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1126 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1127 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1128
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001129 size_t index = 0;
1130 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001131 StyleType::kAllAttributes,
1132 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001133 REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle()));
Julia Lavrova526df262019-08-21 17:49:44 -04001134 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001135 ++index;
1136 return true;
1137 });
1138 REPORTER_ASSERT(reporter, index == 1);
1139}
1140
1141DEF_TEST(SkParagraph_BoldParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001142 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001143 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001144 TestCanvas canvas("SkParagraph_BoldParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001145 const char* text = "This is Red max bold text!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001146 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001147
1148 ParagraphStyle paragraph_style;
1149 paragraph_style.turnHintingOff();
1150 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1151
1152 TextStyle text_style;
1153 text_style.setFontFamilies({SkString("Roboto")});
1154 text_style.setColor(SK_ColorRED);
1155 text_style.setFontSize(60);
1156 text_style.setLetterSpacing(0);
1157 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width,
1158 SkFontStyle::kUpright_Slant));
1159 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001160 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001161 builder.pop();
1162
1163 auto paragraph = builder.Build();
1164 paragraph->layout(VeryLongCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001165 paragraph->paint(canvas.get(), 10.0, 60.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001166
Julia Lavrova3281b962019-12-02 11:32:25 -05001167 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1168
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001169 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1170
1171 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1172 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1173 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1174
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001175 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001176 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001177 StyleType::kAllAttributes,
1178 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001179 REPORTER_ASSERT(reporter, style.equals(text_style));
Julia Lavrova526df262019-08-21 17:49:44 -04001180 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001181 ++index;
1182 return true;
1183 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001184 REPORTER_ASSERT(reporter, index == 1);
1185}
1186
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001187DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001188 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04001189 if (!fontCollection->fontsFound()) return;
1190 TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png");
1191 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001192 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001193
Julia Lavrovac2228562019-08-08 16:51:27 -04001194 ParagraphStyle paragraph_style;
1195 paragraph_style.turnHintingOff();
1196 paragraph_style.setMaxLines(10);
1197 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001198
Julia Lavrovac2228562019-08-08 16:51:27 -04001199 TextStyle text_style;
1200 text_style.setFontFamilies({SkString("Roboto")});
1201 text_style.setFontSize(20);
1202 text_style.setColor(SK_ColorBLACK);
1203 text_style.setHeight(3.6345f);
1204 text_style.setHeightOverride(true);
1205 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001206 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04001207 builder.pop();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001208
Julia Lavrovac2228562019-08-08 16:51:27 -04001209 auto paragraph = builder.Build();
1210 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001211
Julia Lavrovac2228562019-08-08 16:51:27 -04001212 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001213 REPORTER_ASSERT(reporter, impl->runs().size() == 5);
Julia Lavrovac2228562019-08-08 16:51:27 -04001214 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
1215 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001216
Julia Lavrovac2228562019-08-08 16:51:27 -04001217 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001218
Julia Lavrovac2228562019-08-08 16:51:27 -04001219 SkPaint paint;
1220 paint.setStyle(SkPaint::kStroke_Style);
1221 paint.setAntiAlias(true);
1222 paint.setStrokeWidth(1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001223
Julia Lavrovac2228562019-08-08 16:51:27 -04001224 // Tests for GetRectsForRange()
1225 RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle;
1226 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1227 paint.setColor(SK_ColorRED);
1228 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
1229 canvas.drawRects(SK_ColorRED, boxes);
1230 REPORTER_ASSERT(reporter, boxes.size() == 0ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001231
Julia Lavrovac2228562019-08-08 16:51:27 -04001232 boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style);
1233 canvas.drawRects(SK_ColorBLUE, boxes);
1234 REPORTER_ASSERT(reporter, boxes.size() == 3ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001235
Julia Lavrovac2228562019-08-08 16:51:27 -04001236 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100));
1237 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5));
1238 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100));
1239 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001240}
1241
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001242DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001243 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001244 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001245 TestCanvas canvas("SkParagraph_LeftAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001246 const char* text =
1247 "This is a very long sentence to test if the text will properly wrap "
1248 "around and go to the next line. Sometimes, short sentence. Longer "
1249 "sentences are okay too because they are nessecary. Very short. "
1250 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1251 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1252 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1253 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1254 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1255 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1256 "mollit anim id est laborum. "
1257 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1258 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1259 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1260 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1261 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1262 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1263 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001264 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001265
1266 ParagraphStyle paragraph_style;
1267 paragraph_style.setMaxLines(14);
1268 paragraph_style.setTextAlign(TextAlign::kLeft);
1269 paragraph_style.turnHintingOff();
1270 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1271
1272 TextStyle text_style;
1273 text_style.setFontFamilies({SkString("Roboto")});
1274 text_style.setFontSize(26);
1275 text_style.setLetterSpacing(1);
1276 text_style.setWordSpacing(5);
1277 text_style.setColor(SK_ColorBLACK);
1278 text_style.setHeight(1);
1279 text_style.setDecoration(TextDecoration::kUnderline);
1280 text_style.setDecorationColor(SK_ColorBLACK);
1281 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001282 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001283 builder.pop();
1284
1285 auto paragraph = builder.Build();
1286 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001287 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001288
1289 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001290
1291 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1292 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1293 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001294 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001295 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1296
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001297 double expected_y = 0;
1298 double epsilon = 0.01f;
1299 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1300 REPORTER_ASSERT(reporter,
1301 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1302 expected_y += 30;
1303 REPORTER_ASSERT(reporter,
1304 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1305 expected_y += 30;
1306 REPORTER_ASSERT(reporter,
1307 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1308 expected_y += 30;
1309 REPORTER_ASSERT(reporter,
1310 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1311 expected_y += 30 * 10;
1312 REPORTER_ASSERT(reporter,
1313 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1314
1315 REPORTER_ASSERT(reporter,
1316 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1317
1318 // Tests for GetGlyphPositionAtCoordinate()
1319 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0);
1320 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
1321 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
1322 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001323 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001324}
1325
1326DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001327 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001328 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001329 TestCanvas canvas("SkParagraph_RightAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001330 const char* text =
1331 "This is a very long sentence to test if the text will properly wrap "
1332 "around and go to the next line. Sometimes, short sentence. Longer "
1333 "sentences are okay too because they are nessecary. Very short. "
1334 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1335 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1336 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1337 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1338 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1339 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1340 "mollit anim id est laborum. "
1341 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1342 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1343 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1344 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1345 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1346 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1347 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001348 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001349
1350 ParagraphStyle paragraph_style;
1351 paragraph_style.setMaxLines(14);
1352 paragraph_style.setTextAlign(TextAlign::kRight);
1353 paragraph_style.turnHintingOff();
1354 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1355
1356 TextStyle text_style;
1357 text_style.setFontFamilies({SkString("Roboto")});
1358 text_style.setFontSize(26);
1359 text_style.setLetterSpacing(1);
1360 text_style.setWordSpacing(5);
1361 text_style.setColor(SK_ColorBLACK);
1362 text_style.setHeight(1);
1363 text_style.setDecoration(TextDecoration::kUnderline);
1364 text_style.setDecorationColor(SK_ColorBLACK);
1365 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001366 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001367 builder.pop();
1368
1369 auto paragraph = builder.Build();
1370 paragraph->layout(TestCanvasWidth - 100);
1371
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001372 paragraph->paint(canvas.get(), 0, 0);
1373
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001374 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001375
1376 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1377 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001378 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001379 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1380
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001381 double expected_y = 0;
1382 double epsilon = 0.01f;
1383 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1384 REPORTER_ASSERT(reporter,
1385 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1386 expected_y += 30;
1387 REPORTER_ASSERT(reporter,
1388 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1389 expected_y += 30;
1390 REPORTER_ASSERT(reporter,
1391 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1392 expected_y += 30;
1393 REPORTER_ASSERT(reporter,
1394 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1395 expected_y += 30 * 10;
1396 REPORTER_ASSERT(reporter,
1397 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1398
1399 auto calculate = [](const TextLine& line) -> SkScalar {
1400 return TestCanvasWidth - 100 - line.offset().fX - line.width();
1401 };
1402
1403 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1404 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1408
1409 REPORTER_ASSERT(reporter,
1410 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1411}
1412
1413DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001414 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001415 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001416 TestCanvas canvas("SkParagraph_CenterAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001417 const char* text =
1418 "This is a very long sentence to test if the text will properly wrap "
1419 "around and go to the next line. Sometimes, short sentence. Longer "
1420 "sentences are okay too because they are nessecary. Very short. "
1421 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1422 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1423 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1424 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1425 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1426 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1427 "mollit anim id est laborum. "
1428 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1429 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1430 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1431 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1432 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1433 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1434 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001435 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001436
1437 ParagraphStyle paragraph_style;
1438 paragraph_style.setMaxLines(14);
1439 paragraph_style.setTextAlign(TextAlign::kCenter);
1440 paragraph_style.turnHintingOff();
1441 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1442
1443 TextStyle text_style;
1444 text_style.setFontFamilies({SkString("Roboto")});
1445 text_style.setFontSize(26);
1446 text_style.setLetterSpacing(1);
1447 text_style.setWordSpacing(5);
1448 text_style.setColor(SK_ColorBLACK);
1449 text_style.setHeight(1);
1450 text_style.setDecoration(TextDecoration::kUnderline);
1451 text_style.setDecorationColor(SK_ColorBLACK);
1452 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001453 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001454 builder.pop();
1455
1456 auto paragraph = builder.Build();
1457 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001458 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001459
1460 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001461
1462 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1463 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1464 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001465 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001466 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1467
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001468 double expected_y = 0;
1469 double epsilon = 0.01f;
1470 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1471 REPORTER_ASSERT(reporter,
1472 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1473 expected_y += 30;
1474 REPORTER_ASSERT(reporter,
1475 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1476 expected_y += 30;
1477 REPORTER_ASSERT(reporter,
1478 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1479 expected_y += 30;
1480 REPORTER_ASSERT(reporter,
1481 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1482 expected_y += 30 * 10;
1483 REPORTER_ASSERT(reporter,
1484 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1485
1486 auto calculate = [](const TextLine& line) -> SkScalar {
1487 return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width());
1488 };
1489
1490 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1491 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1492 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1495
1496 REPORTER_ASSERT(reporter,
1497 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1498}
1499
1500DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001501 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001502 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001503 TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001504 const char* text =
1505 "This is a very long sentence to test if the text will properly wrap "
1506 "around and go to the next line. Sometimes, short sentence. Longer "
1507 "sentences are okay too because they are nessecary. Very short. "
1508 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1509 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1510 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1511 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1512 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1513 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1514 "mollit anim id est laborum. "
1515 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1516 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1517 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1518 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1519 "velit esse cillum dolore eu fugiat.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001520 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001521
1522 ParagraphStyle paragraph_style;
1523 paragraph_style.setMaxLines(14);
1524 paragraph_style.setTextAlign(TextAlign::kJustify);
1525 paragraph_style.turnHintingOff();
1526 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1527
1528 TextStyle text_style;
1529 text_style.setFontFamilies({SkString("Roboto")});
1530 text_style.setFontSize(26);
1531 text_style.setLetterSpacing(0);
1532 text_style.setWordSpacing(5);
1533 text_style.setColor(SK_ColorBLACK);
1534 text_style.setHeight(1);
1535 text_style.setDecoration(TextDecoration::kUnderline);
1536 text_style.setDecorationColor(SK_ColorBLACK);
1537 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001538 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001539 builder.pop();
1540
1541 auto paragraph = builder.Build();
1542 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001543 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001544
Julia Lavrovac2228562019-08-08 16:51:27 -04001545 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1546 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1547 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1548 canvas.drawRects(SK_ColorRED, boxes);
1549
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001550 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001551
1552 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1553 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1554 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001555 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001556
1557 double expected_y = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001558 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001559 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001560 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001561 expected_y += 30;
1562 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001563 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001564 expected_y += 30;
1565 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001566 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001567 expected_y += 30;
1568 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001569 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001570 expected_y += 30 * 9;
1571 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001572 SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001573
1574 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001575 return line.offset().fX;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001576 };
1577
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001578 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100));
1579 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100));
1580 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100));
1581 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001582
1583 REPORTER_ASSERT(reporter,
1584 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1585}
1586
Julia Lavrovac2228562019-08-08 16:51:27 -04001587// Checked: DIFF (ghost spaces as a separate box in TxtLib)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001588DEF_TEST(SkParagraph_JustifyRTL, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001589 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001590 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001591 TestCanvas canvas("SkParagraph_JustifyRTL.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001592 const char* text =
1593 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1594 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1595 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001596 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001597
1598 ParagraphStyle paragraph_style;
1599 paragraph_style.setMaxLines(14);
1600 paragraph_style.setTextAlign(TextAlign::kJustify);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001601 paragraph_style.setTextDirection(TextDirection::kRtl);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001602 paragraph_style.turnHintingOff();
1603 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1604
1605 TextStyle text_style;
1606 text_style.setFontFamilies({SkString("Ahem")});
1607 text_style.setFontSize(26);
1608 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001609 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001610 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001611 builder.pop();
1612
1613 auto paragraph = builder.Build();
1614 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001615 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001616
1617 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001618
1619 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001620 return TestCanvasWidth - 100 - line.width();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001621 };
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001622 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001623 if (&line == &impl->lines().back()) {
1624 REPORTER_ASSERT(reporter, calculate(line) > EPSILON100);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001625 } else {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001627 }
1628 }
1629
1630 // Just make sure the the text is actually RTL
1631 for (auto& run : impl->runs()) {
1632 REPORTER_ASSERT(reporter, !run.leftToRight());
1633 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001634
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001635 // Tests for GetRectsForRange()
1636 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1637 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1638 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1639 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001640 REPORTER_ASSERT(reporter, boxes.size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001641
1642 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1643 canvas.drawRects(SK_ColorBLUE, boxes);
1644 REPORTER_ASSERT(reporter, boxes.size() == 1);
1645
1646 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100));
1647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100));
1649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1650}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001651
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001652DEF_TEST_DISABLED(SkParagraph_JustifyRTLNewLine, reporter) {
1653 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1654 if (!fontCollection->fontsFound()) return;
1655 TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png");
1656 const char* text =
1657 "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1658 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1659 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
1660
1661 auto icu_text = icu::UnicodeString::fromUTF8(text);
1662 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1663 const size_t len = strlen(text);
1664
1665 ParagraphStyle paragraph_style;
1666 paragraph_style.setMaxLines(14);
1667 paragraph_style.setTextAlign(TextAlign::kJustify);
1668 paragraph_style.setTextDirection(TextDirection::kRtl);
1669 paragraph_style.turnHintingOff();
1670 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1671
1672 TextStyle text_style;
1673 text_style.setFontFamilies({SkString("Ahem")});
1674 text_style.setFontSize(26);
1675 text_style.setColor(SK_ColorBLACK);
1676 builder.pushStyle(text_style);
1677 builder.addText(text, len);
1678 builder.pop();
1679
1680 auto paragraph = builder.Build();
1681 paragraph->layout(TestCanvasWidth - 100);
1682 paragraph->paint(canvas.get(), 0, 0);
1683
1684 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1685
1686 SkPaint paint;
1687 paint.setStyle(SkPaint::kStroke_Style);
1688 paint.setAntiAlias(true);
1689 paint.setStrokeWidth(1);
1690
1691 // Tests for GetRectsForRange()
1692 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1693 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1694 paint.setColor(SK_ColorRED);
1695 auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
1696 for (size_t i = 0; i < boxes.size(); ++i) {
1697 canvas.get()->drawRect(boxes[i].rect, paint);
1698 }
1699 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1700 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
1701 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
1702 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1703 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
1704
1705 paint.setColor(SK_ColorBLUE);
1706 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1707 for (size_t i = 0; i < boxes.size(); ++i) {
1708 canvas.get()->drawRect(boxes[i].rect, paint);
1709 }
1710 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
1711 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
1712 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1713 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
1714 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1715
1716 // All lines should be justified to the width of the
1717 // paragraph.
1718 for (auto& line : impl->lines()) {
1719 REPORTER_ASSERT(reporter,
1720 SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
1721 }
1722}
1723
1724DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
1725 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1726 if (!fontCollection->fontsFound()) return;
1727 TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
1728
1729 const char* text = " leading space";
1730
1731 auto icu_text = icu::UnicodeString::fromUTF8(text);
1732 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1733 const size_t len = strlen(text);
1734
1735 ParagraphStyle paragraph_style;
1736 paragraph_style.setMaxLines(14);
1737 paragraph_style.setTextAlign(TextAlign::kJustify);
1738 paragraph_style.setTextDirection(TextDirection::kRtl);
1739 paragraph_style.turnHintingOff();
1740 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1741
1742 TextStyle text_style;
1743 text_style.setFontFamilies({SkString("Ahem")});
1744 text_style.setFontSize(26);
1745 text_style.setColor(SK_ColorBLACK);
1746 builder.pushStyle(text_style);
1747 builder.addText(text, len);
1748 builder.pop();
1749
1750 auto paragraph = builder.Build();
1751 paragraph->layout(TestCanvasWidth - 100);
1752 paragraph->paint(canvas.get(), 0, 0);
1753
1754 SkPaint paint;
1755 paint.setStyle(SkPaint::kStroke_Style);
1756 paint.setAntiAlias(true);
1757 paint.setStrokeWidth(1);
1758
1759 // Tests for GetRectsForRange()
1760 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1761 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1762 paint.setColor(SK_ColorRED);
1763 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1764 for (size_t i = 0; i < boxes.size(); ++i) {
1765 canvas.get()->drawRect(boxes[i].rect, paint);
1766 }
1767 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1768}
1769
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001770DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001771 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001772 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001773 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001774 const char* text1 = "This text should be";
1775 const char* text2 = " decorated even when";
1776 const char* text3 = " wrapped around to";
1777 const char* text4 = " the next line.";
1778 const char* text5 = " Otherwise, bad things happen.";
1779
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001780 ParagraphStyle paragraph_style;
1781 paragraph_style.setMaxLines(14);
1782 paragraph_style.setTextAlign(TextAlign::kLeft);
1783 paragraph_style.turnHintingOff();
1784 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1785
1786 TextStyle text_style;
1787 text_style.setFontFamilies({SkString("Roboto")});
1788 text_style.setFontSize(26);
1789 text_style.setLetterSpacing(0);
1790 text_style.setWordSpacing(5);
1791 text_style.setColor(SK_ColorBLACK);
1792 text_style.setHeight(2);
1793 text_style.setDecoration(TextDecoration::kUnderline);
1794 text_style.setDecorationColor(SK_ColorBLACK);
1795 text_style.setDecoration((TextDecoration)(
1796 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1797 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1798 text_style.setDecorationColor(SK_ColorBLACK);
1799 text_style.setDecorationThicknessMultiplier(2.0);
1800 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001801 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001802
1803 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1804 text_style.setDecorationColor(SK_ColorBLUE);
1805 text_style.setDecorationThicknessMultiplier(1.0);
1806 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001807 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001808
1809 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1810 text_style.setDecorationColor(SK_ColorBLACK);
1811 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001812 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001813
1814 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1815 text_style.setDecorationColor(SK_ColorBLACK);
1816 text_style.setDecorationThicknessMultiplier(3.0);
1817 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001818 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001819
1820 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1821 text_style.setDecorationColor(SK_ColorRED);
1822 text_style.setDecorationThicknessMultiplier(1.0);
1823 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001824 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001825 builder.pop();
1826
1827 auto paragraph = builder.Build();
1828 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001829 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001830
1831 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001832
1833 size_t index = 0;
1834 for (auto& line : impl->lines()) {
1835 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001836 StyleType::kDecorations,
1837 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001838 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1839 TextDecoration::kOverline |
1840 TextDecoration::kLineThrough);
1841 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1842 switch (index) {
1843 case 0:
1844 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1845 TextDecorationStyle::kSolid);
1846 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1847 REPORTER_ASSERT(reporter,
1848 style.getDecorationThicknessMultiplier() == 2.0);
1849 break;
1850 case 1: // The style appears on 2 lines so it has 2 pieces
1851 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1852 TextDecorationStyle::kDouble);
1853 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1854 REPORTER_ASSERT(reporter,
1855 style.getDecorationThicknessMultiplier() == 1.0);
1856 break;
1857 case 2:
1858 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1859 TextDecorationStyle::kDotted);
1860 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1861 REPORTER_ASSERT(reporter,
1862 style.getDecorationThicknessMultiplier() == 1.0);
1863 break;
1864 case 3:
1865 case 4:
1866 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1867 TextDecorationStyle::kDashed);
1868 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1869 REPORTER_ASSERT(reporter,
1870 style.getDecorationThicknessMultiplier() == 3.0);
1871 break;
1872 case 5:
1873 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1874 TextDecorationStyle::kWavy);
1875 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1876 REPORTER_ASSERT(reporter,
1877 style.getDecorationThicknessMultiplier() == 1.0);
1878 break;
1879 default:
1880 REPORTER_ASSERT(reporter, false);
1881 break;
1882 }
1883 ++index;
1884 return true;
1885 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001886 }
1887}
1888
Julia Lavrovac2228562019-08-08 16:51:27 -04001889DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001890 SkDebugf("TODO: Add test for wavy decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001891}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001892
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001893DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001894 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001895 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001896 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001897 const char* text1 = "No italic ";
1898 const char* text2 = "Yes Italic ";
1899 const char* text3 = "No Italic again.";
1900
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001901 ParagraphStyle paragraph_style;
1902 paragraph_style.turnHintingOff();
1903 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1904
1905 TextStyle text_style;
1906 text_style.setFontFamilies({SkString("Roboto")});
1907 text_style.setFontSize(10);
1908 text_style.setColor(SK_ColorRED);
1909 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001910 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001911
1912 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1913 SkFontStyle::kItalic_Slant));
1914 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001915 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001916 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001917 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001918
1919 auto paragraph = builder.Build();
1920 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001921 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001922
1923 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001924
1925 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1926 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1927 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1928 auto& line = impl->lines()[0];
1929 size_t index = 0;
1930 line.scanStyles(
1931 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001932 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001933 switch (index) {
1934 case 0:
1935 REPORTER_ASSERT(
1936 reporter,
1937 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1938 break;
1939 case 1:
1940 REPORTER_ASSERT(reporter,
1941 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1942 break;
1943 case 2:
1944 REPORTER_ASSERT(
1945 reporter,
1946 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1947 break;
1948 default:
1949 REPORTER_ASSERT(reporter, false);
1950 break;
1951 }
1952 ++index;
1953 return true;
1954 });
1955}
1956
1957DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001958 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001959 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001960 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001961 const char* text =
1962 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1963 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1964 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1965 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1966 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001967 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001968
1969 ParagraphStyle paragraph_style;
1970 paragraph_style.setMaxLines(14);
1971 paragraph_style.setTextAlign(TextAlign::kJustify);
1972 paragraph_style.turnHintingOff();
1973 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1974
1975 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
1976 TextDecoration::kLineThrough);
1977
1978 TextStyle text_style;
1979 text_style.setFontFamilies({SkString("Source Han Serif CN")});
1980 text_style.setFontSize(35);
1981 text_style.setColor(SK_ColorBLACK);
1982 text_style.setLetterSpacing(2);
1983 text_style.setHeight(1);
1984 text_style.setDecoration(decoration);
1985 text_style.setDecorationColor(SK_ColorBLACK);
1986 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1987 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001988 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001989 builder.pop();
1990
1991 auto paragraph = builder.Build();
1992 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001993 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001994
Julia Lavrova3281b962019-12-02 11:32:25 -05001995 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1996
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001997 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001998
1999 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2000 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
2001 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002002 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002003}
2004
Julia Lavrovad3a32c52020-02-03 09:43:52 -05002005// Checked: disabled for TxtLib
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002006DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002007 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002008 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002009 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002010 const char* text =
2011 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2012 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002013 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002014
2015 ParagraphStyle paragraph_style;
2016 paragraph_style.setMaxLines(14);
2017 paragraph_style.setTextAlign(TextAlign::kJustify);
2018 paragraph_style.turnHintingOff();
2019 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2020
2021 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2022 TextDecoration::kLineThrough);
2023
2024 TextStyle text_style;
2025 text_style.setFontFamilies({SkString("Katibeh")});
2026 text_style.setFontSize(35);
2027 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002028 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002029 text_style.setDecoration(decoration);
2030 text_style.setDecorationColor(SK_ColorBLACK);
2031 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2032 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002033 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002034 builder.pop();
2035
2036 auto paragraph = builder.Build();
2037 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002038 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002039
Julia Lavrova3281b962019-12-02 11:32:25 -05002040 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2041
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002042 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002043
2044 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2045 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2046 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002047 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002048}
2049
Julia Lavrovac2228562019-08-08 16:51:27 -04002050// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002051DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
2052
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002053 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002054 if (!fontCollection->fontsFound()) return;
2055 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
2056 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002057 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002058
2059 ParagraphStyle paragraph_style;
2060 paragraph_style.turnHintingOff();
2061 paragraph_style.setMaxLines(14);
2062 paragraph_style.setTextAlign(TextAlign::kRight);
2063 paragraph_style.setTextDirection(TextDirection::kRtl);
2064 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2065
2066 TextStyle text_style;
2067 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2068 text_style.setFontSize(26);
2069 text_style.setWordSpacing(5);
2070 text_style.setColor(SK_ColorBLACK);
2071 text_style.setDecoration(TextDecoration::kUnderline);
2072 text_style.setDecorationColor(SK_ColorBLACK);
2073 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002074 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002075 builder.pop();
2076
2077 auto paragraph = builder.Build();
2078 paragraph->layout(TestCanvasWidth - 100);
2079
2080 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2081 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2082
2083 paragraph->paint(canvas.get(), 0, 0);
2084
2085 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2086 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2087 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
2088 canvas.drawRects(SK_ColorRED, boxes);
2089
Julia Lavrovac2228562019-08-08 16:51:27 -04002090 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002091
Julia Lavrovac2228562019-08-08 16:51:27 -04002092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
2093 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002094 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
2095 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002096}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002097
2098// Checked DIFF+
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002099// This test shows now 2 boxes for [36:40) range:
2100// [36:38) for arabic text and [38:39) for the last space
2101// that has default paragraph direction (LTR) and is placed at the end of the paragraph
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002102DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
2103
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002104 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002105 if (!fontCollection->fontsFound()) return;
2106 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
2107 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002108 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002109
2110 ParagraphStyle paragraph_style;
2111 paragraph_style.turnHintingOff();
2112 paragraph_style.setMaxLines(14);
2113 paragraph_style.setTextAlign(TextAlign::kLeft);
2114 paragraph_style.setTextDirection(TextDirection::kLtr);
2115 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2116
2117 TextStyle text_style;
2118 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2119 text_style.setFontSize(26);
2120 text_style.setWordSpacing(5);
2121 text_style.setColor(SK_ColorBLACK);
2122 text_style.setDecoration(TextDecoration::kUnderline);
2123 text_style.setDecorationColor(SK_ColorBLACK);
2124 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002125 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002126 builder.pop();
2127
2128 auto paragraph = builder.Build();
2129 paragraph->layout(TestCanvasWidth - 100);
2130
2131 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2132 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2133
2134 paragraph->paint(canvas.get(), 0, 0);
2135
2136 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2137 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002138 // 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 -04002139 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2140 canvas.drawRects(SK_ColorRED, boxes);
2141
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002142 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
2143 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.92f, EPSILON100)); // DIFF: 89.40625
2144 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2145 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 110.16f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002146 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002147}
2148
2149// Checked DIFF+
2150DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2151
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002152 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002153 if (!fontCollection->fontsFound()) return;
2154 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2155 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002156 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002157
2158 ParagraphStyle paragraph_style;
2159 paragraph_style.turnHintingOff();
2160 paragraph_style.setMaxLines(14);
2161 paragraph_style.setTextAlign(TextAlign::kRight);
2162 paragraph_style.setTextDirection(TextDirection::kLtr);
2163 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2164
2165 TextStyle text_style;
2166 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2167 text_style.setFontSize(26);
2168 text_style.setWordSpacing(5);
2169 text_style.setColor(SK_ColorBLACK);
2170 text_style.setDecoration(TextDecoration::kUnderline);
2171 text_style.setDecorationColor(SK_ColorBLACK);
2172 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002173 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002174 builder.pop();
2175
2176 auto paragraph = builder.Build();
2177 paragraph->layout(TestCanvasWidth - 100);
2178
2179 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2180 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2181
2182 paragraph->paint(canvas.get(), 0, 0);
2183
2184 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2185 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2186 std::vector<TextBox> boxes =
2187 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2188 canvas.drawRects(SK_ColorRED, boxes);
2189
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002190 REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF
2191 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.5f, EPSILON100)); // DIFF
2192 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2193 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 587.74f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002194 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002195}
2196
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002197DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002198 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002199 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002200 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002201 const char* text =
2202 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2203 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002204 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002205
2206 ParagraphStyle paragraphStyle;
2207 paragraphStyle.setTextAlign(TextAlign::kLeft);
2208 paragraphStyle.setMaxLines(10);
2209 paragraphStyle.turnHintingOff();
2210 TextStyle textStyle;
2211 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002212 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2213 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002214 textStyle.setFontSize(50);
2215 textStyle.setLetterSpacing(1);
2216 textStyle.setWordSpacing(5);
2217 textStyle.setHeight(1);
2218 textStyle.setColor(SK_ColorBLACK);
2219
2220 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2221 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002222 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002223 builder.pop();
2224
2225 auto paragraph = builder.Build();
2226 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002227 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002228
2229 // Tests for getGlyphPositionAtCoordinate()
2230 // NOTE: resulting values can be a few off from their respective positions in
2231 // the original text because the final trailing whitespaces are sometimes not
2232 // drawn (namely, when using "justify" alignment) and therefore are not active
2233 // glyphs.
2234 REPORTER_ASSERT(reporter,
2235 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2236 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2237 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2238 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2239 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2240 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002241 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002242 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2243 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2244 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002245 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002246 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002247 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002248 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2249 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002250 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002251 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2252 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002253 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002254 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2255 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2256 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002257 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002258 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2259}
2260
2261DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002262 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002263 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002264 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002265 const char* text =
2266 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2267 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002268 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002269
2270 ParagraphStyle paragraphStyle;
2271 paragraphStyle.setTextAlign(TextAlign::kLeft);
2272 paragraphStyle.setMaxLines(10);
2273 paragraphStyle.turnHintingOff();
2274 TextStyle textStyle;
2275 textStyle.setFontFamilies({SkString("Roboto")});
2276 textStyle.setFontSize(50);
2277 textStyle.setColor(SK_ColorBLACK);
2278 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2279 SkFontStyle::kUpright_Slant));
2280
2281 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2282 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002283 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002284 builder.pop();
2285
2286 auto paragraph = builder.Build();
2287 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002288 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002289
2290 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2291 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002292
2293 SkPaint paint;
2294 paint.setStyle(SkPaint::kStroke_Style);
2295 paint.setAntiAlias(true);
2296 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002297
2298 {
2299 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2300 REPORTER_ASSERT(reporter, result.empty());
2301 }
2302 {
2303 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002304 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002305 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002306 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2307 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2308 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2309 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002310 }
2311 {
2312 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002313 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002314 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002315 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2316 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2317 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2318 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002319 }
2320 {
2321 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002322 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002323 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002324 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2325 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2326 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2327 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002328 }
2329 {
2330 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002331 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002332 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002333 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2334 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2335 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2336 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2337 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2338 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002341 }
2342 {
2343 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002344 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002345 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002346 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002347 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002348 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002349 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002350 }
2351 {
2352 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2353 REPORTER_ASSERT(reporter, result.empty());
2354 }
2355}
2356
2357DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002358 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002359 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002360 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002361 const char* text =
2362 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2363 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2364 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002365 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002366
2367 ParagraphStyle paragraphStyle;
2368 paragraphStyle.setTextAlign(TextAlign::kLeft);
2369 paragraphStyle.setMaxLines(10);
2370 paragraphStyle.turnHintingOff();
2371 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002372 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002373 textStyle.setFontSize(50);
2374 textStyle.setColor(SK_ColorBLACK);
2375 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2376 SkFontStyle::kUpright_Slant));
2377
2378 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2379 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002380 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002381 builder.pop();
2382
2383 auto paragraph = builder.Build();
2384 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002385 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002386
2387 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2388 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002389 {
2390 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2391 REPORTER_ASSERT(reporter, result.empty());
2392 }
2393 {
2394 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002395 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002396 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002401 }
2402 {
2403 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002404 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002405 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2409 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002410 }
2411 {
2412 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002413 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002414 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2416 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2417 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2418 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002419 }
2420}
2421
Julia Lavrovac2228562019-08-08 16:51:27 -04002422// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002423DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002424 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002425 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002426 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002427 const char* text =
2428 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2429 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2430 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002431 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002432
2433 ParagraphStyle paragraphStyle;
2434 paragraphStyle.setTextAlign(TextAlign::kLeft);
2435 paragraphStyle.setMaxLines(10);
2436 paragraphStyle.turnHintingOff();
2437 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002438 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002439 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002440 textStyle.setHeight(1.6f);
2441 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002442 textStyle.setColor(SK_ColorBLACK);
2443 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2444 SkFontStyle::kUpright_Slant));
2445
2446 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2447 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002448 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002449 builder.pop();
2450
2451 auto paragraph = builder.Build();
2452 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002453 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002454
2455 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002456 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002457 {
2458 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2459 REPORTER_ASSERT(reporter, result.empty());
2460 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002461
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002462 {
2463 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002464 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002465 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002466 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2467 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2468 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2469 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002470 }
2471 {
2472 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002473 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002474 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2476 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2477 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2478 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002479 }
2480 {
2481 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002482 canvas.drawRects(SK_ColorGREEN, result);
2483 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002486 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002487 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(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002491 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002492 REPORTER_ASSERT(reporter, result.size() == 8);
2493
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2496 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2497 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2498
2499 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2500 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2501 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2503
2504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002506 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2508
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002509 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2511 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2512 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2513
2514 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2518
2519 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2520 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2521 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2522 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002523 }
2524 {
2525 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002526 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002527 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002528 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002529 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002530 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002531 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2532
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2536 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002537 }
2538 {
2539 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2540 REPORTER_ASSERT(reporter, result.empty());
2541 }
2542}
2543
Julia Lavrovac2228562019-08-08 16:51:27 -04002544// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002545DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002546 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002547 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002548 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002549 const char* text =
2550 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2551 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2552 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002553 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002554
2555 ParagraphStyle paragraphStyle;
2556 paragraphStyle.setTextAlign(TextAlign::kLeft);
2557 paragraphStyle.setMaxLines(10);
2558 paragraphStyle.turnHintingOff();
2559 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002560 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002561 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002562 textStyle.setHeight(1.6f);
2563 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002564 textStyle.setColor(SK_ColorBLACK);
2565 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2566 SkFontStyle::kUpright_Slant));
2567
2568 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2569 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002570 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002571 builder.pop();
2572
2573 auto paragraph = builder.Build();
2574 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002575 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002576
2577 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002578 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002579 {
2580 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2581 REPORTER_ASSERT(reporter, result.empty());
2582 }
2583
2584 {
2585 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002586 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002587 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002588 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2589 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2590 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2591 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002592 }
2593 {
2594 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002595 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002596 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002597 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2598 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2599 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2600 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002601 }
2602 {
2603 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002604 canvas.drawRects(SK_ColorGREEN, result);
2605 REPORTER_ASSERT(reporter, result.size() == 1);
2606 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2607 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2608 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
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(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002613 canvas.drawRects(SK_ColorMAGENTA, result);
2614 REPORTER_ASSERT(reporter, result.size() == 8);
2615
2616 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2617 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2618 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2619 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2620
2621 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2622 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2623 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2625
2626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2627 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2628 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2629 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2630
2631 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2632 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2633 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2634 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2635
2636 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2637 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2638 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2639 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2640
2641 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2643 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2644 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002645 }
2646 {
2647 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002648 canvas.drawRects(SK_ColorBLACK, result);
2649 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002651 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002653 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2654
2655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002659 }
2660 {
2661 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2662 REPORTER_ASSERT(reporter, result.empty());
2663 }
2664}
2665
Julia Lavrovac2228562019-08-08 16:51:27 -04002666// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002667DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002668 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002669 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002670 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002671 const char* text =
2672 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2673 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2674 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002675 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002676
2677 ParagraphStyle paragraphStyle;
2678 paragraphStyle.setTextAlign(TextAlign::kLeft);
2679 paragraphStyle.setMaxLines(10);
2680 paragraphStyle.turnHintingOff();
2681 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002682 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002683 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002684 textStyle.setHeight(1.6f);
2685 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002686 textStyle.setColor(SK_ColorBLACK);
2687 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2688 SkFontStyle::kUpright_Slant));
2689
2690 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2691 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002692 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002693 builder.pop();
2694
2695 auto paragraph = builder.Build();
2696 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002697 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002698
2699 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002700 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002701 {
2702 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2703 REPORTER_ASSERT(reporter, result.empty());
2704 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002705
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002706 {
2707 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002708 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002709 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002710 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2711 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2712 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2713 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002714 }
2715 {
2716 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002717 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002718 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002719 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2720 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2721 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2722 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002723 }
2724 {
2725 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002726 canvas.drawRects(SK_ColorGREEN, result);
2727 REPORTER_ASSERT(reporter, result.size() == 1);
2728 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2729 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2730 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
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(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002735 canvas.drawRects(SK_ColorMAGENTA, result);
2736 REPORTER_ASSERT(reporter, result.size() == 8);
2737
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002738 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002739 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2740 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2741 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2742
2743 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2744 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2745 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2746 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2747
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002748 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002749 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2750 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2751 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2752
2753 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2754 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2755 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2756 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2757
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002758 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002759 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2760 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2761 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2762
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002763 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002764 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2765 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2766 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002767 }
2768 {
2769 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002770 canvas.drawRects(SK_ColorBLACK, result);
2771 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002772 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002773 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002774 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002775 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2776
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002777 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002778 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2780 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002781 }
2782 {
2783 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2784 REPORTER_ASSERT(reporter, result.empty());
2785 }
2786}
2787
Julia Lavrova2813d452020-03-03 11:43:40 -05002788// This is the test I cannot accommodate
2789// Any text range gets a smallest glyph rectangle
2790DEF_TEST_DISABLED(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002791 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002792 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002793 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002794 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002795 const size_t len = strlen(text);
2796
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002797 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002798 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002799 paragraphStyle.setMaxLines(10);
2800 paragraphStyle.turnHintingOff();
2801 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2802
2803 TextStyle textStyle;
2804 textStyle.setFontFamilies({SkString("Roboto")});
2805 textStyle.setFontSize(50);
2806 textStyle.setLetterSpacing(1);
2807 textStyle.setWordSpacing(5);
2808 textStyle.setHeight(1);
2809 textStyle.setColor(SK_ColorBLACK);
2810
2811 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002812 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002813 builder.pop();
2814
2815 auto paragraph = builder.Build();
2816 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002817 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002818
2819 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002820 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2821
2822 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2823 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2824 {
2825 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2826 REPORTER_ASSERT(reporter, result.empty());
2827 }
2828 {
2829 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2830 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2831 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002832 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2833 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002834 }
2835 {
2836 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2837 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2838 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002839 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2840 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002841 }
2842 {
2843 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2844 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2845 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2846 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002847 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002848 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002849 }
2850}
2851
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002852// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002853DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002854 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002855 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002856 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002857 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2858 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2859 // Any attempt to substitute one for another leads to errors
2860 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002861 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002862 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002863
2864 ParagraphStyle paragraphStyle;
2865 paragraphStyle.setTextAlign(TextAlign::kCenter);
2866 paragraphStyle.setMaxLines(10);
2867 paragraphStyle.turnHintingOff();
2868 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2869
2870 TextStyle textStyle;
2871 textStyle.setFontFamilies({SkString("Roboto")});
2872 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002873 textStyle.setHeight(1);
2874 textStyle.setColor(SK_ColorBLACK);
2875 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2876 SkFontStyle::kUpright_Slant));
2877
2878 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002879 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002880 builder.pop();
2881
2882 auto paragraph = builder.Build();
2883 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002884 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002885
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002886 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002887 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2888 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002889 {
2890 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2891 REPORTER_ASSERT(reporter, result.empty());
2892 }
2893
2894 {
2895 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002896 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002897 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002898 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2899 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2900 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2901 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002902 }
2903
2904 {
2905 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002906 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002907 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002908 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2909 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2910 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2911 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002912 }
2913
2914 {
2915 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002916 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002917 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002918 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2919 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2920 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2921 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002922 }
2923
2924 {
2925 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002926 canvas.drawRects(SK_ColorBLACK, result);
2927 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2928 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2929 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2930 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2931 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002932 }
2933
2934 {
2935 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002936 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002937 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002938 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2939 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2940 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2941 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002942 }
2943
2944 {
2945 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2946 REPORTER_ASSERT(reporter, result.empty());
2947 }
2948}
2949
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002950// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002951DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002952 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002953 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002954 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002955 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002956 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002957
2958 ParagraphStyle paragraphStyle;
2959 paragraphStyle.setTextAlign(TextAlign::kCenter);
2960 paragraphStyle.setMaxLines(10);
2961 paragraphStyle.turnHintingOff();
2962 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2963
2964 TextStyle textStyle;
2965 textStyle.setFontFamilies({SkString("Roboto")});
2966 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002967 textStyle.setHeight(1);
2968 textStyle.setColor(SK_ColorBLACK);
2969 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2970 SkFontStyle::kUpright_Slant));
2971
2972 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002973 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002974 builder.pop();
2975
2976 auto paragraph = builder.Build();
2977 paragraph->layout(550);
2978
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002979 paragraph->paint(canvas.get(), 0, 0);
2980
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002981 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002982 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2983
2984 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2985 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002986 {
2987 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2988 REPORTER_ASSERT(reporter, result.empty());
2989 }
2990
2991 {
2992 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04002993 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002994 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002995 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2996 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2997 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2998 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002999 }
3000
3001 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003002 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3003 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003004 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003005 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3006 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3007 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3008 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003009 }
3010}
3011
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003012// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003013DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003014 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003015 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003016 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3017 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003018 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003019
3020 ParagraphStyle paragraphStyle;
3021 paragraphStyle.setTextAlign(TextAlign::kCenter);
3022 paragraphStyle.setMaxLines(10);
3023 paragraphStyle.turnHintingOff();
3024 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3025
3026 TextStyle textStyle;
3027 textStyle.setFontFamilies({SkString("Roboto")});
3028 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003029 textStyle.setHeight(1);
3030 textStyle.setColor(SK_ColorBLACK);
3031 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3032 SkFontStyle::kUpright_Slant));
3033
3034 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003035 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003036 builder.pop();
3037
3038 auto paragraph = builder.Build();
3039 paragraph->layout(550);
3040
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003041 paragraph->paint(canvas.get(), 0, 0);
3042
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003043 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003044
3045 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3046
3047 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3048 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3049 SkScalar epsilon = 0.01f;
3050 {
3051 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3052 REPORTER_ASSERT(reporter, result.empty());
3053 }
3054 {
3055 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003056 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003057 REPORTER_ASSERT(reporter, result.size() == 1);
3058 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3059 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3060 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3061 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3062 }
3063 {
3064 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003065 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003066 REPORTER_ASSERT(reporter, result.size() == 1);
3067 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3068 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3069 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3070 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3071 }
3072 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003073 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003074 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003075 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003076 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3077 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003078 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003079 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3080 }
3081 {
3082 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003083 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003084 REPORTER_ASSERT(reporter, result.size() == 1);
3085 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3086 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003088 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3089 }
3090 {
3091 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003092 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003093 REPORTER_ASSERT(reporter, result.size() == 1);
3094 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3095 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3096 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3098 }
3099 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003100 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003101 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003102 REPORTER_ASSERT(reporter, result.size() == 1);
3103 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3104 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003105 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3107 }
3108 {
3109 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3110 REPORTER_ASSERT(reporter, result.empty());
3111 }
3112}
3113
Julia Lavrovac2228562019-08-08 16:51:27 -04003114// Checked: DIFF (line height rounding error)
3115DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003116 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003117 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003118 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3119 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003120 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003121
3122 StrutStyle strutStyle;
3123 strutStyle.setStrutEnabled(true);
3124 strutStyle.setFontFamilies({SkString("Roboto")});
3125 strutStyle.setFontSize(14.0);
3126
3127 ParagraphStyle paragraphStyle;
3128 paragraphStyle.setStrutStyle(strutStyle);
3129
3130 TextStyle textStyle;
3131 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3132 textStyle.setFontSize(20);
3133 textStyle.setColor(SK_ColorBLACK);
3134
3135 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3136 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003137 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003138 builder.pop();
3139
3140 auto paragraph = builder.Build();
3141 paragraph->layout(550);
3142 paragraph->paint(canvas.get(), 0, 0);
3143
3144 {
3145 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3146 canvas.drawRects(SK_ColorGREEN, result);
3147 REPORTER_ASSERT(reporter, result.size() == 1);
3148 }
3149
3150 {
3151 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3152 canvas.drawRects(SK_ColorRED, result);
3153 REPORTER_ASSERT(reporter, result.size() == 1);
3154 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3155 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3156 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3157 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3158 }
3159}
3160
3161// Checked: NO DIFF
3162DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003163 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003164 if (!fontCollection->fontsFound()) return;
3165 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3166 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003167 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003168
3169 StrutStyle strutStyle;
3170 strutStyle.setStrutEnabled(false);
3171
3172 ParagraphStyle paragraphStyle;
3173 paragraphStyle.setStrutStyle(strutStyle);
3174
3175 TextStyle textStyle;
3176 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3177 textStyle.setFontSize(20);
3178 textStyle.setColor(SK_ColorBLACK);
3179
3180 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3181 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003182 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003183 builder.pop();
3184
3185 auto paragraph = builder.Build();
3186 paragraph->layout(550);
3187 paragraph->paint(canvas.get(), 0, 0);
3188
3189
3190 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3191 canvas.drawRects(SK_ColorGREEN, result1);
3192 REPORTER_ASSERT(reporter, result1.size() == 1);
3193
3194 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3195 canvas.drawRects(SK_ColorRED, result2);
3196 REPORTER_ASSERT(reporter, result2.size() == 1);
3197
3198 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3199}
3200
3201// Checked: DIFF (small in numbers)
3202DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003203 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003204 if (!fontCollection->fontsFound()) return;
3205 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003206 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3207 "67890 12345 67890 12345 67890 12345";
3208 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003209 ParagraphStyle paragraphStyle;
3210 paragraphStyle.setTextAlign(TextAlign::kLeft);
3211 paragraphStyle.setMaxLines(10);
3212 paragraphStyle.turnHintingOff();
3213 TextStyle textStyle;
3214 textStyle.setFontFamilies({SkString("Roboto")});
3215 textStyle.setFontSize(52);
3216 textStyle.setLetterSpacing(1.19039f);
3217 textStyle.setWordSpacing(5);
3218 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003219 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003220 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003221
3222 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3223 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003224 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003225 builder.pop();
3226
3227 auto paragraph = builder.Build();
3228 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003229 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003230
3231 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3232 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3233 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3234 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3235 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003236 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3237 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003238
3239 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003240 boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003241 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003242
Julia Lavrovac2228562019-08-08 16:51:27 -04003243 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003244 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003245 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003246
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003247 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3248 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3249 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3250 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3251 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3252 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3253 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3254 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3255
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003256 boxes = paragraph->getRectsForRange(12, 13, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003257 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003258 boxes = paragraph->getRectsForRange(13, 14, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003259 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003260 boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003261 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003262 boxes = paragraph->getRectsForRange(19, 20, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003263 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003264 boxes = paragraph->getRectsForRange(24, 25, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003265 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003266 boxes = paragraph->getRectsForRange(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003267 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003268 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003269 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003270 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003271 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003272
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003273 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3274 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003275}
3276
Julia Lavrovac2228562019-08-08 16:51:27 -04003277// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003278DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003279 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003280 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003281 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003282 ParagraphStyle paragraph_style;
3283 paragraph_style.setMaxLines(10);
3284 paragraph_style.setTextAlign(TextAlign::kLeft);
3285 paragraph_style.turnHintingOff();
3286 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3287
3288 TextStyle text_style;
3289 text_style.setFontFamilies({SkString("Roboto")});
3290 text_style.setFontSize(50);
3291 text_style.setLetterSpacing(20);
3292 text_style.setWordSpacing(0);
3293 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003294 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003295 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003296 builder.pop();
3297
3298 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003299 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003300 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003301 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003302 builder.pop();
3303
3304 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003305 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003306 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003307 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003308 builder.pop();
3309
3310 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003311 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003312 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003313 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003314 builder.pop();
3315
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003316 const char* hSpace = "H ";
3317 const size_t len = strlen(hSpace);
3318
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003319 text_style.setLetterSpacing(0);
3320 text_style.setWordSpacing(20);
3321 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003322 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003323 builder.pop();
3324
3325 text_style.setLetterSpacing(0);
3326 text_style.setWordSpacing(0);
3327 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003328 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003329 builder.pop();
3330
3331 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003332 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003333 text_style.setWordSpacing(20);
3334 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003335 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003336 builder.pop();
3337
3338 auto paragraph = builder.Build();
3339 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003340 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003341
3342 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3343 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3344 size_t index = 0;
3345 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003346 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3347 ++index;
3348 return true;
3349 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003350 REPORTER_ASSERT(reporter, index == 4);
3351 index = 0;
3352 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003353 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3354 ++index;
3355 return true;
3356 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003357 REPORTER_ASSERT(reporter, index == 4);
3358}
3359
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003360// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003361DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003362 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003363 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003364 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003365 const char* text =
3366 "A "
3367 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3368 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003369 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003370
3371 ParagraphStyle paragraph_style;
3372 paragraph_style.turnHintingOff();
3373 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3374
3375 TextStyle text_style;
3376 text_style.setFontFamilies({SkString("Roboto")});
3377 text_style.setColor(SK_ColorRED);
3378 text_style.setFontSize(31);
3379 text_style.setLetterSpacing(0);
3380 text_style.setWordSpacing(0);
3381 text_style.setColor(SK_ColorBLACK);
3382 text_style.setHeight(1);
3383 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003384 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003385 builder.pop();
3386
3387 auto paragraph = builder.Build();
3388 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003389 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003390
3391 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3392 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3393 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3394 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003395 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003396 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3397
3398 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3399 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3400 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3401}
3402
Julia Lavrovac2228562019-08-08 16:51:27 -04003403// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003404DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003405 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003406 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003407 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3408
3409 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3410 const char* text2 = " Dialog Text List lots of words to see "
3411 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003412 float scale = 3.0f;
3413 ParagraphStyle paragraph_style;
3414 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3415 TextStyle text_style;
3416 text_style.setFontFamilies({SkString("Droid Serif")});
3417 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003418 text_style.setColor(SK_ColorBLACK);
3419
3420 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003421 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003422 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003423 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003424 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003425 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003426 text_style.setFontSize(14 / scale);
3427 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003428 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003429 builder.pop();
3430
3431 auto paragraph = builder.Build();
3432 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003433 canvas.get()->scale(scale, scale);
3434 paragraph->paint(canvas.get(), 0, 0);
3435 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003436
3437 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003438
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003439 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003440 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003441 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3442 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3443 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3444 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3445 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3446 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003447}
3448
Julia Lavrovac2228562019-08-08 16:51:27 -04003449// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003450DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003451 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003452 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003453 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003454 const char* text =
3455 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3456 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003457 const size_t len = strlen(text);
3458
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003459 ParagraphStyle paragraph_style;
3460 paragraph_style.turnHintingOff();
3461 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3462
3463 TextStyle text_style;
3464 text_style.setFontFamilies({SkString("Roboto")});
3465 text_style.setColor(SK_ColorRED);
3466 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003467 text_style.setColor(SK_ColorBLACK);
3468 text_style.setHeight(1);
3469 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003470 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003471 builder.pop();
3472
3473 auto paragraph = builder.Build();
3474 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003475 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003476
3477 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3478 // Minikin does not count empty lines but SkParagraph does
3479 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3480
3481 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3482 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3483 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3484 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3485 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003486 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3487 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003488}
3489
Julia Lavrova526df262019-08-21 17:49:44 -04003490// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003491DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003492 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003493 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003494 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3495 const char* text =
3496 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3497 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3498 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3499 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003500 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003501
3502 ParagraphStyle paragraph_style;
3503 paragraph_style.turnHintingOff();
3504 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3505
3506 TextStyle text_style;
3507 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3508 text_style.setFontSize(50);
3509 text_style.setDecoration(TextDecoration::kUnderline);
3510 text_style.setColor(SK_ColorBLACK);
3511 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003512 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003513 builder.pop();
3514
3515 auto paragraph = builder.Build();
3516 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003517 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003518
Julia Lavrova3281b962019-12-02 11:32:25 -05003519 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3520
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003521 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003522
3523 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3524 for (auto& line : impl->lines()) {
3525 if (&line != impl->lines().end() - 1) {
3526 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3527 } else {
3528 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3529 }
3530 REPORTER_ASSERT(reporter, line.height() == 59);
3531 }
3532}
3533
Julia Lavrovac2228562019-08-08 16:51:27 -04003534// Checked: DIFF+
3535DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003536 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003537 if (!fontCollection->fontsFound()) return;
3538 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3539 const char* text =
3540 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3541 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3542 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3543 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3544 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3545 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003546 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003547
3548 ParagraphStyle paragraph_style;
3549 paragraph_style.turnHintingOff();
3550 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3551
3552 TextStyle text_style;
3553 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3554 text_style.setFontSize(50);
3555 text_style.setColor(SK_ColorBLACK);
3556 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003557 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003558 builder.pop();
3559
3560 auto paragraph = builder.Build();
3561 paragraph->layout(TestCanvasWidth - 300);
3562 paragraph->paint(canvas.get(), 0, 0);
3563
3564 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3565 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3566
3567 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3568 REPORTER_ASSERT(reporter, result.size() == 0);
3569
3570 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3571 REPORTER_ASSERT(reporter, result.size() == 2);
3572 canvas.drawRects(SK_ColorRED, result);
3573
3574 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrova2813d452020-03-03 11:43:40 -05003575 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04003576 canvas.drawRects(SK_ColorBLUE, result);
3577
3578 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3579 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3580 REPORTER_ASSERT(reporter, result.size() == 2);
3581 canvas.drawRects(SK_ColorGREEN, result);
3582
3583 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3584 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3585 REPORTER_ASSERT(reporter, result.size() == 2);
3586 canvas.drawRects(SK_ColorGREEN, result);
3587
3588 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3589 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3590 REPORTER_ASSERT(reporter, result.size() == 2);
3591 canvas.drawRects(SK_ColorGREEN, result);
3592}
3593
Julia Lavrova916a9042019-08-08 16:51:27 -04003594DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3595 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3596}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003597
Julia Lavrovac2228562019-08-08 16:51:27 -04003598// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003599DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003600 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003601 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003602 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003603 const char* text =
3604 "Sentence to layout at diff widths to get diff line counts. short words "
3605 "short words short words short words short words short words short words "
3606 "short words short words short words short words short words short words "
3607 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003608 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003609
3610 ParagraphStyle paragraph_style;
3611 paragraph_style.turnHintingOff();
3612 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3613
3614 TextStyle text_style;
3615 text_style.setFontFamilies({SkString("Roboto")});
3616 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003617 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003618 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003619 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003620 builder.pop();
3621
3622 auto paragraph = builder.Build();
3623 paragraph->layout(300);
3624
3625 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3626 // Some of the formatting lazily done on paint
3627 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3628 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3629 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3630
3631 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003632 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003633 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3634 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3635 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3636}
3637
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003638// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003639DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003640 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003641 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003642 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003643 const char* text =
3644 "This is a very long sentence to test if the text will properly wrap "
3645 "around and go to the next line. Sometimes, short sentence. Longer "
3646 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003647 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003648
3649 ParagraphStyle paragraph_style;
3650 paragraph_style.setMaxLines(1);
3651 paragraph_style.setEllipsis(u"\u2026");
3652 paragraph_style.turnHintingOff();
3653 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3654
3655 TextStyle text_style;
3656 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003657 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003658 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003659 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003660 builder.pop();
3661
3662 auto paragraph = builder.Build();
3663 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003664 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003665
3666 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003667
3668 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3669 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3670
3671 auto& line = impl->lines()[0];
3672 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003673 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003674}
3675
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003676// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003677DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003678 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003679 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003680 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003681 const char* text1 = "fluttser ";
3682 const char* text2 = "mdje";
3683 const char* text3 = "fluttser mdje";
3684
3685 ParagraphStyle paragraph_style;
3686 paragraph_style.turnHintingOff();
3687 paragraph_style.setTextAlign(TextAlign::kLeft);
3688 paragraph_style.setMaxLines(2);
3689 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3690
3691 TextStyle text_style;
3692 text_style.setFontFamilies({SkString("Roboto")});
3693 text_style.setColor(SK_ColorBLACK);
3694 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003695 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003696 text_style.setDecoration(TextDecoration::kUnderline);
3697 text_style.setDecorationColor(SK_ColorBLACK);
3698 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003699 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003700 builder.pop();
3701
3702 auto paragraph = builder.Build();
3703 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003704 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003705
3706 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3707
3708 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3709 text_style.setDecoration(TextDecoration::kNoDecoration);
3710 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003711 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003712 builder1.pop();
3713
3714 auto paragraph1 = builder1.Build();
3715 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003716 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003717
3718 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3719
3720 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3721 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003722
3723 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3724 .front()
3725 .rect;
3726 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3727 .front()
3728 .rect;
3729 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3730 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3731
3732 for (size_t i = 0; i < 12; ++i) {
Julia Lavrova2813d452020-03-03 11:43:40 -05003733 // Not all ranges produce a rectangle ("fl" goes into one cluster so [0:1) is empty)
3734 auto r1 = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
3735 auto r2 = paragraph1->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003736
Julia Lavrova2813d452020-03-03 11:43:40 -05003737 REPORTER_ASSERT(reporter, r1.size() == r2.size());
3738 if (!r1.empty() && !r2.empty()) {
3739 REPORTER_ASSERT(reporter, r1.front().rect.fLeft == r2.front().rect.fLeft);
3740 REPORTER_ASSERT(reporter, r1.front().rect.fRight == r2.front().rect.fRight);
3741 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003742 }
3743}
3744
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003745// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003746DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003747 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003748 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003749 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003750 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003751 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003752
3753 ParagraphStyle paragraph_style;
3754 paragraph_style.turnHintingOff();
3755 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3756
3757 TextStyle text_style;
3758 text_style.setFontFamilies({SkString("Roboto")});
3759 text_style.setColor(SK_ColorBLACK);
3760 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3761 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003762 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003763
3764 auto paragraph = builder.Build();
3765 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003766 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003767
3768 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3769
3770 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3771 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3772 size_t index = 0;
3773 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003774 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003775 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003776 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3777 ++index;
3778 return true;
3779 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003780 }
3781}
3782
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003783// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003784DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003785 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003786 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003787 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003788 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003789 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003790
3791 ParagraphStyle paragraph_style;
3792 paragraph_style.turnHintingOff();
3793 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3794
3795 TextStyle text_style;
3796 text_style.setFontFamilies({SkString("Roboto")});
3797 text_style.setColor(SK_ColorBLACK);
3798 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3799 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003800 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003801
3802 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3803 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3804 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003805 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003806 builder.pop();
3807
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003808 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003809
3810 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3811 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003812 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003813 builder.pop();
3814
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003815 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003816
3817 auto paragraph = builder.Build();
3818 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003819 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003820
3821 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3822
3823 size_t index = 0;
3824 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003825 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003826 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003827 ++index;
3828 switch (index) {
3829 case 1:
3830 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3831 break;
3832 case 2:
3833 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3834 break;
3835 case 3:
3836 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3837 break;
3838 case 4:
3839 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3840 REPORTER_ASSERT(reporter, style.equals(text_style));
3841 break;
3842 case 5:
3843 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3844 break;
3845 default:
3846 REPORTER_ASSERT(reporter, false);
3847 }
3848 return true;
3849 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003850 }
3851}
3852
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003853// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003854DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003855 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003856 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003857 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003858 const char* text =
3859 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3860 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003861 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003862
3863 ParagraphStyle paragraph_style;
3864 paragraph_style.turnHintingOff();
3865 paragraph_style.setMaxLines(14);
3866 paragraph_style.setTextAlign(TextAlign::kJustify);
3867 paragraph_style.setHeight(1.5);
3868 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3869
3870 TextStyle text_style;
3871 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3872 text_style.setColor(SK_ColorBLACK);
3873 text_style.setFontSize(55);
3874 text_style.setLetterSpacing(2);
3875 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3876 text_style.setDecorationColor(SK_ColorBLACK);
3877 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003878 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003879 builder.pop();
3880
3881 auto paragraph = builder.Build();
3882 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003883 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003884
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003885 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3886 paragraph->getMaxWidth(),
3887 paragraph->getIdeographicBaseline());
3888 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3889 paragraph->getMaxWidth(),
3890 paragraph->getAlphabeticBaseline());
3891 canvas.drawLine(SK_ColorRED, rect1, false);
3892 canvas.drawLine(SK_ColorGREEN, rect2, false);
3893
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003894 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003895 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003896 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003897 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003898}
3899
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003900// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003901DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003902 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003903 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003904 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003905
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003906 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3907 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3908 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003909
3910 ParagraphStyle paragraph_style;
3911 paragraph_style.turnHintingOff();
3912 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3913
3914 TextStyle text_style;
3915 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003916 SkString("Not a real font"),
3917 SkString("Also a fake font"),
3918 SkString("So fake it is obvious"),
3919 SkString("Next one should be a real font..."),
3920 SkString("Roboto"),
3921 SkString("another fake one in between"),
3922 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003923 });
3924 text_style.setColor(SK_ColorBLACK);
3925 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003926 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003927
3928 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003929 SkString("Not a real font"),
3930 SkString("Also a fake font"),
3931 SkString("So fake it is obvious"),
3932 SkString("Homemade Apple"),
3933 SkString("Next one should be a real font..."),
3934 SkString("Roboto"),
3935 SkString("another fake one in between"),
3936 SkString("Noto Sans CJK JP"),
3937 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003938 });
3939 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003940 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003941
3942 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003943 SkString("Not a real font"),
3944 SkString("Also a fake font"),
3945 SkString("So fake it is obvious"),
3946 SkString("Homemade Apple"),
3947 SkString("Next one should be a real font..."),
3948 SkString("Roboto"),
3949 SkString("another fake one in between"),
3950 SkString("Source Han Serif CN"),
3951 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003952 });
3953 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003954 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003955
3956 builder.pop();
3957
3958 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003959 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003960 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003961 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003962
Julia Lavrova3281b962019-12-02 11:32:25 -05003963 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
3964
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003965 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3966
3967 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3968 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3969 // [Apple + Noto] [Apple + Han]
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003970 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003971
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003972 auto robotoAdvance = impl->runs()[0].advance().fX +
3973 impl->runs()[1].advance().fX +
3974 impl->runs()[2].advance().fX;
3975 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
3976 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
3977 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
3978 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
3979 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003980
3981 // When a different font is resolved, then the metrics are different.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003982 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
3983 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003984}
3985
Julia Lavrovac2228562019-08-08 16:51:27 -04003986// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003987DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003988 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003989 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003990 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003991 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003992 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003993 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003994
3995 ParagraphStyle paragraph_style;
3996 paragraph_style.setMaxLines(10);
3997 paragraph_style.setTextAlign(TextAlign::kLeft);
3998 paragraph_style.turnHintingOff();
3999
4000 StrutStyle strut_style;
4001 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004002 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004003 strut_style.setFontSize(50);
4004 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004005 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004006 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004007 paragraph_style.setStrutStyle(strut_style);
4008
4009 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4010
4011 TextStyle text_style;
4012 text_style.setFontFamilies({SkString("Ahem")});
4013 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004014 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004015 text_style.setColor(SK_ColorBLACK);
4016 text_style.setHeight(0.5f);
4017 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004018 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004019 builder.pop();
4020
4021 auto paragraph = builder.Build();
4022 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004023 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004024
4025 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004026 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4027
4028 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4029 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4030 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004031 {
4032 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4033 REPORTER_ASSERT(reporter, boxes.empty());
4034 }
4035 {
4036 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004037 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004038 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004039 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4040 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4041 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4042 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004043 }
4044 {
4045 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004046 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004047 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004048 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004049 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004050 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4051 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004052 }
4053 {
4054 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004055 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004056 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004057 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4058 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004059 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004060 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004061 }
4062 {
4063 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004064 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004065 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004066 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004067 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004068 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004069 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004070 }
4071 {
4072 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004073 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004074 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004075 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004076 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004077 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4078 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004079 }
4080 {
4081 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004082 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004083 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004084 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004085 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004086 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004088 }
4089}
4090
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004091// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004092DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004093 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004094 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004095 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004096 // The chinese extra height should be absorbed by the strut.
4097 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004098 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004099
4100 ParagraphStyle paragraph_style;
4101 paragraph_style.setMaxLines(10);
4102 paragraph_style.setTextAlign(TextAlign::kLeft);
4103 paragraph_style.turnHintingOff();
4104
4105 StrutStyle strut_style;
4106
4107 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004108 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004109 strut_style.setFontSize(50);
4110 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004111 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004112 paragraph_style.setStrutStyle(strut_style);
4113
4114 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4115
4116 TextStyle text_style;
4117 text_style.setFontFamilies({SkString("Ahem")});
4118 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004119 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4120 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004121 text_style.setColor(SK_ColorBLACK);
4122 text_style.setHeight(1);
4123 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004124 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004125 builder.pop();
4126
4127 auto paragraph = builder.Build();
4128 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004129 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004130
4131 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4132 // Font is not resolved and the first line does not fit
4133 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4134
4135 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4136 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4137 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004138 {
4139 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4140 REPORTER_ASSERT(reporter, boxes.empty());
4141 }
4142 {
4143 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004144 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004145 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004146 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4147 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4148 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4149 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004150 }
4151 {
4152 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004153 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004154 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004155 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004156 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004157 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4158 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004159 }
4160 {
4161 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004162 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004163 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004164 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4165 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4166 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4167 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004168 }
4169 {
4170 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004171 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004172 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004173 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004174 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004175 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4176 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004177 }
4178 {
4179 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004180 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004181 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004182 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004183 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004184 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4185 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004186 }
4187 {
4188 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004189 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004190 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004191 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004192 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004193 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4194 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004195 }
4196}
4197
Julia Lavrovac2228562019-08-08 16:51:27 -04004198// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004199DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004200 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004201 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004202 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4203
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004204 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004205 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004206 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004207
4208 ParagraphStyle paragraph_style;
4209 paragraph_style.setMaxLines(10);
4210 paragraph_style.setTextAlign(TextAlign::kLeft);
4211 paragraph_style.turnHintingOff();
4212
4213 StrutStyle strut_style;
4214 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004215 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004216 strut_style.setFontSize(50);
4217 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004218 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004219 paragraph_style.setStrutStyle(strut_style);
4220
4221 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4222
4223 TextStyle text_style;
4224 text_style.setFontFamilies({SkString("Ahem")});
4225 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004226 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4227 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004228 text_style.setColor(SK_ColorBLACK);
4229 text_style.setHeight(1);
4230 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004231 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004232 builder.pop();
4233
4234 auto paragraph = builder.Build();
4235 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004236 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004237
4238 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4239 // Font is not resolved and the first line does not fit
4240 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4241
4242 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4243 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4244 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4245 SkScalar epsilon = 0.001f;
4246 {
4247 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4248 REPORTER_ASSERT(reporter, boxes.empty());
4249 }
4250 {
4251 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004252 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004253 REPORTER_ASSERT(reporter, boxes.size() == 1);
4254 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4255 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4256 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4257 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4258 }
4259 {
4260 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004261 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004262 REPORTER_ASSERT(reporter, boxes.size() == 1);
4263 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004264 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004265 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4266 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4267 }
4268 {
4269 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004270 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004271 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004272 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4273 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004274 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004275 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4276 }
4277 {
4278 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004279 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004280 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004281 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004282 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004283 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4285 }
4286 {
4287 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004288 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004289 REPORTER_ASSERT(reporter, boxes.size() == 1);
4290 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004291 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004292 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4293 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4294 }
4295 {
4296 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004297 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004298 REPORTER_ASSERT(reporter, boxes.size() == 1);
4299 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004300 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004301 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4302 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4303 }
4304}
4305
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004306// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004307DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004308 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004309 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004310 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004311 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004312 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004313
4314 ParagraphStyle paragraph_style;
4315 paragraph_style.setMaxLines(10);
4316 paragraph_style.setTextAlign(TextAlign::kLeft);
4317 paragraph_style.turnHintingOff();
4318
4319 StrutStyle strut_style;
4320 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004321 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004322 strut_style.setFontSize(50);
4323 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004324 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004325 strut_style.setLeading(0.1f);
4326 strut_style.setForceStrutHeight(true);
4327 paragraph_style.setStrutStyle(strut_style);
4328
4329 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4330
4331 TextStyle text_style;
4332 text_style.setFontFamilies({SkString("Ahem")});
4333 text_style.setFontSize(50);
4334 text_style.setLetterSpacing(0);
4335 text_style.setColor(SK_ColorBLACK);
4336 text_style.setHeight(1);
4337 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004338 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004339 builder.pop();
4340
4341 auto paragraph = builder.Build();
4342 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004343 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004344
4345 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4346 // Font is not resolved and the first line does not fit
4347 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4348
4349 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4350 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4351 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004352
4353 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4354 REPORTER_ASSERT(reporter, boxes1.empty());
4355
4356 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004357 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004358 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004359 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4360 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4361 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4362 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004363
4364 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004365 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004366 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004367 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004368 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004369 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4370 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004371
4372 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004373 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004374 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004375 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4376 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4377 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4378 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004379
4380 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004381 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004382 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004383 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004384 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004385 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4386 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004387
4388 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004389 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004390 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004392 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004393 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4394 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004395
4396 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004397 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004398 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004401 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4402 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004403}
4404
Julia Lavrovac2228562019-08-08 16:51:27 -04004405// Checked: NO DIFF
4406DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004407 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004408 if (!fontCollection->fontsFound()) return;
4409 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4410
4411 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004412 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004413
4414 ParagraphStyle paragraph_style;
4415 paragraph_style.setMaxLines(10);
4416 paragraph_style.setTextAlign(TextAlign::kLeft);
4417 paragraph_style.turnHintingOff();
4418
4419 StrutStyle strut_style;
4420 strut_style.setStrutEnabled(true);
4421 strut_style.setFontFamilies({SkString("Ahem")});
4422 strut_style.setFontSize(50);
4423 strut_style.setHeight(1.5f);
4424 strut_style.setLeading(0.1f);
4425 strut_style.setForceStrutHeight(false);
4426 paragraph_style.setStrutStyle(strut_style);
4427
4428 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4429
4430 TextStyle text_style;
4431 text_style.setFontFamilies({SkString("Ahem")});
4432 text_style.setFontSize(20);
4433 text_style.setColor(SK_ColorBLACK);
4434 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004435 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004436 builder.pop();
4437
4438 auto paragraph = builder.Build();
4439 paragraph->layout(550);
4440 paragraph->paint(canvas.get(), 0, 0);
4441
4442 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4443 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4444 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4445 {
4446 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4447 REPORTER_ASSERT(reporter, boxes.empty());
4448 }
4449 {
4450 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4451 canvas.drawRects(SK_ColorRED, boxes);
4452 REPORTER_ASSERT(reporter, boxes.size() == 1);
4453 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4454 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4455 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4456 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4457 }
4458 {
4459 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4460 canvas.drawRects(SK_ColorRED, boxes);
4461 REPORTER_ASSERT(reporter, boxes.size() == 1);
4462 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4463 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4464 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4465 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4466 }
4467}
4468
Julia Lavrovac5313e62019-12-10 12:11:17 -05004469DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4470 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4471 if (!fontCollection->fontsFound()) return;
4472 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4473
4474 const char* text = "12ab\n";
4475
4476 ParagraphStyle paragraph_style;
4477 paragraph_style.turnHintingOff();
4478 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4479
4480 TextStyle text_style;
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004481 text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
Julia Lavrovac5313e62019-12-10 12:11:17 -05004482 text_style.setFontFamilies({SkString("Roboto")});
4483 text_style.setColor(SK_ColorBLACK);
4484
4485 text_style.addFontFeature(SkString("tnum"), 1);
4486 builder.pushStyle(text_style);
4487 builder.addText(text);
4488
4489 text_style.resetFontFeatures();
4490 text_style.addFontFeature(SkString("tnum"), 0);
4491 text_style.addFontFeature(SkString("pnum"), 1);
4492 builder.pushStyle(text_style);
4493 builder.addText(text);
4494
4495 builder.pop();
4496 builder.pop();
4497
4498 auto paragraph = builder.Build();
4499 paragraph->layout(TestCanvasWidth);
4500
4501 paragraph->paint(canvas.get(), 10.0, 15.0);
4502
4503 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4504 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4505
4506 auto& tnum_line = impl->lines()[0];
4507 auto& pnum_line = impl->lines()[1];
4508
4509 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4510 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4511 // Tabular numbers should have equal widths.
4512 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4513 // Proportional numbers should have variable widths.
4514 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4515 // Alphabetic characters should be unaffected.
4516 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4517}
4518
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004519// Not in Minikin
4520DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004521 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004522 if (!fontCollection->fontsFound()) return;
4523 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004524 const size_t len = strlen(text);
4525
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004526 ParagraphStyle paragraph_style;
4527 paragraph_style.turnHintingOff();
4528 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4529
4530 TextStyle text_style;
4531 text_style.setFontFamilies(
4532 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4533 text_style.setFontSize(60);
4534 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004535 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004536 builder.pop();
4537
4538 auto paragraph = builder.Build();
4539 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004540
4541 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4542
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004543 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4544 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4545 auto first = impl->runs()[i].textRange();
4546 auto next = impl->runs()[i + 1].textRange();
4547 REPORTER_ASSERT(reporter, first.end == next.start);
4548 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004549}
4550
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004551DEF_TEST(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004552 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004553 if (!fontCollection->fontsFound()) return;
4554 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004555 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004556
4557 ParagraphStyle paragraph_style;
4558 paragraph_style.turnHintingOff();
4559 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4560
4561 TextStyle text_style;
4562 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4563 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004564 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004565 builder.pop();
4566
4567 auto paragraph = builder.Build();
4568 paragraph->layout(TestCanvasWidth);
4569
4570 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4571 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004572 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004573
4574 auto cluster = 0;
4575 SkShaperJSONWriter::VisualizeClusters(
4576 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4577 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4578 if (cluster == 0) {
4579 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4580 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4581 SkASSERT(glyph1to1.size() == 1);
4582 SkASSERT(*glyph1to1.begin() == 1611);
4583 }
4584 ++cluster;
4585 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004586 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004587}
4588
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004589DEF_TEST(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004590 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004591 if (!fontCollection->fontsFound()) return;
4592 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004593 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004594
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004595 ParagraphStyle paragraph_style;
4596 paragraph_style.turnHintingOff();
4597 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4598
4599 TextStyle text_style;
4600 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4601 text_style.setColor(SK_ColorBLACK);
4602 text_style.setFontSize(50);
4603 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004604 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004605 builder.pop();
4606
4607 auto paragraph = builder.Build();
4608 paragraph->layout(TestCanvasWidth);
4609
4610 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4611 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004612
4613 auto cluster = 0;
4614 for (auto& run : impl->runs()) {
4615 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004616 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4617 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004618 [&](int codePointCount, SkSpan<const char> utf1to1,
4619 SkSpan<const SkGlyphID> glyph1to1) {
4620 if (cluster == 0) {
4621 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4622 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4623 SkASSERT(glyph1to1.size() == 3);
4624 }
4625 ++cluster;
4626 });
4627 }
4628
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004629 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004630}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004631
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004632DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004633 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004634 cache.turnOn(true);
4635 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004636 if (!fontCollection->fontsFound()) return;
4637
4638 ParagraphStyle paragraph_style;
4639 paragraph_style.turnHintingOff();
4640
4641 TextStyle text_style;
4642 text_style.setFontFamilies({SkString("Roboto")});
4643 text_style.setColor(SK_ColorBLACK);
4644
4645 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4646 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4647 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004648 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004649 builder.pop();
4650 auto paragraph = builder.Build();
4651
4652 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4653 REPORTER_ASSERT(reporter, count == cache.count());
4654 auto found = cache.findParagraph(impl);
4655 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4656 auto added = cache.updateParagraph(impl);
4657 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4658 };
4659
4660 test("text1", 0, false);
4661 test("text1", 1, true);
4662 test("text2", 1, false);
4663 test("text2", 2, true);
4664 test("text3", 2, false);
4665}
4666
4667DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004668 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004669 cache.turnOn(true);
4670 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004671 if (!fontCollection->fontsFound()) return;
4672
4673 ParagraphStyle paragraph_style;
4674 paragraph_style.turnHintingOff();
4675
4676 TextStyle text_style;
4677 text_style.setColor(SK_ColorBLACK);
4678
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004679 const char* text = "text";
4680 const size_t len = strlen(text);
4681
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004682 auto test = [&](int count, bool expectedToBeFound) {
4683 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4684 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004685 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004686 builder.pop();
4687 auto paragraph = builder.Build();
4688 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4689
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004690 REPORTER_ASSERT(reporter, count == cache.count());
4691 auto found = cache.findParagraph(impl);
4692 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4693 auto added = cache.updateParagraph(impl);
4694 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4695 };
4696
4697 text_style.setFontFamilies({SkString("Roboto")});
4698 test(0, false);
4699 test(1, true);
4700 text_style.setFontFamilies({SkString("Homemade Apple")});
4701 test(1, false);
4702 test(2, true);
4703 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4704 test(2, false);
4705}
4706
4707DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004708 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004709 cache.turnOn(true);
4710 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004711 if (!fontCollection->fontsFound()) return;
4712
4713 ParagraphStyle paragraph_style;
4714 paragraph_style.turnHintingOff();
4715
4716 TextStyle text_style;
4717 text_style.setFontFamilies({SkString("Roboto")});
4718 text_style.setColor(SK_ColorBLACK);
4719
4720 auto test = [&](const char* text1,
4721 const char* text2,
4722 const char* font1,
4723 const char* font2,
4724 int count,
4725 bool expectedToBeFound) {
4726 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4727 text_style.setFontFamilies({SkString(font1)});
4728 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004729 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004730 builder.pop();
4731 text_style.setFontFamilies({SkString(font2)});
4732 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004733 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004734 builder.pop();
4735 auto paragraph = builder.Build();
4736 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4737
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004738 REPORTER_ASSERT(reporter, count == cache.count());
4739 auto found = cache.findParagraph(impl);
4740 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4741 auto added = cache.updateParagraph(impl);
4742 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4743 };
4744
4745 test("text", "", "Roboto", "Homemade Apple", 0, false);
4746 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4747 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4748 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4749 test("text", "", "Roboto", "Homemade Apple", 4, true);
4750}
4751
4752DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004753 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004754 cache.turnOn(true);
4755 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004756 if (!fontCollection->fontsFound()) return;
4757
4758 ParagraphStyle paragraph_style;
4759 paragraph_style.turnHintingOff();
4760
4761 TextStyle text_style;
4762 text_style.setFontFamilies({SkString("Roboto")});
4763 text_style.setColor(SK_ColorBLACK);
4764
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004765 const char* text = "text";
4766 const size_t len = strlen(text);
4767
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004768 auto test = [&](int count, bool expectedToBeFound) {
4769 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4770 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004771 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004772 builder.pop();
4773 auto paragraph = builder.Build();
4774 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4775
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004776 REPORTER_ASSERT(reporter, count == cache.count());
4777 auto found = cache.findParagraph(impl);
4778 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4779 auto added = cache.updateParagraph(impl);
4780 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4781 };
4782
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004783 test(0, false);
4784 test(1, true);
4785 text_style.setLetterSpacing(10);
4786 test(1, false);
4787 test(2, true);
4788 text_style.setWordSpacing(10);
4789 test(2, false);
4790}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004791
Julia Lavrova526df262019-08-21 17:49:44 -04004792DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004793 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004794 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004795 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4796 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004797
4798 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004799 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004800 text_style.setFontSize(16);
4801 text_style.setFontFamilies({SkString("Roboto")});
4802 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004803 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004804
4805 auto paragraph = builder.Build();
4806 paragraph->layout(TestCanvasWidth);
4807 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004808 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004809}
4810
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004811DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004812 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004813 if (!fontCollection->fontsFound()) return;
4814 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4815 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4816
4817 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4818
4819 ParagraphStyle paragraph_style;
4820 TextStyle text_style;
4821 text_style.setFontSize(16);
4822 text_style.setFontFamilies({SkString("Roboto")});
4823 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4824 builder.addText(text.c_str(), text.size());
4825
4826 auto paragraph = builder.Build();
4827 paragraph->layout(TestCanvasWidth);
4828 paragraph->paint(canvas.get(), 0, 0);
4829}
4830
Julia Lavrovaa40db422019-08-21 13:49:15 -04004831DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004832 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004833 if (!fontCollection->fontsFound()) return;
4834 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4835
4836 ParagraphStyle paragraph_style;
4837 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4838
Julia Lavrova526df262019-08-21 17:49:44 -04004839 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004840 builder.addPlaceholder(placeholder);
4841
4842 auto paragraph = builder.Build();
4843 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004844 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004845 paragraph->paint(canvas.get(), 0, 0);
4846}
4847
4848DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004849 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004850 if (!fontCollection->fontsFound()) return;
4851 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4852 TestCanvas canvas("SkParagraph_Fallbacks.png");
4853
4854 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004855 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004856
4857 const char* androidFonts[] = {
4858 "sans-serif",
4859 "sans-serif-condensed",
4860 "serif",
4861 "monospace",
4862 "serif-monospace",
4863 "casual",
4864 "cursive",
4865 "sans-serif-smallcaps",
4866 };
4867
4868 for (auto& font : androidFonts) {
4869
4870 ParagraphStyle paragraph_style;
4871 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4872
4873 TextStyle text_style;
4874 text_style.setColor(SK_ColorBLACK);
4875 text_style.setLocale(SkString("en_US"));
4876 text_style.setFontSize(20);
4877
4878 text_style.setFontFamilies({ SkString(font) });
4879 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004880 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004881
4882 builder.pop();
4883
4884 auto paragraph = builder.Build();
4885 paragraph->layout(TestCanvasWidth);
4886 paragraph->paint(canvas.get(), 0, 0);
4887 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4888 }
4889}
4890
4891DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004892 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004893 if (!fontCollection->fontsFound()) return;
4894 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004895 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004896 TestCanvas canvas("SkParagraph_Bidi1.png");
4897
4898 std::u16string abc = u"\u202Dabc";
4899 std::u16string DEF = u"\u202EDEF";
4900 std::u16string ghi = u"\u202Dghi";
4901 std::u16string JKL = u"\u202EJKL";
4902 std::u16string mno = u"\u202Dmno";
4903
4904 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4905
4906 ParagraphStyle paragraph_style;
4907 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4908
4909 TextStyle text_style;
4910 text_style.setFontFamilies({ SkString("sans-serif")});
4911 text_style.setFontSize(40);
4912
4913 text_style.setColor(SK_ColorCYAN);
4914 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4915 builder.pushStyle(text_style);
4916 builder.addText(abc);
4917
4918 text_style.setColor(SK_ColorGREEN);
4919 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4920 builder.pushStyle(text_style);
4921 builder.addText(DEF);
4922
4923 text_style.setColor(SK_ColorYELLOW);
4924 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4925 builder.pushStyle(text_style);
4926 builder.addText(ghi);
4927
4928 text_style.setColor(SK_ColorMAGENTA);
4929 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4930 builder.pushStyle(text_style);
4931 builder.addText(JKL);
4932
4933 text_style.setColor(SK_ColorBLUE);
4934 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4935 builder.pushStyle(text_style);
4936 builder.addText(mno);
4937
4938 auto paragraph = builder.Build();
4939 paragraph->layout(400);
4940 paragraph->paint(canvas.get(), 0, 0);
4941}
4942
4943DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004944 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004945 if (!fontCollection->fontsFound()) return;
4946 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004947 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004948 TestCanvas canvas("SkParagraph_Bidi2.png");
4949
4950 std::u16string abcD = u"\u202Dabc\u202ED";
4951 std::u16string EFgh = u"EF\u202Dgh";
4952 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4953
4954 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4955
4956 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004957 TextStyle text_style;
4958 text_style.setFontFamilies({ SkString("sans-serif")});
4959 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004960
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004961 {
4962 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4963 builder.pushStyle(text_style);
4964 builder.addText(abcD);
4965 builder.pushStyle(text_style);
4966 builder.addText(EFgh);
4967 builder.pushStyle(text_style);
4968 builder.addText(iJKLmno);
4969 auto paragraph = builder.Build();
4970 paragraph->layout(360);
4971 paragraph->paint(canvas.get(), 0, 0);
4972 }
4973 canvas.get()->translate(0, 400);
4974 {
4975 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4976 builder.pushStyle(text_style);
4977 builder.addText(abcDEFghiJKLmno);
4978 auto paragraph = builder.Build();
4979 paragraph->layout(360);
4980 paragraph->paint(canvas.get(), 0, 0);
4981 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04004982}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004983
4984DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004985 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004986 if (!fontCollection->fontsFound()) return;
4987 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4988 TestCanvas canvas("SkParagraph_Newline.png");
4989
4990 TextStyle text_style;
4991 text_style.setFontFamilies({SkString("Ahem")});
4992 text_style.setColor(SK_ColorBLACK);
4993 StrutStyle strut_style;
4994 strut_style.setStrutEnabled(false);
4995 ParagraphStyle paragraph_style;
4996 paragraph_style.setStrutStyle(strut_style);
4997 paragraph_style.setTextStyle(text_style);
4998 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4999 builder.addText("\n");
5000 auto paragraph = builder.Build();
5001 paragraph->layout(1000);
5002 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5003}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005004
Julia Lavrovab30d4812019-11-08 14:51:16 -05005005DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005006 TestCanvas canvas("SkParagraph_FontResolutions.png");
5007
5008 sk_sp<TestFontCollection> fontCollection =
5009 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5010 if (!fontCollection->fontsFound()) return;
5011
5012 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5013 return;
5014 }
5015 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5016 return;
5017 }
5018 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5019 return;
5020 }
5021
5022 TextStyle text_style;
5023 text_style.setFontFamilies({SkString("abc")});
5024 text_style.setFontSize(50);
5025
5026 ParagraphStyle paragraph_style;
5027 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5028
5029 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5030 text_style.setColor(SK_ColorBLUE);
5031 builder.pushStyle(text_style);
5032 builder.addText(u"a\u0300");
5033 text_style.setColor(SK_ColorMAGENTA);
5034 builder.pushStyle(text_style);
5035 builder.addText(u"à");
5036
5037 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5038
5039 text_style.setColor(SK_ColorRED);
5040 builder.pushStyle(text_style);
5041 builder.addText(u"a\u0300");
5042 text_style.setColor(SK_ColorGREEN);
5043 builder.pushStyle(text_style);
5044 builder.addText(u"à");
5045
5046 auto paragraph = builder.Build();
5047 paragraph->layout(TestCanvasWidth);
5048
5049 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5050 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5051
5052 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5053 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5054 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5055
5056 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5057 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5058
5059 paragraph->paint(canvas.get(), 100, 100);
5060}
5061
Julia Lavrovab30d4812019-11-08 14:51:16 -05005062DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005063 TestCanvas canvas("SkParagraph_FontStyle.png");
5064
5065 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5066 if (!fontCollection->fontsFound()) return;
5067
5068 TextStyle text_style;
5069 text_style.setFontFamilies({SkString("Roboto")});
5070 text_style.setColor(SK_ColorBLACK);
5071 text_style.setFontSize(20);
5072 SkFontStyle fs = SkFontStyle(
5073 SkFontStyle::Weight::kLight_Weight,
5074 SkFontStyle::Width::kNormal_Width,
5075 SkFontStyle::Slant::kUpright_Slant
5076 );
5077 text_style.setFontStyle(fs);
5078 ParagraphStyle paragraph_style;
5079 paragraph_style.setTextStyle(text_style);
5080 TextStyle boldItalic;
5081 boldItalic.setFontFamilies({SkString("Roboto")});
5082 boldItalic.setColor(SK_ColorRED);
5083 SkFontStyle bi = SkFontStyle(
5084 SkFontStyle::Weight::kBold_Weight,
5085 SkFontStyle::Width::kNormal_Width,
5086 SkFontStyle::Slant::kItalic_Slant
5087 );
5088 boldItalic.setFontStyle(bi);
5089 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5090 builder.addText("Default text\n");
5091 builder.pushStyle(boldItalic);
5092 builder.addText("Bold and Italic\n");
5093 builder.pop();
5094 builder.addText("back to normal");
5095 auto paragraph = builder.Build();
5096 paragraph->layout(250);
5097 paragraph->paint(canvas.get(), 0, 0);
5098}
5099
Julia Lavrovab30d4812019-11-08 14:51:16 -05005100DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005101 TestCanvas canvas("SkParagraph_Shaping.png");
5102
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005103 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5104 sk_sp<TestFontCollection> fontCollection =
5105 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5106 if (!fontCollection->fontsFound()) return;
5107
5108
5109 TextStyle text_style;
5110 text_style.setFontFamilies({SkString("Roboto")});
5111 text_style.setColor(SK_ColorGRAY);
5112 text_style.setFontSize(14);
5113 SkFontStyle b = SkFontStyle(
5114 SkFontStyle::Weight::kNormal_Weight,
5115 SkFontStyle::Width::kNormal_Width,
5116 SkFontStyle::Slant::kUpright_Slant
5117 );
5118 text_style.setFontStyle(b);
5119 ParagraphStyle paragraph_style;
5120 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5121 builder.pushStyle(text_style);
5122 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5123 auto paragraph = builder.Build();
5124 paragraph->layout(380);
5125 paragraph->paint(canvas.get(), 0, 0);
5126}
Julia Lavrovac028b422019-11-25 10:00:43 -05005127
5128DEF_TEST(SkParagraph_Ellipsis, reporter) {
5129 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5130 if (!fontCollection->fontsFound()) return;
5131 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5132 TestCanvas canvas("SkParagraph_Ellipsis.png");
5133
5134 const char* text = "This\n"
5135 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5136 TextStyle text_style;
5137 text_style.setFontFamilies({SkString("Ahem")});
5138 text_style.setColor(SK_ColorBLACK);
5139 text_style.setFontSize(10);
5140
5141 auto relayout = [&](size_t lines, bool ellipsis,
5142 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5143 ParagraphStyle paragraph_style;
5144 SkPaint paint;
5145 paint.setColor(bg);
5146 text_style.setForegroundColor(paint);
5147 paragraph_style.setTextStyle(text_style);
5148 paragraph_style.setMaxLines(lines);
5149 if (ellipsis) {
5150 paragraph_style.setEllipsis(u"\u2026");
5151 }
5152 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5153 builder.addText(text);
5154 auto paragraph = builder.Build();
5155 paragraph->layout(50);
5156 paragraph->paint(canvas.get(), 0, 0);
5157 canvas.get()->translate(50, paragraph->getHeight() + 10);
5158 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5159 SkPaint background;
5160 background.setColor(SK_ColorRED);
5161 background.setStyle(SkPaint::kStroke_Style);
5162 background.setAntiAlias(true);
5163 background.setStrokeWidth(1);
5164 canvas.get()->drawRect(result.front().rect, background);
5165
5166 SkASSERT(width == paragraph->getMaxWidth());
5167 SkASSERT(height == paragraph->getHeight());
5168 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5169 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5170 };
5171
5172 SkPaint paint;
5173 paint.setColor(SK_ColorLTGRAY);
5174 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5175
5176 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005177 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5178 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005179
5180 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005181 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005182 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5183
5184 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005185 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5186 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005187}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005188
5189DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5190 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5191 if (!fontCollection->fontsFound()) return;
5192 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5193
5194 std::string text;
5195 for (size_t i = 0; i < 10; i++)
5196 {
5197 SkPaint paint;
5198 paint.setAntiAlias(true);
5199 paint.setColor(SK_ColorBLACK);
5200
5201 TextStyle textStyle;
5202 textStyle.setForegroundColor(paint);
5203 textStyle.setFontFamilies({ SkString("Roboto") });
5204
5205 ParagraphStyle paragraphStyle;
5206 paragraphStyle.setTextStyle(textStyle);
5207
5208 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5209 text += "Text ";
5210 builder.addText(text.c_str());
5211
5212 auto paragraph = builder.Build();
5213 paragraph->layout(100);
5214
5215 //used to add a delay so I can monitor memory usage
5216 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5217 }
5218};
Julia Lavrovac0360582020-02-05 10:17:53 -05005219
5220DEF_TEST(SkParagraph_FormattingInfinity, reporter) {
5221 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5222 if (!fontCollection->fontsFound()) return;
5223 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5224 TestCanvas canvas("SkParagraph_FormattingInfinity.png");
5225
5226 const char* text = "Some text\nAnother line";
5227
5228 SkPaint paint;
5229 paint.setAntiAlias(true);
5230 paint.setColor(SK_ColorBLACK);
5231
5232 TextStyle textStyle;
5233 textStyle.setForegroundColor(paint);
5234 textStyle.setFontFamilies({ SkString("Roboto") });
5235 ParagraphStyle paragraphStyle;
5236 paragraphStyle.setTextStyle(textStyle);
5237
5238 auto draw = [&](const char* prefix, TextAlign textAlign) {
5239 paragraphStyle.setTextAlign(textAlign);
5240 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5241 builder.addText(text);
5242 auto paragraph = builder.Build();
5243 paragraph->layout(SK_ScalarInfinity);
5244 paragraph->paint(canvas.get(), 0, 0);
5245 canvas.get()->translate(0, 100);
5246 };
5247
5248 draw("left", TextAlign::kLeft);
5249 draw("right", TextAlign::kRight);
5250 draw("center", TextAlign::kCenter);
5251 draw("justify", TextAlign::kJustify);
5252};
5253
5254DEF_TEST(SkParagraph_Infinity, reporter) {
5255 SkASSERT(nearlyEqual(1, SK_ScalarInfinity) == false);
5256 SkASSERT(nearlyEqual(1, SK_ScalarNegativeInfinity) == false);
5257 SkASSERT(nearlyEqual(1, SK_ScalarNaN) == false);
5258
5259 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarInfinity) == true);
5260 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNegativeInfinity) == false);
5261 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNaN) == false);
5262
5263 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarInfinity) == false);
5264 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity) == true);
5265 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNaN) == false);
5266
5267 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarInfinity) == false);
5268 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNegativeInfinity) == false);
5269 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNaN) == false);
5270};