blob: 9378773e4c37e04a561733e4c52764dacf7ec70e [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 Lavrova6e6333f2019-06-17 10:34:10 -04004#include "modules/skparagraph/include/TypefaceFontProvider.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04005#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
6#include "modules/skparagraph/src/ParagraphImpl.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -04007#include "modules/skparagraph/utils/TestFontCollection.h"
Julia Lavrovadb543f62020-01-29 11:43:41 -05008#include "src/core/SkFontMgrPriv.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04009#include "src/core/SkOSFile.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -040010#include "src/utils/SkOSPath.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040011#include "src/utils/SkShaperJSONWriter.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040012#include "tests/CodecPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040013#include "tests/Test.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040014#include "tools/Resources.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040015#include "tools/ToolUtils.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040016
Julia Lavrovab30d4812019-11-08 14:51:16 -050017#include "third_party/icu/SkLoadICU.h"
18
Julia Lavrovaa3552c52019-05-30 16:12:56 -040019#define VeryLongCanvasWidth 1000000
20#define TestCanvasWidth 1000
21#define TestCanvasHeight 600
22
Julia Lavrova2e30fde2019-10-09 09:43:02 -040023#define DEF_TEST_DISABLED(name, reporter) \
24static void test_##name(skiatest::Reporter* reporter, const GrContextOptions&); \
25skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \
Herb Derby126d7a22019-11-27 11:38:16 -050026void test_##name(skiatest::Reporter* reporter, const GrContextOptions&) { /* SkDebugf("Disabled:"#name "\n"); */ } \
Julia Lavrova2e30fde2019-10-09 09:43:02 -040027void disabled_##name(skiatest::Reporter* reporter, const GrContextOptions&)
28
Julia Lavrovaa3552c52019-05-30 16:12:56 -040029using namespace skia::textlayout;
30namespace {
31
Julia Lavrovadb9f6692019-08-01 16:02:17 -040032SkScalar EPSILON100 = 0.01f;
33SkScalar EPSILON50 = 0.02f;
34SkScalar EPSILON20 = 0.05f;
Julia Lavrova916a9042019-08-08 16:51:27 -040035SkScalar EPSILON10 = 0.1f;
Julia Lavrovac2228562019-08-08 16:51:27 -040036SkScalar EPSILON5 = 0.20f;
37SkScalar EPSILON2 = 0.50f;
Julia Lavrovadb9f6692019-08-01 16:02:17 -040038
Julia Lavrova5207f352019-06-21 12:22:32 -040039bool equal(const char* base, TextRange a, const char* b) {
40 return std::strncmp(b, base + a.start, a.width()) == 0;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040041}
Julia Lavrova3281b962019-12-02 11:32:25 -050042
Julia Lavrova2e30fde2019-10-09 09:43:02 -040043class ResourceFontCollection : public FontCollection {
Julia Lavrovaa3552c52019-05-30 16:12:56 -040044public:
Julia Lavrova2e30fde2019-10-09 09:43:02 -040045 ResourceFontCollection(bool testOnly = false)
Julia Lavrovaa3552c52019-05-30 16:12:56 -040046 : fFontsFound(false)
47 , fResolvedFonts(0)
48 , fResourceDir(GetResourcePath("fonts").c_str())
49 , fFontProvider(sk_make_sp<TypefaceFontProvider>()) {
50 std::vector<SkString> fonts;
51 SkOSFile::Iter iter(fResourceDir.c_str());
Julia Lavrova2e30fde2019-10-09 09:43:02 -040052
Julia Lavrovab30d4812019-11-08 14:51:16 -050053 if (!SkLoadICU()) {
54 SkDebugf("ICU not loaded, skipping all the tests\n");
55 return;
56 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040057 SkString path;
58 while (iter.next(&path)) {
59 if (path.endsWith("Roboto-Italic.ttf")) {
60 fFontsFound = true;
61 }
62 fonts.emplace_back(path);
63 }
64
65 if (!fFontsFound) {
Herb Derby126d7a22019-11-27 11:38:16 -050066 // SkDebugf("Fonts not found, skipping all the tests\n");
Julia Lavrovaa3552c52019-05-30 16:12:56 -040067 return;
68 }
69 // Only register fonts if we have to
70 for (auto& font : fonts) {
71 SkString file_path;
72 file_path.printf("%s/%s", fResourceDir.c_str(), font.c_str());
73 fFontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
74 }
75
Julia Lavrova2e30fde2019-10-09 09:43:02 -040076 if (testOnly) {
77 this->setTestFontManager(std::move(fFontProvider));
78 } else {
79 this->setAssetFontManager(std::move(fFontProvider));
80 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040081 this->disableFontFallback();
Julia Lavrovaa3552c52019-05-30 16:12:56 -040082 }
83
Julia Lavrova2e30fde2019-10-09 09:43:02 -040084 ~ResourceFontCollection() = default;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040085
86 size_t resolvedFonts() const { return fResolvedFonts; }
87
88 // TODO: temp solution until we check in fonts
89 bool fontsFound() const { return fFontsFound; }
90
91private:
92 bool fFontsFound;
93 size_t fResolvedFonts;
94 std::string fResourceDir;
95 sk_sp<TypefaceFontProvider> fFontProvider;
96};
Julia Lavrovadb9f6692019-08-01 16:02:17 -040097
98class TestCanvas {
99public:
100 TestCanvas(const char* testName) : name(testName) {
101 bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight);
102 canvas = new SkCanvas(bits);
103 canvas->clear(SK_ColorWHITE);
104 }
105
106 ~TestCanvas() {
Julia Lavrovaaae845f2019-08-16 16:44:40 -0400107 SkString tmpDir = skiatest::GetTmpDir();
108 if (!tmpDir.isEmpty()) {
109 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
110 SkFILEWStream file(path.c_str());
111 if (!SkEncodeImage(&file, bits, SkEncodedImageFormat::kPNG, 100)) {
112 SkDebugf("Cannot write a picture %s\n", name);
113 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400114 }
115 delete canvas;
116 }
117
118 void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) {
119
120 SkPaint paint;
121 if (!fill) {
122 paint.setStyle(SkPaint::kStroke_Style);
123 paint.setAntiAlias(true);
124 paint.setStrokeWidth(1);
125 }
126 paint.setColor(color);
127 for (auto& r : result) {
128 canvas->drawRect(r.rect, paint);
129 }
130 }
131
132 void drawLine(SkColor color, SkRect rect, bool vertical = true) {
133
134 SkPaint paint;
135 paint.setStyle(SkPaint::kStroke_Style);
136 paint.setAntiAlias(true);
137 paint.setStrokeWidth(1);
138 paint.setColor(color);
139 if (vertical) {
140 canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
141 } else {
142 canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint);
143 }
144 }
145
146 void drawLines(SkColor color, std::vector<TextBox>& result) {
147
148 for (auto& r : result) {
149 drawLine(color, r.rect);
150 }
151 }
152
153 SkCanvas* get() { return canvas; }
154private:
155 SkBitmap bits;
156 SkCanvas* canvas;
157 const char* name;
158};
159
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400160} // namespace
161
162DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400163 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400164 if (!fontCollection->fontsFound()) return;
165 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400166 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400167
168 ParagraphStyle paragraph_style;
169 paragraph_style.turnHintingOff();
170 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
171
172 TextStyle text_style;
173 text_style.setFontFamilies({SkString("Roboto")});
174 text_style.setColor(SK_ColorBLACK);
175 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400176 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400177 builder.pop();
178
179 auto paragraph = builder.Build();
180 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500181 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400182
183 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
184 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
185 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400186 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400187
188 size_t index = 0;
189 for (auto& line : impl->lines()) {
190 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400191 [&index, reporter]
192 (TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400193 REPORTER_ASSERT(reporter, index == 0);
194 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorBLACK);
195 ++index;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400196 });
197 }
198}
199
Julia Lavrova916a9042019-08-08 16:51:27 -0400200DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400201 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400202 TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png");
203 if (!fontCollection->fontsFound()) return;
204
205 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400206 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400207
208 ParagraphStyle paragraph_style;
209 paragraph_style.turnHintingOff();
210 paragraph_style.setMaxLines(14);
211 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
212
213 TextStyle text_style;
214 text_style.setFontFamilies({SkString("Roboto")});
215 text_style.setColor(SK_ColorBLACK);
216 text_style.setFontSize(26);
217 text_style.setWordSpacing(5);
218 text_style.setLetterSpacing(1);
219 text_style.setDecoration(TextDecoration::kUnderline);
220 text_style.setDecorationColor(SK_ColorBLACK);
221 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400222 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400223
224 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
225 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400226 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400227 builder.addPlaceholder(placeholder1);
228
229 PlaceholderStyle placeholder2(5, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
230 builder.addPlaceholder(placeholder2);
231 builder.addPlaceholder(placeholder1);
232 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400233 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400234 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400235 builder.addText(text, len);
236 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400237 builder.addPlaceholder(placeholder2);
238 builder.addPlaceholder(placeholder2);
239 builder.addPlaceholder(placeholder2);
240 builder.addPlaceholder(placeholder2);
241 builder.addPlaceholder(placeholder2);
242 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400243 builder.addText(text, len);
244 builder.addText(text, len);
245 builder.addText(text, len);
246 builder.addText(text, len);
247 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400248 builder.addPlaceholder(placeholder2);
249 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400250 builder.addText(text, len);
251 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400252
253 builder.pop();
254
255 auto paragraph = builder.Build();
256 paragraph->layout(TestCanvasWidth);
257 paragraph->paint(canvas.get(), 0, 0);
258
259 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
260 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
261
262 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
263 canvas.drawRects(SK_ColorRED, boxes);
264 REPORTER_ASSERT(reporter, boxes.size() == 1);
265
266 boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
267 canvas.drawRects(SK_ColorGREEN, boxes);
268 REPORTER_ASSERT(reporter, boxes.size() == 1);
269
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400270 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400271 canvas.drawRects(SK_ColorRED, boxes);
272
273 boxes = paragraph->getRectsForRange(4, 17, rect_height_style, rect_width_style);
274 canvas.drawRects(SK_ColorBLUE, boxes);
275
276 REPORTER_ASSERT(reporter, boxes.size() == 7);
277
Julia Lavrovac028b422019-11-25 10:00:43 -0500278 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400279 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500280 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 90.921f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400281 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 100, EPSILON100));
282
Julia Lavrovac028b422019-11-25 10:00:43 -0500283 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.left(), 231.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.right(), 231.343f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.bottom(), 100, EPSILON100));
287
Julia Lavrovac028b422019-11-25 10:00:43 -0500288 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.left(), 281.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400289 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500290 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.right(), 281.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400291 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.bottom(), 50, EPSILON100));
292
Julia Lavrovac028b422019-11-25 10:00:43 -0500293 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.left(), 336.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.right(), 336.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400296 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100));
297}
298
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400299DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400300 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400301 TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png");
302 if (!fontCollection->fontsFound()) return;
303
304 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400305 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400306
307 ParagraphStyle paragraph_style;
308 paragraph_style.turnHintingOff();
309 paragraph_style.setMaxLines(14);
310 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
311
312 TextStyle text_style;
313 text_style.setFontFamilies({SkString("Roboto")});
314 text_style.setColor(SK_ColorBLACK);
315 text_style.setFontSize(26);
316 text_style.setWordSpacing(5);
317 text_style.setLetterSpacing(1);
318 text_style.setDecoration(TextDecoration::kUnderline);
319 text_style.setDecorationColor(SK_ColorBLACK);
320 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400321 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400322
323 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 38.347f);
324 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400325 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400326
327 builder.pop();
328
329 auto paragraph = builder.Build();
330 paragraph->layout(TestCanvasWidth);
331 paragraph->paint(canvas.get(), 0, 0);
332
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400333 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400334 canvas.drawRects(SK_ColorRED, boxes);
335
336 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500337 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400338 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
341
342 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
343 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
344
345 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
346 canvas.drawRects(SK_ColorBLUE, boxes);
347
348 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500349 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400350 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 14.226f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500351 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400353}
Julia Lavrova916a9042019-08-08 16:51:27 -0400354
Julia Lavrova916a9042019-08-08 16:51:27 -0400355DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400356 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400357 TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png");
358 if (!fontCollection->fontsFound()) return;
359
360 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400361 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400362
363 ParagraphStyle paragraph_style;
364 paragraph_style.turnHintingOff();
365 paragraph_style.setMaxLines(14);
366 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
367
368 TextStyle text_style;
369 text_style.setFontFamilies({SkString("Roboto")});
370 text_style.setColor(SK_ColorBLACK);
371 text_style.setFontSize(26);
372 text_style.setWordSpacing(5);
373 text_style.setLetterSpacing(1);
374 text_style.setDecoration(TextDecoration::kUnderline);
375 text_style.setDecorationColor(SK_ColorBLACK);
376 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400377 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400378
379 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kAboveBaseline, TextBaseline::kAlphabetic, 903129.129308f);
380 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400381 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400382
383 builder.pop();
384
385 auto paragraph = builder.Build();
386 paragraph->layout(TestCanvasWidth);
387 paragraph->paint(canvas.get(), 0, 0);
388
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400389 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400390 canvas.drawRects(SK_ColorRED, boxes);
391
392 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500393 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400394 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.347f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500395 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400396 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 49.652f, EPSILON100));
397
398 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
399 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
400
401 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
402 canvas.drawRects(SK_ColorBLUE, boxes);
403
404 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 25.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400409}
Julia Lavrova916a9042019-08-08 16:51:27 -0400410
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400411DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400412 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400413 TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png");
414 if (!fontCollection->fontsFound()) return;
415
416 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400417 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400418
419 ParagraphStyle paragraph_style;
420 paragraph_style.turnHintingOff();
421 paragraph_style.setMaxLines(14);
422 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
423
424 TextStyle text_style;
425 text_style.setFontFamilies({SkString("Roboto")});
426 text_style.setColor(SK_ColorBLACK);
427 text_style.setFontSize(26);
428 text_style.setWordSpacing(5);
429 text_style.setLetterSpacing(1);
430 text_style.setDecoration(TextDecoration::kUnderline);
431 text_style.setDecorationColor(SK_ColorBLACK);
432 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400433 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400434
435 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBelowBaseline, TextBaseline::kAlphabetic, 903129.129308f);
436 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400437 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400438
439 builder.pop();
440
441 auto paragraph = builder.Build();
442 paragraph->layout(TestCanvasWidth);
443 paragraph->paint(canvas.get(), 0, 0);
444
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400445 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400446 canvas.drawRects(SK_ColorRED, boxes);
447
448 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500449 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400450 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500451 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400452 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
453
454 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
455 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
456
457 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
458 canvas.drawRects(SK_ColorBLUE, boxes);
459
460 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500461 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400462 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.121f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500463 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400464 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400465}
Julia Lavrova916a9042019-08-08 16:51:27 -0400466
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400467DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400468 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400469 TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png");
470 if (!fontCollection->fontsFound()) return;
471
472 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400473 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400474
475 ParagraphStyle paragraph_style;
476 paragraph_style.turnHintingOff();
477 paragraph_style.setMaxLines(14);
478 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
479
480 TextStyle text_style;
481 text_style.setFontFamilies({SkString("Roboto")});
482 text_style.setColor(SK_ColorBLACK);
483 text_style.setFontSize(26);
484 text_style.setWordSpacing(5);
485 text_style.setLetterSpacing(1);
486 text_style.setDecoration(TextDecoration::kUnderline);
487 text_style.setDecorationColor(SK_ColorBLACK);
488 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400489 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400490
491 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBottom, TextBaseline::kAlphabetic, 0);
492 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400493 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400494
495 builder.pop();
496
497 auto paragraph = builder.Build();
498 paragraph->layout(TestCanvasWidth);
499 paragraph->paint(canvas.get(), 0, 0);
500
501 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
502 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
503
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400504 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400505 canvas.drawRects(SK_ColorRED, boxes);
506 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400508 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500509 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
511
512 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
513 canvas.drawRects(SK_ColorBLUE, boxes);
514 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 19.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400518 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400519}
Julia Lavrova916a9042019-08-08 16:51:27 -0400520
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400521DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400522 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400523 TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png");
524 if (!fontCollection->fontsFound()) return;
525
526 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400527 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400528
529 ParagraphStyle paragraph_style;
530 paragraph_style.turnHintingOff();
531 paragraph_style.setMaxLines(14);
532 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
533
534 TextStyle text_style;
535 text_style.setFontFamilies({SkString("Roboto")});
536 text_style.setColor(SK_ColorBLACK);
537 text_style.setFontSize(26);
538 text_style.setWordSpacing(5);
539 text_style.setLetterSpacing(1);
540 text_style.setDecoration(TextDecoration::kUnderline);
541 text_style.setDecorationColor(SK_ColorBLACK);
542 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400543 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400544
545 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kTop, TextBaseline::kAlphabetic, 0);
546 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400547 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400548
549 builder.pop();
550
551 auto paragraph = builder.Build();
552 paragraph->layout(TestCanvasWidth);
553 paragraph->paint(canvas.get(), 0, 0);
554
555 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
556 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
557
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400558 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400559 canvas.drawRects(SK_ColorRED, boxes);
560 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500561 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400562 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500563 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400564 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
565
566 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
567 canvas.drawRects(SK_ColorBLUE, boxes);
568 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500569 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400570 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500571 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400572 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400573}
Julia Lavrova916a9042019-08-08 16:51:27 -0400574
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400575DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400576 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400577 TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png");
578 if (!fontCollection->fontsFound()) return;
579
580 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400581 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400582
583 ParagraphStyle paragraph_style;
584 paragraph_style.turnHintingOff();
585 paragraph_style.setMaxLines(14);
586 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
587
588 TextStyle text_style;
589 text_style.setFontFamilies({SkString("Roboto")});
590 text_style.setColor(SK_ColorBLACK);
591 text_style.setFontSize(26);
592 text_style.setWordSpacing(5);
593 text_style.setLetterSpacing(1);
594 text_style.setDecoration(TextDecoration::kUnderline);
595 text_style.setDecorationColor(SK_ColorBLACK);
596 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400597 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400598
599 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kMiddle, TextBaseline::kAlphabetic, 0);
600 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400601 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400602
603 builder.pop();
604
605 auto paragraph = builder.Build();
606 paragraph->layout(TestCanvasWidth);
607 paragraph->paint(canvas.get(), 0, 0);
608
609 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
610 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
611
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400612 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400613 canvas.drawRects(SK_ColorRED, boxes);
614 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500615 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400616 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500617 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400618 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
619
620 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
621 canvas.drawRects(SK_ColorBLUE, boxes);
622 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500623 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 9.765f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500625 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400627}
Julia Lavrova916a9042019-08-08 16:51:27 -0400628
Julia Lavrova916a9042019-08-08 16:51:27 -0400629DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400630 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400631 TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png");
632 if (!fontCollection->fontsFound()) return;
633
634 const char* text = "給能上目秘使";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400635 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400636
637 ParagraphStyle paragraph_style;
638 paragraph_style.turnHintingOff();
639 paragraph_style.setMaxLines(14);
640 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
641
642 TextStyle text_style;
643 text_style.setFontFamilies({SkString("Source Han Serif CN")});
644 text_style.setColor(SK_ColorBLACK);
645 text_style.setFontSize(26);
646 text_style.setWordSpacing(5);
647 text_style.setLetterSpacing(1);
648 text_style.setDecoration(TextDecoration::kUnderline);
649 text_style.setDecorationColor(SK_ColorBLACK);
650 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400651 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400652 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kIdeographic, 38.347f);
653 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400654 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400655
656 builder.pop();
657
658 auto paragraph = builder.Build();
659 paragraph->layout(TestCanvasWidth);
660 paragraph->paint(canvas.get(), 0, 0);
661
662 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
663 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
664
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400665 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400666 canvas.drawRects(SK_ColorRED, boxes);
667 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500668 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400669 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500670 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400671 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
672
673 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
674 canvas.drawRects(SK_ColorBLUE, boxes);
675 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500676 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 135.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400677 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 4.703f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500678 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400679 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400680}
Julia Lavrova916a9042019-08-08 16:51:27 -0400681
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400682DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400683 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400684 TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png");
685 if (!fontCollection->fontsFound()) return;
686
687 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400688 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400689
690 ParagraphStyle paragraph_style;
691 paragraph_style.turnHintingOff();
692 paragraph_style.setMaxLines(14);
693 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
694
695 TextStyle text_style;
696 text_style.setFontFamilies({SkString("Roboto")});
697 text_style.setColor(SK_ColorBLACK);
698 text_style.setFontSize(26);
699 text_style.setWordSpacing(5);
700 text_style.setLetterSpacing(1);
701 text_style.setDecoration(TextDecoration::kUnderline);
702 text_style.setDecorationColor(SK_ColorBLACK);
703 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400704 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400705
706 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
707 PlaceholderStyle placeholder2(25, 25, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 12.5f);
708
709 builder.addPlaceholder(placeholder1);
710 builder.addPlaceholder(placeholder1);
711 builder.addPlaceholder(placeholder1);
712 builder.addPlaceholder(placeholder2);
713 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400714 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400715
716 builder.addPlaceholder(placeholder1);
717 builder.addPlaceholder(placeholder1);
718 builder.addPlaceholder(placeholder1);
719 builder.addPlaceholder(placeholder1);
720 builder.addPlaceholder(placeholder2); // 4 + 1
721 builder.addPlaceholder(placeholder1);
722 builder.addPlaceholder(placeholder1);
723 builder.addPlaceholder(placeholder1);
724 builder.addPlaceholder(placeholder1);
725 builder.addPlaceholder(placeholder1);
726 builder.addPlaceholder(placeholder1);
727 builder.addPlaceholder(placeholder2); // 6 + 1
728 builder.addPlaceholder(placeholder1);
729 builder.addPlaceholder(placeholder1);
730 builder.addPlaceholder(placeholder1);
731 builder.addPlaceholder(placeholder1);
732 builder.addPlaceholder(placeholder1);
733 builder.addPlaceholder(placeholder1);
734 builder.addPlaceholder(placeholder1);
735 builder.addPlaceholder(placeholder2); // 7 + 1
736
737 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400738 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400739 builder.addPlaceholder(placeholder1);
740 builder.addPlaceholder(placeholder2);
741
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400742 builder.addText(text, len);
743 builder.addText(text, len);
744 builder.addText(text, len);
745 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400746
747 builder.addPlaceholder(placeholder2);
748 builder.addPlaceholder(placeholder1);
749
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400750 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400751
752 builder.addPlaceholder(placeholder2);
753
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400754 builder.addText(text, len);
755 builder.addText(text, len);
756 builder.addText(text, len);
757 builder.addText(text, len);
758 builder.addText(text, len);
759 builder.addText(text, len);
760 builder.addText(text, len);
761 builder.addText(text, len);
762 builder.addText(text, len);
763 builder.addText(text, len);
764 builder.addText(text, len);
765 builder.addText(text, len);
766 builder.addText(text, len);
767 builder.addText(text, len);
768 builder.addText(text, len);
769 builder.addText(text, len);
770 builder.addText(text, len);
771 builder.addText(text, len);
772 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400773
774 builder.pop();
775
776 auto paragraph = builder.Build();
777 paragraph->layout(TestCanvasWidth - 100);
778 paragraph->paint(canvas.get(), 0, 0);
779
780 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
781 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
782
783 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
784 canvas.drawRects(SK_ColorRED, boxes);
785 REPORTER_ASSERT(reporter, boxes.size() == 1);
786
787 boxes = paragraph->getRectsForRange(175, 176, rect_height_style, rect_width_style);
788 canvas.drawRects(SK_ColorGREEN, boxes);
789 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500790 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 31.695f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400791 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 218.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500792 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 47.292f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400793 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 249, EPSILON100));
794
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400795 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400796 canvas.drawRects(SK_ColorRED, boxes);
797
798 boxes = paragraph->getRectsForRange(4, 45, rect_height_style, rect_width_style);
799 canvas.drawRects(SK_ColorBLUE, boxes);
800 REPORTER_ASSERT(reporter, boxes.size() == 30);
Julia Lavrovac028b422019-11-25 10:00:43 -0500801 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 59.726f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400802 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.378f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500803 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400804 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56.847f, EPSILON100));
805
Julia Lavrovac028b422019-11-25 10:00:43 -0500806 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.left(), 606.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400807 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.top(), 38, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500808 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.right(), 631.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400809 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.bottom(), 63, EPSILON100));
810
Julia Lavrovac028b422019-11-25 10:00:43 -0500811 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400812 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.top(), 63.5f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500813 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.right(), 50.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400814 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400815}
Julia Lavrova916a9042019-08-08 16:51:27 -0400816
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400817DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400818 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400819 TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png");
820 if (!fontCollection->fontsFound()) return;
821
822 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400823 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400824
825 ParagraphStyle paragraph_style;
826 paragraph_style.turnHintingOff();
827 paragraph_style.setMaxLines(14);
828 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
829
830 TextStyle text_style;
831 text_style.setFontFamilies({SkString("Roboto")});
832 text_style.setColor(SK_ColorBLACK);
833 text_style.setFontSize(26);
834 text_style.setWordSpacing(5);
835 text_style.setLetterSpacing(1);
836 text_style.setDecoration(TextDecoration::kUnderline);
837 text_style.setDecorationColor(SK_ColorBLACK);
838 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400839 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400840
841 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
842 PlaceholderStyle placeholder2(5, 20, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 10);
843
844 builder.addPlaceholder(placeholder1);
845 builder.addPlaceholder(placeholder1);
846 builder.addPlaceholder(placeholder1);
847 builder.addPlaceholder(placeholder1);
848 builder.addPlaceholder(placeholder1);
849 builder.addPlaceholder(placeholder1);
850 builder.addPlaceholder(placeholder1);
851 builder.addPlaceholder(placeholder1);
852 builder.addPlaceholder(placeholder2); // 8 + 1
853 builder.addPlaceholder(placeholder1);
854 builder.addPlaceholder(placeholder1);
855 builder.addPlaceholder(placeholder1);
856 builder.addPlaceholder(placeholder1);
857 builder.addPlaceholder(placeholder1);
858 builder.addPlaceholder(placeholder2); // 5 + 1
859 builder.addPlaceholder(placeholder1);
860 builder.addPlaceholder(placeholder1);
861 builder.addPlaceholder(placeholder1);
862 builder.addPlaceholder(placeholder1);
863 builder.addPlaceholder(placeholder1);
864 builder.addPlaceholder(placeholder1);
865 builder.addPlaceholder(placeholder1);
866 builder.addPlaceholder(placeholder1); // 8 + 0
867
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400868 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400869
870 builder.addPlaceholder(placeholder1);
871 builder.addPlaceholder(placeholder2);
872 builder.addPlaceholder(placeholder2); // 1 + 2
873 builder.addPlaceholder(placeholder1);
874 builder.addPlaceholder(placeholder2);
875 builder.addPlaceholder(placeholder2); // 1 + 2
876
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400877 builder.addText(text, len);
878 builder.addText(text, len);
879 builder.addText(text, len);
880 builder.addText(text, len);
881 builder.addText(text, len);
882 builder.addText(text, len);
883 builder.addText(text, len);
884 builder.addText(text, len);
885 builder.addText(text, len);
886 builder.addText(text, len);
887 builder.addText(text, len); // 11
Julia Lavrova916a9042019-08-08 16:51:27 -0400888
889 builder.addPlaceholder(placeholder2);
890 builder.addPlaceholder(placeholder1);
891 builder.addPlaceholder(placeholder2);
892 builder.addPlaceholder(placeholder1);
893 builder.addPlaceholder(placeholder2);
894
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400895 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400896
897 builder.pop();
898
899 auto paragraph = builder.Build();
900 paragraph->layout(TestCanvasWidth);
901 paragraph->paint(canvas.get(), 0, 0);
902
903 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
904 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
905
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400906 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400907 canvas.drawRects(SK_ColorRED, boxes);
908
909 REPORTER_ASSERT(reporter, boxes.size() == 34);
Julia Lavrovac028b422019-11-25 10:00:43 -0500910 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400911 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500912 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 140.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400913 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
914
Julia Lavrovac028b422019-11-25 10:00:43 -0500915 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.left(), 800.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500917 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.right(), 850.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400918 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.bottom(), 50, EPSILON100));
919
Julia Lavrovac028b422019-11-25 10:00:43 -0500920 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.left(), 503.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400921 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.top(), 160, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500922 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.right(), 508.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400923 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.bottom(), 180, EPSILON100));
924
925 boxes = paragraph->getRectsForRange(30, 50, rect_height_style, rect_width_style);
926 canvas.drawRects(SK_ColorBLUE, boxes);
927
928 REPORTER_ASSERT(reporter, boxes.size() == 8);
Julia Lavrovac028b422019-11-25 10:00:43 -0500929 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 216.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400930 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500931 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 290.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400932 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 120, EPSILON100));
933
Julia Lavrovac028b422019-11-25 10:00:43 -0500934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 290.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 340.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 120, EPSILON100));
938
Julia Lavrovac028b422019-11-25 10:00:43 -0500939 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.left(), 340.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400940 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500941 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.right(), 345.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400942 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400943}
944
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400945DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400946 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400947 if (!fontCollection->fontsFound()) return;
948 const char* text = "I am RED";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400949 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400950
951 ParagraphStyle paragraph_style;
952 paragraph_style.turnHintingOff();
953 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
954
955 TextStyle text_style;
956 text_style.setFontFamilies({SkString("Roboto")});
957 text_style.setColor(SK_ColorRED);
958 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400959 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400960 builder.pop();
961
962 auto paragraph = builder.Build();
963 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500964 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400965
966 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
967 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
968 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400969 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400970
971 size_t index = 0;
972 for (auto& line : impl->lines()) {
973 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400974 [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
975 REPORTER_ASSERT(reporter, index == 0);
976 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED);
977 ++index;
978 return true;
979 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400980 }
981}
982
Julia Lavrovac2228562019-08-08 16:51:27 -0400983// Checked: DIFF+ (Space between 1 & 2 style blocks)
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400984DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400985 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400986 TestCanvas canvas("SkParagraph_RainbowParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400987 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400988 const char* text1 = "Red Roboto"; // [0:10)
989 const char* text2 = "big Greeen Default"; // [10:28)
990 const char* text3 = "Defcolor Homemade Apple"; // [28:51)
991 const char* text4 = "Small Blue Roboto"; // [51:68)
Julia Lavrovac2228562019-08-08 16:51:27 -0400992 const char* text41 = "Small Blue ";
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400993 const char* text5 =
994 "Continue Last Style With lots of words to check if it overlaps "
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400995 "properly or not"; // [68:)
996 const char* text42 =
997 "Roboto"
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400998 "Continue Last Style With lots of words to check if it overlaps "
999 "properly or not";
1000
1001 ParagraphStyle paragraph_style;
1002 paragraph_style.turnHintingOff();
1003 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001004 paragraph_style.setMaxLines(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001005 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1006
1007 TextStyle text_style1;
1008 text_style1.setFontFamilies({SkString("Roboto")});
1009
1010 text_style1.setColor(SK_ColorRED);
1011 builder.pushStyle(text_style1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001012 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001013
1014 TextStyle text_style2;
1015 text_style2.setFontFamilies({SkString("Roboto")});
1016 text_style2.setFontSize(50);
1017 text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1018 SkFontStyle::kUpright_Slant));
1019 text_style2.setLetterSpacing(10);
1020 text_style2.setDecorationColor(SK_ColorBLACK);
1021 text_style2.setDecoration((TextDecoration)(
1022 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1023 text_style2.setWordSpacing(30);
1024 text_style2.setColor(SK_ColorGREEN);
1025 builder.pushStyle(text_style2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001026 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001027
1028 TextStyle text_style3;
1029 text_style3.setFontFamilies({SkString("Homemade Apple")});
Julia Lavrova526df262019-08-21 17:49:44 -04001030 text_style3.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001031 builder.pushStyle(text_style3);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001032 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001033
1034 TextStyle text_style4;
1035 text_style4.setFontFamilies({SkString("Roboto")});
1036 text_style4.setFontSize(14);
1037 text_style4.setDecorationColor(SK_ColorBLACK);
1038 text_style4.setDecoration((TextDecoration)(
1039 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1040 text_style4.setColor(SK_ColorBLUE);
1041 builder.pushStyle(text_style4);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001042 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001043
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001044 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001045 builder.pop();
1046
1047 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001048 paragraph->layout(1000);
1049 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001050
Julia Lavrova3281b962019-12-02 11:32:25 -05001051 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1052
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001053 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1054 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
1055 REPORTER_ASSERT(reporter, impl->styles().size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001056 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1057
1058 auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight);
1059 canvas.drawRects(SK_ColorMAGENTA, rects);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001060
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001061 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001062 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001063 StyleType::kAllAttributes,
1064 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001065 switch (index) {
1066 case 0:
1067 REPORTER_ASSERT(reporter, style.equals(text_style1));
Julia Lavrova526df262019-08-21 17:49:44 -04001068 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001069 break;
1070 case 1:
1071 REPORTER_ASSERT(reporter, style.equals(text_style2));
Julia Lavrova526df262019-08-21 17:49:44 -04001072 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001073 break;
1074 case 2:
1075 REPORTER_ASSERT(reporter, style.equals(text_style3));
Julia Lavrova526df262019-08-21 17:49:44 -04001076 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001077 break;
1078 case 3:
1079 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001080 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001081 break;
1082 default:
1083 REPORTER_ASSERT(reporter, false);
1084 break;
1085 }
1086 ++index;
1087 return true;
1088 });
1089 impl->lines()[1].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001090 StyleType::kAllAttributes,
1091 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001092 switch (index) {
1093 case 4:
1094 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001095 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001096 break;
1097 default:
1098 REPORTER_ASSERT(reporter, false);
1099 break;
1100 }
1101 ++index;
1102 return true;
1103 });
1104 REPORTER_ASSERT(reporter, index == 5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001105}
1106
1107DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001108 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001109 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001110 TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001111 const char* text = "No TextStyle! Uh Oh!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001112 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001113
1114 ParagraphStyle paragraph_style;
1115 TextStyle defaultStyle;
1116 defaultStyle.setFontFamilies({SkString("Roboto")});
1117 paragraph_style.setTextStyle(defaultStyle);
1118 paragraph_style.turnHintingOff();
1119 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001120 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001121
1122 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001123 paragraph->layout(TestCanvasWidth);
1124 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001125
Julia Lavrova3281b962019-12-02 11:32:25 -05001126 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1127
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001128 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1129
1130 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1131 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1132 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1133
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001134 size_t index = 0;
1135 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001136 StyleType::kAllAttributes,
1137 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001138 REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle()));
Julia Lavrova526df262019-08-21 17:49:44 -04001139 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001140 ++index;
1141 return true;
1142 });
1143 REPORTER_ASSERT(reporter, index == 1);
1144}
1145
1146DEF_TEST(SkParagraph_BoldParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001147 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001148 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001149 TestCanvas canvas("SkParagraph_BoldParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001150 const char* text = "This is Red max bold text!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001151 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001152
1153 ParagraphStyle paragraph_style;
1154 paragraph_style.turnHintingOff();
1155 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1156
1157 TextStyle text_style;
1158 text_style.setFontFamilies({SkString("Roboto")});
1159 text_style.setColor(SK_ColorRED);
1160 text_style.setFontSize(60);
1161 text_style.setLetterSpacing(0);
1162 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width,
1163 SkFontStyle::kUpright_Slant));
1164 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001165 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001166 builder.pop();
1167
1168 auto paragraph = builder.Build();
1169 paragraph->layout(VeryLongCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001170 paragraph->paint(canvas.get(), 10.0, 60.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001171
Julia Lavrova3281b962019-12-02 11:32:25 -05001172 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1173
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001174 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1175
1176 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1177 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1178 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1179
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001180 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001181 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001182 StyleType::kAllAttributes,
1183 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001184 REPORTER_ASSERT(reporter, style.equals(text_style));
Julia Lavrova526df262019-08-21 17:49:44 -04001185 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001186 ++index;
1187 return true;
1188 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001189 REPORTER_ASSERT(reporter, index == 1);
1190}
1191
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001192DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001193 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04001194 if (!fontCollection->fontsFound()) return;
1195 TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png");
1196 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001197 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001198
Julia Lavrovac2228562019-08-08 16:51:27 -04001199 ParagraphStyle paragraph_style;
1200 paragraph_style.turnHintingOff();
1201 paragraph_style.setMaxLines(10);
1202 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001203
Julia Lavrovac2228562019-08-08 16:51:27 -04001204 TextStyle text_style;
1205 text_style.setFontFamilies({SkString("Roboto")});
1206 text_style.setFontSize(20);
1207 text_style.setColor(SK_ColorBLACK);
1208 text_style.setHeight(3.6345f);
1209 text_style.setHeightOverride(true);
1210 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001211 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04001212 builder.pop();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001213
Julia Lavrovac2228562019-08-08 16:51:27 -04001214 auto paragraph = builder.Build();
1215 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001216
Julia Lavrovac2228562019-08-08 16:51:27 -04001217 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001218 REPORTER_ASSERT(reporter, impl->runs().size() == 5);
Julia Lavrovac2228562019-08-08 16:51:27 -04001219 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
1220 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001221
Julia Lavrovac2228562019-08-08 16:51:27 -04001222 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001223
Julia Lavrovac2228562019-08-08 16:51:27 -04001224 SkPaint paint;
1225 paint.setStyle(SkPaint::kStroke_Style);
1226 paint.setAntiAlias(true);
1227 paint.setStrokeWidth(1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001228
Julia Lavrovac2228562019-08-08 16:51:27 -04001229 // Tests for GetRectsForRange()
1230 RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle;
1231 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1232 paint.setColor(SK_ColorRED);
1233 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
1234 canvas.drawRects(SK_ColorRED, boxes);
1235 REPORTER_ASSERT(reporter, boxes.size() == 0ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001236
Julia Lavrovac2228562019-08-08 16:51:27 -04001237 boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style);
1238 canvas.drawRects(SK_ColorBLUE, boxes);
1239 REPORTER_ASSERT(reporter, boxes.size() == 3ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001240
Julia Lavrovac2228562019-08-08 16:51:27 -04001241 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100));
1242 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5));
1243 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100));
1244 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001245}
1246
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001247DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001248 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001249 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001250 TestCanvas canvas("SkParagraph_LeftAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001251 const char* text =
1252 "This is a very long sentence to test if the text will properly wrap "
1253 "around and go to the next line. Sometimes, short sentence. Longer "
1254 "sentences are okay too because they are nessecary. Very short. "
1255 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1256 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1257 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1258 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1259 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1260 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1261 "mollit anim id est laborum. "
1262 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1263 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1264 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1265 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1266 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1267 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1268 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001269 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001270
1271 ParagraphStyle paragraph_style;
1272 paragraph_style.setMaxLines(14);
1273 paragraph_style.setTextAlign(TextAlign::kLeft);
1274 paragraph_style.turnHintingOff();
1275 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1276
1277 TextStyle text_style;
1278 text_style.setFontFamilies({SkString("Roboto")});
1279 text_style.setFontSize(26);
1280 text_style.setLetterSpacing(1);
1281 text_style.setWordSpacing(5);
1282 text_style.setColor(SK_ColorBLACK);
1283 text_style.setHeight(1);
1284 text_style.setDecoration(TextDecoration::kUnderline);
1285 text_style.setDecorationColor(SK_ColorBLACK);
1286 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001287 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001288 builder.pop();
1289
1290 auto paragraph = builder.Build();
1291 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001292 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001293
1294 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001295
1296 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1297 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1298 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001299 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001300 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1301
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001302 double expected_y = 0;
1303 double epsilon = 0.01f;
1304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1305 REPORTER_ASSERT(reporter,
1306 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1307 expected_y += 30;
1308 REPORTER_ASSERT(reporter,
1309 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1310 expected_y += 30;
1311 REPORTER_ASSERT(reporter,
1312 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1313 expected_y += 30;
1314 REPORTER_ASSERT(reporter,
1315 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1316 expected_y += 30 * 10;
1317 REPORTER_ASSERT(reporter,
1318 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1319
1320 REPORTER_ASSERT(reporter,
1321 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1322
1323 // Tests for GetGlyphPositionAtCoordinate()
1324 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0);
1325 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
1326 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
1327 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001328 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001329}
1330
1331DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001332 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001333 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001334 TestCanvas canvas("SkParagraph_RightAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001335 const char* text =
1336 "This is a very long sentence to test if the text will properly wrap "
1337 "around and go to the next line. Sometimes, short sentence. Longer "
1338 "sentences are okay too because they are nessecary. Very short. "
1339 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1340 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1341 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1342 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1343 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1344 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1345 "mollit anim id est laborum. "
1346 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1347 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1348 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1349 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1350 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1351 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1352 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001353 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001354
1355 ParagraphStyle paragraph_style;
1356 paragraph_style.setMaxLines(14);
1357 paragraph_style.setTextAlign(TextAlign::kRight);
1358 paragraph_style.turnHintingOff();
1359 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1360
1361 TextStyle text_style;
1362 text_style.setFontFamilies({SkString("Roboto")});
1363 text_style.setFontSize(26);
1364 text_style.setLetterSpacing(1);
1365 text_style.setWordSpacing(5);
1366 text_style.setColor(SK_ColorBLACK);
1367 text_style.setHeight(1);
1368 text_style.setDecoration(TextDecoration::kUnderline);
1369 text_style.setDecorationColor(SK_ColorBLACK);
1370 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001371 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001372 builder.pop();
1373
1374 auto paragraph = builder.Build();
1375 paragraph->layout(TestCanvasWidth - 100);
1376
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001377 paragraph->paint(canvas.get(), 0, 0);
1378
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001379 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001380
1381 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1382 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001383 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001384 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1385
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001386 double expected_y = 0;
1387 double epsilon = 0.01f;
1388 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1389 REPORTER_ASSERT(reporter,
1390 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1391 expected_y += 30;
1392 REPORTER_ASSERT(reporter,
1393 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1394 expected_y += 30;
1395 REPORTER_ASSERT(reporter,
1396 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1397 expected_y += 30;
1398 REPORTER_ASSERT(reporter,
1399 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1400 expected_y += 30 * 10;
1401 REPORTER_ASSERT(reporter,
1402 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1403
1404 auto calculate = [](const TextLine& line) -> SkScalar {
1405 return TestCanvasWidth - 100 - line.offset().fX - line.width();
1406 };
1407
1408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1409 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1410 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1411 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1413
1414 REPORTER_ASSERT(reporter,
1415 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1416}
1417
1418DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001419 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001420 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001421 TestCanvas canvas("SkParagraph_CenterAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001422 const char* text =
1423 "This is a very long sentence to test if the text will properly wrap "
1424 "around and go to the next line. Sometimes, short sentence. Longer "
1425 "sentences are okay too because they are nessecary. Very short. "
1426 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1427 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1428 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1429 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1430 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1431 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1432 "mollit anim id est laborum. "
1433 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1434 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1435 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1436 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1437 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1438 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1439 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001440 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001441
1442 ParagraphStyle paragraph_style;
1443 paragraph_style.setMaxLines(14);
1444 paragraph_style.setTextAlign(TextAlign::kCenter);
1445 paragraph_style.turnHintingOff();
1446 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1447
1448 TextStyle text_style;
1449 text_style.setFontFamilies({SkString("Roboto")});
1450 text_style.setFontSize(26);
1451 text_style.setLetterSpacing(1);
1452 text_style.setWordSpacing(5);
1453 text_style.setColor(SK_ColorBLACK);
1454 text_style.setHeight(1);
1455 text_style.setDecoration(TextDecoration::kUnderline);
1456 text_style.setDecorationColor(SK_ColorBLACK);
1457 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001458 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001459 builder.pop();
1460
1461 auto paragraph = builder.Build();
1462 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001463 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001464
1465 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001466
1467 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1468 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1469 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001470 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001471 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1472
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001473 double expected_y = 0;
1474 double epsilon = 0.01f;
1475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1476 REPORTER_ASSERT(reporter,
1477 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1478 expected_y += 30;
1479 REPORTER_ASSERT(reporter,
1480 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1481 expected_y += 30;
1482 REPORTER_ASSERT(reporter,
1483 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1484 expected_y += 30;
1485 REPORTER_ASSERT(reporter,
1486 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1487 expected_y += 30 * 10;
1488 REPORTER_ASSERT(reporter,
1489 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1490
1491 auto calculate = [](const TextLine& line) -> SkScalar {
1492 return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width());
1493 };
1494
1495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1496 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1497 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1498 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1499 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1500
1501 REPORTER_ASSERT(reporter,
1502 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1503}
1504
1505DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001506 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001507 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001508 TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001509 const char* text =
1510 "This is a very long sentence to test if the text will properly wrap "
1511 "around and go to the next line. Sometimes, short sentence. Longer "
1512 "sentences are okay too because they are nessecary. Very short. "
1513 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1514 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1515 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1516 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1517 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1518 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1519 "mollit anim id est laborum. "
1520 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1521 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1522 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1523 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1524 "velit esse cillum dolore eu fugiat.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001525 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001526
1527 ParagraphStyle paragraph_style;
1528 paragraph_style.setMaxLines(14);
1529 paragraph_style.setTextAlign(TextAlign::kJustify);
1530 paragraph_style.turnHintingOff();
1531 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1532
1533 TextStyle text_style;
1534 text_style.setFontFamilies({SkString("Roboto")});
1535 text_style.setFontSize(26);
1536 text_style.setLetterSpacing(0);
1537 text_style.setWordSpacing(5);
1538 text_style.setColor(SK_ColorBLACK);
1539 text_style.setHeight(1);
1540 text_style.setDecoration(TextDecoration::kUnderline);
1541 text_style.setDecorationColor(SK_ColorBLACK);
1542 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001543 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001544 builder.pop();
1545
1546 auto paragraph = builder.Build();
1547 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001548 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001549
Julia Lavrovac2228562019-08-08 16:51:27 -04001550 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1551 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1552 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1553 canvas.drawRects(SK_ColorRED, boxes);
1554
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001555 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001556
1557 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1558 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1559 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001560 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001561
1562 double expected_y = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001563 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001564 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001565 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001566 expected_y += 30;
1567 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001568 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001569 expected_y += 30;
1570 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001571 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001572 expected_y += 30;
1573 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001574 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001575 expected_y += 30 * 9;
1576 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001577 SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001578
1579 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001580 return line.offset().fX;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001581 };
1582
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001583 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100));
1584 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100));
1585 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100));
1586 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001587
1588 REPORTER_ASSERT(reporter,
1589 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1590}
1591
Julia Lavrovac2228562019-08-08 16:51:27 -04001592// Checked: DIFF (ghost spaces as a separate box in TxtLib)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001593DEF_TEST(SkParagraph_JustifyRTL, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001594 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001595 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001596 TestCanvas canvas("SkParagraph_JustifyRTL.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001597 const char* text =
1598 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1599 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1600 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001601 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001602
1603 ParagraphStyle paragraph_style;
1604 paragraph_style.setMaxLines(14);
1605 paragraph_style.setTextAlign(TextAlign::kJustify);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001606 paragraph_style.setTextDirection(TextDirection::kRtl);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001607 paragraph_style.turnHintingOff();
1608 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1609
1610 TextStyle text_style;
1611 text_style.setFontFamilies({SkString("Ahem")});
1612 text_style.setFontSize(26);
1613 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001614 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001615 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001616 builder.pop();
1617
1618 auto paragraph = builder.Build();
1619 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001620 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001621
1622 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001623
1624 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001625 return TestCanvasWidth - 100 - line.width();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001626 };
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001627 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001628 if (&line == &impl->lines().back()) {
1629 REPORTER_ASSERT(reporter, calculate(line) > EPSILON100);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001630 } else {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001631 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001632 }
1633 }
1634
1635 // Just make sure the the text is actually RTL
1636 for (auto& run : impl->runs()) {
1637 REPORTER_ASSERT(reporter, !run.leftToRight());
1638 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001639
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001640 // Tests for GetRectsForRange()
1641 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1642 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1643 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1644 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001645 REPORTER_ASSERT(reporter, boxes.size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001646
1647 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1648 canvas.drawRects(SK_ColorBLUE, boxes);
1649 REPORTER_ASSERT(reporter, boxes.size() == 1);
1650
1651 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100));
1652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1653 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100));
1654 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1655}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001656
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001657DEF_TEST_DISABLED(SkParagraph_JustifyRTLNewLine, reporter) {
1658 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1659 if (!fontCollection->fontsFound()) return;
1660 TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png");
1661 const char* text =
1662 "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1663 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1664 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
1665
1666 auto icu_text = icu::UnicodeString::fromUTF8(text);
1667 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1668 const size_t len = strlen(text);
1669
1670 ParagraphStyle paragraph_style;
1671 paragraph_style.setMaxLines(14);
1672 paragraph_style.setTextAlign(TextAlign::kJustify);
1673 paragraph_style.setTextDirection(TextDirection::kRtl);
1674 paragraph_style.turnHintingOff();
1675 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1676
1677 TextStyle text_style;
1678 text_style.setFontFamilies({SkString("Ahem")});
1679 text_style.setFontSize(26);
1680 text_style.setColor(SK_ColorBLACK);
1681 builder.pushStyle(text_style);
1682 builder.addText(text, len);
1683 builder.pop();
1684
1685 auto paragraph = builder.Build();
1686 paragraph->layout(TestCanvasWidth - 100);
1687 paragraph->paint(canvas.get(), 0, 0);
1688
1689 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1690
1691 SkPaint paint;
1692 paint.setStyle(SkPaint::kStroke_Style);
1693 paint.setAntiAlias(true);
1694 paint.setStrokeWidth(1);
1695
1696 // Tests for GetRectsForRange()
1697 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1698 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1699 paint.setColor(SK_ColorRED);
1700 auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
1701 for (size_t i = 0; i < boxes.size(); ++i) {
1702 canvas.get()->drawRect(boxes[i].rect, paint);
1703 }
1704 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1705 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
1706 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
1707 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1708 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
1709
1710 paint.setColor(SK_ColorBLUE);
1711 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1712 for (size_t i = 0; i < boxes.size(); ++i) {
1713 canvas.get()->drawRect(boxes[i].rect, paint);
1714 }
1715 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
1716 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
1717 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1718 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
1719 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1720
1721 // All lines should be justified to the width of the
1722 // paragraph.
1723 for (auto& line : impl->lines()) {
1724 REPORTER_ASSERT(reporter,
1725 SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
1726 }
1727}
1728
1729DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
1730 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1731 if (!fontCollection->fontsFound()) return;
1732 TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
1733
1734 const char* text = " leading space";
1735
1736 auto icu_text = icu::UnicodeString::fromUTF8(text);
1737 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1738 const size_t len = strlen(text);
1739
1740 ParagraphStyle paragraph_style;
1741 paragraph_style.setMaxLines(14);
1742 paragraph_style.setTextAlign(TextAlign::kJustify);
1743 paragraph_style.setTextDirection(TextDirection::kRtl);
1744 paragraph_style.turnHintingOff();
1745 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1746
1747 TextStyle text_style;
1748 text_style.setFontFamilies({SkString("Ahem")});
1749 text_style.setFontSize(26);
1750 text_style.setColor(SK_ColorBLACK);
1751 builder.pushStyle(text_style);
1752 builder.addText(text, len);
1753 builder.pop();
1754
1755 auto paragraph = builder.Build();
1756 paragraph->layout(TestCanvasWidth - 100);
1757 paragraph->paint(canvas.get(), 0, 0);
1758
1759 SkPaint paint;
1760 paint.setStyle(SkPaint::kStroke_Style);
1761 paint.setAntiAlias(true);
1762 paint.setStrokeWidth(1);
1763
1764 // Tests for GetRectsForRange()
1765 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1766 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1767 paint.setColor(SK_ColorRED);
1768 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1769 for (size_t i = 0; i < boxes.size(); ++i) {
1770 canvas.get()->drawRect(boxes[i].rect, paint);
1771 }
1772 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1773}
1774
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001775DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001776 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001777 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001778 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001779 const char* text1 = "This text should be";
1780 const char* text2 = " decorated even when";
1781 const char* text3 = " wrapped around to";
1782 const char* text4 = " the next line.";
1783 const char* text5 = " Otherwise, bad things happen.";
1784
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001785 ParagraphStyle paragraph_style;
1786 paragraph_style.setMaxLines(14);
1787 paragraph_style.setTextAlign(TextAlign::kLeft);
1788 paragraph_style.turnHintingOff();
1789 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1790
1791 TextStyle text_style;
1792 text_style.setFontFamilies({SkString("Roboto")});
1793 text_style.setFontSize(26);
1794 text_style.setLetterSpacing(0);
1795 text_style.setWordSpacing(5);
1796 text_style.setColor(SK_ColorBLACK);
1797 text_style.setHeight(2);
1798 text_style.setDecoration(TextDecoration::kUnderline);
1799 text_style.setDecorationColor(SK_ColorBLACK);
1800 text_style.setDecoration((TextDecoration)(
1801 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1802 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1803 text_style.setDecorationColor(SK_ColorBLACK);
1804 text_style.setDecorationThicknessMultiplier(2.0);
1805 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001806 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001807
1808 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1809 text_style.setDecorationColor(SK_ColorBLUE);
1810 text_style.setDecorationThicknessMultiplier(1.0);
1811 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001812 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001813
1814 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1815 text_style.setDecorationColor(SK_ColorBLACK);
1816 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001817 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001818
1819 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1820 text_style.setDecorationColor(SK_ColorBLACK);
1821 text_style.setDecorationThicknessMultiplier(3.0);
1822 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001823 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001824
1825 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1826 text_style.setDecorationColor(SK_ColorRED);
1827 text_style.setDecorationThicknessMultiplier(1.0);
1828 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001829 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001830 builder.pop();
1831
1832 auto paragraph = builder.Build();
1833 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001834 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001835
1836 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001837
1838 size_t index = 0;
1839 for (auto& line : impl->lines()) {
1840 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001841 StyleType::kDecorations,
1842 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001843 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1844 TextDecoration::kOverline |
1845 TextDecoration::kLineThrough);
1846 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1847 switch (index) {
1848 case 0:
1849 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1850 TextDecorationStyle::kSolid);
1851 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1852 REPORTER_ASSERT(reporter,
1853 style.getDecorationThicknessMultiplier() == 2.0);
1854 break;
1855 case 1: // The style appears on 2 lines so it has 2 pieces
1856 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1857 TextDecorationStyle::kDouble);
1858 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1859 REPORTER_ASSERT(reporter,
1860 style.getDecorationThicknessMultiplier() == 1.0);
1861 break;
1862 case 2:
1863 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1864 TextDecorationStyle::kDotted);
1865 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1866 REPORTER_ASSERT(reporter,
1867 style.getDecorationThicknessMultiplier() == 1.0);
1868 break;
1869 case 3:
1870 case 4:
1871 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1872 TextDecorationStyle::kDashed);
1873 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1874 REPORTER_ASSERT(reporter,
1875 style.getDecorationThicknessMultiplier() == 3.0);
1876 break;
1877 case 5:
1878 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1879 TextDecorationStyle::kWavy);
1880 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1881 REPORTER_ASSERT(reporter,
1882 style.getDecorationThicknessMultiplier() == 1.0);
1883 break;
1884 default:
1885 REPORTER_ASSERT(reporter, false);
1886 break;
1887 }
1888 ++index;
1889 return true;
1890 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001891 }
1892}
1893
Julia Lavrovac2228562019-08-08 16:51:27 -04001894DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001895 SkDebugf("TODO: Add test for wavy decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001896}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001897
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001898DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001899 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001900 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001901 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001902 const char* text1 = "No italic ";
1903 const char* text2 = "Yes Italic ";
1904 const char* text3 = "No Italic again.";
1905
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001906 ParagraphStyle paragraph_style;
1907 paragraph_style.turnHintingOff();
1908 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1909
1910 TextStyle text_style;
1911 text_style.setFontFamilies({SkString("Roboto")});
1912 text_style.setFontSize(10);
1913 text_style.setColor(SK_ColorRED);
1914 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001915 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001916
1917 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1918 SkFontStyle::kItalic_Slant));
1919 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001920 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001921 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001922 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001923
1924 auto paragraph = builder.Build();
1925 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001926 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001927
1928 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001929
1930 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1931 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1932 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1933 auto& line = impl->lines()[0];
1934 size_t index = 0;
1935 line.scanStyles(
1936 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001937 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001938 switch (index) {
1939 case 0:
1940 REPORTER_ASSERT(
1941 reporter,
1942 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1943 break;
1944 case 1:
1945 REPORTER_ASSERT(reporter,
1946 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1947 break;
1948 case 2:
1949 REPORTER_ASSERT(
1950 reporter,
1951 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1952 break;
1953 default:
1954 REPORTER_ASSERT(reporter, false);
1955 break;
1956 }
1957 ++index;
1958 return true;
1959 });
1960}
1961
1962DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001963 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001964 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001965 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001966 const char* text =
1967 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1968 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1969 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1970 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1971 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001972 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001973
1974 ParagraphStyle paragraph_style;
1975 paragraph_style.setMaxLines(14);
1976 paragraph_style.setTextAlign(TextAlign::kJustify);
1977 paragraph_style.turnHintingOff();
1978 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1979
1980 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
1981 TextDecoration::kLineThrough);
1982
1983 TextStyle text_style;
1984 text_style.setFontFamilies({SkString("Source Han Serif CN")});
1985 text_style.setFontSize(35);
1986 text_style.setColor(SK_ColorBLACK);
1987 text_style.setLetterSpacing(2);
1988 text_style.setHeight(1);
1989 text_style.setDecoration(decoration);
1990 text_style.setDecorationColor(SK_ColorBLACK);
1991 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1992 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001993 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001994 builder.pop();
1995
1996 auto paragraph = builder.Build();
1997 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001998 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001999
Julia Lavrova3281b962019-12-02 11:32:25 -05002000 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2001
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002002 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002003
2004 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2005 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
2006 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002007 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002008}
2009
Julia Lavrovad3a32c52020-02-03 09:43:52 -05002010// Checked: disabled for TxtLib
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002011DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002012 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002013 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002014 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002015 const char* text =
2016 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2017 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002018 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002019
2020 ParagraphStyle paragraph_style;
2021 paragraph_style.setMaxLines(14);
2022 paragraph_style.setTextAlign(TextAlign::kJustify);
2023 paragraph_style.turnHintingOff();
2024 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2025
2026 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2027 TextDecoration::kLineThrough);
2028
2029 TextStyle text_style;
2030 text_style.setFontFamilies({SkString("Katibeh")});
2031 text_style.setFontSize(35);
2032 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002033 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002034 text_style.setDecoration(decoration);
2035 text_style.setDecorationColor(SK_ColorBLACK);
2036 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2037 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002038 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002039 builder.pop();
2040
2041 auto paragraph = builder.Build();
2042 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002043 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002044
Julia Lavrova3281b962019-12-02 11:32:25 -05002045 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2046
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002047 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002048
2049 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2050 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2051 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002052 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002053}
2054
Julia Lavrovac2228562019-08-08 16:51:27 -04002055// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002056DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
2057
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002058 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002059 if (!fontCollection->fontsFound()) return;
2060 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
2061 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002062 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002063
2064 ParagraphStyle paragraph_style;
2065 paragraph_style.turnHintingOff();
2066 paragraph_style.setMaxLines(14);
2067 paragraph_style.setTextAlign(TextAlign::kRight);
2068 paragraph_style.setTextDirection(TextDirection::kRtl);
2069 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2070
2071 TextStyle text_style;
2072 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2073 text_style.setFontSize(26);
2074 text_style.setWordSpacing(5);
2075 text_style.setColor(SK_ColorBLACK);
2076 text_style.setDecoration(TextDecoration::kUnderline);
2077 text_style.setDecorationColor(SK_ColorBLACK);
2078 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002079 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002080 builder.pop();
2081
2082 auto paragraph = builder.Build();
2083 paragraph->layout(TestCanvasWidth - 100);
2084
2085 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2086 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2087
2088 paragraph->paint(canvas.get(), 0, 0);
2089
2090 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2091 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2092 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
2093 canvas.drawRects(SK_ColorRED, boxes);
2094
Julia Lavrovac2228562019-08-08 16:51:27 -04002095 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002096
Julia Lavrovac2228562019-08-08 16:51:27 -04002097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
2098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
2100 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002101}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002102
2103// Checked DIFF+
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002104// This test shows now 2 boxes for [36:40) range:
2105// [36:38) for arabic text and [38:39) for the last space
2106// that has default paragraph direction (LTR) and is placed at the end of the paragraph
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002107DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
2108
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002109 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002110 if (!fontCollection->fontsFound()) return;
2111 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
2112 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002113 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002114
2115 ParagraphStyle paragraph_style;
2116 paragraph_style.turnHintingOff();
2117 paragraph_style.setMaxLines(14);
2118 paragraph_style.setTextAlign(TextAlign::kLeft);
2119 paragraph_style.setTextDirection(TextDirection::kLtr);
2120 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2121
2122 TextStyle text_style;
2123 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2124 text_style.setFontSize(26);
2125 text_style.setWordSpacing(5);
2126 text_style.setColor(SK_ColorBLACK);
2127 text_style.setDecoration(TextDecoration::kUnderline);
2128 text_style.setDecorationColor(SK_ColorBLACK);
2129 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002130 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002131 builder.pop();
2132
2133 auto paragraph = builder.Build();
2134 paragraph->layout(TestCanvasWidth - 100);
2135
2136 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2137 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2138
2139 paragraph->paint(canvas.get(), 0, 0);
2140
2141 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2142 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002143 // 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 -04002144 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2145 canvas.drawRects(SK_ColorRED, boxes);
2146
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002147 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
2148 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.92f, EPSILON100)); // DIFF: 89.40625
2149 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2150 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 110.16f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002151 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002152}
2153
2154// Checked DIFF+
2155DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2156
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002157 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002158 if (!fontCollection->fontsFound()) return;
2159 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2160 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002161 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002162
2163 ParagraphStyle paragraph_style;
2164 paragraph_style.turnHintingOff();
2165 paragraph_style.setMaxLines(14);
2166 paragraph_style.setTextAlign(TextAlign::kRight);
2167 paragraph_style.setTextDirection(TextDirection::kLtr);
2168 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2169
2170 TextStyle text_style;
2171 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2172 text_style.setFontSize(26);
2173 text_style.setWordSpacing(5);
2174 text_style.setColor(SK_ColorBLACK);
2175 text_style.setDecoration(TextDecoration::kUnderline);
2176 text_style.setDecorationColor(SK_ColorBLACK);
2177 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002178 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002179 builder.pop();
2180
2181 auto paragraph = builder.Build();
2182 paragraph->layout(TestCanvasWidth - 100);
2183
2184 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2185 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2186
2187 paragraph->paint(canvas.get(), 0, 0);
2188
2189 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2190 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2191 std::vector<TextBox> boxes =
2192 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2193 canvas.drawRects(SK_ColorRED, boxes);
2194
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002195 REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF
2196 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.5f, EPSILON100)); // DIFF
2197 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2198 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 587.74f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002199 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002200}
2201
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002202DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002203 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002204 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002205 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002206 const char* text =
2207 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2208 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002209 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002210
2211 ParagraphStyle paragraphStyle;
2212 paragraphStyle.setTextAlign(TextAlign::kLeft);
2213 paragraphStyle.setMaxLines(10);
2214 paragraphStyle.turnHintingOff();
2215 TextStyle textStyle;
2216 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002217 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2218 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002219 textStyle.setFontSize(50);
2220 textStyle.setLetterSpacing(1);
2221 textStyle.setWordSpacing(5);
2222 textStyle.setHeight(1);
2223 textStyle.setColor(SK_ColorBLACK);
2224
2225 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2226 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002227 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002228 builder.pop();
2229
2230 auto paragraph = builder.Build();
2231 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002232 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002233
2234 // Tests for getGlyphPositionAtCoordinate()
2235 // NOTE: resulting values can be a few off from their respective positions in
2236 // the original text because the final trailing whitespaces are sometimes not
2237 // drawn (namely, when using "justify" alignment) and therefore are not active
2238 // glyphs.
2239 REPORTER_ASSERT(reporter,
2240 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2241 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2242 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2243 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2244 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2245 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002246 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002247 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2248 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2249 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002250 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002251 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002252 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002253 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2254 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002255 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002256 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2257 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002258 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002259 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2260 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2261 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002262 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002263 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2264}
2265
2266DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002267 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002268 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002269 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002270 const char* text =
2271 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2272 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002273 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002274
2275 ParagraphStyle paragraphStyle;
2276 paragraphStyle.setTextAlign(TextAlign::kLeft);
2277 paragraphStyle.setMaxLines(10);
2278 paragraphStyle.turnHintingOff();
2279 TextStyle textStyle;
2280 textStyle.setFontFamilies({SkString("Roboto")});
2281 textStyle.setFontSize(50);
2282 textStyle.setColor(SK_ColorBLACK);
2283 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2284 SkFontStyle::kUpright_Slant));
2285
2286 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2287 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002288 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002289 builder.pop();
2290
2291 auto paragraph = builder.Build();
2292 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002293 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002294
2295 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2296 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002297
2298 SkPaint paint;
2299 paint.setStyle(SkPaint::kStroke_Style);
2300 paint.setAntiAlias(true);
2301 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002302
2303 {
2304 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2305 REPORTER_ASSERT(reporter, result.empty());
2306 }
2307 {
2308 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002309 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002310 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002311 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2313 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2314 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002315 }
2316 {
2317 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002318 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002319 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2323 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002324 }
2325 {
2326 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002327 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002328 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002329 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2330 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002333 }
2334 {
2335 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002336 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002337 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002338 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2341 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2342 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2343 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2344 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2345 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002346 }
2347 {
2348 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002349 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002350 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002351 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002353 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002354 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002355 }
2356 {
2357 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2358 REPORTER_ASSERT(reporter, result.empty());
2359 }
2360}
2361
2362DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002363 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002364 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002365 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002366 const char* text =
2367 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2368 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2369 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002370 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002371
2372 ParagraphStyle paragraphStyle;
2373 paragraphStyle.setTextAlign(TextAlign::kLeft);
2374 paragraphStyle.setMaxLines(10);
2375 paragraphStyle.turnHintingOff();
2376 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002377 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002378 textStyle.setFontSize(50);
2379 textStyle.setColor(SK_ColorBLACK);
2380 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2381 SkFontStyle::kUpright_Slant));
2382
2383 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2384 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002385 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002386 builder.pop();
2387
2388 auto paragraph = builder.Build();
2389 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002390 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002391
2392 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2393 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002394 {
2395 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2396 REPORTER_ASSERT(reporter, result.empty());
2397 }
2398 {
2399 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002400 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002401 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002402 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2403 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2404 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002406 }
2407 {
2408 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002409 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002410 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002411 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2413 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002415 }
2416 {
2417 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002418 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002419 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002420 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2421 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2423 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002424 }
2425}
2426
Julia Lavrovac2228562019-08-08 16:51:27 -04002427// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002428DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002429 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002430 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002431 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002432 const char* text =
2433 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2434 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2435 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002436 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002437
2438 ParagraphStyle paragraphStyle;
2439 paragraphStyle.setTextAlign(TextAlign::kLeft);
2440 paragraphStyle.setMaxLines(10);
2441 paragraphStyle.turnHintingOff();
2442 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002443 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002444 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002445 textStyle.setHeight(1.6f);
2446 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002447 textStyle.setColor(SK_ColorBLACK);
2448 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2449 SkFontStyle::kUpright_Slant));
2450
2451 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2452 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002453 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002454 builder.pop();
2455
2456 auto paragraph = builder.Build();
2457 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002458 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002459
2460 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002461 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002462 {
2463 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2464 REPORTER_ASSERT(reporter, result.empty());
2465 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002466
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002467 {
2468 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002469 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002470 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002471 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2472 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2473 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2474 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002475 }
2476 {
2477 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002478 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002479 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002480 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2481 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2482 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2483 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002484 }
2485 {
2486 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002487 canvas.drawRects(SK_ColorGREEN, result);
2488 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002489 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002490 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002491 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002492 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002493 }
2494 {
2495 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002496 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002497 REPORTER_ASSERT(reporter, result.size() == 8);
2498
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002499 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002500 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2501 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2503
2504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2506 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2508
2509 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002511 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002512 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2513
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002514 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2518
2519 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2520 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2521 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2522 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2523
2524 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2525 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2526 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2527 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002528 }
2529 {
2530 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002531 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002532 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002536 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2537
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002538 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002539 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2540 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2541 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002542 }
2543 {
2544 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2545 REPORTER_ASSERT(reporter, result.empty());
2546 }
2547}
2548
Julia Lavrovac2228562019-08-08 16:51:27 -04002549// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002550DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002551 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002552 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002553 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002554 const char* text =
2555 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2556 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2557 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002558 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002559
2560 ParagraphStyle paragraphStyle;
2561 paragraphStyle.setTextAlign(TextAlign::kLeft);
2562 paragraphStyle.setMaxLines(10);
2563 paragraphStyle.turnHintingOff();
2564 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002565 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002566 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002567 textStyle.setHeight(1.6f);
2568 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002569 textStyle.setColor(SK_ColorBLACK);
2570 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2571 SkFontStyle::kUpright_Slant));
2572
2573 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2574 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002575 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002576 builder.pop();
2577
2578 auto paragraph = builder.Build();
2579 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002580 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002581
2582 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002583 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002584 {
2585 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2586 REPORTER_ASSERT(reporter, result.empty());
2587 }
2588
2589 {
2590 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002591 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002592 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002593 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2594 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2595 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2596 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002597 }
2598 {
2599 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002600 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002601 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002602 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2603 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2604 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2605 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002606 }
2607 {
2608 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002609 canvas.drawRects(SK_ColorGREEN, result);
2610 REPORTER_ASSERT(reporter, result.size() == 1);
2611 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2612 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2613 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2614 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002615 }
2616 {
2617 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002618 canvas.drawRects(SK_ColorMAGENTA, result);
2619 REPORTER_ASSERT(reporter, result.size() == 8);
2620
2621 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2622 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2623 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2625
2626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2627 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2628 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2629 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2630
2631 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2632 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2633 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2634 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2635
2636 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2637 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2638 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2639 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2640
2641 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2643 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2644 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2645
2646 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002650 }
2651 {
2652 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002653 canvas.drawRects(SK_ColorBLACK, result);
2654 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2659
2660 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2661 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2662 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2663 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002664 }
2665 {
2666 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2667 REPORTER_ASSERT(reporter, result.empty());
2668 }
2669}
2670
Julia Lavrovac2228562019-08-08 16:51:27 -04002671// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002672DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002673 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002674 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002675 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002676 const char* text =
2677 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2678 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2679 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002680 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002681
2682 ParagraphStyle paragraphStyle;
2683 paragraphStyle.setTextAlign(TextAlign::kLeft);
2684 paragraphStyle.setMaxLines(10);
2685 paragraphStyle.turnHintingOff();
2686 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002687 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002688 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002689 textStyle.setHeight(1.6f);
2690 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002691 textStyle.setColor(SK_ColorBLACK);
2692 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2693 SkFontStyle::kUpright_Slant));
2694
2695 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2696 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002697 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002698 builder.pop();
2699
2700 auto paragraph = builder.Build();
2701 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002702 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002703
2704 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002705 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002706 {
2707 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2708 REPORTER_ASSERT(reporter, result.empty());
2709 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002710
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002711 {
2712 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002713 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002714 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002715 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2716 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2717 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2718 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002719 }
2720 {
2721 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002722 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002723 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002724 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2725 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2726 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2727 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002728 }
2729 {
2730 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002731 canvas.drawRects(SK_ColorGREEN, result);
2732 REPORTER_ASSERT(reporter, result.size() == 1);
2733 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2734 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2735 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
2736 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002737 }
2738 {
2739 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002740 canvas.drawRects(SK_ColorMAGENTA, result);
2741 REPORTER_ASSERT(reporter, result.size() == 8);
2742
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002743 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002744 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2745 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2746 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2747
2748 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2749 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2750 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2751 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2752
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002753 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002754 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2755 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2756 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2757
2758 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2759 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2760 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2761 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2762
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002763 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002764 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2765 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2766 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2767
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002768 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002769 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2770 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2771 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002772 }
2773 {
2774 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002775 canvas.drawRects(SK_ColorBLACK, result);
2776 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002777 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002778 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002780 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2781
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002782 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002783 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2784 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2785 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002786 }
2787 {
2788 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2789 REPORTER_ASSERT(reporter, result.empty());
2790 }
2791}
2792
Julia Lavrovac2228562019-08-08 16:51:27 -04002793// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002794DEF_TEST(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002795 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002796 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002797 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002798 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002799 const size_t len = strlen(text);
2800
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002801 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002802 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002803 paragraphStyle.setMaxLines(10);
2804 paragraphStyle.turnHintingOff();
2805 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2806
2807 TextStyle textStyle;
2808 textStyle.setFontFamilies({SkString("Roboto")});
2809 textStyle.setFontSize(50);
2810 textStyle.setLetterSpacing(1);
2811 textStyle.setWordSpacing(5);
2812 textStyle.setHeight(1);
2813 textStyle.setColor(SK_ColorBLACK);
2814
2815 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002816 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002817 builder.pop();
2818
2819 auto paragraph = builder.Build();
2820 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002821 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002822
2823 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002824 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2825
2826 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2827 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2828 {
2829 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2830 REPORTER_ASSERT(reporter, result.empty());
2831 }
2832 {
2833 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2834 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2835 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002836 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2837 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002838 }
2839 {
2840 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2841 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2842 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002843 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2844 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002845 }
2846 {
2847 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2848 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2849 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2850 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002851 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002852 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002853 }
2854}
2855
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002856// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002857DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002858 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002859 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002860 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002861 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2862 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2863 // Any attempt to substitute one for another leads to errors
2864 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002865 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002866 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002867
2868 ParagraphStyle paragraphStyle;
2869 paragraphStyle.setTextAlign(TextAlign::kCenter);
2870 paragraphStyle.setMaxLines(10);
2871 paragraphStyle.turnHintingOff();
2872 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2873
2874 TextStyle textStyle;
2875 textStyle.setFontFamilies({SkString("Roboto")});
2876 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002877 textStyle.setHeight(1);
2878 textStyle.setColor(SK_ColorBLACK);
2879 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2880 SkFontStyle::kUpright_Slant));
2881
2882 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002883 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002884 builder.pop();
2885
2886 auto paragraph = builder.Build();
2887 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002888 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002889
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002890 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002891 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2892 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002893 {
2894 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2895 REPORTER_ASSERT(reporter, result.empty());
2896 }
2897
2898 {
2899 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002900 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002901 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002902 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2903 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2904 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2905 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002906 }
2907
2908 {
2909 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002910 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002911 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002912 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2913 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2914 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2915 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002916 }
2917
2918 {
2919 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002920 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002921 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002922 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2923 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2924 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2925 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002926 }
2927
2928 {
2929 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002930 canvas.drawRects(SK_ColorBLACK, result);
2931 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2932 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2933 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002936 }
2937
2938 {
2939 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002940 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002941 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002942 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2943 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2944 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2945 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002946 }
2947
2948 {
2949 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2950 REPORTER_ASSERT(reporter, result.empty());
2951 }
2952}
2953
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002954// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002955DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002956 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002957 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002958 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002959 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002960 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002961
2962 ParagraphStyle paragraphStyle;
2963 paragraphStyle.setTextAlign(TextAlign::kCenter);
2964 paragraphStyle.setMaxLines(10);
2965 paragraphStyle.turnHintingOff();
2966 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2967
2968 TextStyle textStyle;
2969 textStyle.setFontFamilies({SkString("Roboto")});
2970 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002971 textStyle.setHeight(1);
2972 textStyle.setColor(SK_ColorBLACK);
2973 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2974 SkFontStyle::kUpright_Slant));
2975
2976 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002977 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002978 builder.pop();
2979
2980 auto paragraph = builder.Build();
2981 paragraph->layout(550);
2982
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002983 paragraph->paint(canvas.get(), 0, 0);
2984
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002985 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002986 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2987
2988 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2989 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002990 {
2991 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2992 REPORTER_ASSERT(reporter, result.empty());
2993 }
2994
2995 {
2996 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04002997 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002998 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002999 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
3000 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
3001 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
3002 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003003 }
3004
3005 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003006 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3007 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003008 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003009 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3010 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3011 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3012 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003013 }
3014}
3015
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003016// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003017DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003018 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003019 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003020 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3021 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003022 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003023
3024 ParagraphStyle paragraphStyle;
3025 paragraphStyle.setTextAlign(TextAlign::kCenter);
3026 paragraphStyle.setMaxLines(10);
3027 paragraphStyle.turnHintingOff();
3028 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3029
3030 TextStyle textStyle;
3031 textStyle.setFontFamilies({SkString("Roboto")});
3032 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003033 textStyle.setHeight(1);
3034 textStyle.setColor(SK_ColorBLACK);
3035 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3036 SkFontStyle::kUpright_Slant));
3037
3038 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003039 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003040 builder.pop();
3041
3042 auto paragraph = builder.Build();
3043 paragraph->layout(550);
3044
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003045 paragraph->paint(canvas.get(), 0, 0);
3046
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003047 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003048
3049 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3050
3051 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3052 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3053 SkScalar epsilon = 0.01f;
3054 {
3055 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3056 REPORTER_ASSERT(reporter, result.empty());
3057 }
3058 {
3059 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003060 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003061 REPORTER_ASSERT(reporter, result.size() == 1);
3062 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3063 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3064 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3065 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3066 }
3067 {
3068 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003069 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003070 REPORTER_ASSERT(reporter, result.size() == 1);
3071 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3072 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3073 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3074 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3075 }
3076 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003077 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003078 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003079 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003080 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3081 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003082 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003083 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3084 }
3085 {
3086 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003087 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003088 REPORTER_ASSERT(reporter, result.size() == 1);
3089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3093 }
3094 {
3095 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003096 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003097 REPORTER_ASSERT(reporter, result.size() == 1);
3098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3100 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3101 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3102 }
3103 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003104 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003105 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003106 REPORTER_ASSERT(reporter, result.size() == 1);
3107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3111 }
3112 {
3113 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3114 REPORTER_ASSERT(reporter, result.empty());
3115 }
3116}
3117
Julia Lavrovac2228562019-08-08 16:51:27 -04003118// Checked: DIFF (line height rounding error)
3119DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003120 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003121 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003122 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3123 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003124 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003125
3126 StrutStyle strutStyle;
3127 strutStyle.setStrutEnabled(true);
3128 strutStyle.setFontFamilies({SkString("Roboto")});
3129 strutStyle.setFontSize(14.0);
3130
3131 ParagraphStyle paragraphStyle;
3132 paragraphStyle.setStrutStyle(strutStyle);
3133
3134 TextStyle textStyle;
3135 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3136 textStyle.setFontSize(20);
3137 textStyle.setColor(SK_ColorBLACK);
3138
3139 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3140 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003141 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003142 builder.pop();
3143
3144 auto paragraph = builder.Build();
3145 paragraph->layout(550);
3146 paragraph->paint(canvas.get(), 0, 0);
3147
3148 {
3149 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3150 canvas.drawRects(SK_ColorGREEN, result);
3151 REPORTER_ASSERT(reporter, result.size() == 1);
3152 }
3153
3154 {
3155 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3156 canvas.drawRects(SK_ColorRED, result);
3157 REPORTER_ASSERT(reporter, result.size() == 1);
3158 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3159 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3160 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3161 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3162 }
3163}
3164
3165// Checked: NO DIFF
3166DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003167 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003168 if (!fontCollection->fontsFound()) return;
3169 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3170 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003171 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003172
3173 StrutStyle strutStyle;
3174 strutStyle.setStrutEnabled(false);
3175
3176 ParagraphStyle paragraphStyle;
3177 paragraphStyle.setStrutStyle(strutStyle);
3178
3179 TextStyle textStyle;
3180 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3181 textStyle.setFontSize(20);
3182 textStyle.setColor(SK_ColorBLACK);
3183
3184 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3185 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003186 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003187 builder.pop();
3188
3189 auto paragraph = builder.Build();
3190 paragraph->layout(550);
3191 paragraph->paint(canvas.get(), 0, 0);
3192
3193
3194 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3195 canvas.drawRects(SK_ColorGREEN, result1);
3196 REPORTER_ASSERT(reporter, result1.size() == 1);
3197
3198 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3199 canvas.drawRects(SK_ColorRED, result2);
3200 REPORTER_ASSERT(reporter, result2.size() == 1);
3201
3202 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3203}
3204
3205// Checked: DIFF (small in numbers)
3206DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003207 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003208 if (!fontCollection->fontsFound()) return;
3209 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003210 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3211 "67890 12345 67890 12345 67890 12345";
3212 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003213 ParagraphStyle paragraphStyle;
3214 paragraphStyle.setTextAlign(TextAlign::kLeft);
3215 paragraphStyle.setMaxLines(10);
3216 paragraphStyle.turnHintingOff();
3217 TextStyle textStyle;
3218 textStyle.setFontFamilies({SkString("Roboto")});
3219 textStyle.setFontSize(52);
3220 textStyle.setLetterSpacing(1.19039f);
3221 textStyle.setWordSpacing(5);
3222 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003223 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003224 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003225
3226 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3227 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003228 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003229 builder.pop();
3230
3231 auto paragraph = builder.Build();
3232 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003233 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003234
3235 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3236 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3237 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3238 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3239 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003240 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3241 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003242
3243 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003244 boxes = paragraph->getRectsForRange(6, 7, 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 Lavrovac2228562019-08-08 16:51:27 -04003247 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003248 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003249 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003250
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003251 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3252 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3253 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3254 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3255 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3256 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3257 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3258 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3259
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003260 boxes = paragraph->getRectsForRange(12, 13, 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(13, 14, 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(18, 19, 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(19, 20, 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(24, 25, 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(25, 26, 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 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003273 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003274 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003275 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003276
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003277 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3278 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003279}
3280
Julia Lavrovac2228562019-08-08 16:51:27 -04003281// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003282DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003283 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003284 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003285 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003286 ParagraphStyle paragraph_style;
3287 paragraph_style.setMaxLines(10);
3288 paragraph_style.setTextAlign(TextAlign::kLeft);
3289 paragraph_style.turnHintingOff();
3290 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3291
3292 TextStyle text_style;
3293 text_style.setFontFamilies({SkString("Roboto")});
3294 text_style.setFontSize(50);
3295 text_style.setLetterSpacing(20);
3296 text_style.setWordSpacing(0);
3297 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003298 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003299 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003300 builder.pop();
3301
3302 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003303 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003304 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003305 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003306 builder.pop();
3307
3308 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003309 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003310 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003311 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003312 builder.pop();
3313
3314 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003315 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003316 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003317 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003318 builder.pop();
3319
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003320 const char* hSpace = "H ";
3321 const size_t len = strlen(hSpace);
3322
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003323 text_style.setLetterSpacing(0);
3324 text_style.setWordSpacing(20);
3325 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003326 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003327 builder.pop();
3328
3329 text_style.setLetterSpacing(0);
3330 text_style.setWordSpacing(0);
3331 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003332 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003333 builder.pop();
3334
3335 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003336 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003337 text_style.setWordSpacing(20);
3338 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003339 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003340 builder.pop();
3341
3342 auto paragraph = builder.Build();
3343 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003344 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003345
3346 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3347 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3348 size_t index = 0;
3349 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003350 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3351 ++index;
3352 return true;
3353 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003354 REPORTER_ASSERT(reporter, index == 4);
3355 index = 0;
3356 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003357 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3358 ++index;
3359 return true;
3360 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003361 REPORTER_ASSERT(reporter, index == 4);
3362}
3363
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003364// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003365DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003366 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003367 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003368 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003369 const char* text =
3370 "A "
3371 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3372 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003373 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003374
3375 ParagraphStyle paragraph_style;
3376 paragraph_style.turnHintingOff();
3377 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3378
3379 TextStyle text_style;
3380 text_style.setFontFamilies({SkString("Roboto")});
3381 text_style.setColor(SK_ColorRED);
3382 text_style.setFontSize(31);
3383 text_style.setLetterSpacing(0);
3384 text_style.setWordSpacing(0);
3385 text_style.setColor(SK_ColorBLACK);
3386 text_style.setHeight(1);
3387 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003388 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003389 builder.pop();
3390
3391 auto paragraph = builder.Build();
3392 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003393 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003394
3395 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3396 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3397 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3398 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003399 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003400 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3401
3402 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3403 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3404 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3405}
3406
Julia Lavrovac2228562019-08-08 16:51:27 -04003407// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003408DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003409 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003410 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003411 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3412
3413 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3414 const char* text2 = " Dialog Text List lots of words to see "
3415 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003416 float scale = 3.0f;
3417 ParagraphStyle paragraph_style;
3418 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3419 TextStyle text_style;
3420 text_style.setFontFamilies({SkString("Droid Serif")});
3421 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003422 text_style.setColor(SK_ColorBLACK);
3423
3424 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003425 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003426 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003427 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003428 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003429 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003430 text_style.setFontSize(14 / scale);
3431 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003432 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003433 builder.pop();
3434
3435 auto paragraph = builder.Build();
3436 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003437 canvas.get()->scale(scale, scale);
3438 paragraph->paint(canvas.get(), 0, 0);
3439 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003440
3441 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003442
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003443 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003444 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003445 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3446 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3447 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3448 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3449 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3450 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003451}
3452
Julia Lavrovac2228562019-08-08 16:51:27 -04003453// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003454DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003455 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003456 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003457 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003458 const char* text =
3459 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3460 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003461 const size_t len = strlen(text);
3462
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003463 ParagraphStyle paragraph_style;
3464 paragraph_style.turnHintingOff();
3465 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3466
3467 TextStyle text_style;
3468 text_style.setFontFamilies({SkString("Roboto")});
3469 text_style.setColor(SK_ColorRED);
3470 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003471 text_style.setColor(SK_ColorBLACK);
3472 text_style.setHeight(1);
3473 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003474 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003475 builder.pop();
3476
3477 auto paragraph = builder.Build();
3478 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003479 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003480
3481 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3482 // Minikin does not count empty lines but SkParagraph does
3483 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3484
3485 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3486 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3487 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3488 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3489 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003490 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3491 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003492}
3493
Julia Lavrova526df262019-08-21 17:49:44 -04003494// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003495DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003496 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003497 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003498 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3499 const char* text =
3500 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3501 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3502 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3503 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003504 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003505
3506 ParagraphStyle paragraph_style;
3507 paragraph_style.turnHintingOff();
3508 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3509
3510 TextStyle text_style;
3511 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3512 text_style.setFontSize(50);
3513 text_style.setDecoration(TextDecoration::kUnderline);
3514 text_style.setColor(SK_ColorBLACK);
3515 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003516 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003517 builder.pop();
3518
3519 auto paragraph = builder.Build();
3520 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003521 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003522
Julia Lavrova3281b962019-12-02 11:32:25 -05003523 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3524
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003525 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003526
3527 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3528 for (auto& line : impl->lines()) {
3529 if (&line != impl->lines().end() - 1) {
3530 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3531 } else {
3532 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3533 }
3534 REPORTER_ASSERT(reporter, line.height() == 59);
3535 }
3536}
3537
Julia Lavrovac2228562019-08-08 16:51:27 -04003538// Checked: DIFF+
3539DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003540 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003541 if (!fontCollection->fontsFound()) return;
3542 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3543 const char* text =
3544 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3545 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3546 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3547 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3548 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3549 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003550 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003551
3552 ParagraphStyle paragraph_style;
3553 paragraph_style.turnHintingOff();
3554 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3555
3556 TextStyle text_style;
3557 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3558 text_style.setFontSize(50);
3559 text_style.setColor(SK_ColorBLACK);
3560 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003561 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003562 builder.pop();
3563
3564 auto paragraph = builder.Build();
3565 paragraph->layout(TestCanvasWidth - 300);
3566 paragraph->paint(canvas.get(), 0, 0);
3567
3568 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3569 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3570
3571 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3572 REPORTER_ASSERT(reporter, result.size() == 0);
3573
3574 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3575 REPORTER_ASSERT(reporter, result.size() == 2);
3576 canvas.drawRects(SK_ColorRED, result);
3577
3578 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003579 REPORTER_ASSERT(reporter, result.size() == 0); // There is no single glyph
Julia Lavrovac2228562019-08-08 16:51:27 -04003580 canvas.drawRects(SK_ColorBLUE, result);
3581
3582 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3583 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3584 REPORTER_ASSERT(reporter, result.size() == 2);
3585 canvas.drawRects(SK_ColorGREEN, result);
3586
3587 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3588 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3589 REPORTER_ASSERT(reporter, result.size() == 2);
3590 canvas.drawRects(SK_ColorGREEN, result);
3591
3592 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3593 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3594 REPORTER_ASSERT(reporter, result.size() == 2);
3595 canvas.drawRects(SK_ColorGREEN, result);
3596}
3597
Julia Lavrova916a9042019-08-08 16:51:27 -04003598DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3599 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3600}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003601
Julia Lavrovac2228562019-08-08 16:51:27 -04003602// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003603DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003604 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003605 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003606 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003607 const char* text =
3608 "Sentence to layout at diff widths to get diff line counts. short words "
3609 "short words short words short words short words short words short words "
3610 "short words short words short words short words short words short words "
3611 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003612 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003613
3614 ParagraphStyle paragraph_style;
3615 paragraph_style.turnHintingOff();
3616 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3617
3618 TextStyle text_style;
3619 text_style.setFontFamilies({SkString("Roboto")});
3620 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003621 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003622 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003623 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003624 builder.pop();
3625
3626 auto paragraph = builder.Build();
3627 paragraph->layout(300);
3628
3629 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3630 // Some of the formatting lazily done on paint
3631 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3632 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3633 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3634
3635 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003636 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003637 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3638 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3639 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3640}
3641
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003642// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003643DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003644 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003645 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003646 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003647 const char* text =
3648 "This is a very long sentence to test if the text will properly wrap "
3649 "around and go to the next line. Sometimes, short sentence. Longer "
3650 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003651 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003652
3653 ParagraphStyle paragraph_style;
3654 paragraph_style.setMaxLines(1);
3655 paragraph_style.setEllipsis(u"\u2026");
3656 paragraph_style.turnHintingOff();
3657 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3658
3659 TextStyle text_style;
3660 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003661 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003662 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003663 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003664 builder.pop();
3665
3666 auto paragraph = builder.Build();
3667 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003668 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003669
3670 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003671
3672 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3673 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3674
3675 auto& line = impl->lines()[0];
3676 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003677 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003678}
3679
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003680// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003681DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003682 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003683 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003684 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003685 const char* text1 = "fluttser ";
3686 const char* text2 = "mdje";
3687 const char* text3 = "fluttser mdje";
3688
3689 ParagraphStyle paragraph_style;
3690 paragraph_style.turnHintingOff();
3691 paragraph_style.setTextAlign(TextAlign::kLeft);
3692 paragraph_style.setMaxLines(2);
3693 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3694
3695 TextStyle text_style;
3696 text_style.setFontFamilies({SkString("Roboto")});
3697 text_style.setColor(SK_ColorBLACK);
3698 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003699 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003700 text_style.setDecoration(TextDecoration::kUnderline);
3701 text_style.setDecorationColor(SK_ColorBLACK);
3702 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003703 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003704 builder.pop();
3705
3706 auto paragraph = builder.Build();
3707 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003708 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003709
3710 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3711
3712 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3713 text_style.setDecoration(TextDecoration::kNoDecoration);
3714 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003715 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003716 builder1.pop();
3717
3718 auto paragraph1 = builder1.Build();
3719 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003720 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003721
3722 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3723
3724 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3725 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003726
3727 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3728 .front()
3729 .rect;
3730 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3731 .front()
3732 .rect;
3733 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3734 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3735
3736 for (size_t i = 0; i < 12; ++i) {
3737 auto r =
3738 paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
3739 .front()
3740 .rect;
3741 auto r1 =
3742 paragraph1
3743 ->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
3744 .front()
3745 .rect;
3746
3747 REPORTER_ASSERT(reporter, r.fLeft == r1.fLeft);
3748 REPORTER_ASSERT(reporter, r.fRight == r1.fRight);
3749 }
3750}
3751
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003752// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003753DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003754 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003755 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003756 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003757 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003758 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003759
3760 ParagraphStyle paragraph_style;
3761 paragraph_style.turnHintingOff();
3762 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3763
3764 TextStyle text_style;
3765 text_style.setFontFamilies({SkString("Roboto")});
3766 text_style.setColor(SK_ColorBLACK);
3767 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3768 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003769 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003770
3771 auto paragraph = builder.Build();
3772 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003773 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003774
3775 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3776
3777 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3778 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3779 size_t index = 0;
3780 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003781 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003782 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003783 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3784 ++index;
3785 return true;
3786 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003787 }
3788}
3789
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003790// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003791DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003792 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003793 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003794 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003795 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003796 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003797
3798 ParagraphStyle paragraph_style;
3799 paragraph_style.turnHintingOff();
3800 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3801
3802 TextStyle text_style;
3803 text_style.setFontFamilies({SkString("Roboto")});
3804 text_style.setColor(SK_ColorBLACK);
3805 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3806 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003807 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003808
3809 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3810 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.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 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3818 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003819 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003820 builder.pop();
3821
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003822 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003823
3824 auto paragraph = builder.Build();
3825 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003826 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003827
3828 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3829
3830 size_t index = 0;
3831 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003832 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003833 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003834 ++index;
3835 switch (index) {
3836 case 1:
3837 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3838 break;
3839 case 2:
3840 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3841 break;
3842 case 3:
3843 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3844 break;
3845 case 4:
3846 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3847 REPORTER_ASSERT(reporter, style.equals(text_style));
3848 break;
3849 case 5:
3850 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3851 break;
3852 default:
3853 REPORTER_ASSERT(reporter, false);
3854 }
3855 return true;
3856 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003857 }
3858}
3859
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003860// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003861DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003862 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003863 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003864 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003865 const char* text =
3866 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3867 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003868 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003869
3870 ParagraphStyle paragraph_style;
3871 paragraph_style.turnHintingOff();
3872 paragraph_style.setMaxLines(14);
3873 paragraph_style.setTextAlign(TextAlign::kJustify);
3874 paragraph_style.setHeight(1.5);
3875 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3876
3877 TextStyle text_style;
3878 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3879 text_style.setColor(SK_ColorBLACK);
3880 text_style.setFontSize(55);
3881 text_style.setLetterSpacing(2);
3882 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3883 text_style.setDecorationColor(SK_ColorBLACK);
3884 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003885 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003886 builder.pop();
3887
3888 auto paragraph = builder.Build();
3889 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003890 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003892 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3893 paragraph->getMaxWidth(),
3894 paragraph->getIdeographicBaseline());
3895 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3896 paragraph->getMaxWidth(),
3897 paragraph->getAlphabeticBaseline());
3898 canvas.drawLine(SK_ColorRED, rect1, false);
3899 canvas.drawLine(SK_ColorGREEN, rect2, false);
3900
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003901 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003902 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003903 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003904 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003905}
3906
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003907// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003908DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003909 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003910 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003911 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003912
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003913 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3914 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3915 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003916
3917 ParagraphStyle paragraph_style;
3918 paragraph_style.turnHintingOff();
3919 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3920
3921 TextStyle text_style;
3922 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003923 SkString("Not a real font"),
3924 SkString("Also a fake font"),
3925 SkString("So fake it is obvious"),
3926 SkString("Next one should be a real font..."),
3927 SkString("Roboto"),
3928 SkString("another fake one in between"),
3929 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003930 });
3931 text_style.setColor(SK_ColorBLACK);
3932 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003933 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003934
3935 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003936 SkString("Not a real font"),
3937 SkString("Also a fake font"),
3938 SkString("So fake it is obvious"),
3939 SkString("Homemade Apple"),
3940 SkString("Next one should be a real font..."),
3941 SkString("Roboto"),
3942 SkString("another fake one in between"),
3943 SkString("Noto Sans CJK JP"),
3944 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003945 });
3946 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003947 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003948
3949 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003950 SkString("Not a real font"),
3951 SkString("Also a fake font"),
3952 SkString("So fake it is obvious"),
3953 SkString("Homemade Apple"),
3954 SkString("Next one should be a real font..."),
3955 SkString("Roboto"),
3956 SkString("another fake one in between"),
3957 SkString("Source Han Serif CN"),
3958 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003959 });
3960 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003961 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003962
3963 builder.pop();
3964
3965 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003966 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003967 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003968 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003969
Julia Lavrova3281b962019-12-02 11:32:25 -05003970 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
3971
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003972 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3973
3974 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3975 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3976 // [Apple + Noto] [Apple + Han]
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003977 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003978
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003979 auto robotoAdvance = impl->runs()[0].advance().fX +
3980 impl->runs()[1].advance().fX +
3981 impl->runs()[2].advance().fX;
3982 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
3983 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
3984 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
3985 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
3986 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003987
3988 // When a different font is resolved, then the metrics are different.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003989 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
3990 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003991}
3992
Julia Lavrovac2228562019-08-08 16:51:27 -04003993// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003994DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003995 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003996 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003997 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003998 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003999 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004000 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004001
4002 ParagraphStyle paragraph_style;
4003 paragraph_style.setMaxLines(10);
4004 paragraph_style.setTextAlign(TextAlign::kLeft);
4005 paragraph_style.turnHintingOff();
4006
4007 StrutStyle strut_style;
4008 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004009 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004010 strut_style.setFontSize(50);
4011 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004012 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004013 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004014 paragraph_style.setStrutStyle(strut_style);
4015
4016 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4017
4018 TextStyle text_style;
4019 text_style.setFontFamilies({SkString("Ahem")});
4020 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004021 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004022 text_style.setColor(SK_ColorBLACK);
4023 text_style.setHeight(0.5f);
4024 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004025 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004026 builder.pop();
4027
4028 auto paragraph = builder.Build();
4029 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004030 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004031
4032 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004033 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4034
4035 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4036 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4037 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004038 {
4039 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4040 REPORTER_ASSERT(reporter, boxes.empty());
4041 }
4042 {
4043 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004044 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004045 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004046 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4047 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4048 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4049 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004050 }
4051 {
4052 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004053 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004054 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004055 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004056 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004057 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4058 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004059 }
4060 {
4061 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004062 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004063 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004064 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4065 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004066 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004067 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004068 }
4069 {
4070 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004071 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004072 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004073 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004074 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004075 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004076 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004077 }
4078 {
4079 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004080 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004081 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004082 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004083 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004084 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4085 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004086 }
4087 {
4088 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004089 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004090 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004093 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004094 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004095 }
4096}
4097
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004098// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004099DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004100 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004101 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004102 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004103 // The chinese extra height should be absorbed by the strut.
4104 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004105 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004106
4107 ParagraphStyle paragraph_style;
4108 paragraph_style.setMaxLines(10);
4109 paragraph_style.setTextAlign(TextAlign::kLeft);
4110 paragraph_style.turnHintingOff();
4111
4112 StrutStyle strut_style;
4113
4114 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004115 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004116 strut_style.setFontSize(50);
4117 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004118 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004119 paragraph_style.setStrutStyle(strut_style);
4120
4121 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4122
4123 TextStyle text_style;
4124 text_style.setFontFamilies({SkString("Ahem")});
4125 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004126 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4127 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004128 text_style.setColor(SK_ColorBLACK);
4129 text_style.setHeight(1);
4130 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004131 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004132 builder.pop();
4133
4134 auto paragraph = builder.Build();
4135 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004136 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004137
4138 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4139 // Font is not resolved and the first line does not fit
4140 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4141
4142 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4143 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4144 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004145 {
4146 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4147 REPORTER_ASSERT(reporter, boxes.empty());
4148 }
4149 {
4150 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004151 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004152 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004153 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4154 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4155 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4156 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004157 }
4158 {
4159 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004160 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004161 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004162 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004163 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004164 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4165 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004166 }
4167 {
4168 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004169 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004170 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004171 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4172 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4173 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4174 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004175 }
4176 {
4177 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004178 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004179 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004180 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004181 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004182 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4183 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004184 }
4185 {
4186 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004187 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004188 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004189 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004190 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004191 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4192 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004193 }
4194 {
4195 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004196 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004197 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004198 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004199 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004200 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4201 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004202 }
4203}
4204
Julia Lavrovac2228562019-08-08 16:51:27 -04004205// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004206DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004207 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004208 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004209 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4210
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004211 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004212 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004213 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004214
4215 ParagraphStyle paragraph_style;
4216 paragraph_style.setMaxLines(10);
4217 paragraph_style.setTextAlign(TextAlign::kLeft);
4218 paragraph_style.turnHintingOff();
4219
4220 StrutStyle strut_style;
4221 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004222 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004223 strut_style.setFontSize(50);
4224 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004225 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004226 paragraph_style.setStrutStyle(strut_style);
4227
4228 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4229
4230 TextStyle text_style;
4231 text_style.setFontFamilies({SkString("Ahem")});
4232 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004233 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4234 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004235 text_style.setColor(SK_ColorBLACK);
4236 text_style.setHeight(1);
4237 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004238 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004239 builder.pop();
4240
4241 auto paragraph = builder.Build();
4242 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004243 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004244
4245 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4246 // Font is not resolved and the first line does not fit
4247 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4248
4249 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4250 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4251 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4252 SkScalar epsilon = 0.001f;
4253 {
4254 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4255 REPORTER_ASSERT(reporter, boxes.empty());
4256 }
4257 {
4258 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004259 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004260 REPORTER_ASSERT(reporter, boxes.size() == 1);
4261 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4262 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4263 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4264 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4265 }
4266 {
4267 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004268 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004269 REPORTER_ASSERT(reporter, boxes.size() == 1);
4270 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004271 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004272 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4273 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4274 }
4275 {
4276 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004277 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004278 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004279 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4280 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004281 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004282 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4283 }
4284 {
4285 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004286 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004287 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004288 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004289 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004290 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004291 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4292 }
4293 {
4294 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004295 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004296 REPORTER_ASSERT(reporter, boxes.size() == 1);
4297 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004298 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004299 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4300 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4301 }
4302 {
4303 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004304 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004305 REPORTER_ASSERT(reporter, boxes.size() == 1);
4306 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004307 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004308 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4309 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4310 }
4311}
4312
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004313// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004314DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004315 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004316 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004317 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004318 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004319 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004320
4321 ParagraphStyle paragraph_style;
4322 paragraph_style.setMaxLines(10);
4323 paragraph_style.setTextAlign(TextAlign::kLeft);
4324 paragraph_style.turnHintingOff();
4325
4326 StrutStyle strut_style;
4327 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004328 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004329 strut_style.setFontSize(50);
4330 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004331 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004332 strut_style.setLeading(0.1f);
4333 strut_style.setForceStrutHeight(true);
4334 paragraph_style.setStrutStyle(strut_style);
4335
4336 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4337
4338 TextStyle text_style;
4339 text_style.setFontFamilies({SkString("Ahem")});
4340 text_style.setFontSize(50);
4341 text_style.setLetterSpacing(0);
4342 text_style.setColor(SK_ColorBLACK);
4343 text_style.setHeight(1);
4344 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004345 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004346 builder.pop();
4347
4348 auto paragraph = builder.Build();
4349 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004350 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004351
4352 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4353 // Font is not resolved and the first line does not fit
4354 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4355
4356 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4357 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4358 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004359
4360 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4361 REPORTER_ASSERT(reporter, boxes1.empty());
4362
4363 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004364 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004365 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004366 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4367 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4368 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4369 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004370
4371 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004372 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004373 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004374 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004375 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004376 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4377 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004378
4379 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004380 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004381 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004382 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4383 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4384 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4385 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004386
4387 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004388 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004389 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004392 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4393 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004394
4395 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004396 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004397 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4401 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004402
4403 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004404 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004405 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4409 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004410}
4411
Julia Lavrovac2228562019-08-08 16:51:27 -04004412// Checked: NO DIFF
4413DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004414 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004415 if (!fontCollection->fontsFound()) return;
4416 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4417
4418 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004419 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004420
4421 ParagraphStyle paragraph_style;
4422 paragraph_style.setMaxLines(10);
4423 paragraph_style.setTextAlign(TextAlign::kLeft);
4424 paragraph_style.turnHintingOff();
4425
4426 StrutStyle strut_style;
4427 strut_style.setStrutEnabled(true);
4428 strut_style.setFontFamilies({SkString("Ahem")});
4429 strut_style.setFontSize(50);
4430 strut_style.setHeight(1.5f);
4431 strut_style.setLeading(0.1f);
4432 strut_style.setForceStrutHeight(false);
4433 paragraph_style.setStrutStyle(strut_style);
4434
4435 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4436
4437 TextStyle text_style;
4438 text_style.setFontFamilies({SkString("Ahem")});
4439 text_style.setFontSize(20);
4440 text_style.setColor(SK_ColorBLACK);
4441 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004442 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004443 builder.pop();
4444
4445 auto paragraph = builder.Build();
4446 paragraph->layout(550);
4447 paragraph->paint(canvas.get(), 0, 0);
4448
4449 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4450 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4451 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4452 {
4453 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4454 REPORTER_ASSERT(reporter, boxes.empty());
4455 }
4456 {
4457 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4458 canvas.drawRects(SK_ColorRED, boxes);
4459 REPORTER_ASSERT(reporter, boxes.size() == 1);
4460 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4461 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4462 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4463 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4464 }
4465 {
4466 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4467 canvas.drawRects(SK_ColorRED, boxes);
4468 REPORTER_ASSERT(reporter, boxes.size() == 1);
4469 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4470 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4471 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4472 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4473 }
4474}
4475
Julia Lavrovac5313e62019-12-10 12:11:17 -05004476DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4477 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4478 if (!fontCollection->fontsFound()) return;
4479 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4480
4481 const char* text = "12ab\n";
4482
4483 ParagraphStyle paragraph_style;
4484 paragraph_style.turnHintingOff();
4485 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4486
4487 TextStyle text_style;
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004488 text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
Julia Lavrovac5313e62019-12-10 12:11:17 -05004489 text_style.setFontFamilies({SkString("Roboto")});
4490 text_style.setColor(SK_ColorBLACK);
4491
4492 text_style.addFontFeature(SkString("tnum"), 1);
4493 builder.pushStyle(text_style);
4494 builder.addText(text);
4495
4496 text_style.resetFontFeatures();
4497 text_style.addFontFeature(SkString("tnum"), 0);
4498 text_style.addFontFeature(SkString("pnum"), 1);
4499 builder.pushStyle(text_style);
4500 builder.addText(text);
4501
4502 builder.pop();
4503 builder.pop();
4504
4505 auto paragraph = builder.Build();
4506 paragraph->layout(TestCanvasWidth);
4507
4508 paragraph->paint(canvas.get(), 10.0, 15.0);
4509
4510 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4511 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4512
4513 auto& tnum_line = impl->lines()[0];
4514 auto& pnum_line = impl->lines()[1];
4515
4516 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4517 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4518 // Tabular numbers should have equal widths.
4519 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4520 // Proportional numbers should have variable widths.
4521 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4522 // Alphabetic characters should be unaffected.
4523 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4524}
4525
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004526// Not in Minikin
4527DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004528 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004529 if (!fontCollection->fontsFound()) return;
4530 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004531 const size_t len = strlen(text);
4532
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004533 ParagraphStyle paragraph_style;
4534 paragraph_style.turnHintingOff();
4535 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4536
4537 TextStyle text_style;
4538 text_style.setFontFamilies(
4539 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4540 text_style.setFontSize(60);
4541 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004542 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004543 builder.pop();
4544
4545 auto paragraph = builder.Build();
4546 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004547
4548 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4549
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004550 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4551 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4552 auto first = impl->runs()[i].textRange();
4553 auto next = impl->runs()[i + 1].textRange();
4554 REPORTER_ASSERT(reporter, first.end == next.start);
4555 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004556}
4557
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004558DEF_TEST(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004559 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004560 if (!fontCollection->fontsFound()) return;
4561 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004562 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004563
4564 ParagraphStyle paragraph_style;
4565 paragraph_style.turnHintingOff();
4566 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4567
4568 TextStyle text_style;
4569 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4570 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004571 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004572 builder.pop();
4573
4574 auto paragraph = builder.Build();
4575 paragraph->layout(TestCanvasWidth);
4576
4577 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4578 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004579 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004580
4581 auto cluster = 0;
4582 SkShaperJSONWriter::VisualizeClusters(
4583 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4584 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4585 if (cluster == 0) {
4586 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4587 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4588 SkASSERT(glyph1to1.size() == 1);
4589 SkASSERT(*glyph1to1.begin() == 1611);
4590 }
4591 ++cluster;
4592 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004593 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004594}
4595
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004596DEF_TEST(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004597 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004598 if (!fontCollection->fontsFound()) return;
4599 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004600 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004601
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004602 ParagraphStyle paragraph_style;
4603 paragraph_style.turnHintingOff();
4604 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4605
4606 TextStyle text_style;
4607 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4608 text_style.setColor(SK_ColorBLACK);
4609 text_style.setFontSize(50);
4610 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004611 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004612 builder.pop();
4613
4614 auto paragraph = builder.Build();
4615 paragraph->layout(TestCanvasWidth);
4616
4617 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4618 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004619
4620 auto cluster = 0;
4621 for (auto& run : impl->runs()) {
4622 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004623 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4624 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004625 [&](int codePointCount, SkSpan<const char> utf1to1,
4626 SkSpan<const SkGlyphID> glyph1to1) {
4627 if (cluster == 0) {
4628 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4629 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4630 SkASSERT(glyph1to1.size() == 3);
4631 }
4632 ++cluster;
4633 });
4634 }
4635
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004636 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004637}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004638
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004639DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004640 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004641 cache.turnOn(true);
4642 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004643 if (!fontCollection->fontsFound()) return;
4644
4645 ParagraphStyle paragraph_style;
4646 paragraph_style.turnHintingOff();
4647
4648 TextStyle text_style;
4649 text_style.setFontFamilies({SkString("Roboto")});
4650 text_style.setColor(SK_ColorBLACK);
4651
4652 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4653 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4654 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004655 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004656 builder.pop();
4657 auto paragraph = builder.Build();
4658
4659 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4660 REPORTER_ASSERT(reporter, count == cache.count());
4661 auto found = cache.findParagraph(impl);
4662 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4663 auto added = cache.updateParagraph(impl);
4664 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4665 };
4666
4667 test("text1", 0, false);
4668 test("text1", 1, true);
4669 test("text2", 1, false);
4670 test("text2", 2, true);
4671 test("text3", 2, false);
4672}
4673
4674DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004675 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004676 cache.turnOn(true);
4677 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004678 if (!fontCollection->fontsFound()) return;
4679
4680 ParagraphStyle paragraph_style;
4681 paragraph_style.turnHintingOff();
4682
4683 TextStyle text_style;
4684 text_style.setColor(SK_ColorBLACK);
4685
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004686 const char* text = "text";
4687 const size_t len = strlen(text);
4688
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004689 auto test = [&](int count, bool expectedToBeFound) {
4690 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4691 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004692 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004693 builder.pop();
4694 auto paragraph = builder.Build();
4695 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4696
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004697 REPORTER_ASSERT(reporter, count == cache.count());
4698 auto found = cache.findParagraph(impl);
4699 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4700 auto added = cache.updateParagraph(impl);
4701 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4702 };
4703
4704 text_style.setFontFamilies({SkString("Roboto")});
4705 test(0, false);
4706 test(1, true);
4707 text_style.setFontFamilies({SkString("Homemade Apple")});
4708 test(1, false);
4709 test(2, true);
4710 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4711 test(2, false);
4712}
4713
4714DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004715 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004716 cache.turnOn(true);
4717 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004718 if (!fontCollection->fontsFound()) return;
4719
4720 ParagraphStyle paragraph_style;
4721 paragraph_style.turnHintingOff();
4722
4723 TextStyle text_style;
4724 text_style.setFontFamilies({SkString("Roboto")});
4725 text_style.setColor(SK_ColorBLACK);
4726
4727 auto test = [&](const char* text1,
4728 const char* text2,
4729 const char* font1,
4730 const char* font2,
4731 int count,
4732 bool expectedToBeFound) {
4733 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4734 text_style.setFontFamilies({SkString(font1)});
4735 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004736 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004737 builder.pop();
4738 text_style.setFontFamilies({SkString(font2)});
4739 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004740 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004741 builder.pop();
4742 auto paragraph = builder.Build();
4743 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4744
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004745 REPORTER_ASSERT(reporter, count == cache.count());
4746 auto found = cache.findParagraph(impl);
4747 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4748 auto added = cache.updateParagraph(impl);
4749 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4750 };
4751
4752 test("text", "", "Roboto", "Homemade Apple", 0, false);
4753 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4754 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4755 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4756 test("text", "", "Roboto", "Homemade Apple", 4, true);
4757}
4758
4759DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004760 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004761 cache.turnOn(true);
4762 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004763 if (!fontCollection->fontsFound()) return;
4764
4765 ParagraphStyle paragraph_style;
4766 paragraph_style.turnHintingOff();
4767
4768 TextStyle text_style;
4769 text_style.setFontFamilies({SkString("Roboto")});
4770 text_style.setColor(SK_ColorBLACK);
4771
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004772 const char* text = "text";
4773 const size_t len = strlen(text);
4774
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004775 auto test = [&](int count, bool expectedToBeFound) {
4776 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4777 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004778 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004779 builder.pop();
4780 auto paragraph = builder.Build();
4781 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4782
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004783 REPORTER_ASSERT(reporter, count == cache.count());
4784 auto found = cache.findParagraph(impl);
4785 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4786 auto added = cache.updateParagraph(impl);
4787 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4788 };
4789
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004790 test(0, false);
4791 test(1, true);
4792 text_style.setLetterSpacing(10);
4793 test(1, false);
4794 test(2, true);
4795 text_style.setWordSpacing(10);
4796 test(2, false);
4797}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004798
Julia Lavrova526df262019-08-21 17:49:44 -04004799DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004800 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004801 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004802 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4803 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004804
4805 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004806 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004807 text_style.setFontSize(16);
4808 text_style.setFontFamilies({SkString("Roboto")});
4809 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004810 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004811
4812 auto paragraph = builder.Build();
4813 paragraph->layout(TestCanvasWidth);
4814 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004815 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004816}
4817
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004818DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004819 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004820 if (!fontCollection->fontsFound()) return;
4821 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4822 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4823
4824 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4825
4826 ParagraphStyle paragraph_style;
4827 TextStyle text_style;
4828 text_style.setFontSize(16);
4829 text_style.setFontFamilies({SkString("Roboto")});
4830 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4831 builder.addText(text.c_str(), text.size());
4832
4833 auto paragraph = builder.Build();
4834 paragraph->layout(TestCanvasWidth);
4835 paragraph->paint(canvas.get(), 0, 0);
4836}
4837
Julia Lavrovaa40db422019-08-21 13:49:15 -04004838DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004839 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004840 if (!fontCollection->fontsFound()) return;
4841 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4842
4843 ParagraphStyle paragraph_style;
4844 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4845
Julia Lavrova526df262019-08-21 17:49:44 -04004846 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004847 builder.addPlaceholder(placeholder);
4848
4849 auto paragraph = builder.Build();
4850 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004851 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004852 paragraph->paint(canvas.get(), 0, 0);
4853}
4854
4855DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004856 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004857 if (!fontCollection->fontsFound()) return;
4858 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4859 TestCanvas canvas("SkParagraph_Fallbacks.png");
4860
4861 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004862 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004863
4864 const char* androidFonts[] = {
4865 "sans-serif",
4866 "sans-serif-condensed",
4867 "serif",
4868 "monospace",
4869 "serif-monospace",
4870 "casual",
4871 "cursive",
4872 "sans-serif-smallcaps",
4873 };
4874
4875 for (auto& font : androidFonts) {
4876
4877 ParagraphStyle paragraph_style;
4878 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4879
4880 TextStyle text_style;
4881 text_style.setColor(SK_ColorBLACK);
4882 text_style.setLocale(SkString("en_US"));
4883 text_style.setFontSize(20);
4884
4885 text_style.setFontFamilies({ SkString(font) });
4886 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004887 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004888
4889 builder.pop();
4890
4891 auto paragraph = builder.Build();
4892 paragraph->layout(TestCanvasWidth);
4893 paragraph->paint(canvas.get(), 0, 0);
4894 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4895 }
4896}
4897
4898DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004899 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004900 if (!fontCollection->fontsFound()) return;
4901 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004902 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004903 TestCanvas canvas("SkParagraph_Bidi1.png");
4904
4905 std::u16string abc = u"\u202Dabc";
4906 std::u16string DEF = u"\u202EDEF";
4907 std::u16string ghi = u"\u202Dghi";
4908 std::u16string JKL = u"\u202EJKL";
4909 std::u16string mno = u"\u202Dmno";
4910
4911 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4912
4913 ParagraphStyle paragraph_style;
4914 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4915
4916 TextStyle text_style;
4917 text_style.setFontFamilies({ SkString("sans-serif")});
4918 text_style.setFontSize(40);
4919
4920 text_style.setColor(SK_ColorCYAN);
4921 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4922 builder.pushStyle(text_style);
4923 builder.addText(abc);
4924
4925 text_style.setColor(SK_ColorGREEN);
4926 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4927 builder.pushStyle(text_style);
4928 builder.addText(DEF);
4929
4930 text_style.setColor(SK_ColorYELLOW);
4931 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4932 builder.pushStyle(text_style);
4933 builder.addText(ghi);
4934
4935 text_style.setColor(SK_ColorMAGENTA);
4936 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4937 builder.pushStyle(text_style);
4938 builder.addText(JKL);
4939
4940 text_style.setColor(SK_ColorBLUE);
4941 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4942 builder.pushStyle(text_style);
4943 builder.addText(mno);
4944
4945 auto paragraph = builder.Build();
4946 paragraph->layout(400);
4947 paragraph->paint(canvas.get(), 0, 0);
4948}
4949
4950DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004951 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004952 if (!fontCollection->fontsFound()) return;
4953 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004954 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004955 TestCanvas canvas("SkParagraph_Bidi2.png");
4956
4957 std::u16string abcD = u"\u202Dabc\u202ED";
4958 std::u16string EFgh = u"EF\u202Dgh";
4959 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4960
4961 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4962
4963 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004964 TextStyle text_style;
4965 text_style.setFontFamilies({ SkString("sans-serif")});
4966 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004967
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004968 {
4969 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4970 builder.pushStyle(text_style);
4971 builder.addText(abcD);
4972 builder.pushStyle(text_style);
4973 builder.addText(EFgh);
4974 builder.pushStyle(text_style);
4975 builder.addText(iJKLmno);
4976 auto paragraph = builder.Build();
4977 paragraph->layout(360);
4978 paragraph->paint(canvas.get(), 0, 0);
4979 }
4980 canvas.get()->translate(0, 400);
4981 {
4982 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4983 builder.pushStyle(text_style);
4984 builder.addText(abcDEFghiJKLmno);
4985 auto paragraph = builder.Build();
4986 paragraph->layout(360);
4987 paragraph->paint(canvas.get(), 0, 0);
4988 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04004989}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004990
4991DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004992 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004993 if (!fontCollection->fontsFound()) return;
4994 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4995 TestCanvas canvas("SkParagraph_Newline.png");
4996
4997 TextStyle text_style;
4998 text_style.setFontFamilies({SkString("Ahem")});
4999 text_style.setColor(SK_ColorBLACK);
5000 StrutStyle strut_style;
5001 strut_style.setStrutEnabled(false);
5002 ParagraphStyle paragraph_style;
5003 paragraph_style.setStrutStyle(strut_style);
5004 paragraph_style.setTextStyle(text_style);
5005 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5006 builder.addText("\n");
5007 auto paragraph = builder.Build();
5008 paragraph->layout(1000);
5009 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5010}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005011
Julia Lavrovab30d4812019-11-08 14:51:16 -05005012DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005013 TestCanvas canvas("SkParagraph_FontResolutions.png");
5014
5015 sk_sp<TestFontCollection> fontCollection =
5016 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5017 if (!fontCollection->fontsFound()) return;
5018
5019 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5020 return;
5021 }
5022 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5023 return;
5024 }
5025 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5026 return;
5027 }
5028
5029 TextStyle text_style;
5030 text_style.setFontFamilies({SkString("abc")});
5031 text_style.setFontSize(50);
5032
5033 ParagraphStyle paragraph_style;
5034 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5035
5036 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5037 text_style.setColor(SK_ColorBLUE);
5038 builder.pushStyle(text_style);
5039 builder.addText(u"a\u0300");
5040 text_style.setColor(SK_ColorMAGENTA);
5041 builder.pushStyle(text_style);
5042 builder.addText(u"à");
5043
5044 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5045
5046 text_style.setColor(SK_ColorRED);
5047 builder.pushStyle(text_style);
5048 builder.addText(u"a\u0300");
5049 text_style.setColor(SK_ColorGREEN);
5050 builder.pushStyle(text_style);
5051 builder.addText(u"à");
5052
5053 auto paragraph = builder.Build();
5054 paragraph->layout(TestCanvasWidth);
5055
5056 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5057 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5058
5059 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5060 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5061 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5062
5063 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5064 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5065
5066 paragraph->paint(canvas.get(), 100, 100);
5067}
5068
Julia Lavrovab30d4812019-11-08 14:51:16 -05005069DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005070 TestCanvas canvas("SkParagraph_FontStyle.png");
5071
5072 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5073 if (!fontCollection->fontsFound()) return;
5074
5075 TextStyle text_style;
5076 text_style.setFontFamilies({SkString("Roboto")});
5077 text_style.setColor(SK_ColorBLACK);
5078 text_style.setFontSize(20);
5079 SkFontStyle fs = SkFontStyle(
5080 SkFontStyle::Weight::kLight_Weight,
5081 SkFontStyle::Width::kNormal_Width,
5082 SkFontStyle::Slant::kUpright_Slant
5083 );
5084 text_style.setFontStyle(fs);
5085 ParagraphStyle paragraph_style;
5086 paragraph_style.setTextStyle(text_style);
5087 TextStyle boldItalic;
5088 boldItalic.setFontFamilies({SkString("Roboto")});
5089 boldItalic.setColor(SK_ColorRED);
5090 SkFontStyle bi = SkFontStyle(
5091 SkFontStyle::Weight::kBold_Weight,
5092 SkFontStyle::Width::kNormal_Width,
5093 SkFontStyle::Slant::kItalic_Slant
5094 );
5095 boldItalic.setFontStyle(bi);
5096 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5097 builder.addText("Default text\n");
5098 builder.pushStyle(boldItalic);
5099 builder.addText("Bold and Italic\n");
5100 builder.pop();
5101 builder.addText("back to normal");
5102 auto paragraph = builder.Build();
5103 paragraph->layout(250);
5104 paragraph->paint(canvas.get(), 0, 0);
5105}
5106
Julia Lavrovab30d4812019-11-08 14:51:16 -05005107DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005108 TestCanvas canvas("SkParagraph_Shaping.png");
5109
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005110 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5111 sk_sp<TestFontCollection> fontCollection =
5112 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5113 if (!fontCollection->fontsFound()) return;
5114
5115
5116 TextStyle text_style;
5117 text_style.setFontFamilies({SkString("Roboto")});
5118 text_style.setColor(SK_ColorGRAY);
5119 text_style.setFontSize(14);
5120 SkFontStyle b = SkFontStyle(
5121 SkFontStyle::Weight::kNormal_Weight,
5122 SkFontStyle::Width::kNormal_Width,
5123 SkFontStyle::Slant::kUpright_Slant
5124 );
5125 text_style.setFontStyle(b);
5126 ParagraphStyle paragraph_style;
5127 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5128 builder.pushStyle(text_style);
5129 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5130 auto paragraph = builder.Build();
5131 paragraph->layout(380);
5132 paragraph->paint(canvas.get(), 0, 0);
5133}
Julia Lavrovac028b422019-11-25 10:00:43 -05005134
5135DEF_TEST(SkParagraph_Ellipsis, reporter) {
5136 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5137 if (!fontCollection->fontsFound()) return;
5138 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5139 TestCanvas canvas("SkParagraph_Ellipsis.png");
5140
5141 const char* text = "This\n"
5142 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5143 TextStyle text_style;
5144 text_style.setFontFamilies({SkString("Ahem")});
5145 text_style.setColor(SK_ColorBLACK);
5146 text_style.setFontSize(10);
5147
5148 auto relayout = [&](size_t lines, bool ellipsis,
5149 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5150 ParagraphStyle paragraph_style;
5151 SkPaint paint;
5152 paint.setColor(bg);
5153 text_style.setForegroundColor(paint);
5154 paragraph_style.setTextStyle(text_style);
5155 paragraph_style.setMaxLines(lines);
5156 if (ellipsis) {
5157 paragraph_style.setEllipsis(u"\u2026");
5158 }
5159 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5160 builder.addText(text);
5161 auto paragraph = builder.Build();
5162 paragraph->layout(50);
5163 paragraph->paint(canvas.get(), 0, 0);
5164 canvas.get()->translate(50, paragraph->getHeight() + 10);
5165 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5166 SkPaint background;
5167 background.setColor(SK_ColorRED);
5168 background.setStyle(SkPaint::kStroke_Style);
5169 background.setAntiAlias(true);
5170 background.setStrokeWidth(1);
5171 canvas.get()->drawRect(result.front().rect, background);
5172
5173 SkASSERT(width == paragraph->getMaxWidth());
5174 SkASSERT(height == paragraph->getHeight());
5175 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5176 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5177 };
5178
5179 SkPaint paint;
5180 paint.setColor(SK_ColorLTGRAY);
5181 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5182
5183 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005184 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5185 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005186
5187 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005188 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005189 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5190
5191 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005192 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5193 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005194}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005195
5196DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5197 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5198 if (!fontCollection->fontsFound()) return;
5199 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5200
5201 std::string text;
5202 for (size_t i = 0; i < 10; i++)
5203 {
5204 SkPaint paint;
5205 paint.setAntiAlias(true);
5206 paint.setColor(SK_ColorBLACK);
5207
5208 TextStyle textStyle;
5209 textStyle.setForegroundColor(paint);
5210 textStyle.setFontFamilies({ SkString("Roboto") });
5211
5212 ParagraphStyle paragraphStyle;
5213 paragraphStyle.setTextStyle(textStyle);
5214
5215 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5216 text += "Text ";
5217 builder.addText(text.c_str());
5218
5219 auto paragraph = builder.Build();
5220 paragraph->layout(100);
5221
5222 //used to add a delay so I can monitor memory usage
5223 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5224 }
5225};