blob: 20de68bee2534ed42eda21eb421e2d62ad072ae7 [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 Lavrova2813d452020-03-03 11:43:40 -05002793// This is the test I cannot accommodate
2794// Any text range gets a smallest glyph rectangle
2795DEF_TEST_DISABLED(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002796 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002797 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002798 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002799 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002800 const size_t len = strlen(text);
2801
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002802 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002803 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002804 paragraphStyle.setMaxLines(10);
2805 paragraphStyle.turnHintingOff();
2806 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2807
2808 TextStyle textStyle;
2809 textStyle.setFontFamilies({SkString("Roboto")});
2810 textStyle.setFontSize(50);
2811 textStyle.setLetterSpacing(1);
2812 textStyle.setWordSpacing(5);
2813 textStyle.setHeight(1);
2814 textStyle.setColor(SK_ColorBLACK);
2815
2816 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002817 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002818 builder.pop();
2819
2820 auto paragraph = builder.Build();
2821 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002822 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002823
2824 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002825 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2826
2827 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2828 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2829 {
2830 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2831 REPORTER_ASSERT(reporter, result.empty());
2832 }
2833 {
2834 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2835 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2836 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002837 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2838 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002839 }
2840 {
2841 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2842 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2843 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002844 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2845 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002846 }
2847 {
2848 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2849 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2850 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2851 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002852 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002853 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002854 }
2855}
2856
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002857// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002858DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002859 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002860 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002861 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002862 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2863 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2864 // Any attempt to substitute one for another leads to errors
2865 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002866 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002867 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002868
2869 ParagraphStyle paragraphStyle;
2870 paragraphStyle.setTextAlign(TextAlign::kCenter);
2871 paragraphStyle.setMaxLines(10);
2872 paragraphStyle.turnHintingOff();
2873 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2874
2875 TextStyle textStyle;
2876 textStyle.setFontFamilies({SkString("Roboto")});
2877 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002878 textStyle.setHeight(1);
2879 textStyle.setColor(SK_ColorBLACK);
2880 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2881 SkFontStyle::kUpright_Slant));
2882
2883 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002884 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002885 builder.pop();
2886
2887 auto paragraph = builder.Build();
2888 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002889 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002890
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002891 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002892 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2893 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002894 {
2895 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2896 REPORTER_ASSERT(reporter, result.empty());
2897 }
2898
2899 {
2900 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002901 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002902 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002903 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2904 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2905 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2906 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002907 }
2908
2909 {
2910 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002911 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002912 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002913 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2914 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2915 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002917 }
2918
2919 {
2920 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002921 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002922 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002923 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2924 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2925 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2926 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002927 }
2928
2929 {
2930 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002931 canvas.drawRects(SK_ColorBLACK, result);
2932 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2933 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002937 }
2938
2939 {
2940 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002941 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002942 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002943 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2944 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2945 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2946 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002947 }
2948
2949 {
2950 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2951 REPORTER_ASSERT(reporter, result.empty());
2952 }
2953}
2954
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002955// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002956DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002957 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002958 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002959 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002960 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002961 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002962
2963 ParagraphStyle paragraphStyle;
2964 paragraphStyle.setTextAlign(TextAlign::kCenter);
2965 paragraphStyle.setMaxLines(10);
2966 paragraphStyle.turnHintingOff();
2967 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2968
2969 TextStyle textStyle;
2970 textStyle.setFontFamilies({SkString("Roboto")});
2971 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002972 textStyle.setHeight(1);
2973 textStyle.setColor(SK_ColorBLACK);
2974 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2975 SkFontStyle::kUpright_Slant));
2976
2977 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002978 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002979 builder.pop();
2980
2981 auto paragraph = builder.Build();
2982 paragraph->layout(550);
2983
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002984 paragraph->paint(canvas.get(), 0, 0);
2985
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002986 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002987 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2988
2989 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2990 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002991 {
2992 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2993 REPORTER_ASSERT(reporter, result.empty());
2994 }
2995
2996 {
2997 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04002998 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002999 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003000 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
3001 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
3002 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
3003 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003004 }
3005
3006 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003007 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3008 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003009 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003010 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3011 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3012 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3013 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003014 }
3015}
3016
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003017// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003018DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003019 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003020 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003021 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3022 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003023 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003024
3025 ParagraphStyle paragraphStyle;
3026 paragraphStyle.setTextAlign(TextAlign::kCenter);
3027 paragraphStyle.setMaxLines(10);
3028 paragraphStyle.turnHintingOff();
3029 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3030
3031 TextStyle textStyle;
3032 textStyle.setFontFamilies({SkString("Roboto")});
3033 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003034 textStyle.setHeight(1);
3035 textStyle.setColor(SK_ColorBLACK);
3036 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3037 SkFontStyle::kUpright_Slant));
3038
3039 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003040 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003041 builder.pop();
3042
3043 auto paragraph = builder.Build();
3044 paragraph->layout(550);
3045
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003046 paragraph->paint(canvas.get(), 0, 0);
3047
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003048 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003049
3050 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3051
3052 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3053 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3054 SkScalar epsilon = 0.01f;
3055 {
3056 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3057 REPORTER_ASSERT(reporter, result.empty());
3058 }
3059 {
3060 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003061 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003062 REPORTER_ASSERT(reporter, result.size() == 1);
3063 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3064 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3065 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3066 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3067 }
3068 {
3069 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003070 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003071 REPORTER_ASSERT(reporter, result.size() == 1);
3072 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3073 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3074 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3075 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3076 }
3077 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003078 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003079 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003080 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003081 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3082 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003083 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003084 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3085 }
3086 {
3087 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003088 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003089 REPORTER_ASSERT(reporter, result.size() == 1);
3090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003093 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3094 }
3095 {
3096 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003097 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003098 REPORTER_ASSERT(reporter, result.size() == 1);
3099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3100 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3101 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3102 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3103 }
3104 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003105 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003106 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003107 REPORTER_ASSERT(reporter, result.size() == 1);
3108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003111 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3112 }
3113 {
3114 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3115 REPORTER_ASSERT(reporter, result.empty());
3116 }
3117}
3118
Julia Lavrovac2228562019-08-08 16:51:27 -04003119// Checked: DIFF (line height rounding error)
3120DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003121 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003122 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003123 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3124 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003125 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003126
3127 StrutStyle strutStyle;
3128 strutStyle.setStrutEnabled(true);
3129 strutStyle.setFontFamilies({SkString("Roboto")});
3130 strutStyle.setFontSize(14.0);
3131
3132 ParagraphStyle paragraphStyle;
3133 paragraphStyle.setStrutStyle(strutStyle);
3134
3135 TextStyle textStyle;
3136 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3137 textStyle.setFontSize(20);
3138 textStyle.setColor(SK_ColorBLACK);
3139
3140 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3141 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003142 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003143 builder.pop();
3144
3145 auto paragraph = builder.Build();
3146 paragraph->layout(550);
3147 paragraph->paint(canvas.get(), 0, 0);
3148
3149 {
3150 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3151 canvas.drawRects(SK_ColorGREEN, result);
3152 REPORTER_ASSERT(reporter, result.size() == 1);
3153 }
3154
3155 {
3156 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3157 canvas.drawRects(SK_ColorRED, result);
3158 REPORTER_ASSERT(reporter, result.size() == 1);
3159 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3160 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3161 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3162 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3163 }
3164}
3165
3166// Checked: NO DIFF
3167DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003168 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003169 if (!fontCollection->fontsFound()) return;
3170 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3171 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003172 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003173
3174 StrutStyle strutStyle;
3175 strutStyle.setStrutEnabled(false);
3176
3177 ParagraphStyle paragraphStyle;
3178 paragraphStyle.setStrutStyle(strutStyle);
3179
3180 TextStyle textStyle;
3181 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3182 textStyle.setFontSize(20);
3183 textStyle.setColor(SK_ColorBLACK);
3184
3185 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3186 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003187 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003188 builder.pop();
3189
3190 auto paragraph = builder.Build();
3191 paragraph->layout(550);
3192 paragraph->paint(canvas.get(), 0, 0);
3193
3194
3195 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3196 canvas.drawRects(SK_ColorGREEN, result1);
3197 REPORTER_ASSERT(reporter, result1.size() == 1);
3198
3199 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3200 canvas.drawRects(SK_ColorRED, result2);
3201 REPORTER_ASSERT(reporter, result2.size() == 1);
3202
3203 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3204}
3205
3206// Checked: DIFF (small in numbers)
3207DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003208 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003209 if (!fontCollection->fontsFound()) return;
3210 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003211 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3212 "67890 12345 67890 12345 67890 12345";
3213 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003214 ParagraphStyle paragraphStyle;
3215 paragraphStyle.setTextAlign(TextAlign::kLeft);
3216 paragraphStyle.setMaxLines(10);
3217 paragraphStyle.turnHintingOff();
3218 TextStyle textStyle;
3219 textStyle.setFontFamilies({SkString("Roboto")});
3220 textStyle.setFontSize(52);
3221 textStyle.setLetterSpacing(1.19039f);
3222 textStyle.setWordSpacing(5);
3223 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003224 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003225 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003226
3227 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3228 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003229 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003230 builder.pop();
3231
3232 auto paragraph = builder.Build();
3233 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003234 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003235
3236 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3237 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3238 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3239 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3240 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003241 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3242 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003243
3244 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003245 boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003246 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003247
Julia Lavrovac2228562019-08-08 16:51:27 -04003248 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003249 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003250 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003251
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003252 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3253 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3254 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3255 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3256 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3257 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3258 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3259 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3260
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003261 boxes = paragraph->getRectsForRange(12, 13, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003262 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003263 boxes = paragraph->getRectsForRange(13, 14, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003264 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003265 boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003266 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003267 boxes = paragraph->getRectsForRange(19, 20, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003268 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003269 boxes = paragraph->getRectsForRange(24, 25, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003270 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003271 boxes = paragraph->getRectsForRange(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003272 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003273 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003274 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003275 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003276 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003277
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003278 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3279 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003280}
3281
Julia Lavrovac2228562019-08-08 16:51:27 -04003282// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003283DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003284 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003285 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003286 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003287 ParagraphStyle paragraph_style;
3288 paragraph_style.setMaxLines(10);
3289 paragraph_style.setTextAlign(TextAlign::kLeft);
3290 paragraph_style.turnHintingOff();
3291 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3292
3293 TextStyle text_style;
3294 text_style.setFontFamilies({SkString("Roboto")});
3295 text_style.setFontSize(50);
3296 text_style.setLetterSpacing(20);
3297 text_style.setWordSpacing(0);
3298 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003299 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003300 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003301 builder.pop();
3302
3303 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003304 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003305 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003306 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003307 builder.pop();
3308
3309 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003310 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003311 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003312 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003313 builder.pop();
3314
3315 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003316 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003317 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003318 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003319 builder.pop();
3320
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003321 const char* hSpace = "H ";
3322 const size_t len = strlen(hSpace);
3323
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003324 text_style.setLetterSpacing(0);
3325 text_style.setWordSpacing(20);
3326 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003327 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003328 builder.pop();
3329
3330 text_style.setLetterSpacing(0);
3331 text_style.setWordSpacing(0);
3332 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003333 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003334 builder.pop();
3335
3336 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003337 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003338 text_style.setWordSpacing(20);
3339 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003340 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003341 builder.pop();
3342
3343 auto paragraph = builder.Build();
3344 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003345 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003346
3347 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3348 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3349 size_t index = 0;
3350 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003351 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3352 ++index;
3353 return true;
3354 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003355 REPORTER_ASSERT(reporter, index == 4);
3356 index = 0;
3357 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003358 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3359 ++index;
3360 return true;
3361 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003362 REPORTER_ASSERT(reporter, index == 4);
3363}
3364
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003365// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003366DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003367 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003368 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003369 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003370 const char* text =
3371 "A "
3372 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3373 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003374 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003375
3376 ParagraphStyle paragraph_style;
3377 paragraph_style.turnHintingOff();
3378 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3379
3380 TextStyle text_style;
3381 text_style.setFontFamilies({SkString("Roboto")});
3382 text_style.setColor(SK_ColorRED);
3383 text_style.setFontSize(31);
3384 text_style.setLetterSpacing(0);
3385 text_style.setWordSpacing(0);
3386 text_style.setColor(SK_ColorBLACK);
3387 text_style.setHeight(1);
3388 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003389 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003390 builder.pop();
3391
3392 auto paragraph = builder.Build();
3393 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003394 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003395
3396 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3397 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3398 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3399 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003400 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003401 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3402
3403 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3404 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3405 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3406}
3407
Julia Lavrovac2228562019-08-08 16:51:27 -04003408// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003409DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003410 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003411 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003412 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3413
3414 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3415 const char* text2 = " Dialog Text List lots of words to see "
3416 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003417 float scale = 3.0f;
3418 ParagraphStyle paragraph_style;
3419 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3420 TextStyle text_style;
3421 text_style.setFontFamilies({SkString("Droid Serif")});
3422 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003423 text_style.setColor(SK_ColorBLACK);
3424
3425 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003426 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003427 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003428 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003429 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003430 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003431 text_style.setFontSize(14 / scale);
3432 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003433 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003434 builder.pop();
3435
3436 auto paragraph = builder.Build();
3437 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003438 canvas.get()->scale(scale, scale);
3439 paragraph->paint(canvas.get(), 0, 0);
3440 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003441
3442 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003443
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003444 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003445 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003446 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3447 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3448 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3449 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3450 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3451 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003452}
3453
Julia Lavrovac2228562019-08-08 16:51:27 -04003454// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003455DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003456 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003457 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003458 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003459 const char* text =
3460 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3461 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003462 const size_t len = strlen(text);
3463
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003464 ParagraphStyle paragraph_style;
3465 paragraph_style.turnHintingOff();
3466 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3467
3468 TextStyle text_style;
3469 text_style.setFontFamilies({SkString("Roboto")});
3470 text_style.setColor(SK_ColorRED);
3471 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003472 text_style.setColor(SK_ColorBLACK);
3473 text_style.setHeight(1);
3474 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003475 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003476 builder.pop();
3477
3478 auto paragraph = builder.Build();
3479 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003480 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003481
3482 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3483 // Minikin does not count empty lines but SkParagraph does
3484 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3485
3486 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3487 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3488 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3489 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3490 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003491 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3492 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003493}
3494
Julia Lavrova526df262019-08-21 17:49:44 -04003495// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003496DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003497 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003498 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003499 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3500 const char* text =
3501 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3502 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3503 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3504 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003505 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003506
3507 ParagraphStyle paragraph_style;
3508 paragraph_style.turnHintingOff();
3509 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3510
3511 TextStyle text_style;
3512 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3513 text_style.setFontSize(50);
3514 text_style.setDecoration(TextDecoration::kUnderline);
3515 text_style.setColor(SK_ColorBLACK);
3516 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003517 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003518 builder.pop();
3519
3520 auto paragraph = builder.Build();
3521 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003522 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003523
Julia Lavrova3281b962019-12-02 11:32:25 -05003524 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3525
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003526 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003527
3528 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3529 for (auto& line : impl->lines()) {
3530 if (&line != impl->lines().end() - 1) {
3531 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3532 } else {
3533 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3534 }
3535 REPORTER_ASSERT(reporter, line.height() == 59);
3536 }
3537}
3538
Julia Lavrovac2228562019-08-08 16:51:27 -04003539// Checked: DIFF+
3540DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003541 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003542 if (!fontCollection->fontsFound()) return;
3543 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3544 const char* text =
3545 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3546 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3547 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3548 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3549 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3550 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003551 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003552
3553 ParagraphStyle paragraph_style;
3554 paragraph_style.turnHintingOff();
3555 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3556
3557 TextStyle text_style;
3558 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3559 text_style.setFontSize(50);
3560 text_style.setColor(SK_ColorBLACK);
3561 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003562 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003563 builder.pop();
3564
3565 auto paragraph = builder.Build();
3566 paragraph->layout(TestCanvasWidth - 300);
3567 paragraph->paint(canvas.get(), 0, 0);
3568
3569 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3570 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3571
3572 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3573 REPORTER_ASSERT(reporter, result.size() == 0);
3574
3575 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3576 REPORTER_ASSERT(reporter, result.size() == 2);
3577 canvas.drawRects(SK_ColorRED, result);
3578
3579 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrova2813d452020-03-03 11:43:40 -05003580 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04003581 canvas.drawRects(SK_ColorBLUE, result);
3582
3583 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3584 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3585 REPORTER_ASSERT(reporter, result.size() == 2);
3586 canvas.drawRects(SK_ColorGREEN, result);
3587
3588 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3589 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3590 REPORTER_ASSERT(reporter, result.size() == 2);
3591 canvas.drawRects(SK_ColorGREEN, result);
3592
3593 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3594 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3595 REPORTER_ASSERT(reporter, result.size() == 2);
3596 canvas.drawRects(SK_ColorGREEN, result);
3597}
3598
Julia Lavrova916a9042019-08-08 16:51:27 -04003599DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3600 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3601}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003602
Julia Lavrovac2228562019-08-08 16:51:27 -04003603// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003604DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003605 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003606 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003607 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003608 const char* text =
3609 "Sentence to layout at diff widths to get diff line counts. short words "
3610 "short words short words short words short words short words short words "
3611 "short words short words short words short words short words short words "
3612 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003613 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003614
3615 ParagraphStyle paragraph_style;
3616 paragraph_style.turnHintingOff();
3617 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3618
3619 TextStyle text_style;
3620 text_style.setFontFamilies({SkString("Roboto")});
3621 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003622 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003623 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003624 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003625 builder.pop();
3626
3627 auto paragraph = builder.Build();
3628 paragraph->layout(300);
3629
3630 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3631 // Some of the formatting lazily done on paint
3632 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3633 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3634 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3635
3636 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003637 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003638 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3639 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3640 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3641}
3642
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003643// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003644DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003645 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003646 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003647 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003648 const char* text =
3649 "This is a very long sentence to test if the text will properly wrap "
3650 "around and go to the next line. Sometimes, short sentence. Longer "
3651 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003652 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003653
3654 ParagraphStyle paragraph_style;
3655 paragraph_style.setMaxLines(1);
3656 paragraph_style.setEllipsis(u"\u2026");
3657 paragraph_style.turnHintingOff();
3658 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3659
3660 TextStyle text_style;
3661 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003662 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003663 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003664 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003665 builder.pop();
3666
3667 auto paragraph = builder.Build();
3668 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003669 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003670
3671 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003672
3673 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3674 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3675
3676 auto& line = impl->lines()[0];
3677 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003678 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003679}
3680
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003681// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003682DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003683 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003684 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003685 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003686 const char* text1 = "fluttser ";
3687 const char* text2 = "mdje";
3688 const char* text3 = "fluttser mdje";
3689
3690 ParagraphStyle paragraph_style;
3691 paragraph_style.turnHintingOff();
3692 paragraph_style.setTextAlign(TextAlign::kLeft);
3693 paragraph_style.setMaxLines(2);
3694 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3695
3696 TextStyle text_style;
3697 text_style.setFontFamilies({SkString("Roboto")});
3698 text_style.setColor(SK_ColorBLACK);
3699 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003700 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003701 text_style.setDecoration(TextDecoration::kUnderline);
3702 text_style.setDecorationColor(SK_ColorBLACK);
3703 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003704 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003705 builder.pop();
3706
3707 auto paragraph = builder.Build();
3708 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003709 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003710
3711 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3712
3713 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3714 text_style.setDecoration(TextDecoration::kNoDecoration);
3715 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003716 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003717 builder1.pop();
3718
3719 auto paragraph1 = builder1.Build();
3720 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003721 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003722
3723 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3724
3725 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3726 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003727
3728 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3729 .front()
3730 .rect;
3731 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3732 .front()
3733 .rect;
3734 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3735 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3736
3737 for (size_t i = 0; i < 12; ++i) {
Julia Lavrova2813d452020-03-03 11:43:40 -05003738 // Not all ranges produce a rectangle ("fl" goes into one cluster so [0:1) is empty)
3739 auto r1 = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
3740 auto r2 = paragraph1->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003741
Julia Lavrova2813d452020-03-03 11:43:40 -05003742 REPORTER_ASSERT(reporter, r1.size() == r2.size());
3743 if (!r1.empty() && !r2.empty()) {
3744 REPORTER_ASSERT(reporter, r1.front().rect.fLeft == r2.front().rect.fLeft);
3745 REPORTER_ASSERT(reporter, r1.front().rect.fRight == r2.front().rect.fRight);
3746 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003747 }
3748}
3749
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003750// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003751DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003752 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003753 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003754 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003755 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003756 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003757
3758 ParagraphStyle paragraph_style;
3759 paragraph_style.turnHintingOff();
3760 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3761
3762 TextStyle text_style;
3763 text_style.setFontFamilies({SkString("Roboto")});
3764 text_style.setColor(SK_ColorBLACK);
3765 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3766 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003767 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003768
3769 auto paragraph = builder.Build();
3770 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003771 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003772
3773 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3774
3775 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3776 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3777 size_t index = 0;
3778 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003779 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003780 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003781 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3782 ++index;
3783 return true;
3784 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003785 }
3786}
3787
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003788// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003789DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003790 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003791 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003792 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003793 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003794 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003795
3796 ParagraphStyle paragraph_style;
3797 paragraph_style.turnHintingOff();
3798 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3799
3800 TextStyle text_style;
3801 text_style.setFontFamilies({SkString("Roboto")});
3802 text_style.setColor(SK_ColorBLACK);
3803 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3804 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003805 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003806
3807 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3808 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3809 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003810 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003811 builder.pop();
3812
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003813 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003814
3815 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3816 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003817 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003818 builder.pop();
3819
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003820 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003821
3822 auto paragraph = builder.Build();
3823 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003824 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003825
3826 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3827
3828 size_t index = 0;
3829 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003830 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003831 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003832 ++index;
3833 switch (index) {
3834 case 1:
3835 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3836 break;
3837 case 2:
3838 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3839 break;
3840 case 3:
3841 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3842 break;
3843 case 4:
3844 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3845 REPORTER_ASSERT(reporter, style.equals(text_style));
3846 break;
3847 case 5:
3848 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3849 break;
3850 default:
3851 REPORTER_ASSERT(reporter, false);
3852 }
3853 return true;
3854 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003855 }
3856}
3857
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003858// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003859DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003860 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003861 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003862 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003863 const char* text =
3864 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3865 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003866 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003867
3868 ParagraphStyle paragraph_style;
3869 paragraph_style.turnHintingOff();
3870 paragraph_style.setMaxLines(14);
3871 paragraph_style.setTextAlign(TextAlign::kJustify);
3872 paragraph_style.setHeight(1.5);
3873 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3874
3875 TextStyle text_style;
3876 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3877 text_style.setColor(SK_ColorBLACK);
3878 text_style.setFontSize(55);
3879 text_style.setLetterSpacing(2);
3880 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3881 text_style.setDecorationColor(SK_ColorBLACK);
3882 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003883 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003884 builder.pop();
3885
3886 auto paragraph = builder.Build();
3887 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003888 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003889
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003890 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3891 paragraph->getMaxWidth(),
3892 paragraph->getIdeographicBaseline());
3893 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3894 paragraph->getMaxWidth(),
3895 paragraph->getAlphabeticBaseline());
3896 canvas.drawLine(SK_ColorRED, rect1, false);
3897 canvas.drawLine(SK_ColorGREEN, rect2, false);
3898
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003899 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003900 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003901 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003902 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003903}
3904
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003905// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003906DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003907 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003908 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003909 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003910
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003911 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3912 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3913 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003914
3915 ParagraphStyle paragraph_style;
3916 paragraph_style.turnHintingOff();
3917 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3918
3919 TextStyle text_style;
3920 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003921 SkString("Not a real font"),
3922 SkString("Also a fake font"),
3923 SkString("So fake it is obvious"),
3924 SkString("Next one should be a real font..."),
3925 SkString("Roboto"),
3926 SkString("another fake one in between"),
3927 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003928 });
3929 text_style.setColor(SK_ColorBLACK);
3930 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003931 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003932
3933 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003934 SkString("Not a real font"),
3935 SkString("Also a fake font"),
3936 SkString("So fake it is obvious"),
3937 SkString("Homemade Apple"),
3938 SkString("Next one should be a real font..."),
3939 SkString("Roboto"),
3940 SkString("another fake one in between"),
3941 SkString("Noto Sans CJK JP"),
3942 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003943 });
3944 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003945 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003946
3947 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003948 SkString("Not a real font"),
3949 SkString("Also a fake font"),
3950 SkString("So fake it is obvious"),
3951 SkString("Homemade Apple"),
3952 SkString("Next one should be a real font..."),
3953 SkString("Roboto"),
3954 SkString("another fake one in between"),
3955 SkString("Source Han Serif CN"),
3956 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003957 });
3958 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003959 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003960
3961 builder.pop();
3962
3963 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003964 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003965 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003966 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003967
Julia Lavrova3281b962019-12-02 11:32:25 -05003968 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
3969
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003970 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3971
3972 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3973 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3974 // [Apple + Noto] [Apple + Han]
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003975 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003976
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003977 auto robotoAdvance = impl->runs()[0].advance().fX +
3978 impl->runs()[1].advance().fX +
3979 impl->runs()[2].advance().fX;
3980 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
3981 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
3982 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
3983 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
3984 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003985
3986 // When a different font is resolved, then the metrics are different.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003987 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
3988 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003989}
3990
Julia Lavrovac2228562019-08-08 16:51:27 -04003991// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003992DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003993 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003994 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003995 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003996 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003997 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003998 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003999
4000 ParagraphStyle paragraph_style;
4001 paragraph_style.setMaxLines(10);
4002 paragraph_style.setTextAlign(TextAlign::kLeft);
4003 paragraph_style.turnHintingOff();
4004
4005 StrutStyle strut_style;
4006 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004007 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004008 strut_style.setFontSize(50);
4009 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004010 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004011 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004012 paragraph_style.setStrutStyle(strut_style);
4013
4014 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4015
4016 TextStyle text_style;
4017 text_style.setFontFamilies({SkString("Ahem")});
4018 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004019 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004020 text_style.setColor(SK_ColorBLACK);
4021 text_style.setHeight(0.5f);
4022 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004023 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004024 builder.pop();
4025
4026 auto paragraph = builder.Build();
4027 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004028 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004029
4030 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004031 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4032
4033 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4034 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4035 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004036 {
4037 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4038 REPORTER_ASSERT(reporter, boxes.empty());
4039 }
4040 {
4041 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004042 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004043 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004044 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4045 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4046 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4047 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004048 }
4049 {
4050 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004051 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004052 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004053 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004054 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004055 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4056 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004057 }
4058 {
4059 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004060 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004061 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004062 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4063 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004064 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004065 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004066 }
4067 {
4068 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004069 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004070 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004071 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004072 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004073 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004074 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004075 }
4076 {
4077 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004078 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004079 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004080 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004081 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004082 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4083 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004084 }
4085 {
4086 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004087 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004088 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004093 }
4094}
4095
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004096// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004097DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004098 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004099 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004100 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004101 // The chinese extra height should be absorbed by the strut.
4102 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004103 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004104
4105 ParagraphStyle paragraph_style;
4106 paragraph_style.setMaxLines(10);
4107 paragraph_style.setTextAlign(TextAlign::kLeft);
4108 paragraph_style.turnHintingOff();
4109
4110 StrutStyle strut_style;
4111
4112 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004113 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004114 strut_style.setFontSize(50);
4115 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004116 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004117 paragraph_style.setStrutStyle(strut_style);
4118
4119 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4120
4121 TextStyle text_style;
4122 text_style.setFontFamilies({SkString("Ahem")});
4123 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004124 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4125 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004126 text_style.setColor(SK_ColorBLACK);
4127 text_style.setHeight(1);
4128 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004129 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004130 builder.pop();
4131
4132 auto paragraph = builder.Build();
4133 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004134 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004135
4136 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4137 // Font is not resolved and the first line does not fit
4138 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4139
4140 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4141 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4142 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004143 {
4144 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4145 REPORTER_ASSERT(reporter, boxes.empty());
4146 }
4147 {
4148 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004149 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004150 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004151 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4152 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4153 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4154 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004155 }
4156 {
4157 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004158 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004159 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004160 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004161 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004162 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4163 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004164 }
4165 {
4166 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004167 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004168 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004169 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4170 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4171 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4172 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004173 }
4174 {
4175 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004176 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004177 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004178 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004179 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004180 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4181 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004182 }
4183 {
4184 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004185 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004186 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004187 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004188 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004189 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4190 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004191 }
4192 {
4193 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004194 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004195 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004196 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004197 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004198 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4199 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004200 }
4201}
4202
Julia Lavrovac2228562019-08-08 16:51:27 -04004203// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004204DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004205 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004206 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004207 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4208
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004209 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004210 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004211 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004212
4213 ParagraphStyle paragraph_style;
4214 paragraph_style.setMaxLines(10);
4215 paragraph_style.setTextAlign(TextAlign::kLeft);
4216 paragraph_style.turnHintingOff();
4217
4218 StrutStyle strut_style;
4219 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004220 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004221 strut_style.setFontSize(50);
4222 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004223 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004224 paragraph_style.setStrutStyle(strut_style);
4225
4226 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4227
4228 TextStyle text_style;
4229 text_style.setFontFamilies({SkString("Ahem")});
4230 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004231 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4232 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004233 text_style.setColor(SK_ColorBLACK);
4234 text_style.setHeight(1);
4235 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004236 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004237 builder.pop();
4238
4239 auto paragraph = builder.Build();
4240 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004241 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004242
4243 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4244 // Font is not resolved and the first line does not fit
4245 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4246
4247 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4248 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4249 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4250 SkScalar epsilon = 0.001f;
4251 {
4252 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4253 REPORTER_ASSERT(reporter, boxes.empty());
4254 }
4255 {
4256 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004257 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004258 REPORTER_ASSERT(reporter, boxes.size() == 1);
4259 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4260 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4261 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4262 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4263 }
4264 {
4265 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004266 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004267 REPORTER_ASSERT(reporter, boxes.size() == 1);
4268 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004269 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004270 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4271 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4272 }
4273 {
4274 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004275 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004276 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004277 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4278 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004279 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004280 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4281 }
4282 {
4283 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004284 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004285 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004287 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004288 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004289 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4290 }
4291 {
4292 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004293 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004294 REPORTER_ASSERT(reporter, boxes.size() == 1);
4295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004296 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004297 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4298 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4299 }
4300 {
4301 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004302 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004303 REPORTER_ASSERT(reporter, boxes.size() == 1);
4304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004305 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004306 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4307 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4308 }
4309}
4310
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004311// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004312DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004313 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004314 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004315 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004316 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004317 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004318
4319 ParagraphStyle paragraph_style;
4320 paragraph_style.setMaxLines(10);
4321 paragraph_style.setTextAlign(TextAlign::kLeft);
4322 paragraph_style.turnHintingOff();
4323
4324 StrutStyle strut_style;
4325 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004326 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004327 strut_style.setFontSize(50);
4328 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004329 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004330 strut_style.setLeading(0.1f);
4331 strut_style.setForceStrutHeight(true);
4332 paragraph_style.setStrutStyle(strut_style);
4333
4334 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4335
4336 TextStyle text_style;
4337 text_style.setFontFamilies({SkString("Ahem")});
4338 text_style.setFontSize(50);
4339 text_style.setLetterSpacing(0);
4340 text_style.setColor(SK_ColorBLACK);
4341 text_style.setHeight(1);
4342 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004343 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004344 builder.pop();
4345
4346 auto paragraph = builder.Build();
4347 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004348 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004349
4350 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4351 // Font is not resolved and the first line does not fit
4352 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4353
4354 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4355 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4356 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004357
4358 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4359 REPORTER_ASSERT(reporter, boxes1.empty());
4360
4361 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004362 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004363 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004364 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4365 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4366 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4367 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004368
4369 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004370 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004371 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004372 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004373 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004374 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4375 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004376
4377 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004378 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004379 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004380 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4381 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4382 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4383 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004384
4385 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004386 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004387 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004388 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004392
4393 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004394 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004395 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004396 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004400
4401 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004402 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004403 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004404 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004408}
4409
Julia Lavrovac2228562019-08-08 16:51:27 -04004410// Checked: NO DIFF
4411DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004412 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004413 if (!fontCollection->fontsFound()) return;
4414 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4415
4416 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004417 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004418
4419 ParagraphStyle paragraph_style;
4420 paragraph_style.setMaxLines(10);
4421 paragraph_style.setTextAlign(TextAlign::kLeft);
4422 paragraph_style.turnHintingOff();
4423
4424 StrutStyle strut_style;
4425 strut_style.setStrutEnabled(true);
4426 strut_style.setFontFamilies({SkString("Ahem")});
4427 strut_style.setFontSize(50);
4428 strut_style.setHeight(1.5f);
4429 strut_style.setLeading(0.1f);
4430 strut_style.setForceStrutHeight(false);
4431 paragraph_style.setStrutStyle(strut_style);
4432
4433 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4434
4435 TextStyle text_style;
4436 text_style.setFontFamilies({SkString("Ahem")});
4437 text_style.setFontSize(20);
4438 text_style.setColor(SK_ColorBLACK);
4439 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004440 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004441 builder.pop();
4442
4443 auto paragraph = builder.Build();
4444 paragraph->layout(550);
4445 paragraph->paint(canvas.get(), 0, 0);
4446
4447 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4448 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4449 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4450 {
4451 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4452 REPORTER_ASSERT(reporter, boxes.empty());
4453 }
4454 {
4455 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4456 canvas.drawRects(SK_ColorRED, boxes);
4457 REPORTER_ASSERT(reporter, boxes.size() == 1);
4458 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4459 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4460 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4461 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4462 }
4463 {
4464 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4465 canvas.drawRects(SK_ColorRED, boxes);
4466 REPORTER_ASSERT(reporter, boxes.size() == 1);
4467 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4468 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4469 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4470 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4471 }
4472}
4473
Julia Lavrovac5313e62019-12-10 12:11:17 -05004474DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4475 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4476 if (!fontCollection->fontsFound()) return;
4477 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4478
4479 const char* text = "12ab\n";
4480
4481 ParagraphStyle paragraph_style;
4482 paragraph_style.turnHintingOff();
4483 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4484
4485 TextStyle text_style;
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004486 text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
Julia Lavrovac5313e62019-12-10 12:11:17 -05004487 text_style.setFontFamilies({SkString("Roboto")});
4488 text_style.setColor(SK_ColorBLACK);
4489
4490 text_style.addFontFeature(SkString("tnum"), 1);
4491 builder.pushStyle(text_style);
4492 builder.addText(text);
4493
4494 text_style.resetFontFeatures();
4495 text_style.addFontFeature(SkString("tnum"), 0);
4496 text_style.addFontFeature(SkString("pnum"), 1);
4497 builder.pushStyle(text_style);
4498 builder.addText(text);
4499
4500 builder.pop();
4501 builder.pop();
4502
4503 auto paragraph = builder.Build();
4504 paragraph->layout(TestCanvasWidth);
4505
4506 paragraph->paint(canvas.get(), 10.0, 15.0);
4507
4508 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4509 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4510
4511 auto& tnum_line = impl->lines()[0];
4512 auto& pnum_line = impl->lines()[1];
4513
4514 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4515 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4516 // Tabular numbers should have equal widths.
4517 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4518 // Proportional numbers should have variable widths.
4519 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4520 // Alphabetic characters should be unaffected.
4521 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4522}
4523
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004524// Not in Minikin
4525DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004526 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004527 if (!fontCollection->fontsFound()) return;
4528 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004529 const size_t len = strlen(text);
4530
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004531 ParagraphStyle paragraph_style;
4532 paragraph_style.turnHintingOff();
4533 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4534
4535 TextStyle text_style;
4536 text_style.setFontFamilies(
4537 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4538 text_style.setFontSize(60);
4539 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004540 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004541 builder.pop();
4542
4543 auto paragraph = builder.Build();
4544 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004545
4546 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4547
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004548 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4549 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4550 auto first = impl->runs()[i].textRange();
4551 auto next = impl->runs()[i + 1].textRange();
4552 REPORTER_ASSERT(reporter, first.end == next.start);
4553 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004554}
4555
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004556DEF_TEST(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004557 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004558 if (!fontCollection->fontsFound()) return;
4559 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004560 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004561
4562 ParagraphStyle paragraph_style;
4563 paragraph_style.turnHintingOff();
4564 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4565
4566 TextStyle text_style;
4567 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4568 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004569 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004570 builder.pop();
4571
4572 auto paragraph = builder.Build();
4573 paragraph->layout(TestCanvasWidth);
4574
4575 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4576 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004577 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004578
4579 auto cluster = 0;
4580 SkShaperJSONWriter::VisualizeClusters(
4581 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4582 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4583 if (cluster == 0) {
4584 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4585 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4586 SkASSERT(glyph1to1.size() == 1);
4587 SkASSERT(*glyph1to1.begin() == 1611);
4588 }
4589 ++cluster;
4590 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004591 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004592}
4593
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004594DEF_TEST(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004595 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004596 if (!fontCollection->fontsFound()) return;
4597 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004598 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004599
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004600 ParagraphStyle paragraph_style;
4601 paragraph_style.turnHintingOff();
4602 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4603
4604 TextStyle text_style;
4605 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4606 text_style.setColor(SK_ColorBLACK);
4607 text_style.setFontSize(50);
4608 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004609 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004610 builder.pop();
4611
4612 auto paragraph = builder.Build();
4613 paragraph->layout(TestCanvasWidth);
4614
4615 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4616 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004617
4618 auto cluster = 0;
4619 for (auto& run : impl->runs()) {
4620 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004621 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4622 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004623 [&](int codePointCount, SkSpan<const char> utf1to1,
4624 SkSpan<const SkGlyphID> glyph1to1) {
4625 if (cluster == 0) {
4626 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4627 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4628 SkASSERT(glyph1to1.size() == 3);
4629 }
4630 ++cluster;
4631 });
4632 }
4633
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004634 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004635}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004636
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004637DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004638 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004639 cache.turnOn(true);
4640 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004641 if (!fontCollection->fontsFound()) return;
4642
4643 ParagraphStyle paragraph_style;
4644 paragraph_style.turnHintingOff();
4645
4646 TextStyle text_style;
4647 text_style.setFontFamilies({SkString("Roboto")});
4648 text_style.setColor(SK_ColorBLACK);
4649
4650 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4651 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4652 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004653 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004654 builder.pop();
4655 auto paragraph = builder.Build();
4656
4657 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4658 REPORTER_ASSERT(reporter, count == cache.count());
4659 auto found = cache.findParagraph(impl);
4660 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4661 auto added = cache.updateParagraph(impl);
4662 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4663 };
4664
4665 test("text1", 0, false);
4666 test("text1", 1, true);
4667 test("text2", 1, false);
4668 test("text2", 2, true);
4669 test("text3", 2, false);
4670}
4671
4672DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004673 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004674 cache.turnOn(true);
4675 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004676 if (!fontCollection->fontsFound()) return;
4677
4678 ParagraphStyle paragraph_style;
4679 paragraph_style.turnHintingOff();
4680
4681 TextStyle text_style;
4682 text_style.setColor(SK_ColorBLACK);
4683
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004684 const char* text = "text";
4685 const size_t len = strlen(text);
4686
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004687 auto test = [&](int count, bool expectedToBeFound) {
4688 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4689 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004690 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004691 builder.pop();
4692 auto paragraph = builder.Build();
4693 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4694
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004695 REPORTER_ASSERT(reporter, count == cache.count());
4696 auto found = cache.findParagraph(impl);
4697 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4698 auto added = cache.updateParagraph(impl);
4699 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4700 };
4701
4702 text_style.setFontFamilies({SkString("Roboto")});
4703 test(0, false);
4704 test(1, true);
4705 text_style.setFontFamilies({SkString("Homemade Apple")});
4706 test(1, false);
4707 test(2, true);
4708 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4709 test(2, false);
4710}
4711
4712DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004713 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004714 cache.turnOn(true);
4715 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004716 if (!fontCollection->fontsFound()) return;
4717
4718 ParagraphStyle paragraph_style;
4719 paragraph_style.turnHintingOff();
4720
4721 TextStyle text_style;
4722 text_style.setFontFamilies({SkString("Roboto")});
4723 text_style.setColor(SK_ColorBLACK);
4724
4725 auto test = [&](const char* text1,
4726 const char* text2,
4727 const char* font1,
4728 const char* font2,
4729 int count,
4730 bool expectedToBeFound) {
4731 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4732 text_style.setFontFamilies({SkString(font1)});
4733 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004734 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004735 builder.pop();
4736 text_style.setFontFamilies({SkString(font2)});
4737 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004738 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004739 builder.pop();
4740 auto paragraph = builder.Build();
4741 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4742
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004743 REPORTER_ASSERT(reporter, count == cache.count());
4744 auto found = cache.findParagraph(impl);
4745 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4746 auto added = cache.updateParagraph(impl);
4747 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4748 };
4749
4750 test("text", "", "Roboto", "Homemade Apple", 0, false);
4751 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4752 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4753 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4754 test("text", "", "Roboto", "Homemade Apple", 4, true);
4755}
4756
4757DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004758 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004759 cache.turnOn(true);
4760 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004761 if (!fontCollection->fontsFound()) return;
4762
4763 ParagraphStyle paragraph_style;
4764 paragraph_style.turnHintingOff();
4765
4766 TextStyle text_style;
4767 text_style.setFontFamilies({SkString("Roboto")});
4768 text_style.setColor(SK_ColorBLACK);
4769
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004770 const char* text = "text";
4771 const size_t len = strlen(text);
4772
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004773 auto test = [&](int count, bool expectedToBeFound) {
4774 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4775 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004776 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004777 builder.pop();
4778 auto paragraph = builder.Build();
4779 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4780
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004781 REPORTER_ASSERT(reporter, count == cache.count());
4782 auto found = cache.findParagraph(impl);
4783 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4784 auto added = cache.updateParagraph(impl);
4785 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4786 };
4787
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004788 test(0, false);
4789 test(1, true);
4790 text_style.setLetterSpacing(10);
4791 test(1, false);
4792 test(2, true);
4793 text_style.setWordSpacing(10);
4794 test(2, false);
4795}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004796
Julia Lavrova526df262019-08-21 17:49:44 -04004797DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004798 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004799 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004800 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4801 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004802
4803 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004804 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004805 text_style.setFontSize(16);
4806 text_style.setFontFamilies({SkString("Roboto")});
4807 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004808 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004809
4810 auto paragraph = builder.Build();
4811 paragraph->layout(TestCanvasWidth);
4812 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004813 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004814}
4815
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004816DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004817 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004818 if (!fontCollection->fontsFound()) return;
4819 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4820 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4821
4822 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4823
4824 ParagraphStyle paragraph_style;
4825 TextStyle text_style;
4826 text_style.setFontSize(16);
4827 text_style.setFontFamilies({SkString("Roboto")});
4828 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4829 builder.addText(text.c_str(), text.size());
4830
4831 auto paragraph = builder.Build();
4832 paragraph->layout(TestCanvasWidth);
4833 paragraph->paint(canvas.get(), 0, 0);
4834}
4835
Julia Lavrovaa40db422019-08-21 13:49:15 -04004836DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004837 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004838 if (!fontCollection->fontsFound()) return;
4839 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4840
4841 ParagraphStyle paragraph_style;
4842 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4843
Julia Lavrova526df262019-08-21 17:49:44 -04004844 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004845 builder.addPlaceholder(placeholder);
4846
4847 auto paragraph = builder.Build();
4848 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004849 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004850 paragraph->paint(canvas.get(), 0, 0);
4851}
4852
4853DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004854 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004855 if (!fontCollection->fontsFound()) return;
4856 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4857 TestCanvas canvas("SkParagraph_Fallbacks.png");
4858
4859 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004860 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004861
4862 const char* androidFonts[] = {
4863 "sans-serif",
4864 "sans-serif-condensed",
4865 "serif",
4866 "monospace",
4867 "serif-monospace",
4868 "casual",
4869 "cursive",
4870 "sans-serif-smallcaps",
4871 };
4872
4873 for (auto& font : androidFonts) {
4874
4875 ParagraphStyle paragraph_style;
4876 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4877
4878 TextStyle text_style;
4879 text_style.setColor(SK_ColorBLACK);
4880 text_style.setLocale(SkString("en_US"));
4881 text_style.setFontSize(20);
4882
4883 text_style.setFontFamilies({ SkString(font) });
4884 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004885 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004886
4887 builder.pop();
4888
4889 auto paragraph = builder.Build();
4890 paragraph->layout(TestCanvasWidth);
4891 paragraph->paint(canvas.get(), 0, 0);
4892 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4893 }
4894}
4895
4896DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004897 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004898 if (!fontCollection->fontsFound()) return;
4899 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004900 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004901 TestCanvas canvas("SkParagraph_Bidi1.png");
4902
4903 std::u16string abc = u"\u202Dabc";
4904 std::u16string DEF = u"\u202EDEF";
4905 std::u16string ghi = u"\u202Dghi";
4906 std::u16string JKL = u"\u202EJKL";
4907 std::u16string mno = u"\u202Dmno";
4908
4909 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4910
4911 ParagraphStyle paragraph_style;
4912 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4913
4914 TextStyle text_style;
4915 text_style.setFontFamilies({ SkString("sans-serif")});
4916 text_style.setFontSize(40);
4917
4918 text_style.setColor(SK_ColorCYAN);
4919 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4920 builder.pushStyle(text_style);
4921 builder.addText(abc);
4922
4923 text_style.setColor(SK_ColorGREEN);
4924 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4925 builder.pushStyle(text_style);
4926 builder.addText(DEF);
4927
4928 text_style.setColor(SK_ColorYELLOW);
4929 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4930 builder.pushStyle(text_style);
4931 builder.addText(ghi);
4932
4933 text_style.setColor(SK_ColorMAGENTA);
4934 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4935 builder.pushStyle(text_style);
4936 builder.addText(JKL);
4937
4938 text_style.setColor(SK_ColorBLUE);
4939 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4940 builder.pushStyle(text_style);
4941 builder.addText(mno);
4942
4943 auto paragraph = builder.Build();
4944 paragraph->layout(400);
4945 paragraph->paint(canvas.get(), 0, 0);
4946}
4947
4948DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004949 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004950 if (!fontCollection->fontsFound()) return;
4951 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004952 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004953 TestCanvas canvas("SkParagraph_Bidi2.png");
4954
4955 std::u16string abcD = u"\u202Dabc\u202ED";
4956 std::u16string EFgh = u"EF\u202Dgh";
4957 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4958
4959 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4960
4961 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004962 TextStyle text_style;
4963 text_style.setFontFamilies({ SkString("sans-serif")});
4964 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004965
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004966 {
4967 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4968 builder.pushStyle(text_style);
4969 builder.addText(abcD);
4970 builder.pushStyle(text_style);
4971 builder.addText(EFgh);
4972 builder.pushStyle(text_style);
4973 builder.addText(iJKLmno);
4974 auto paragraph = builder.Build();
4975 paragraph->layout(360);
4976 paragraph->paint(canvas.get(), 0, 0);
4977 }
4978 canvas.get()->translate(0, 400);
4979 {
4980 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4981 builder.pushStyle(text_style);
4982 builder.addText(abcDEFghiJKLmno);
4983 auto paragraph = builder.Build();
4984 paragraph->layout(360);
4985 paragraph->paint(canvas.get(), 0, 0);
4986 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04004987}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004988
4989DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004990 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004991 if (!fontCollection->fontsFound()) return;
4992 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4993 TestCanvas canvas("SkParagraph_Newline.png");
4994
4995 TextStyle text_style;
4996 text_style.setFontFamilies({SkString("Ahem")});
4997 text_style.setColor(SK_ColorBLACK);
4998 StrutStyle strut_style;
4999 strut_style.setStrutEnabled(false);
5000 ParagraphStyle paragraph_style;
5001 paragraph_style.setStrutStyle(strut_style);
5002 paragraph_style.setTextStyle(text_style);
5003 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5004 builder.addText("\n");
5005 auto paragraph = builder.Build();
5006 paragraph->layout(1000);
5007 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5008}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005009
Julia Lavrovab30d4812019-11-08 14:51:16 -05005010DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005011 TestCanvas canvas("SkParagraph_FontResolutions.png");
5012
5013 sk_sp<TestFontCollection> fontCollection =
5014 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5015 if (!fontCollection->fontsFound()) return;
5016
5017 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5018 return;
5019 }
5020 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5021 return;
5022 }
5023 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5024 return;
5025 }
5026
5027 TextStyle text_style;
5028 text_style.setFontFamilies({SkString("abc")});
5029 text_style.setFontSize(50);
5030
5031 ParagraphStyle paragraph_style;
5032 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5033
5034 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5035 text_style.setColor(SK_ColorBLUE);
5036 builder.pushStyle(text_style);
5037 builder.addText(u"a\u0300");
5038 text_style.setColor(SK_ColorMAGENTA);
5039 builder.pushStyle(text_style);
5040 builder.addText(u"à");
5041
5042 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5043
5044 text_style.setColor(SK_ColorRED);
5045 builder.pushStyle(text_style);
5046 builder.addText(u"a\u0300");
5047 text_style.setColor(SK_ColorGREEN);
5048 builder.pushStyle(text_style);
5049 builder.addText(u"à");
5050
5051 auto paragraph = builder.Build();
5052 paragraph->layout(TestCanvasWidth);
5053
5054 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5055 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5056
5057 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5058 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5059 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5060
5061 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5062 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5063
5064 paragraph->paint(canvas.get(), 100, 100);
5065}
5066
Julia Lavrovab30d4812019-11-08 14:51:16 -05005067DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005068 TestCanvas canvas("SkParagraph_FontStyle.png");
5069
5070 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5071 if (!fontCollection->fontsFound()) return;
5072
5073 TextStyle text_style;
5074 text_style.setFontFamilies({SkString("Roboto")});
5075 text_style.setColor(SK_ColorBLACK);
5076 text_style.setFontSize(20);
5077 SkFontStyle fs = SkFontStyle(
5078 SkFontStyle::Weight::kLight_Weight,
5079 SkFontStyle::Width::kNormal_Width,
5080 SkFontStyle::Slant::kUpright_Slant
5081 );
5082 text_style.setFontStyle(fs);
5083 ParagraphStyle paragraph_style;
5084 paragraph_style.setTextStyle(text_style);
5085 TextStyle boldItalic;
5086 boldItalic.setFontFamilies({SkString("Roboto")});
5087 boldItalic.setColor(SK_ColorRED);
5088 SkFontStyle bi = SkFontStyle(
5089 SkFontStyle::Weight::kBold_Weight,
5090 SkFontStyle::Width::kNormal_Width,
5091 SkFontStyle::Slant::kItalic_Slant
5092 );
5093 boldItalic.setFontStyle(bi);
5094 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5095 builder.addText("Default text\n");
5096 builder.pushStyle(boldItalic);
5097 builder.addText("Bold and Italic\n");
5098 builder.pop();
5099 builder.addText("back to normal");
5100 auto paragraph = builder.Build();
5101 paragraph->layout(250);
5102 paragraph->paint(canvas.get(), 0, 0);
5103}
5104
Julia Lavrovab30d4812019-11-08 14:51:16 -05005105DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005106 TestCanvas canvas("SkParagraph_Shaping.png");
5107
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005108 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5109 sk_sp<TestFontCollection> fontCollection =
5110 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5111 if (!fontCollection->fontsFound()) return;
5112
5113
5114 TextStyle text_style;
5115 text_style.setFontFamilies({SkString("Roboto")});
5116 text_style.setColor(SK_ColorGRAY);
5117 text_style.setFontSize(14);
5118 SkFontStyle b = SkFontStyle(
5119 SkFontStyle::Weight::kNormal_Weight,
5120 SkFontStyle::Width::kNormal_Width,
5121 SkFontStyle::Slant::kUpright_Slant
5122 );
5123 text_style.setFontStyle(b);
5124 ParagraphStyle paragraph_style;
5125 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5126 builder.pushStyle(text_style);
5127 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5128 auto paragraph = builder.Build();
5129 paragraph->layout(380);
5130 paragraph->paint(canvas.get(), 0, 0);
5131}
Julia Lavrovac028b422019-11-25 10:00:43 -05005132
5133DEF_TEST(SkParagraph_Ellipsis, reporter) {
5134 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5135 if (!fontCollection->fontsFound()) return;
5136 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5137 TestCanvas canvas("SkParagraph_Ellipsis.png");
5138
5139 const char* text = "This\n"
5140 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5141 TextStyle text_style;
5142 text_style.setFontFamilies({SkString("Ahem")});
5143 text_style.setColor(SK_ColorBLACK);
5144 text_style.setFontSize(10);
5145
5146 auto relayout = [&](size_t lines, bool ellipsis,
5147 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5148 ParagraphStyle paragraph_style;
5149 SkPaint paint;
5150 paint.setColor(bg);
5151 text_style.setForegroundColor(paint);
5152 paragraph_style.setTextStyle(text_style);
5153 paragraph_style.setMaxLines(lines);
5154 if (ellipsis) {
5155 paragraph_style.setEllipsis(u"\u2026");
5156 }
5157 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5158 builder.addText(text);
5159 auto paragraph = builder.Build();
5160 paragraph->layout(50);
5161 paragraph->paint(canvas.get(), 0, 0);
5162 canvas.get()->translate(50, paragraph->getHeight() + 10);
5163 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5164 SkPaint background;
5165 background.setColor(SK_ColorRED);
5166 background.setStyle(SkPaint::kStroke_Style);
5167 background.setAntiAlias(true);
5168 background.setStrokeWidth(1);
5169 canvas.get()->drawRect(result.front().rect, background);
5170
5171 SkASSERT(width == paragraph->getMaxWidth());
5172 SkASSERT(height == paragraph->getHeight());
5173 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5174 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5175 };
5176
5177 SkPaint paint;
5178 paint.setColor(SK_ColorLTGRAY);
5179 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5180
5181 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005182 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5183 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005184
5185 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005186 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005187 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5188
5189 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005190 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5191 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005192}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005193
5194DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5195 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5196 if (!fontCollection->fontsFound()) return;
5197 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5198
5199 std::string text;
5200 for (size_t i = 0; i < 10; i++)
5201 {
5202 SkPaint paint;
5203 paint.setAntiAlias(true);
5204 paint.setColor(SK_ColorBLACK);
5205
5206 TextStyle textStyle;
5207 textStyle.setForegroundColor(paint);
5208 textStyle.setFontFamilies({ SkString("Roboto") });
5209
5210 ParagraphStyle paragraphStyle;
5211 paragraphStyle.setTextStyle(textStyle);
5212
5213 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5214 text += "Text ";
5215 builder.addText(text.c_str());
5216
5217 auto paragraph = builder.Build();
5218 paragraph->layout(100);
5219
5220 //used to add a delay so I can monitor memory usage
5221 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5222 }
5223};
Julia Lavrovac0360582020-02-05 10:17:53 -05005224
5225DEF_TEST(SkParagraph_FormattingInfinity, reporter) {
5226 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5227 if (!fontCollection->fontsFound()) return;
5228 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5229 TestCanvas canvas("SkParagraph_FormattingInfinity.png");
5230
5231 const char* text = "Some text\nAnother line";
5232
5233 SkPaint paint;
5234 paint.setAntiAlias(true);
5235 paint.setColor(SK_ColorBLACK);
5236
5237 TextStyle textStyle;
5238 textStyle.setForegroundColor(paint);
5239 textStyle.setFontFamilies({ SkString("Roboto") });
5240 ParagraphStyle paragraphStyle;
5241 paragraphStyle.setTextStyle(textStyle);
5242
5243 auto draw = [&](const char* prefix, TextAlign textAlign) {
5244 paragraphStyle.setTextAlign(textAlign);
5245 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5246 builder.addText(text);
5247 auto paragraph = builder.Build();
5248 paragraph->layout(SK_ScalarInfinity);
5249 paragraph->paint(canvas.get(), 0, 0);
5250 canvas.get()->translate(0, 100);
5251 };
5252
5253 draw("left", TextAlign::kLeft);
5254 draw("right", TextAlign::kRight);
5255 draw("center", TextAlign::kCenter);
5256 draw("justify", TextAlign::kJustify);
5257};
5258
5259DEF_TEST(SkParagraph_Infinity, reporter) {
5260 SkASSERT(nearlyEqual(1, SK_ScalarInfinity) == false);
5261 SkASSERT(nearlyEqual(1, SK_ScalarNegativeInfinity) == false);
5262 SkASSERT(nearlyEqual(1, SK_ScalarNaN) == false);
5263
5264 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarInfinity) == true);
5265 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNegativeInfinity) == false);
5266 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNaN) == false);
5267
5268 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarInfinity) == false);
5269 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity) == true);
5270 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNaN) == false);
5271
5272 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarInfinity) == false);
5273 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNegativeInfinity) == false);
5274 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNaN) == false);
5275};