blob: 253463706980febbc13e66c53f292a14b1470d19 [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#include <sstream>
Julia Lavrovadb543f62020-01-29 11:43:41 -05003#include <thread>
Julia Lavrovacd2d4e42020-03-27 15:40:37 -04004#include "include/core/SkFontMgr.h"
Julia Lavrova6e6333f2019-06-17 10:34:10 -04005#include "modules/skparagraph/include/TypefaceFontProvider.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04006#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
7#include "modules/skparagraph/src/ParagraphImpl.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -04008#include "modules/skparagraph/utils/TestFontCollection.h"
Julia Lavrovadb543f62020-01-29 11:43:41 -05009#include "src/core/SkFontMgrPriv.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040010#include "src/core/SkOSFile.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -040011#include "src/utils/SkOSPath.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040012#include "src/utils/SkShaperJSONWriter.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040013#include "tests/CodecPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040014#include "tests/Test.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040015#include "tools/Resources.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040016#include "tools/ToolUtils.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040017
Julia Lavrovab30d4812019-11-08 14:51:16 -050018#include "third_party/icu/SkLoadICU.h"
19
Julia Lavrovaa3552c52019-05-30 16:12:56 -040020#define VeryLongCanvasWidth 1000000
21#define TestCanvasWidth 1000
22#define TestCanvasHeight 600
23
Julia Lavrova2e30fde2019-10-09 09:43:02 -040024#define DEF_TEST_DISABLED(name, reporter) \
25static void test_##name(skiatest::Reporter* reporter, const GrContextOptions&); \
26skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \
Herb Derby126d7a22019-11-27 11:38:16 -050027void test_##name(skiatest::Reporter* reporter, const GrContextOptions&) { /* SkDebugf("Disabled:"#name "\n"); */ } \
Julia Lavrova2e30fde2019-10-09 09:43:02 -040028void disabled_##name(skiatest::Reporter* reporter, const GrContextOptions&)
29
Julia Lavrovaa3552c52019-05-30 16:12:56 -040030using namespace skia::textlayout;
31namespace {
32
Julia Lavrovadb9f6692019-08-01 16:02:17 -040033SkScalar EPSILON100 = 0.01f;
34SkScalar EPSILON50 = 0.02f;
35SkScalar EPSILON20 = 0.05f;
Julia Lavrova916a9042019-08-08 16:51:27 -040036SkScalar EPSILON10 = 0.1f;
Julia Lavrovac2228562019-08-08 16:51:27 -040037SkScalar EPSILON5 = 0.20f;
38SkScalar EPSILON2 = 0.50f;
Julia Lavrovadb9f6692019-08-01 16:02:17 -040039
Julia Lavrova5207f352019-06-21 12:22:32 -040040bool equal(const char* base, TextRange a, const char* b) {
41 return std::strncmp(b, base + a.start, a.width()) == 0;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040042}
Julia Lavrova3281b962019-12-02 11:32:25 -050043
Julia Lavrova2e30fde2019-10-09 09:43:02 -040044class ResourceFontCollection : public FontCollection {
Julia Lavrovaa3552c52019-05-30 16:12:56 -040045public:
Julia Lavrova2e30fde2019-10-09 09:43:02 -040046 ResourceFontCollection(bool testOnly = false)
Julia Lavrovaa3552c52019-05-30 16:12:56 -040047 : fFontsFound(false)
48 , fResolvedFonts(0)
49 , fResourceDir(GetResourcePath("fonts").c_str())
50 , fFontProvider(sk_make_sp<TypefaceFontProvider>()) {
51 std::vector<SkString> fonts;
52 SkOSFile::Iter iter(fResourceDir.c_str());
Julia Lavrova2e30fde2019-10-09 09:43:02 -040053
Julia Lavrovab30d4812019-11-08 14:51:16 -050054 if (!SkLoadICU()) {
55 SkDebugf("ICU not loaded, skipping all the tests\n");
56 return;
57 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040058 SkString path;
59 while (iter.next(&path)) {
60 if (path.endsWith("Roboto-Italic.ttf")) {
61 fFontsFound = true;
62 }
63 fonts.emplace_back(path);
64 }
65
66 if (!fFontsFound) {
Herb Derby126d7a22019-11-27 11:38:16 -050067 // SkDebugf("Fonts not found, skipping all the tests\n");
Julia Lavrovaa3552c52019-05-30 16:12:56 -040068 return;
69 }
70 // Only register fonts if we have to
71 for (auto& font : fonts) {
72 SkString file_path;
73 file_path.printf("%s/%s", fResourceDir.c_str(), font.c_str());
74 fFontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
75 }
76
Julia Lavrova2e30fde2019-10-09 09:43:02 -040077 if (testOnly) {
78 this->setTestFontManager(std::move(fFontProvider));
79 } else {
80 this->setAssetFontManager(std::move(fFontProvider));
81 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040082 this->disableFontFallback();
Julia Lavrovaa3552c52019-05-30 16:12:56 -040083 }
84
Julia Lavrova2e30fde2019-10-09 09:43:02 -040085 ~ResourceFontCollection() = default;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040086
87 size_t resolvedFonts() const { return fResolvedFonts; }
88
89 // TODO: temp solution until we check in fonts
90 bool fontsFound() const { return fFontsFound; }
91
92private:
93 bool fFontsFound;
94 size_t fResolvedFonts;
95 std::string fResourceDir;
96 sk_sp<TypefaceFontProvider> fFontProvider;
97};
Julia Lavrovadb9f6692019-08-01 16:02:17 -040098
99class TestCanvas {
100public:
101 TestCanvas(const char* testName) : name(testName) {
102 bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight);
103 canvas = new SkCanvas(bits);
104 canvas->clear(SK_ColorWHITE);
105 }
106
107 ~TestCanvas() {
Julia Lavrovaaae845f2019-08-16 16:44:40 -0400108 SkString tmpDir = skiatest::GetTmpDir();
109 if (!tmpDir.isEmpty()) {
110 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
111 SkFILEWStream file(path.c_str());
112 if (!SkEncodeImage(&file, bits, SkEncodedImageFormat::kPNG, 100)) {
113 SkDebugf("Cannot write a picture %s\n", name);
114 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400115 }
116 delete canvas;
117 }
118
119 void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) {
120
121 SkPaint paint;
122 if (!fill) {
123 paint.setStyle(SkPaint::kStroke_Style);
124 paint.setAntiAlias(true);
125 paint.setStrokeWidth(1);
126 }
127 paint.setColor(color);
128 for (auto& r : result) {
129 canvas->drawRect(r.rect, paint);
130 }
131 }
132
133 void drawLine(SkColor color, SkRect rect, bool vertical = true) {
134
135 SkPaint paint;
136 paint.setStyle(SkPaint::kStroke_Style);
137 paint.setAntiAlias(true);
138 paint.setStrokeWidth(1);
139 paint.setColor(color);
140 if (vertical) {
141 canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
142 } else {
143 canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint);
144 }
145 }
146
147 void drawLines(SkColor color, std::vector<TextBox>& result) {
148
149 for (auto& r : result) {
150 drawLine(color, r.rect);
151 }
152 }
153
154 SkCanvas* get() { return canvas; }
155private:
156 SkBitmap bits;
157 SkCanvas* canvas;
158 const char* name;
159};
160
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400161} // namespace
162
163DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400164 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400165 if (!fontCollection->fontsFound()) return;
166 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400167 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400168
169 ParagraphStyle paragraph_style;
170 paragraph_style.turnHintingOff();
171 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
172
173 TextStyle text_style;
174 text_style.setFontFamilies({SkString("Roboto")});
175 text_style.setColor(SK_ColorBLACK);
176 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400177 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400178 builder.pop();
179
180 auto paragraph = builder.Build();
181 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500182 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400183
184 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
185 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
186 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400187 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400188
189 size_t index = 0;
190 for (auto& line : impl->lines()) {
191 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400192 [&index, reporter]
193 (TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400194 REPORTER_ASSERT(reporter, index == 0);
195 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorBLACK);
196 ++index;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400197 });
198 }
199}
200
Julia Lavrova916a9042019-08-08 16:51:27 -0400201DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400202 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400203 TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png");
204 if (!fontCollection->fontsFound()) return;
205
206 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400207 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400208
209 ParagraphStyle paragraph_style;
210 paragraph_style.turnHintingOff();
211 paragraph_style.setMaxLines(14);
212 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
213
214 TextStyle text_style;
215 text_style.setFontFamilies({SkString("Roboto")});
216 text_style.setColor(SK_ColorBLACK);
217 text_style.setFontSize(26);
218 text_style.setWordSpacing(5);
219 text_style.setLetterSpacing(1);
220 text_style.setDecoration(TextDecoration::kUnderline);
221 text_style.setDecorationColor(SK_ColorBLACK);
222 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400223 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400224
225 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
226 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400227 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400228 builder.addPlaceholder(placeholder1);
229
230 PlaceholderStyle placeholder2(5, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
231 builder.addPlaceholder(placeholder2);
232 builder.addPlaceholder(placeholder1);
233 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400234 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400235 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400236 builder.addText(text, len);
237 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400238 builder.addPlaceholder(placeholder2);
239 builder.addPlaceholder(placeholder2);
240 builder.addPlaceholder(placeholder2);
241 builder.addPlaceholder(placeholder2);
242 builder.addPlaceholder(placeholder2);
243 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400244 builder.addText(text, len);
245 builder.addText(text, len);
246 builder.addText(text, len);
247 builder.addText(text, len);
248 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400249 builder.addPlaceholder(placeholder2);
250 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400251 builder.addText(text, len);
252 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400253
254 builder.pop();
255
256 auto paragraph = builder.Build();
257 paragraph->layout(TestCanvasWidth);
258 paragraph->paint(canvas.get(), 0, 0);
259
260 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
261 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
262
263 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
264 canvas.drawRects(SK_ColorRED, boxes);
265 REPORTER_ASSERT(reporter, boxes.size() == 1);
266
267 boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
268 canvas.drawRects(SK_ColorGREEN, boxes);
269 REPORTER_ASSERT(reporter, boxes.size() == 1);
270
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400271 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400272 canvas.drawRects(SK_ColorRED, boxes);
273
274 boxes = paragraph->getRectsForRange(4, 17, rect_height_style, rect_width_style);
275 canvas.drawRects(SK_ColorBLUE, boxes);
276
277 REPORTER_ASSERT(reporter, boxes.size() == 7);
278
Julia Lavrovac028b422019-11-25 10:00:43 -0500279 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400280 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500281 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 90.921f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400282 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 100, EPSILON100));
283
Julia Lavrovac028b422019-11-25 10:00:43 -0500284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.left(), 231.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.right(), 231.343f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400287 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.bottom(), 100, EPSILON100));
288
Julia Lavrovac028b422019-11-25 10:00:43 -0500289 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.left(), 281.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400290 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500291 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.right(), 281.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400292 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.bottom(), 50, EPSILON100));
293
Julia Lavrovac028b422019-11-25 10:00:43 -0500294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.left(), 336.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500296 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.right(), 336.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400297 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100));
298}
299
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400300DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400301 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400302 TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png");
303 if (!fontCollection->fontsFound()) return;
304
305 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400306 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400307
308 ParagraphStyle paragraph_style;
309 paragraph_style.turnHintingOff();
310 paragraph_style.setMaxLines(14);
311 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
312
313 TextStyle text_style;
314 text_style.setFontFamilies({SkString("Roboto")});
315 text_style.setColor(SK_ColorBLACK);
316 text_style.setFontSize(26);
317 text_style.setWordSpacing(5);
318 text_style.setLetterSpacing(1);
319 text_style.setDecoration(TextDecoration::kUnderline);
320 text_style.setDecorationColor(SK_ColorBLACK);
321 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400322 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400323
324 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 38.347f);
325 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400326 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400327
328 builder.pop();
329
330 auto paragraph = builder.Build();
331 paragraph->layout(TestCanvasWidth);
332 paragraph->paint(canvas.get(), 0, 0);
333
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400334 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400335 canvas.drawRects(SK_ColorRED, boxes);
336
337 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500338 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400341 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
342
343 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
344 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
345
346 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
347 canvas.drawRects(SK_ColorBLUE, boxes);
348
349 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500350 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400351 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 14.226f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400353 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400354}
Julia Lavrova916a9042019-08-08 16:51:27 -0400355
Julia Lavrova916a9042019-08-08 16:51:27 -0400356DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400357 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400358 TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png");
359 if (!fontCollection->fontsFound()) return;
360
361 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400362 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400363
364 ParagraphStyle paragraph_style;
365 paragraph_style.turnHintingOff();
366 paragraph_style.setMaxLines(14);
367 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
368
369 TextStyle text_style;
370 text_style.setFontFamilies({SkString("Roboto")});
371 text_style.setColor(SK_ColorBLACK);
372 text_style.setFontSize(26);
373 text_style.setWordSpacing(5);
374 text_style.setLetterSpacing(1);
375 text_style.setDecoration(TextDecoration::kUnderline);
376 text_style.setDecorationColor(SK_ColorBLACK);
377 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400378 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400379
380 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kAboveBaseline, TextBaseline::kAlphabetic, 903129.129308f);
381 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400382 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400383
384 builder.pop();
385
386 auto paragraph = builder.Build();
387 paragraph->layout(TestCanvasWidth);
388 paragraph->paint(canvas.get(), 0, 0);
389
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400390 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400391 canvas.drawRects(SK_ColorRED, boxes);
392
393 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500394 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400395 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.347f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500396 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 49.652f, EPSILON100));
398
399 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
400 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
401
402 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
403 canvas.drawRects(SK_ColorBLUE, boxes);
404
405 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 25.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400409 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400410}
Julia Lavrova916a9042019-08-08 16:51:27 -0400411
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400412DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400413 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400414 TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png");
415 if (!fontCollection->fontsFound()) return;
416
417 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400418 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400419
420 ParagraphStyle paragraph_style;
421 paragraph_style.turnHintingOff();
422 paragraph_style.setMaxLines(14);
423 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
424
425 TextStyle text_style;
426 text_style.setFontFamilies({SkString("Roboto")});
427 text_style.setColor(SK_ColorBLACK);
428 text_style.setFontSize(26);
429 text_style.setWordSpacing(5);
430 text_style.setLetterSpacing(1);
431 text_style.setDecoration(TextDecoration::kUnderline);
432 text_style.setDecorationColor(SK_ColorBLACK);
433 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400434 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400435
436 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBelowBaseline, TextBaseline::kAlphabetic, 903129.129308f);
437 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400438 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400439
440 builder.pop();
441
442 auto paragraph = builder.Build();
443 paragraph->layout(TestCanvasWidth);
444 paragraph->paint(canvas.get(), 0, 0);
445
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400446 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400447 canvas.drawRects(SK_ColorRED, boxes);
448
449 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500450 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400451 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500452 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400453 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
454
455 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
456 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
457
458 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
459 canvas.drawRects(SK_ColorBLUE, boxes);
460
461 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500462 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400463 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.121f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500464 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400465 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400466}
Julia Lavrova916a9042019-08-08 16:51:27 -0400467
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400468DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400469 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400470 TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png");
471 if (!fontCollection->fontsFound()) return;
472
473 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400474 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400475
476 ParagraphStyle paragraph_style;
477 paragraph_style.turnHintingOff();
478 paragraph_style.setMaxLines(14);
479 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
480
481 TextStyle text_style;
482 text_style.setFontFamilies({SkString("Roboto")});
483 text_style.setColor(SK_ColorBLACK);
484 text_style.setFontSize(26);
485 text_style.setWordSpacing(5);
486 text_style.setLetterSpacing(1);
487 text_style.setDecoration(TextDecoration::kUnderline);
488 text_style.setDecorationColor(SK_ColorBLACK);
489 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400490 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400491
492 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBottom, TextBaseline::kAlphabetic, 0);
493 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400494 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400495
496 builder.pop();
497
498 auto paragraph = builder.Build();
499 paragraph->layout(TestCanvasWidth);
500 paragraph->paint(canvas.get(), 0, 0);
501
502 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
503 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
504
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400505 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400506 canvas.drawRects(SK_ColorRED, boxes);
507 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500508 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400509 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400511 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
512
513 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
514 canvas.drawRects(SK_ColorBLUE, boxes);
515 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 19.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500518 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400519 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400520}
Julia Lavrova916a9042019-08-08 16:51:27 -0400521
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400522DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400523 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400524 TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png");
525 if (!fontCollection->fontsFound()) return;
526
527 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400528 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400529
530 ParagraphStyle paragraph_style;
531 paragraph_style.turnHintingOff();
532 paragraph_style.setMaxLines(14);
533 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
534
535 TextStyle text_style;
536 text_style.setFontFamilies({SkString("Roboto")});
537 text_style.setColor(SK_ColorBLACK);
538 text_style.setFontSize(26);
539 text_style.setWordSpacing(5);
540 text_style.setLetterSpacing(1);
541 text_style.setDecoration(TextDecoration::kUnderline);
542 text_style.setDecorationColor(SK_ColorBLACK);
543 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400544 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400545
546 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kTop, TextBaseline::kAlphabetic, 0);
547 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400548 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400549
550 builder.pop();
551
552 auto paragraph = builder.Build();
553 paragraph->layout(TestCanvasWidth);
554 paragraph->paint(canvas.get(), 0, 0);
555
556 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
557 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
558
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400559 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400560 canvas.drawRects(SK_ColorRED, boxes);
561 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500562 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400563 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500564 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400565 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
566
567 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
568 canvas.drawRects(SK_ColorBLUE, boxes);
569 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500570 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400571 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500572 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400573 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400574}
Julia Lavrova916a9042019-08-08 16:51:27 -0400575
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400576DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400577 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400578 TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png");
579 if (!fontCollection->fontsFound()) return;
580
581 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400582 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400583
584 ParagraphStyle paragraph_style;
585 paragraph_style.turnHintingOff();
586 paragraph_style.setMaxLines(14);
587 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
588
589 TextStyle text_style;
590 text_style.setFontFamilies({SkString("Roboto")});
591 text_style.setColor(SK_ColorBLACK);
592 text_style.setFontSize(26);
593 text_style.setWordSpacing(5);
594 text_style.setLetterSpacing(1);
595 text_style.setDecoration(TextDecoration::kUnderline);
596 text_style.setDecorationColor(SK_ColorBLACK);
597 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400598 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400599
600 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kMiddle, TextBaseline::kAlphabetic, 0);
601 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400602 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400603
604 builder.pop();
605
606 auto paragraph = builder.Build();
607 paragraph->layout(TestCanvasWidth);
608 paragraph->paint(canvas.get(), 0, 0);
609
610 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
611 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
612
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400613 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400614 canvas.drawRects(SK_ColorRED, boxes);
615 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500616 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400617 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500618 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400619 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
620
621 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
622 canvas.drawRects(SK_ColorBLUE, boxes);
623 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400625 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 9.765f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400627 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400628}
Julia Lavrova916a9042019-08-08 16:51:27 -0400629
Julia Lavrova916a9042019-08-08 16:51:27 -0400630DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400631 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400632 TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png");
633 if (!fontCollection->fontsFound()) return;
634
635 const char* text = "給能上目秘使";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400636 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400637
638 ParagraphStyle paragraph_style;
639 paragraph_style.turnHintingOff();
640 paragraph_style.setMaxLines(14);
641 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
642
643 TextStyle text_style;
644 text_style.setFontFamilies({SkString("Source Han Serif CN")});
645 text_style.setColor(SK_ColorBLACK);
646 text_style.setFontSize(26);
647 text_style.setWordSpacing(5);
648 text_style.setLetterSpacing(1);
649 text_style.setDecoration(TextDecoration::kUnderline);
650 text_style.setDecorationColor(SK_ColorBLACK);
651 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400652 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400653 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kIdeographic, 38.347f);
654 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400655 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400656
657 builder.pop();
658
659 auto paragraph = builder.Build();
660 paragraph->layout(TestCanvasWidth);
661 paragraph->paint(canvas.get(), 0, 0);
662
663 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
664 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
665
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400666 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400667 canvas.drawRects(SK_ColorRED, boxes);
668 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500669 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400670 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500671 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400672 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
673
674 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
675 canvas.drawRects(SK_ColorBLUE, boxes);
676 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500677 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 135.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400678 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 4.703f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500679 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400680 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400681}
Julia Lavrova916a9042019-08-08 16:51:27 -0400682
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400683DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400684 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400685 TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png");
686 if (!fontCollection->fontsFound()) return;
687
688 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400689 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400690
691 ParagraphStyle paragraph_style;
692 paragraph_style.turnHintingOff();
693 paragraph_style.setMaxLines(14);
694 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
695
696 TextStyle text_style;
697 text_style.setFontFamilies({SkString("Roboto")});
698 text_style.setColor(SK_ColorBLACK);
699 text_style.setFontSize(26);
700 text_style.setWordSpacing(5);
701 text_style.setLetterSpacing(1);
702 text_style.setDecoration(TextDecoration::kUnderline);
703 text_style.setDecorationColor(SK_ColorBLACK);
704 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400705 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400706
707 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
708 PlaceholderStyle placeholder2(25, 25, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 12.5f);
709
710 builder.addPlaceholder(placeholder1);
711 builder.addPlaceholder(placeholder1);
712 builder.addPlaceholder(placeholder1);
713 builder.addPlaceholder(placeholder2);
714 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400715 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400716
717 builder.addPlaceholder(placeholder1);
718 builder.addPlaceholder(placeholder1);
719 builder.addPlaceholder(placeholder1);
720 builder.addPlaceholder(placeholder1);
721 builder.addPlaceholder(placeholder2); // 4 + 1
722 builder.addPlaceholder(placeholder1);
723 builder.addPlaceholder(placeholder1);
724 builder.addPlaceholder(placeholder1);
725 builder.addPlaceholder(placeholder1);
726 builder.addPlaceholder(placeholder1);
727 builder.addPlaceholder(placeholder1);
728 builder.addPlaceholder(placeholder2); // 6 + 1
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(placeholder1);
736 builder.addPlaceholder(placeholder2); // 7 + 1
737
738 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400739 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400740 builder.addPlaceholder(placeholder1);
741 builder.addPlaceholder(placeholder2);
742
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400743 builder.addText(text, len);
744 builder.addText(text, len);
745 builder.addText(text, len);
746 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400747
748 builder.addPlaceholder(placeholder2);
749 builder.addPlaceholder(placeholder1);
750
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400751 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400752
753 builder.addPlaceholder(placeholder2);
754
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400755 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);
773 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400774
775 builder.pop();
776
777 auto paragraph = builder.Build();
778 paragraph->layout(TestCanvasWidth - 100);
779 paragraph->paint(canvas.get(), 0, 0);
780
781 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
782 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
783
784 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
785 canvas.drawRects(SK_ColorRED, boxes);
786 REPORTER_ASSERT(reporter, boxes.size() == 1);
787
788 boxes = paragraph->getRectsForRange(175, 176, rect_height_style, rect_width_style);
789 canvas.drawRects(SK_ColorGREEN, boxes);
790 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500791 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 31.695f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400792 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 218.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500793 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 47.292f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400794 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 249, EPSILON100));
795
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400796 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400797 canvas.drawRects(SK_ColorRED, boxes);
798
799 boxes = paragraph->getRectsForRange(4, 45, rect_height_style, rect_width_style);
800 canvas.drawRects(SK_ColorBLUE, boxes);
801 REPORTER_ASSERT(reporter, boxes.size() == 30);
Julia Lavrovac028b422019-11-25 10:00:43 -0500802 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 59.726f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400803 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.378f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500804 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400805 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56.847f, EPSILON100));
806
Julia Lavrovac028b422019-11-25 10:00:43 -0500807 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.left(), 606.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400808 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.top(), 38, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500809 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.right(), 631.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400810 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.bottom(), 63, EPSILON100));
811
Julia Lavrovac028b422019-11-25 10:00:43 -0500812 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400813 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.top(), 63.5f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500814 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.right(), 50.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400815 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400816}
Julia Lavrova916a9042019-08-08 16:51:27 -0400817
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400818DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400819 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400820 TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png");
821 if (!fontCollection->fontsFound()) return;
822
823 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400824 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400825
826 ParagraphStyle paragraph_style;
827 paragraph_style.turnHintingOff();
828 paragraph_style.setMaxLines(14);
829 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
830
831 TextStyle text_style;
832 text_style.setFontFamilies({SkString("Roboto")});
833 text_style.setColor(SK_ColorBLACK);
834 text_style.setFontSize(26);
835 text_style.setWordSpacing(5);
836 text_style.setLetterSpacing(1);
837 text_style.setDecoration(TextDecoration::kUnderline);
838 text_style.setDecorationColor(SK_ColorBLACK);
839 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400840 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400841
842 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
843 PlaceholderStyle placeholder2(5, 20, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 10);
844
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(placeholder1);
853 builder.addPlaceholder(placeholder2); // 8 + 1
854 builder.addPlaceholder(placeholder1);
855 builder.addPlaceholder(placeholder1);
856 builder.addPlaceholder(placeholder1);
857 builder.addPlaceholder(placeholder1);
858 builder.addPlaceholder(placeholder1);
859 builder.addPlaceholder(placeholder2); // 5 + 1
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);
867 builder.addPlaceholder(placeholder1); // 8 + 0
868
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400869 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400870
871 builder.addPlaceholder(placeholder1);
872 builder.addPlaceholder(placeholder2);
873 builder.addPlaceholder(placeholder2); // 1 + 2
874 builder.addPlaceholder(placeholder1);
875 builder.addPlaceholder(placeholder2);
876 builder.addPlaceholder(placeholder2); // 1 + 2
877
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400878 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);
888 builder.addText(text, len); // 11
Julia Lavrova916a9042019-08-08 16:51:27 -0400889
890 builder.addPlaceholder(placeholder2);
891 builder.addPlaceholder(placeholder1);
892 builder.addPlaceholder(placeholder2);
893 builder.addPlaceholder(placeholder1);
894 builder.addPlaceholder(placeholder2);
895
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400896 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400897
898 builder.pop();
899
900 auto paragraph = builder.Build();
901 paragraph->layout(TestCanvasWidth);
902 paragraph->paint(canvas.get(), 0, 0);
903
904 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
905 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
906
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400907 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400908 canvas.drawRects(SK_ColorRED, boxes);
909
910 REPORTER_ASSERT(reporter, boxes.size() == 34);
Julia Lavrovac028b422019-11-25 10:00:43 -0500911 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400912 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500913 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 140.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400914 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
915
Julia Lavrovac028b422019-11-25 10:00:43 -0500916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.left(), 800.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400917 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500918 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.right(), 850.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400919 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.bottom(), 50, EPSILON100));
920
Julia Lavrovac028b422019-11-25 10:00:43 -0500921 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.left(), 503.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400922 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.top(), 160, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500923 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.right(), 508.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400924 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.bottom(), 180, EPSILON100));
925
926 boxes = paragraph->getRectsForRange(30, 50, rect_height_style, rect_width_style);
927 canvas.drawRects(SK_ColorBLUE, boxes);
928
929 REPORTER_ASSERT(reporter, boxes.size() == 8);
Julia Lavrovac028b422019-11-25 10:00:43 -0500930 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 216.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400931 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500932 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 290.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400933 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 120, EPSILON100));
934
Julia Lavrovac028b422019-11-25 10:00:43 -0500935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 290.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 340.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400938 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 120, EPSILON100));
939
Julia Lavrovac028b422019-11-25 10:00:43 -0500940 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.left(), 340.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400941 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500942 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.right(), 345.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400943 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400944}
945
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400946DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400947 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400948 if (!fontCollection->fontsFound()) return;
949 const char* text = "I am RED";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400950 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400951
952 ParagraphStyle paragraph_style;
953 paragraph_style.turnHintingOff();
954 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
955
956 TextStyle text_style;
957 text_style.setFontFamilies({SkString("Roboto")});
958 text_style.setColor(SK_ColorRED);
959 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400960 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400961 builder.pop();
962
963 auto paragraph = builder.Build();
964 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500965 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400966
967 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
968 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
969 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400970 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400971
972 size_t index = 0;
973 for (auto& line : impl->lines()) {
974 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400975 [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
976 REPORTER_ASSERT(reporter, index == 0);
977 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED);
978 ++index;
979 return true;
980 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400981 }
982}
983
Julia Lavrovac2228562019-08-08 16:51:27 -0400984// Checked: DIFF+ (Space between 1 & 2 style blocks)
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400985DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400986 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400987 TestCanvas canvas("SkParagraph_RainbowParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400988 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400989 const char* text1 = "Red Roboto"; // [0:10)
990 const char* text2 = "big Greeen Default"; // [10:28)
991 const char* text3 = "Defcolor Homemade Apple"; // [28:51)
992 const char* text4 = "Small Blue Roboto"; // [51:68)
Julia Lavrovac2228562019-08-08 16:51:27 -0400993 const char* text41 = "Small Blue ";
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400994 const char* text5 =
995 "Continue Last Style With lots of words to check if it overlaps "
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400996 "properly or not"; // [68:)
997 const char* text42 =
998 "Roboto"
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400999 "Continue Last Style With lots of words to check if it overlaps "
1000 "properly or not";
1001
1002 ParagraphStyle paragraph_style;
1003 paragraph_style.turnHintingOff();
1004 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001005 paragraph_style.setMaxLines(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001006 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1007
1008 TextStyle text_style1;
1009 text_style1.setFontFamilies({SkString("Roboto")});
1010
1011 text_style1.setColor(SK_ColorRED);
1012 builder.pushStyle(text_style1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001013 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001014
1015 TextStyle text_style2;
1016 text_style2.setFontFamilies({SkString("Roboto")});
1017 text_style2.setFontSize(50);
1018 text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1019 SkFontStyle::kUpright_Slant));
1020 text_style2.setLetterSpacing(10);
1021 text_style2.setDecorationColor(SK_ColorBLACK);
1022 text_style2.setDecoration((TextDecoration)(
1023 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1024 text_style2.setWordSpacing(30);
1025 text_style2.setColor(SK_ColorGREEN);
1026 builder.pushStyle(text_style2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001027 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001028
1029 TextStyle text_style3;
1030 text_style3.setFontFamilies({SkString("Homemade Apple")});
Julia Lavrova526df262019-08-21 17:49:44 -04001031 text_style3.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001032 builder.pushStyle(text_style3);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001033 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001034
1035 TextStyle text_style4;
1036 text_style4.setFontFamilies({SkString("Roboto")});
1037 text_style4.setFontSize(14);
1038 text_style4.setDecorationColor(SK_ColorBLACK);
1039 text_style4.setDecoration((TextDecoration)(
1040 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1041 text_style4.setColor(SK_ColorBLUE);
1042 builder.pushStyle(text_style4);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001043 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001044
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001045 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001046 builder.pop();
1047
1048 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001049 paragraph->layout(1000);
1050 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001051
Julia Lavrova3281b962019-12-02 11:32:25 -05001052 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1053
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001054 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1055 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
1056 REPORTER_ASSERT(reporter, impl->styles().size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001057 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1058
1059 auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight);
1060 canvas.drawRects(SK_ColorMAGENTA, rects);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001061
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001062 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001063 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001064 StyleType::kAllAttributes,
1065 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001066 switch (index) {
1067 case 0:
1068 REPORTER_ASSERT(reporter, style.equals(text_style1));
Julia Lavrova526df262019-08-21 17:49:44 -04001069 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001070 break;
1071 case 1:
1072 REPORTER_ASSERT(reporter, style.equals(text_style2));
Julia Lavrova526df262019-08-21 17:49:44 -04001073 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001074 break;
1075 case 2:
1076 REPORTER_ASSERT(reporter, style.equals(text_style3));
Julia Lavrova526df262019-08-21 17:49:44 -04001077 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001078 break;
1079 case 3:
1080 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001081 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001082 break;
1083 default:
1084 REPORTER_ASSERT(reporter, false);
1085 break;
1086 }
1087 ++index;
1088 return true;
1089 });
1090 impl->lines()[1].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001091 StyleType::kAllAttributes,
1092 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001093 switch (index) {
1094 case 4:
1095 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001096 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001097 break;
1098 default:
1099 REPORTER_ASSERT(reporter, false);
1100 break;
1101 }
1102 ++index;
1103 return true;
1104 });
1105 REPORTER_ASSERT(reporter, index == 5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001106}
1107
1108DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001109 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001110 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001111 TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001112 const char* text = "No TextStyle! Uh Oh!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001113 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001114
1115 ParagraphStyle paragraph_style;
1116 TextStyle defaultStyle;
1117 defaultStyle.setFontFamilies({SkString("Roboto")});
1118 paragraph_style.setTextStyle(defaultStyle);
1119 paragraph_style.turnHintingOff();
1120 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001121 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001122
1123 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001124 paragraph->layout(TestCanvasWidth);
1125 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001126
Julia Lavrova3281b962019-12-02 11:32:25 -05001127 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1128
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001129 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1130
1131 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1132 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1133 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1134
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001135 size_t index = 0;
1136 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001137 StyleType::kAllAttributes,
1138 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001139 REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle()));
Julia Lavrova526df262019-08-21 17:49:44 -04001140 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001141 ++index;
1142 return true;
1143 });
1144 REPORTER_ASSERT(reporter, index == 1);
1145}
1146
1147DEF_TEST(SkParagraph_BoldParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001148 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001149 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001150 TestCanvas canvas("SkParagraph_BoldParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001151 const char* text = "This is Red max bold text!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001152 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001153
1154 ParagraphStyle paragraph_style;
1155 paragraph_style.turnHintingOff();
1156 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1157
1158 TextStyle text_style;
1159 text_style.setFontFamilies({SkString("Roboto")});
1160 text_style.setColor(SK_ColorRED);
1161 text_style.setFontSize(60);
1162 text_style.setLetterSpacing(0);
1163 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width,
1164 SkFontStyle::kUpright_Slant));
1165 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001166 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001167 builder.pop();
1168
1169 auto paragraph = builder.Build();
1170 paragraph->layout(VeryLongCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001171 paragraph->paint(canvas.get(), 10.0, 60.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001172
Julia Lavrova3281b962019-12-02 11:32:25 -05001173 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1174
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001175 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1176
1177 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1178 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1179 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1180
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001181 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001182 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001183 StyleType::kAllAttributes,
1184 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001185 REPORTER_ASSERT(reporter, style.equals(text_style));
Julia Lavrova526df262019-08-21 17:49:44 -04001186 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001187 ++index;
1188 return true;
1189 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001190 REPORTER_ASSERT(reporter, index == 1);
1191}
1192
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001193DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001194 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04001195 if (!fontCollection->fontsFound()) return;
1196 TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png");
1197 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001198 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001199
Julia Lavrovac2228562019-08-08 16:51:27 -04001200 ParagraphStyle paragraph_style;
1201 paragraph_style.turnHintingOff();
1202 paragraph_style.setMaxLines(10);
1203 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001204
Julia Lavrovac2228562019-08-08 16:51:27 -04001205 TextStyle text_style;
1206 text_style.setFontFamilies({SkString("Roboto")});
1207 text_style.setFontSize(20);
1208 text_style.setColor(SK_ColorBLACK);
1209 text_style.setHeight(3.6345f);
1210 text_style.setHeightOverride(true);
1211 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001212 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04001213 builder.pop();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001214
Julia Lavrovac2228562019-08-08 16:51:27 -04001215 auto paragraph = builder.Build();
1216 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001217
Julia Lavrovac2228562019-08-08 16:51:27 -04001218 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001219 REPORTER_ASSERT(reporter, impl->runs().size() == 5);
Julia Lavrovac2228562019-08-08 16:51:27 -04001220 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
1221 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001222
Julia Lavrovac2228562019-08-08 16:51:27 -04001223 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001224
Julia Lavrovac2228562019-08-08 16:51:27 -04001225 SkPaint paint;
1226 paint.setStyle(SkPaint::kStroke_Style);
1227 paint.setAntiAlias(true);
1228 paint.setStrokeWidth(1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001229
Julia Lavrovac2228562019-08-08 16:51:27 -04001230 // Tests for GetRectsForRange()
1231 RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle;
1232 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1233 paint.setColor(SK_ColorRED);
1234 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
1235 canvas.drawRects(SK_ColorRED, boxes);
1236 REPORTER_ASSERT(reporter, boxes.size() == 0ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001237
Julia Lavrovac2228562019-08-08 16:51:27 -04001238 boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style);
1239 canvas.drawRects(SK_ColorBLUE, boxes);
1240 REPORTER_ASSERT(reporter, boxes.size() == 3ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001241
Julia Lavrovac2228562019-08-08 16:51:27 -04001242 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100));
1243 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5));
1244 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100));
1245 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001246}
1247
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001248DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001249 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001250 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001251 TestCanvas canvas("SkParagraph_LeftAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001252 const char* text =
1253 "This is a very long sentence to test if the text will properly wrap "
1254 "around and go to the next line. Sometimes, short sentence. Longer "
1255 "sentences are okay too because they are nessecary. Very short. "
1256 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1257 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1258 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1259 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1260 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1261 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1262 "mollit anim id est laborum. "
1263 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1264 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1265 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1266 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1267 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1268 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1269 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001270 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001271
1272 ParagraphStyle paragraph_style;
1273 paragraph_style.setMaxLines(14);
1274 paragraph_style.setTextAlign(TextAlign::kLeft);
1275 paragraph_style.turnHintingOff();
1276 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1277
1278 TextStyle text_style;
1279 text_style.setFontFamilies({SkString("Roboto")});
1280 text_style.setFontSize(26);
1281 text_style.setLetterSpacing(1);
1282 text_style.setWordSpacing(5);
1283 text_style.setColor(SK_ColorBLACK);
1284 text_style.setHeight(1);
1285 text_style.setDecoration(TextDecoration::kUnderline);
1286 text_style.setDecorationColor(SK_ColorBLACK);
1287 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001288 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001289 builder.pop();
1290
1291 auto paragraph = builder.Build();
1292 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001293 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001294
1295 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001296
1297 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1298 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1299 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001300 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001301 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1302
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001303 double expected_y = 0;
1304 double epsilon = 0.01f;
1305 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1306 REPORTER_ASSERT(reporter,
1307 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1308 expected_y += 30;
1309 REPORTER_ASSERT(reporter,
1310 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1311 expected_y += 30;
1312 REPORTER_ASSERT(reporter,
1313 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1314 expected_y += 30;
1315 REPORTER_ASSERT(reporter,
1316 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1317 expected_y += 30 * 10;
1318 REPORTER_ASSERT(reporter,
1319 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1320
1321 REPORTER_ASSERT(reporter,
1322 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1323
1324 // Tests for GetGlyphPositionAtCoordinate()
1325 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0);
1326 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
1327 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
1328 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001329 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001330}
1331
1332DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001333 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001334 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001335 TestCanvas canvas("SkParagraph_RightAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001336 const char* text =
1337 "This is a very long sentence to test if the text will properly wrap "
1338 "around and go to the next line. Sometimes, short sentence. Longer "
1339 "sentences are okay too because they are nessecary. Very short. "
1340 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1341 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1342 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1343 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1344 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1345 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1346 "mollit anim id est laborum. "
1347 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1348 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1349 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1350 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1351 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1352 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1353 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001354 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001355
1356 ParagraphStyle paragraph_style;
1357 paragraph_style.setMaxLines(14);
1358 paragraph_style.setTextAlign(TextAlign::kRight);
1359 paragraph_style.turnHintingOff();
1360 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1361
1362 TextStyle text_style;
1363 text_style.setFontFamilies({SkString("Roboto")});
1364 text_style.setFontSize(26);
1365 text_style.setLetterSpacing(1);
1366 text_style.setWordSpacing(5);
1367 text_style.setColor(SK_ColorBLACK);
1368 text_style.setHeight(1);
1369 text_style.setDecoration(TextDecoration::kUnderline);
1370 text_style.setDecorationColor(SK_ColorBLACK);
1371 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001372 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001373 builder.pop();
1374
1375 auto paragraph = builder.Build();
1376 paragraph->layout(TestCanvasWidth - 100);
1377
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001378 paragraph->paint(canvas.get(), 0, 0);
1379
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001380 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001381
1382 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1383 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001384 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001385 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1386
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001387 double expected_y = 0;
1388 double epsilon = 0.01f;
1389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1390 REPORTER_ASSERT(reporter,
1391 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1392 expected_y += 30;
1393 REPORTER_ASSERT(reporter,
1394 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1395 expected_y += 30;
1396 REPORTER_ASSERT(reporter,
1397 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1398 expected_y += 30;
1399 REPORTER_ASSERT(reporter,
1400 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1401 expected_y += 30 * 10;
1402 REPORTER_ASSERT(reporter,
1403 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1404
1405 auto calculate = [](const TextLine& line) -> SkScalar {
1406 return TestCanvasWidth - 100 - line.offset().fX - line.width();
1407 };
1408
1409 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1410 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1411 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1413 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1414
1415 REPORTER_ASSERT(reporter,
1416 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1417}
1418
1419DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001420 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001421 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001422 TestCanvas canvas("SkParagraph_CenterAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001423 const char* text =
1424 "This is a very long sentence to test if the text will properly wrap "
1425 "around and go to the next line. Sometimes, short sentence. Longer "
1426 "sentences are okay too because they are nessecary. Very short. "
1427 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1428 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1429 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1430 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1431 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1432 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1433 "mollit anim id est laborum. "
1434 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1435 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1436 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1437 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1438 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1439 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1440 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001441 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001442
1443 ParagraphStyle paragraph_style;
1444 paragraph_style.setMaxLines(14);
1445 paragraph_style.setTextAlign(TextAlign::kCenter);
1446 paragraph_style.turnHintingOff();
1447 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1448
1449 TextStyle text_style;
1450 text_style.setFontFamilies({SkString("Roboto")});
1451 text_style.setFontSize(26);
1452 text_style.setLetterSpacing(1);
1453 text_style.setWordSpacing(5);
1454 text_style.setColor(SK_ColorBLACK);
1455 text_style.setHeight(1);
1456 text_style.setDecoration(TextDecoration::kUnderline);
1457 text_style.setDecorationColor(SK_ColorBLACK);
1458 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001459 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001460 builder.pop();
1461
1462 auto paragraph = builder.Build();
1463 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001464 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001465
1466 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001467
1468 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1469 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1470 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001471 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001472 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1473
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001474 double expected_y = 0;
1475 double epsilon = 0.01f;
1476 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1477 REPORTER_ASSERT(reporter,
1478 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1479 expected_y += 30;
1480 REPORTER_ASSERT(reporter,
1481 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1482 expected_y += 30;
1483 REPORTER_ASSERT(reporter,
1484 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1485 expected_y += 30;
1486 REPORTER_ASSERT(reporter,
1487 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1488 expected_y += 30 * 10;
1489 REPORTER_ASSERT(reporter,
1490 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1491
1492 auto calculate = [](const TextLine& line) -> SkScalar {
1493 return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width());
1494 };
1495
1496 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1497 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1498 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1499 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1500 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1501
1502 REPORTER_ASSERT(reporter,
1503 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1504}
1505
1506DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001507 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001508 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001509 TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001510 const char* text =
1511 "This is a very long sentence to test if the text will properly wrap "
1512 "around and go to the next line. Sometimes, short sentence. Longer "
1513 "sentences are okay too because they are nessecary. Very short. "
1514 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1515 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1516 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1517 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1518 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1519 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1520 "mollit anim id est laborum. "
1521 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1522 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1523 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1524 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1525 "velit esse cillum dolore eu fugiat.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001526 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001527
1528 ParagraphStyle paragraph_style;
1529 paragraph_style.setMaxLines(14);
1530 paragraph_style.setTextAlign(TextAlign::kJustify);
1531 paragraph_style.turnHintingOff();
1532 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1533
1534 TextStyle text_style;
1535 text_style.setFontFamilies({SkString("Roboto")});
1536 text_style.setFontSize(26);
1537 text_style.setLetterSpacing(0);
1538 text_style.setWordSpacing(5);
1539 text_style.setColor(SK_ColorBLACK);
1540 text_style.setHeight(1);
1541 text_style.setDecoration(TextDecoration::kUnderline);
1542 text_style.setDecorationColor(SK_ColorBLACK);
1543 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001544 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001545 builder.pop();
1546
1547 auto paragraph = builder.Build();
1548 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001549 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001550
Julia Lavrovac2228562019-08-08 16:51:27 -04001551 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1552 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1553 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1554 canvas.drawRects(SK_ColorRED, boxes);
1555
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001556 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001557
1558 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1559 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1560 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001561 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001562
1563 double expected_y = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001564 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001565 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001566 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001567 expected_y += 30;
1568 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001569 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001570 expected_y += 30;
1571 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001572 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001573 expected_y += 30;
1574 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001575 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001576 expected_y += 30 * 9;
1577 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001578 SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001579
1580 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001581 return line.offset().fX;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001582 };
1583
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001584 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100));
1585 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100));
1586 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100));
1587 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001588
1589 REPORTER_ASSERT(reporter,
1590 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1591}
1592
Julia Lavrovac2228562019-08-08 16:51:27 -04001593// Checked: DIFF (ghost spaces as a separate box in TxtLib)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001594DEF_TEST(SkParagraph_JustifyRTL, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001595 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001596 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001597 TestCanvas canvas("SkParagraph_JustifyRTL.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001598 const char* text =
1599 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1600 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1601 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001602 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001603
1604 ParagraphStyle paragraph_style;
1605 paragraph_style.setMaxLines(14);
1606 paragraph_style.setTextAlign(TextAlign::kJustify);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001607 paragraph_style.setTextDirection(TextDirection::kRtl);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001608 paragraph_style.turnHintingOff();
1609 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1610
1611 TextStyle text_style;
1612 text_style.setFontFamilies({SkString("Ahem")});
1613 text_style.setFontSize(26);
1614 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001615 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001616 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001617 builder.pop();
1618
1619 auto paragraph = builder.Build();
1620 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001621 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001622
1623 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001624
1625 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001626 return TestCanvasWidth - 100 - line.width();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001627 };
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001628 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001629 if (&line == &impl->lines().back()) {
1630 REPORTER_ASSERT(reporter, calculate(line) > EPSILON100);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001631 } else {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001632 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001633 }
1634 }
1635
1636 // Just make sure the the text is actually RTL
1637 for (auto& run : impl->runs()) {
1638 REPORTER_ASSERT(reporter, !run.leftToRight());
1639 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001640
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001641 // Tests for GetRectsForRange()
1642 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1643 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1644 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1645 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001646 REPORTER_ASSERT(reporter, boxes.size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001647
1648 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1649 canvas.drawRects(SK_ColorBLUE, boxes);
1650 REPORTER_ASSERT(reporter, boxes.size() == 1);
1651
1652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100));
1653 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1654 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100));
1655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1656}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001657
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001658DEF_TEST_DISABLED(SkParagraph_JustifyRTLNewLine, reporter) {
1659 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1660 if (!fontCollection->fontsFound()) return;
1661 TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png");
1662 const char* text =
1663 "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1664 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1665 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
1666
1667 auto icu_text = icu::UnicodeString::fromUTF8(text);
1668 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1669 const size_t len = strlen(text);
1670
1671 ParagraphStyle paragraph_style;
1672 paragraph_style.setMaxLines(14);
1673 paragraph_style.setTextAlign(TextAlign::kJustify);
1674 paragraph_style.setTextDirection(TextDirection::kRtl);
1675 paragraph_style.turnHintingOff();
1676 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1677
1678 TextStyle text_style;
1679 text_style.setFontFamilies({SkString("Ahem")});
1680 text_style.setFontSize(26);
1681 text_style.setColor(SK_ColorBLACK);
1682 builder.pushStyle(text_style);
1683 builder.addText(text, len);
1684 builder.pop();
1685
1686 auto paragraph = builder.Build();
1687 paragraph->layout(TestCanvasWidth - 100);
1688 paragraph->paint(canvas.get(), 0, 0);
1689
1690 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1691
1692 SkPaint paint;
1693 paint.setStyle(SkPaint::kStroke_Style);
1694 paint.setAntiAlias(true);
1695 paint.setStrokeWidth(1);
1696
1697 // Tests for GetRectsForRange()
1698 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1699 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1700 paint.setColor(SK_ColorRED);
1701 auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
1702 for (size_t i = 0; i < boxes.size(); ++i) {
1703 canvas.get()->drawRect(boxes[i].rect, paint);
1704 }
1705 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1706 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
1707 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
1708 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1709 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
1710
1711 paint.setColor(SK_ColorBLUE);
1712 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1713 for (size_t i = 0; i < boxes.size(); ++i) {
1714 canvas.get()->drawRect(boxes[i].rect, paint);
1715 }
1716 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
1717 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
1718 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1719 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
1720 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1721
1722 // All lines should be justified to the width of the
1723 // paragraph.
1724 for (auto& line : impl->lines()) {
1725 REPORTER_ASSERT(reporter,
1726 SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
1727 }
1728}
1729
1730DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
1731 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1732 if (!fontCollection->fontsFound()) return;
1733 TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
1734
1735 const char* text = " leading space";
1736
1737 auto icu_text = icu::UnicodeString::fromUTF8(text);
1738 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1739 const size_t len = strlen(text);
1740
1741 ParagraphStyle paragraph_style;
1742 paragraph_style.setMaxLines(14);
1743 paragraph_style.setTextAlign(TextAlign::kJustify);
1744 paragraph_style.setTextDirection(TextDirection::kRtl);
1745 paragraph_style.turnHintingOff();
1746 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1747
1748 TextStyle text_style;
1749 text_style.setFontFamilies({SkString("Ahem")});
1750 text_style.setFontSize(26);
1751 text_style.setColor(SK_ColorBLACK);
1752 builder.pushStyle(text_style);
1753 builder.addText(text, len);
1754 builder.pop();
1755
1756 auto paragraph = builder.Build();
1757 paragraph->layout(TestCanvasWidth - 100);
1758 paragraph->paint(canvas.get(), 0, 0);
1759
1760 SkPaint paint;
1761 paint.setStyle(SkPaint::kStroke_Style);
1762 paint.setAntiAlias(true);
1763 paint.setStrokeWidth(1);
1764
1765 // Tests for GetRectsForRange()
1766 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1767 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1768 paint.setColor(SK_ColorRED);
1769 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1770 for (size_t i = 0; i < boxes.size(); ++i) {
1771 canvas.get()->drawRect(boxes[i].rect, paint);
1772 }
1773 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1774}
1775
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001776DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001777 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001778 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001779 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001780 const char* text1 = "This text should be";
1781 const char* text2 = " decorated even when";
1782 const char* text3 = " wrapped around to";
1783 const char* text4 = " the next line.";
1784 const char* text5 = " Otherwise, bad things happen.";
1785
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001786 ParagraphStyle paragraph_style;
1787 paragraph_style.setMaxLines(14);
1788 paragraph_style.setTextAlign(TextAlign::kLeft);
1789 paragraph_style.turnHintingOff();
1790 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1791
1792 TextStyle text_style;
1793 text_style.setFontFamilies({SkString("Roboto")});
1794 text_style.setFontSize(26);
1795 text_style.setLetterSpacing(0);
1796 text_style.setWordSpacing(5);
1797 text_style.setColor(SK_ColorBLACK);
1798 text_style.setHeight(2);
1799 text_style.setDecoration(TextDecoration::kUnderline);
1800 text_style.setDecorationColor(SK_ColorBLACK);
1801 text_style.setDecoration((TextDecoration)(
1802 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1803 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1804 text_style.setDecorationColor(SK_ColorBLACK);
1805 text_style.setDecorationThicknessMultiplier(2.0);
1806 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001807 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001808
1809 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1810 text_style.setDecorationColor(SK_ColorBLUE);
1811 text_style.setDecorationThicknessMultiplier(1.0);
1812 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001813 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001814
1815 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1816 text_style.setDecorationColor(SK_ColorBLACK);
1817 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001818 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001819
1820 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1821 text_style.setDecorationColor(SK_ColorBLACK);
1822 text_style.setDecorationThicknessMultiplier(3.0);
1823 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001824 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001825
1826 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1827 text_style.setDecorationColor(SK_ColorRED);
1828 text_style.setDecorationThicknessMultiplier(1.0);
1829 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001830 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001831 builder.pop();
1832
1833 auto paragraph = builder.Build();
1834 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001835 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001836
1837 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001838
1839 size_t index = 0;
1840 for (auto& line : impl->lines()) {
1841 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001842 StyleType::kDecorations,
1843 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001844 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1845 TextDecoration::kOverline |
1846 TextDecoration::kLineThrough);
1847 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1848 switch (index) {
1849 case 0:
1850 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1851 TextDecorationStyle::kSolid);
1852 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1853 REPORTER_ASSERT(reporter,
1854 style.getDecorationThicknessMultiplier() == 2.0);
1855 break;
1856 case 1: // The style appears on 2 lines so it has 2 pieces
1857 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1858 TextDecorationStyle::kDouble);
1859 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1860 REPORTER_ASSERT(reporter,
1861 style.getDecorationThicknessMultiplier() == 1.0);
1862 break;
1863 case 2:
1864 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1865 TextDecorationStyle::kDotted);
1866 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1867 REPORTER_ASSERT(reporter,
1868 style.getDecorationThicknessMultiplier() == 1.0);
1869 break;
1870 case 3:
1871 case 4:
1872 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1873 TextDecorationStyle::kDashed);
1874 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1875 REPORTER_ASSERT(reporter,
1876 style.getDecorationThicknessMultiplier() == 3.0);
1877 break;
1878 case 5:
1879 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1880 TextDecorationStyle::kWavy);
1881 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1882 REPORTER_ASSERT(reporter,
1883 style.getDecorationThicknessMultiplier() == 1.0);
1884 break;
1885 default:
1886 REPORTER_ASSERT(reporter, false);
1887 break;
1888 }
1889 ++index;
1890 return true;
1891 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001892 }
1893}
1894
Julia Lavrovac2228562019-08-08 16:51:27 -04001895DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001896 SkDebugf("TODO: Add test for wavy decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001897}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001898
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001899DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001900 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001901 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001902 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001903 const char* text1 = "No italic ";
1904 const char* text2 = "Yes Italic ";
1905 const char* text3 = "No Italic again.";
1906
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001907 ParagraphStyle paragraph_style;
1908 paragraph_style.turnHintingOff();
1909 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1910
1911 TextStyle text_style;
1912 text_style.setFontFamilies({SkString("Roboto")});
1913 text_style.setFontSize(10);
1914 text_style.setColor(SK_ColorRED);
1915 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001916 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001917
1918 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1919 SkFontStyle::kItalic_Slant));
1920 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001921 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001922 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001923 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001924
1925 auto paragraph = builder.Build();
1926 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001927 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001928
1929 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001930
1931 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1932 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1933 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1934 auto& line = impl->lines()[0];
1935 size_t index = 0;
1936 line.scanStyles(
1937 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001938 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001939 switch (index) {
1940 case 0:
1941 REPORTER_ASSERT(
1942 reporter,
1943 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1944 break;
1945 case 1:
1946 REPORTER_ASSERT(reporter,
1947 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1948 break;
1949 case 2:
1950 REPORTER_ASSERT(
1951 reporter,
1952 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1953 break;
1954 default:
1955 REPORTER_ASSERT(reporter, false);
1956 break;
1957 }
1958 ++index;
1959 return true;
1960 });
1961}
1962
1963DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001964 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001965 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001966 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001967 const char* text =
1968 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1969 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1970 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1971 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1972 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001973 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001974
1975 ParagraphStyle paragraph_style;
1976 paragraph_style.setMaxLines(14);
1977 paragraph_style.setTextAlign(TextAlign::kJustify);
1978 paragraph_style.turnHintingOff();
1979 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1980
1981 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
1982 TextDecoration::kLineThrough);
1983
1984 TextStyle text_style;
1985 text_style.setFontFamilies({SkString("Source Han Serif CN")});
1986 text_style.setFontSize(35);
1987 text_style.setColor(SK_ColorBLACK);
1988 text_style.setLetterSpacing(2);
1989 text_style.setHeight(1);
1990 text_style.setDecoration(decoration);
1991 text_style.setDecorationColor(SK_ColorBLACK);
1992 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1993 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001994 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001995 builder.pop();
1996
1997 auto paragraph = builder.Build();
1998 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001999 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002000
Julia Lavrova3281b962019-12-02 11:32:25 -05002001 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2002
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002003 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002004
2005 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2006 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
2007 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002008 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002009}
2010
Julia Lavrovad3a32c52020-02-03 09:43:52 -05002011// Checked: disabled for TxtLib
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002012DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002013 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002014 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002015 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002016 const char* text =
2017 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2018 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002019 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002020
2021 ParagraphStyle paragraph_style;
2022 paragraph_style.setMaxLines(14);
2023 paragraph_style.setTextAlign(TextAlign::kJustify);
2024 paragraph_style.turnHintingOff();
2025 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2026
2027 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2028 TextDecoration::kLineThrough);
2029
2030 TextStyle text_style;
2031 text_style.setFontFamilies({SkString("Katibeh")});
2032 text_style.setFontSize(35);
2033 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002034 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002035 text_style.setDecoration(decoration);
2036 text_style.setDecorationColor(SK_ColorBLACK);
2037 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2038 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002039 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002040 builder.pop();
2041
2042 auto paragraph = builder.Build();
2043 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002044 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002045
Julia Lavrova3281b962019-12-02 11:32:25 -05002046 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2047
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002048 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002049
2050 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2051 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2052 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002053 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002054}
2055
Julia Lavrovac2228562019-08-08 16:51:27 -04002056// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002057DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
2058
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002059 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002060 if (!fontCollection->fontsFound()) return;
2061 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
2062 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002063 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002064
2065 ParagraphStyle paragraph_style;
2066 paragraph_style.turnHintingOff();
2067 paragraph_style.setMaxLines(14);
2068 paragraph_style.setTextAlign(TextAlign::kRight);
2069 paragraph_style.setTextDirection(TextDirection::kRtl);
2070 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2071
2072 TextStyle text_style;
2073 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2074 text_style.setFontSize(26);
2075 text_style.setWordSpacing(5);
2076 text_style.setColor(SK_ColorBLACK);
2077 text_style.setDecoration(TextDecoration::kUnderline);
2078 text_style.setDecorationColor(SK_ColorBLACK);
2079 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002080 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002081 builder.pop();
2082
2083 auto paragraph = builder.Build();
2084 paragraph->layout(TestCanvasWidth - 100);
2085
2086 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2087 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2088
2089 paragraph->paint(canvas.get(), 0, 0);
2090
2091 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2092 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2093 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
2094 canvas.drawRects(SK_ColorRED, boxes);
2095
Julia Lavrovac2228562019-08-08 16:51:27 -04002096 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002097
Julia Lavrovac2228562019-08-08 16:51:27 -04002098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
2099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002100 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
2101 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002102}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002103
2104// Checked DIFF+
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002105// This test shows now 2 boxes for [36:40) range:
2106// [36:38) for arabic text and [38:39) for the last space
2107// that has default paragraph direction (LTR) and is placed at the end of the paragraph
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002108DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
2109
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002110 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002111 if (!fontCollection->fontsFound()) return;
2112 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
2113 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002114 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002115
2116 ParagraphStyle paragraph_style;
2117 paragraph_style.turnHintingOff();
2118 paragraph_style.setMaxLines(14);
2119 paragraph_style.setTextAlign(TextAlign::kLeft);
2120 paragraph_style.setTextDirection(TextDirection::kLtr);
2121 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2122
2123 TextStyle text_style;
2124 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2125 text_style.setFontSize(26);
2126 text_style.setWordSpacing(5);
2127 text_style.setColor(SK_ColorBLACK);
2128 text_style.setDecoration(TextDecoration::kUnderline);
2129 text_style.setDecorationColor(SK_ColorBLACK);
2130 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002131 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002132 builder.pop();
2133
2134 auto paragraph = builder.Build();
2135 paragraph->layout(TestCanvasWidth - 100);
2136
2137 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2138 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2139
2140 paragraph->paint(canvas.get(), 0, 0);
2141
2142 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2143 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002144 // 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 -04002145 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2146 canvas.drawRects(SK_ColorRED, boxes);
2147
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002148 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
2149 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.92f, EPSILON100)); // DIFF: 89.40625
2150 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2151 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 110.16f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002152 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002153}
2154
2155// Checked DIFF+
2156DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2157
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002158 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002159 if (!fontCollection->fontsFound()) return;
2160 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2161 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002162 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002163
2164 ParagraphStyle paragraph_style;
2165 paragraph_style.turnHintingOff();
2166 paragraph_style.setMaxLines(14);
2167 paragraph_style.setTextAlign(TextAlign::kRight);
2168 paragraph_style.setTextDirection(TextDirection::kLtr);
2169 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2170
2171 TextStyle text_style;
2172 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2173 text_style.setFontSize(26);
2174 text_style.setWordSpacing(5);
2175 text_style.setColor(SK_ColorBLACK);
2176 text_style.setDecoration(TextDecoration::kUnderline);
2177 text_style.setDecorationColor(SK_ColorBLACK);
2178 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002179 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002180 builder.pop();
2181
2182 auto paragraph = builder.Build();
2183 paragraph->layout(TestCanvasWidth - 100);
2184
2185 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2186 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2187
2188 paragraph->paint(canvas.get(), 0, 0);
2189
2190 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2191 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2192 std::vector<TextBox> boxes =
2193 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2194 canvas.drawRects(SK_ColorRED, boxes);
2195
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002196 REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF
2197 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.5f, EPSILON100)); // DIFF
2198 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2199 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 587.74f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002200 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002201}
2202
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002203DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002204 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002205 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002206 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002207 const char* text =
2208 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2209 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002210 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002211
2212 ParagraphStyle paragraphStyle;
2213 paragraphStyle.setTextAlign(TextAlign::kLeft);
2214 paragraphStyle.setMaxLines(10);
2215 paragraphStyle.turnHintingOff();
2216 TextStyle textStyle;
2217 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002218 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2219 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002220 textStyle.setFontSize(50);
2221 textStyle.setLetterSpacing(1);
2222 textStyle.setWordSpacing(5);
2223 textStyle.setHeight(1);
2224 textStyle.setColor(SK_ColorBLACK);
2225
2226 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2227 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002228 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002229 builder.pop();
2230
2231 auto paragraph = builder.Build();
2232 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002233 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002234
2235 // Tests for getGlyphPositionAtCoordinate()
2236 // NOTE: resulting values can be a few off from their respective positions in
2237 // the original text because the final trailing whitespaces are sometimes not
2238 // drawn (namely, when using "justify" alignment) and therefore are not active
2239 // glyphs.
2240 REPORTER_ASSERT(reporter,
2241 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2242 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2243 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2244 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2245 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2246 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002247 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002248 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2249 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2250 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002251 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002252 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002253 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002254 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2255 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002256 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002257 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2258 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002259 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002260 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2261 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2262 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002263 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002264 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2265}
2266
2267DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002268 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002269 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002270 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002271 const char* text =
2272 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2273 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002274 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002275
2276 ParagraphStyle paragraphStyle;
2277 paragraphStyle.setTextAlign(TextAlign::kLeft);
2278 paragraphStyle.setMaxLines(10);
2279 paragraphStyle.turnHintingOff();
2280 TextStyle textStyle;
2281 textStyle.setFontFamilies({SkString("Roboto")});
2282 textStyle.setFontSize(50);
2283 textStyle.setColor(SK_ColorBLACK);
2284 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2285 SkFontStyle::kUpright_Slant));
2286
2287 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2288 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002289 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002290 builder.pop();
2291
2292 auto paragraph = builder.Build();
2293 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002294 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002295
2296 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2297 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002298
2299 SkPaint paint;
2300 paint.setStyle(SkPaint::kStroke_Style);
2301 paint.setAntiAlias(true);
2302 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002303
2304 {
2305 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2306 REPORTER_ASSERT(reporter, result.empty());
2307 }
2308 {
2309 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002310 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002311 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2313 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2314 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2315 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002316 }
2317 {
2318 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002319 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002320 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2323 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2324 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002325 }
2326 {
2327 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002328 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002329 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002330 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2333 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002334 }
2335 {
2336 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002337 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002338 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2341 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2342 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2343 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2344 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2345 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2346 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002347 }
2348 {
2349 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002350 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002351 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002353 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002354 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002355 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002356 }
2357 {
2358 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2359 REPORTER_ASSERT(reporter, result.empty());
2360 }
2361}
2362
2363DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002364 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002365 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002366 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002367 const char* text =
2368 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2369 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2370 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002371 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002372
2373 ParagraphStyle paragraphStyle;
2374 paragraphStyle.setTextAlign(TextAlign::kLeft);
2375 paragraphStyle.setMaxLines(10);
2376 paragraphStyle.turnHintingOff();
2377 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002378 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002379 textStyle.setFontSize(50);
2380 textStyle.setColor(SK_ColorBLACK);
2381 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2382 SkFontStyle::kUpright_Slant));
2383
2384 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2385 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002386 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002387 builder.pop();
2388
2389 auto paragraph = builder.Build();
2390 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002391 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002392
2393 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2394 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002395 {
2396 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2397 REPORTER_ASSERT(reporter, result.empty());
2398 }
2399 {
2400 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002401 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002402 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002403 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2404 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002407 }
2408 {
2409 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002410 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002411 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2413 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002416 }
2417 {
2418 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002419 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002420 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002421 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2423 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2424 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002425 }
2426}
2427
Julia Lavrovac2228562019-08-08 16:51:27 -04002428// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002429DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002430 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002431 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002432 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002433 const char* text =
2434 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2435 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2436 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002437 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002438
2439 ParagraphStyle paragraphStyle;
2440 paragraphStyle.setTextAlign(TextAlign::kLeft);
2441 paragraphStyle.setMaxLines(10);
2442 paragraphStyle.turnHintingOff();
2443 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002444 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002445 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002446 textStyle.setHeight(1.6f);
2447 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002448 textStyle.setColor(SK_ColorBLACK);
2449 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2450 SkFontStyle::kUpright_Slant));
2451
2452 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2453 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002454 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002455 builder.pop();
2456
2457 auto paragraph = builder.Build();
2458 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002459 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002460
2461 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002462 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002463 {
2464 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2465 REPORTER_ASSERT(reporter, result.empty());
2466 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002467
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002468 {
2469 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002470 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002471 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002472 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2473 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2474 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002476 }
2477 {
2478 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002479 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002480 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002481 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2482 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2483 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002485 }
2486 {
2487 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002488 canvas.drawRects(SK_ColorGREEN, result);
2489 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002490 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002491 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002492 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002494 }
2495 {
2496 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002497 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002498 REPORTER_ASSERT(reporter, result.size() == 8);
2499
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002500 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002501 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2504
2505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2506 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2508 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2509
2510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2511 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002512 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002513 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2514
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2518 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2519
2520 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2521 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2522 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2523 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2524
2525 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2526 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2527 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2528 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002529 }
2530 {
2531 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002532 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002533 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002536 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002537 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2538
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002539 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002540 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2541 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2542 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002543 }
2544 {
2545 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2546 REPORTER_ASSERT(reporter, result.empty());
2547 }
2548}
2549
Julia Lavrovac2228562019-08-08 16:51:27 -04002550// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002551DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002552 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002553 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002554 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002555 const char* text =
2556 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2557 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2558 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002559 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002560
2561 ParagraphStyle paragraphStyle;
2562 paragraphStyle.setTextAlign(TextAlign::kLeft);
2563 paragraphStyle.setMaxLines(10);
2564 paragraphStyle.turnHintingOff();
2565 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002566 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002567 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002568 textStyle.setHeight(1.6f);
2569 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002570 textStyle.setColor(SK_ColorBLACK);
2571 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2572 SkFontStyle::kUpright_Slant));
2573
2574 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2575 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002576 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002577 builder.pop();
2578
2579 auto paragraph = builder.Build();
2580 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002581 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002582
2583 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002584 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002585 {
2586 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2587 REPORTER_ASSERT(reporter, result.empty());
2588 }
2589
2590 {
2591 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002592 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002593 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002594 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2595 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2596 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2597 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002598 }
2599 {
2600 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002601 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002602 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002603 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2604 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2605 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2606 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002607 }
2608 {
2609 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002610 canvas.drawRects(SK_ColorGREEN, result);
2611 REPORTER_ASSERT(reporter, result.size() == 1);
2612 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2613 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2614 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2615 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002616 }
2617 {
2618 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002619 canvas.drawRects(SK_ColorMAGENTA, result);
2620 REPORTER_ASSERT(reporter, result.size() == 8);
2621
2622 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2623 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2625 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2626
2627 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2628 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2629 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2630 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2631
2632 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2633 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2634 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2635 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2636
2637 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2638 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2639 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2640 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2641
2642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2643 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2644 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2645 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2646
2647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002651 }
2652 {
2653 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002654 canvas.drawRects(SK_ColorBLACK, result);
2655 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002659 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2660
2661 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2662 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2663 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2664 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002665 }
2666 {
2667 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2668 REPORTER_ASSERT(reporter, result.empty());
2669 }
2670}
2671
Julia Lavrovac2228562019-08-08 16:51:27 -04002672// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002673DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002674 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002675 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002676 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002677 const char* text =
2678 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2679 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2680 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002681 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002682
2683 ParagraphStyle paragraphStyle;
2684 paragraphStyle.setTextAlign(TextAlign::kLeft);
2685 paragraphStyle.setMaxLines(10);
2686 paragraphStyle.turnHintingOff();
2687 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002688 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002689 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002690 textStyle.setHeight(1.6f);
2691 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002692 textStyle.setColor(SK_ColorBLACK);
2693 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2694 SkFontStyle::kUpright_Slant));
2695
2696 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2697 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002698 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002699 builder.pop();
2700
2701 auto paragraph = builder.Build();
2702 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002703 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002704
2705 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002706 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002707 {
2708 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2709 REPORTER_ASSERT(reporter, result.empty());
2710 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002711
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002712 {
2713 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002714 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002715 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002716 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2717 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2718 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2719 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002720 }
2721 {
2722 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002723 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002724 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002725 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2726 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2727 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2728 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002729 }
2730 {
2731 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002732 canvas.drawRects(SK_ColorGREEN, result);
2733 REPORTER_ASSERT(reporter, result.size() == 1);
2734 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2735 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2736 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
2737 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002738 }
2739 {
2740 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002741 canvas.drawRects(SK_ColorMAGENTA, result);
2742 REPORTER_ASSERT(reporter, result.size() == 8);
2743
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002744 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002745 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2746 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2747 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2748
2749 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2750 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2751 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2752 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2753
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002754 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002755 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2756 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2757 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2758
2759 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2760 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2761 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2762 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2763
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002764 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002765 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2766 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2767 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2768
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002769 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002770 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2771 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2772 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002773 }
2774 {
2775 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002776 canvas.drawRects(SK_ColorBLACK, result);
2777 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002778 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002780 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002781 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2782
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002783 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002784 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2785 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2786 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002787 }
2788 {
2789 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2790 REPORTER_ASSERT(reporter, result.empty());
2791 }
2792}
2793
Julia Lavrova2813d452020-03-03 11:43:40 -05002794// This is the test I cannot accommodate
2795// Any text range gets a smallest glyph rectangle
2796DEF_TEST_DISABLED(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002797 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002798 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002799 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002800 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002801 const size_t len = strlen(text);
2802
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002803 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002804 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002805 paragraphStyle.setMaxLines(10);
2806 paragraphStyle.turnHintingOff();
2807 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2808
2809 TextStyle textStyle;
2810 textStyle.setFontFamilies({SkString("Roboto")});
2811 textStyle.setFontSize(50);
2812 textStyle.setLetterSpacing(1);
2813 textStyle.setWordSpacing(5);
2814 textStyle.setHeight(1);
2815 textStyle.setColor(SK_ColorBLACK);
2816
2817 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002818 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002819 builder.pop();
2820
2821 auto paragraph = builder.Build();
2822 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002823 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002824
2825 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002826 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2827
2828 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2829 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2830 {
2831 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2832 REPORTER_ASSERT(reporter, result.empty());
2833 }
2834 {
2835 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2836 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2837 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002838 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2839 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002840 }
2841 {
2842 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2843 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2844 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002845 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2846 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002847 }
2848 {
2849 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2850 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2851 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2852 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002853 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002854 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002855 }
2856}
2857
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002858// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002859DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002860 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002861 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002862 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002863 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2864 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2865 // Any attempt to substitute one for another leads to errors
2866 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002867 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002868 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002869
2870 ParagraphStyle paragraphStyle;
2871 paragraphStyle.setTextAlign(TextAlign::kCenter);
2872 paragraphStyle.setMaxLines(10);
2873 paragraphStyle.turnHintingOff();
2874 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2875
2876 TextStyle textStyle;
2877 textStyle.setFontFamilies({SkString("Roboto")});
2878 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002879 textStyle.setHeight(1);
2880 textStyle.setColor(SK_ColorBLACK);
2881 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2882 SkFontStyle::kUpright_Slant));
2883
2884 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002885 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002886 builder.pop();
2887
2888 auto paragraph = builder.Build();
2889 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002890 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002891
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002892 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002893 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2894 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002895 {
2896 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2897 REPORTER_ASSERT(reporter, result.empty());
2898 }
2899
2900 {
2901 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002902 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002903 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002904 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2905 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2906 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2907 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002908 }
2909
2910 {
2911 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002912 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002913 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002914 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2915 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2917 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002918 }
2919
2920 {
2921 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002922 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002923 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002924 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2925 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2926 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2927 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002928 }
2929
2930 {
2931 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002932 canvas.drawRects(SK_ColorBLACK, result);
2933 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002938 }
2939
2940 {
2941 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002942 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002943 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002944 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2945 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2946 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2947 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002948 }
2949
2950 {
2951 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2952 REPORTER_ASSERT(reporter, result.empty());
2953 }
2954}
2955
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002956// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002957DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002958 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002959 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002960 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002961 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002962 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002963
2964 ParagraphStyle paragraphStyle;
2965 paragraphStyle.setTextAlign(TextAlign::kCenter);
2966 paragraphStyle.setMaxLines(10);
2967 paragraphStyle.turnHintingOff();
2968 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2969
2970 TextStyle textStyle;
2971 textStyle.setFontFamilies({SkString("Roboto")});
2972 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002973 textStyle.setHeight(1);
2974 textStyle.setColor(SK_ColorBLACK);
2975 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2976 SkFontStyle::kUpright_Slant));
2977
2978 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002979 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002980 builder.pop();
2981
2982 auto paragraph = builder.Build();
2983 paragraph->layout(550);
2984
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002985 paragraph->paint(canvas.get(), 0, 0);
2986
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002987 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002988 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2989
2990 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2991 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002992 {
2993 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2994 REPORTER_ASSERT(reporter, result.empty());
2995 }
2996
2997 {
2998 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04002999 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003000 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003001 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
3002 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
3003 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
3004 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003005 }
3006
3007 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003008 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3009 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003010 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003011 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3012 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3013 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3014 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003015 }
3016}
3017
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003018// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003019DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003020 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003021 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003022 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3023 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003024 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003025
3026 ParagraphStyle paragraphStyle;
3027 paragraphStyle.setTextAlign(TextAlign::kCenter);
3028 paragraphStyle.setMaxLines(10);
3029 paragraphStyle.turnHintingOff();
3030 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3031
3032 TextStyle textStyle;
3033 textStyle.setFontFamilies({SkString("Roboto")});
3034 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003035 textStyle.setHeight(1);
3036 textStyle.setColor(SK_ColorBLACK);
3037 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3038 SkFontStyle::kUpright_Slant));
3039
3040 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003041 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003042 builder.pop();
3043
3044 auto paragraph = builder.Build();
3045 paragraph->layout(550);
3046
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003047 paragraph->paint(canvas.get(), 0, 0);
3048
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003049 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003050
3051 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3052
3053 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3054 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3055 SkScalar epsilon = 0.01f;
3056 {
3057 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3058 REPORTER_ASSERT(reporter, result.empty());
3059 }
3060 {
3061 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003062 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003063 REPORTER_ASSERT(reporter, result.size() == 1);
3064 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3065 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3066 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3067 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3068 }
3069 {
3070 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003071 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003072 REPORTER_ASSERT(reporter, result.size() == 1);
3073 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3074 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3075 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3076 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3077 }
3078 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003079 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003080 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003081 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003082 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3083 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003084 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003085 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3086 }
3087 {
3088 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003089 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003090 REPORTER_ASSERT(reporter, result.size() == 1);
3091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003093 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003094 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3095 }
3096 {
3097 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003098 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003099 REPORTER_ASSERT(reporter, result.size() == 1);
3100 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3101 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3102 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3103 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3104 }
3105 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003106 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003107 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003108 REPORTER_ASSERT(reporter, result.size() == 1);
3109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003111 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003112 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3113 }
3114 {
3115 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3116 REPORTER_ASSERT(reporter, result.empty());
3117 }
3118}
3119
Julia Lavrovac2228562019-08-08 16:51:27 -04003120// Checked: DIFF (line height rounding error)
3121DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003122 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003123 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003124 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3125 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003126 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003127
3128 StrutStyle strutStyle;
3129 strutStyle.setStrutEnabled(true);
3130 strutStyle.setFontFamilies({SkString("Roboto")});
3131 strutStyle.setFontSize(14.0);
3132
3133 ParagraphStyle paragraphStyle;
3134 paragraphStyle.setStrutStyle(strutStyle);
3135
3136 TextStyle textStyle;
3137 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3138 textStyle.setFontSize(20);
3139 textStyle.setColor(SK_ColorBLACK);
3140
3141 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3142 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003143 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003144 builder.pop();
3145
3146 auto paragraph = builder.Build();
3147 paragraph->layout(550);
3148 paragraph->paint(canvas.get(), 0, 0);
3149
3150 {
3151 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3152 canvas.drawRects(SK_ColorGREEN, result);
3153 REPORTER_ASSERT(reporter, result.size() == 1);
3154 }
3155
3156 {
3157 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3158 canvas.drawRects(SK_ColorRED, result);
3159 REPORTER_ASSERT(reporter, result.size() == 1);
3160 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3161 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3162 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3163 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3164 }
3165}
3166
3167// Checked: NO DIFF
3168DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003169 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003170 if (!fontCollection->fontsFound()) return;
3171 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3172 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003173 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003174
3175 StrutStyle strutStyle;
3176 strutStyle.setStrutEnabled(false);
3177
3178 ParagraphStyle paragraphStyle;
3179 paragraphStyle.setStrutStyle(strutStyle);
3180
3181 TextStyle textStyle;
3182 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3183 textStyle.setFontSize(20);
3184 textStyle.setColor(SK_ColorBLACK);
3185
3186 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3187 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003188 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003189 builder.pop();
3190
3191 auto paragraph = builder.Build();
3192 paragraph->layout(550);
3193 paragraph->paint(canvas.get(), 0, 0);
3194
3195
3196 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3197 canvas.drawRects(SK_ColorGREEN, result1);
3198 REPORTER_ASSERT(reporter, result1.size() == 1);
3199
3200 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3201 canvas.drawRects(SK_ColorRED, result2);
3202 REPORTER_ASSERT(reporter, result2.size() == 1);
3203
3204 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3205}
3206
3207// Checked: DIFF (small in numbers)
3208DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003209 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003210 if (!fontCollection->fontsFound()) return;
3211 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003212 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3213 "67890 12345 67890 12345 67890 12345";
3214 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003215 ParagraphStyle paragraphStyle;
3216 paragraphStyle.setTextAlign(TextAlign::kLeft);
3217 paragraphStyle.setMaxLines(10);
3218 paragraphStyle.turnHintingOff();
3219 TextStyle textStyle;
3220 textStyle.setFontFamilies({SkString("Roboto")});
3221 textStyle.setFontSize(52);
3222 textStyle.setLetterSpacing(1.19039f);
3223 textStyle.setWordSpacing(5);
3224 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003225 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003226 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003227
3228 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3229 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003230 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003231 builder.pop();
3232
3233 auto paragraph = builder.Build();
3234 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003235 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003236
3237 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3238 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3239 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3240 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3241 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003242 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3243 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003244
3245 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003246 boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003247 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003248
Julia Lavrovac2228562019-08-08 16:51:27 -04003249 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003250 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003251 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003252
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003253 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3254 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3255 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3256 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3257 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3258 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3259 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3260 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3261
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003262 boxes = paragraph->getRectsForRange(12, 13, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003263 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003264 boxes = paragraph->getRectsForRange(13, 14, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003265 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003266 boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003267 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003268 boxes = paragraph->getRectsForRange(19, 20, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003269 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003270 boxes = paragraph->getRectsForRange(24, 25, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003271 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003272 boxes = paragraph->getRectsForRange(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003273 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003274 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003275 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003276 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003277 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003278
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003279 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3280 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003281}
3282
Julia Lavrovac2228562019-08-08 16:51:27 -04003283// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003284DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003285 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003286 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003287 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003288 ParagraphStyle paragraph_style;
3289 paragraph_style.setMaxLines(10);
3290 paragraph_style.setTextAlign(TextAlign::kLeft);
3291 paragraph_style.turnHintingOff();
3292 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3293
3294 TextStyle text_style;
3295 text_style.setFontFamilies({SkString("Roboto")});
3296 text_style.setFontSize(50);
3297 text_style.setLetterSpacing(20);
3298 text_style.setWordSpacing(0);
3299 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003300 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003301 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003302 builder.pop();
3303
3304 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003305 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003306 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003307 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003308 builder.pop();
3309
3310 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003311 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003312 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003313 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003314 builder.pop();
3315
3316 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003317 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003318 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003319 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003320 builder.pop();
3321
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003322 const char* hSpace = "H ";
3323 const size_t len = strlen(hSpace);
3324
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003325 text_style.setLetterSpacing(0);
3326 text_style.setWordSpacing(20);
3327 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003328 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003329 builder.pop();
3330
3331 text_style.setLetterSpacing(0);
3332 text_style.setWordSpacing(0);
3333 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003334 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003335 builder.pop();
3336
3337 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003338 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003339 text_style.setWordSpacing(20);
3340 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003341 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003342 builder.pop();
3343
3344 auto paragraph = builder.Build();
3345 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003346 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003347
3348 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3349 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3350 size_t index = 0;
3351 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003352 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3353 ++index;
3354 return true;
3355 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003356 REPORTER_ASSERT(reporter, index == 4);
3357 index = 0;
3358 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003359 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3360 ++index;
3361 return true;
3362 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003363 REPORTER_ASSERT(reporter, index == 4);
3364}
3365
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003366// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003367DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003368 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003369 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003370 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003371 const char* text =
3372 "A "
3373 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3374 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003375 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003376
3377 ParagraphStyle paragraph_style;
3378 paragraph_style.turnHintingOff();
3379 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3380
3381 TextStyle text_style;
3382 text_style.setFontFamilies({SkString("Roboto")});
3383 text_style.setColor(SK_ColorRED);
3384 text_style.setFontSize(31);
3385 text_style.setLetterSpacing(0);
3386 text_style.setWordSpacing(0);
3387 text_style.setColor(SK_ColorBLACK);
3388 text_style.setHeight(1);
3389 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003390 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003391 builder.pop();
3392
3393 auto paragraph = builder.Build();
3394 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003395 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003396
3397 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3398 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3399 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3400 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003401 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003402 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3403
3404 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3405 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3406 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3407}
3408
Julia Lavrovac2228562019-08-08 16:51:27 -04003409// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003410DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003411 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003412 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003413 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3414
3415 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3416 const char* text2 = " Dialog Text List lots of words to see "
3417 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003418 float scale = 3.0f;
3419 ParagraphStyle paragraph_style;
3420 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3421 TextStyle text_style;
3422 text_style.setFontFamilies({SkString("Droid Serif")});
3423 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003424 text_style.setColor(SK_ColorBLACK);
3425
3426 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003427 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003428 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003429 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003430 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003431 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003432 text_style.setFontSize(14 / scale);
3433 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003434 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003435 builder.pop();
3436
3437 auto paragraph = builder.Build();
3438 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003439 canvas.get()->scale(scale, scale);
3440 paragraph->paint(canvas.get(), 0, 0);
3441 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003442
3443 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003444
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003445 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003446 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003447 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3448 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3449 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3450 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3451 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3452 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003453}
3454
Julia Lavrovac2228562019-08-08 16:51:27 -04003455// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003456DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003457 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003458 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003459 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003460 const char* text =
3461 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3462 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003463 const size_t len = strlen(text);
3464
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003465 ParagraphStyle paragraph_style;
3466 paragraph_style.turnHintingOff();
3467 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3468
3469 TextStyle text_style;
3470 text_style.setFontFamilies({SkString("Roboto")});
3471 text_style.setColor(SK_ColorRED);
3472 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003473 text_style.setColor(SK_ColorBLACK);
3474 text_style.setHeight(1);
3475 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003476 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003477 builder.pop();
3478
3479 auto paragraph = builder.Build();
3480 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003481 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003482
3483 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3484 // Minikin does not count empty lines but SkParagraph does
3485 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3486
3487 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3488 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3489 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3490 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3491 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003492 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3493 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003494}
3495
Julia Lavrova526df262019-08-21 17:49:44 -04003496// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003497DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003498 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003499 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003500 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3501 const char* text =
3502 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3503 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3504 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3505 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003506 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003507
3508 ParagraphStyle paragraph_style;
3509 paragraph_style.turnHintingOff();
3510 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3511
3512 TextStyle text_style;
3513 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3514 text_style.setFontSize(50);
3515 text_style.setDecoration(TextDecoration::kUnderline);
3516 text_style.setColor(SK_ColorBLACK);
3517 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003518 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003519 builder.pop();
3520
3521 auto paragraph = builder.Build();
3522 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003523 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003524
Julia Lavrova3281b962019-12-02 11:32:25 -05003525 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3526
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003527 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003528
3529 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3530 for (auto& line : impl->lines()) {
3531 if (&line != impl->lines().end() - 1) {
3532 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3533 } else {
3534 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3535 }
3536 REPORTER_ASSERT(reporter, line.height() == 59);
3537 }
3538}
3539
Julia Lavrovac2228562019-08-08 16:51:27 -04003540// Checked: DIFF+
3541DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003542 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003543 if (!fontCollection->fontsFound()) return;
3544 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3545 const char* text =
3546 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3547 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3548 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3549 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3550 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3551 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003552 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003553
3554 ParagraphStyle paragraph_style;
3555 paragraph_style.turnHintingOff();
3556 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3557
3558 TextStyle text_style;
3559 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3560 text_style.setFontSize(50);
3561 text_style.setColor(SK_ColorBLACK);
3562 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003563 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003564 builder.pop();
3565
3566 auto paragraph = builder.Build();
3567 paragraph->layout(TestCanvasWidth - 300);
3568 paragraph->paint(canvas.get(), 0, 0);
3569
3570 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3571 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3572
3573 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3574 REPORTER_ASSERT(reporter, result.size() == 0);
3575
3576 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3577 REPORTER_ASSERT(reporter, result.size() == 2);
3578 canvas.drawRects(SK_ColorRED, result);
3579
3580 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrova2813d452020-03-03 11:43:40 -05003581 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04003582 canvas.drawRects(SK_ColorBLUE, result);
3583
3584 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3585 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3586 REPORTER_ASSERT(reporter, result.size() == 2);
3587 canvas.drawRects(SK_ColorGREEN, result);
3588
3589 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3590 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3591 REPORTER_ASSERT(reporter, result.size() == 2);
3592 canvas.drawRects(SK_ColorGREEN, result);
3593
3594 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3595 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3596 REPORTER_ASSERT(reporter, result.size() == 2);
3597 canvas.drawRects(SK_ColorGREEN, result);
3598}
3599
Julia Lavrova916a9042019-08-08 16:51:27 -04003600DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3601 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3602}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003603
Julia Lavrovac2228562019-08-08 16:51:27 -04003604// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003605DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003606 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003607 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003608 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003609 const char* text =
3610 "Sentence to layout at diff widths to get diff line counts. short words "
3611 "short words short words short words short words short words short words "
3612 "short words short words short words short words short words short words "
3613 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003614 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003615
3616 ParagraphStyle paragraph_style;
3617 paragraph_style.turnHintingOff();
3618 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3619
3620 TextStyle text_style;
3621 text_style.setFontFamilies({SkString("Roboto")});
3622 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003623 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003624 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003625 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003626 builder.pop();
3627
3628 auto paragraph = builder.Build();
3629 paragraph->layout(300);
3630
3631 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3632 // Some of the formatting lazily done on paint
3633 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3634 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3635 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3636
3637 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003638 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003639 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3640 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3641 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3642}
3643
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003644// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003645DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003646 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003647 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003648 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003649 const char* text =
3650 "This is a very long sentence to test if the text will properly wrap "
3651 "around and go to the next line. Sometimes, short sentence. Longer "
3652 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003653 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003654
3655 ParagraphStyle paragraph_style;
3656 paragraph_style.setMaxLines(1);
3657 paragraph_style.setEllipsis(u"\u2026");
3658 paragraph_style.turnHintingOff();
3659 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3660
3661 TextStyle text_style;
3662 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003663 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003664 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003665 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003666 builder.pop();
3667
3668 auto paragraph = builder.Build();
3669 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003670 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003671
3672 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003673
3674 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3675 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3676
3677 auto& line = impl->lines()[0];
3678 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003679 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003680}
3681
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003682// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003683DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003684 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003685 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003686 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003687 const char* text1 = "fluttser ";
3688 const char* text2 = "mdje";
3689 const char* text3 = "fluttser mdje";
3690
3691 ParagraphStyle paragraph_style;
3692 paragraph_style.turnHintingOff();
3693 paragraph_style.setTextAlign(TextAlign::kLeft);
3694 paragraph_style.setMaxLines(2);
3695 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3696
3697 TextStyle text_style;
3698 text_style.setFontFamilies({SkString("Roboto")});
3699 text_style.setColor(SK_ColorBLACK);
3700 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003701 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003702 text_style.setDecoration(TextDecoration::kUnderline);
3703 text_style.setDecorationColor(SK_ColorBLACK);
3704 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003705 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003706 builder.pop();
3707
3708 auto paragraph = builder.Build();
3709 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003710 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003711
3712 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3713
3714 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3715 text_style.setDecoration(TextDecoration::kNoDecoration);
3716 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003717 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003718 builder1.pop();
3719
3720 auto paragraph1 = builder1.Build();
3721 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003722 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003723
3724 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3725
3726 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3727 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003728
3729 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3730 .front()
3731 .rect;
3732 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3733 .front()
3734 .rect;
3735 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3736 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3737
3738 for (size_t i = 0; i < 12; ++i) {
Julia Lavrova2813d452020-03-03 11:43:40 -05003739 // Not all ranges produce a rectangle ("fl" goes into one cluster so [0:1) is empty)
3740 auto r1 = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
3741 auto r2 = paragraph1->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003742
Julia Lavrova2813d452020-03-03 11:43:40 -05003743 REPORTER_ASSERT(reporter, r1.size() == r2.size());
3744 if (!r1.empty() && !r2.empty()) {
3745 REPORTER_ASSERT(reporter, r1.front().rect.fLeft == r2.front().rect.fLeft);
3746 REPORTER_ASSERT(reporter, r1.front().rect.fRight == r2.front().rect.fRight);
3747 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003748 }
3749}
3750
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003751// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003752DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003753 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003754 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003755 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003756 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003757 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003758
3759 ParagraphStyle paragraph_style;
3760 paragraph_style.turnHintingOff();
3761 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3762
3763 TextStyle text_style;
3764 text_style.setFontFamilies({SkString("Roboto")});
3765 text_style.setColor(SK_ColorBLACK);
3766 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3767 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003768 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003769
3770 auto paragraph = builder.Build();
3771 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003772 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003773
3774 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3775
3776 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3777 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3778 size_t index = 0;
3779 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003780 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003781 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003782 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3783 ++index;
3784 return true;
3785 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003786 }
3787}
3788
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003789// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003790DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003791 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003792 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003793 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003794 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003795 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003796
3797 ParagraphStyle paragraph_style;
3798 paragraph_style.turnHintingOff();
3799 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3800
3801 TextStyle text_style;
3802 text_style.setFontFamilies({SkString("Roboto")});
3803 text_style.setColor(SK_ColorBLACK);
3804 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3805 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003806 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003807
3808 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3809 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3810 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003811 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003812 builder.pop();
3813
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003814 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003815
3816 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3817 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003818 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003819 builder.pop();
3820
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003821 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003822
3823 auto paragraph = builder.Build();
3824 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003825 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003826
3827 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3828
3829 size_t index = 0;
3830 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003831 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003832 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003833 ++index;
3834 switch (index) {
3835 case 1:
3836 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3837 break;
3838 case 2:
3839 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3840 break;
3841 case 3:
3842 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3843 break;
3844 case 4:
3845 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3846 REPORTER_ASSERT(reporter, style.equals(text_style));
3847 break;
3848 case 5:
3849 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3850 break;
3851 default:
3852 REPORTER_ASSERT(reporter, false);
3853 }
3854 return true;
3855 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003856 }
3857}
3858
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003859// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003860DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003861 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003862 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003863 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003864 const char* text =
3865 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3866 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003867 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003868
3869 ParagraphStyle paragraph_style;
3870 paragraph_style.turnHintingOff();
3871 paragraph_style.setMaxLines(14);
3872 paragraph_style.setTextAlign(TextAlign::kJustify);
3873 paragraph_style.setHeight(1.5);
3874 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3875
3876 TextStyle text_style;
3877 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3878 text_style.setColor(SK_ColorBLACK);
3879 text_style.setFontSize(55);
3880 text_style.setLetterSpacing(2);
3881 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3882 text_style.setDecorationColor(SK_ColorBLACK);
3883 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003884 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003885 builder.pop();
3886
3887 auto paragraph = builder.Build();
3888 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003889 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003890
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003891 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3892 paragraph->getMaxWidth(),
3893 paragraph->getIdeographicBaseline());
3894 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3895 paragraph->getMaxWidth(),
3896 paragraph->getAlphabeticBaseline());
3897 canvas.drawLine(SK_ColorRED, rect1, false);
3898 canvas.drawLine(SK_ColorGREEN, rect2, false);
3899
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003900 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003901 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003902 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003903 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003904}
3905
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003906// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003907DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003908 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003909 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003910 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003911
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003912 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3913 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3914 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003915
3916 ParagraphStyle paragraph_style;
3917 paragraph_style.turnHintingOff();
3918 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3919
3920 TextStyle text_style;
3921 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003922 SkString("Not a real font"),
3923 SkString("Also a fake font"),
3924 SkString("So fake it is obvious"),
3925 SkString("Next one should be a real font..."),
3926 SkString("Roboto"),
3927 SkString("another fake one in between"),
3928 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003929 });
3930 text_style.setColor(SK_ColorBLACK);
3931 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003932 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003933
3934 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003935 SkString("Not a real font"),
3936 SkString("Also a fake font"),
3937 SkString("So fake it is obvious"),
3938 SkString("Homemade Apple"),
3939 SkString("Next one should be a real font..."),
3940 SkString("Roboto"),
3941 SkString("another fake one in between"),
3942 SkString("Noto Sans CJK JP"),
3943 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003944 });
3945 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003946 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003947
3948 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003949 SkString("Not a real font"),
3950 SkString("Also a fake font"),
3951 SkString("So fake it is obvious"),
3952 SkString("Homemade Apple"),
3953 SkString("Next one should be a real font..."),
3954 SkString("Roboto"),
3955 SkString("another fake one in between"),
3956 SkString("Source Han Serif CN"),
3957 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003958 });
3959 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003960 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003961
3962 builder.pop();
3963
3964 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003965 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003966 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003967 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003968
Julia Lavrova3281b962019-12-02 11:32:25 -05003969 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
3970
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003971 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3972
3973 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3974 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3975 // [Apple + Noto] [Apple + Han]
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003976 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003977
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003978 auto robotoAdvance = impl->runs()[0].advance().fX +
3979 impl->runs()[1].advance().fX +
3980 impl->runs()[2].advance().fX;
3981 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
3982 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
3983 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
3984 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
3985 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003986
3987 // When a different font is resolved, then the metrics are different.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003988 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
3989 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003990}
3991
Julia Lavrovac2228562019-08-08 16:51:27 -04003992// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003993DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003994 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003995 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003996 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003997 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003998 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003999 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004000
4001 ParagraphStyle paragraph_style;
4002 paragraph_style.setMaxLines(10);
4003 paragraph_style.setTextAlign(TextAlign::kLeft);
4004 paragraph_style.turnHintingOff();
4005
4006 StrutStyle strut_style;
4007 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004008 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004009 strut_style.setFontSize(50);
4010 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004011 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004012 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004013 paragraph_style.setStrutStyle(strut_style);
4014
4015 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4016
4017 TextStyle text_style;
4018 text_style.setFontFamilies({SkString("Ahem")});
4019 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004020 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004021 text_style.setColor(SK_ColorBLACK);
4022 text_style.setHeight(0.5f);
4023 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004024 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004025 builder.pop();
4026
4027 auto paragraph = builder.Build();
4028 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004029 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004030
4031 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004032 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4033
4034 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4035 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4036 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004037 {
4038 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4039 REPORTER_ASSERT(reporter, boxes.empty());
4040 }
4041 {
4042 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004043 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004044 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004045 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4046 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4047 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4048 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004049 }
4050 {
4051 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004052 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004053 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004054 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004055 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004056 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4057 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004058 }
4059 {
4060 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004061 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004062 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004063 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4064 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004065 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004066 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004067 }
4068 {
4069 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004070 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004071 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004072 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004073 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004074 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004075 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004076 }
4077 {
4078 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004079 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004080 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004081 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004082 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004083 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4084 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004085 }
4086 {
4087 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004088 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004089 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004093 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004094 }
4095}
4096
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004097// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004098DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004099 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004100 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004101 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004102 // The chinese extra height should be absorbed by the strut.
4103 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004104 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004105
4106 ParagraphStyle paragraph_style;
4107 paragraph_style.setMaxLines(10);
4108 paragraph_style.setTextAlign(TextAlign::kLeft);
4109 paragraph_style.turnHintingOff();
4110
4111 StrutStyle strut_style;
4112
4113 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004114 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004115 strut_style.setFontSize(50);
4116 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004117 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004118 paragraph_style.setStrutStyle(strut_style);
4119
4120 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4121
4122 TextStyle text_style;
4123 text_style.setFontFamilies({SkString("Ahem")});
4124 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004125 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4126 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004127 text_style.setColor(SK_ColorBLACK);
4128 text_style.setHeight(1);
4129 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004130 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004131 builder.pop();
4132
4133 auto paragraph = builder.Build();
4134 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004135 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004136
4137 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4138 // Font is not resolved and the first line does not fit
4139 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4140
4141 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4142 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4143 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004144 {
4145 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4146 REPORTER_ASSERT(reporter, boxes.empty());
4147 }
4148 {
4149 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004150 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004151 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004152 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4153 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4154 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4155 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004156 }
4157 {
4158 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004159 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004160 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004161 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004162 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004163 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4164 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004165 }
4166 {
4167 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004168 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004169 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004170 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4171 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4172 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4173 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004174 }
4175 {
4176 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004177 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004178 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004179 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004180 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004181 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4182 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004183 }
4184 {
4185 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004186 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004187 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004188 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004189 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004190 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4191 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004192 }
4193 {
4194 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004195 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004196 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004197 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004198 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004199 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4200 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004201 }
4202}
4203
Julia Lavrovac2228562019-08-08 16:51:27 -04004204// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004205DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004206 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004207 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004208 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4209
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004210 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004211 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004212 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004213
4214 ParagraphStyle paragraph_style;
4215 paragraph_style.setMaxLines(10);
4216 paragraph_style.setTextAlign(TextAlign::kLeft);
4217 paragraph_style.turnHintingOff();
4218
4219 StrutStyle strut_style;
4220 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004221 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004222 strut_style.setFontSize(50);
4223 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004224 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004225 paragraph_style.setStrutStyle(strut_style);
4226
4227 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4228
4229 TextStyle text_style;
4230 text_style.setFontFamilies({SkString("Ahem")});
4231 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004232 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4233 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004234 text_style.setColor(SK_ColorBLACK);
4235 text_style.setHeight(1);
4236 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004237 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004238 builder.pop();
4239
4240 auto paragraph = builder.Build();
4241 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004242 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004243
4244 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4245 // Font is not resolved and the first line does not fit
4246 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4247
4248 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4249 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4250 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4251 SkScalar epsilon = 0.001f;
4252 {
4253 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4254 REPORTER_ASSERT(reporter, boxes.empty());
4255 }
4256 {
4257 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004258 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004259 REPORTER_ASSERT(reporter, boxes.size() == 1);
4260 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4261 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4262 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4263 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4264 }
4265 {
4266 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004267 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004268 REPORTER_ASSERT(reporter, boxes.size() == 1);
4269 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004270 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004271 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4272 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4273 }
4274 {
4275 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004276 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004277 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004278 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4279 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004280 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004281 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4282 }
4283 {
4284 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004285 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004286 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004287 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004288 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004289 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004290 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4291 }
4292 {
4293 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004294 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004295 REPORTER_ASSERT(reporter, boxes.size() == 1);
4296 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004297 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004298 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4299 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4300 }
4301 {
4302 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004303 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004304 REPORTER_ASSERT(reporter, boxes.size() == 1);
4305 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004306 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004307 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4308 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4309 }
4310}
4311
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004312// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004313DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004314 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004315 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004316 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004317 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004318 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004319
4320 ParagraphStyle paragraph_style;
4321 paragraph_style.setMaxLines(10);
4322 paragraph_style.setTextAlign(TextAlign::kLeft);
4323 paragraph_style.turnHintingOff();
4324
4325 StrutStyle strut_style;
4326 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004327 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004328 strut_style.setFontSize(50);
4329 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004330 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004331 strut_style.setLeading(0.1f);
4332 strut_style.setForceStrutHeight(true);
4333 paragraph_style.setStrutStyle(strut_style);
4334
4335 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4336
4337 TextStyle text_style;
4338 text_style.setFontFamilies({SkString("Ahem")});
4339 text_style.setFontSize(50);
4340 text_style.setLetterSpacing(0);
4341 text_style.setColor(SK_ColorBLACK);
4342 text_style.setHeight(1);
4343 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004344 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004345 builder.pop();
4346
4347 auto paragraph = builder.Build();
4348 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004349 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004350
4351 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4352 // Font is not resolved and the first line does not fit
4353 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4354
4355 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4356 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4357 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004358
4359 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4360 REPORTER_ASSERT(reporter, boxes1.empty());
4361
4362 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004363 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004364 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004365 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4366 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4367 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4368 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004369
4370 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004371 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004372 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004373 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004374 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004375 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4376 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004377
4378 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004379 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004380 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004381 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4382 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4383 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4384 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004385
4386 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004387 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004388 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4392 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004393
4394 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004395 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004396 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004401
4402 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004403 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004404 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004409}
4410
Julia Lavrovac2228562019-08-08 16:51:27 -04004411// Checked: NO DIFF
4412DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004413 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004414 if (!fontCollection->fontsFound()) return;
4415 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4416
4417 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004418 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004419
4420 ParagraphStyle paragraph_style;
4421 paragraph_style.setMaxLines(10);
4422 paragraph_style.setTextAlign(TextAlign::kLeft);
4423 paragraph_style.turnHintingOff();
4424
4425 StrutStyle strut_style;
4426 strut_style.setStrutEnabled(true);
4427 strut_style.setFontFamilies({SkString("Ahem")});
4428 strut_style.setFontSize(50);
4429 strut_style.setHeight(1.5f);
4430 strut_style.setLeading(0.1f);
4431 strut_style.setForceStrutHeight(false);
4432 paragraph_style.setStrutStyle(strut_style);
4433
4434 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4435
4436 TextStyle text_style;
4437 text_style.setFontFamilies({SkString("Ahem")});
4438 text_style.setFontSize(20);
4439 text_style.setColor(SK_ColorBLACK);
4440 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004441 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004442 builder.pop();
4443
4444 auto paragraph = builder.Build();
4445 paragraph->layout(550);
4446 paragraph->paint(canvas.get(), 0, 0);
4447
4448 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4449 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4450 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4451 {
4452 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4453 REPORTER_ASSERT(reporter, boxes.empty());
4454 }
4455 {
4456 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4457 canvas.drawRects(SK_ColorRED, boxes);
4458 REPORTER_ASSERT(reporter, boxes.size() == 1);
4459 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4460 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4461 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4462 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4463 }
4464 {
4465 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4466 canvas.drawRects(SK_ColorRED, boxes);
4467 REPORTER_ASSERT(reporter, boxes.size() == 1);
4468 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4469 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4470 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4471 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4472 }
4473}
4474
Julia Lavrovac5313e62019-12-10 12:11:17 -05004475DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4476 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4477 if (!fontCollection->fontsFound()) return;
4478 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4479
4480 const char* text = "12ab\n";
4481
4482 ParagraphStyle paragraph_style;
4483 paragraph_style.turnHintingOff();
4484 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4485
4486 TextStyle text_style;
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004487 text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
Julia Lavrovac5313e62019-12-10 12:11:17 -05004488 text_style.setFontFamilies({SkString("Roboto")});
4489 text_style.setColor(SK_ColorBLACK);
4490
4491 text_style.addFontFeature(SkString("tnum"), 1);
4492 builder.pushStyle(text_style);
4493 builder.addText(text);
4494
4495 text_style.resetFontFeatures();
4496 text_style.addFontFeature(SkString("tnum"), 0);
4497 text_style.addFontFeature(SkString("pnum"), 1);
4498 builder.pushStyle(text_style);
4499 builder.addText(text);
4500
4501 builder.pop();
4502 builder.pop();
4503
4504 auto paragraph = builder.Build();
4505 paragraph->layout(TestCanvasWidth);
4506
4507 paragraph->paint(canvas.get(), 10.0, 15.0);
4508
4509 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4510 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4511
4512 auto& tnum_line = impl->lines()[0];
4513 auto& pnum_line = impl->lines()[1];
4514
4515 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4516 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4517 // Tabular numbers should have equal widths.
4518 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4519 // Proportional numbers should have variable widths.
4520 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4521 // Alphabetic characters should be unaffected.
4522 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4523}
4524
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004525// Not in Minikin
4526DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004527 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004528 if (!fontCollection->fontsFound()) return;
4529 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004530 const size_t len = strlen(text);
4531
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004532 ParagraphStyle paragraph_style;
4533 paragraph_style.turnHintingOff();
4534 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4535
4536 TextStyle text_style;
4537 text_style.setFontFamilies(
4538 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4539 text_style.setFontSize(60);
4540 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004541 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004542 builder.pop();
4543
4544 auto paragraph = builder.Build();
4545 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004546
4547 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4548
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004549 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4550 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4551 auto first = impl->runs()[i].textRange();
4552 auto next = impl->runs()[i + 1].textRange();
4553 REPORTER_ASSERT(reporter, first.end == next.start);
4554 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004555}
4556
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004557DEF_TEST(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004558 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004559 if (!fontCollection->fontsFound()) return;
4560 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004561 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004562
4563 ParagraphStyle paragraph_style;
4564 paragraph_style.turnHintingOff();
4565 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4566
4567 TextStyle text_style;
4568 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4569 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004570 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004571 builder.pop();
4572
4573 auto paragraph = builder.Build();
4574 paragraph->layout(TestCanvasWidth);
4575
4576 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4577 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004578 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004579
4580 auto cluster = 0;
4581 SkShaperJSONWriter::VisualizeClusters(
4582 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4583 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4584 if (cluster == 0) {
4585 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4586 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4587 SkASSERT(glyph1to1.size() == 1);
4588 SkASSERT(*glyph1to1.begin() == 1611);
4589 }
4590 ++cluster;
4591 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004592 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004593}
4594
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004595DEF_TEST(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004596 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004597 if (!fontCollection->fontsFound()) return;
4598 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004599 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004600
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004601 ParagraphStyle paragraph_style;
4602 paragraph_style.turnHintingOff();
4603 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4604
4605 TextStyle text_style;
4606 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4607 text_style.setColor(SK_ColorBLACK);
4608 text_style.setFontSize(50);
4609 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004610 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004611 builder.pop();
4612
4613 auto paragraph = builder.Build();
4614 paragraph->layout(TestCanvasWidth);
4615
4616 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4617 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004618
4619 auto cluster = 0;
4620 for (auto& run : impl->runs()) {
4621 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004622 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4623 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004624 [&](int codePointCount, SkSpan<const char> utf1to1,
4625 SkSpan<const SkGlyphID> glyph1to1) {
4626 if (cluster == 0) {
4627 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4628 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4629 SkASSERT(glyph1to1.size() == 3);
4630 }
4631 ++cluster;
4632 });
4633 }
4634
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004635 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004636}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004637
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004638DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004639 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004640 cache.turnOn(true);
4641 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004642 if (!fontCollection->fontsFound()) return;
4643
4644 ParagraphStyle paragraph_style;
4645 paragraph_style.turnHintingOff();
4646
4647 TextStyle text_style;
4648 text_style.setFontFamilies({SkString("Roboto")});
4649 text_style.setColor(SK_ColorBLACK);
4650
4651 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4652 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4653 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004654 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004655 builder.pop();
4656 auto paragraph = builder.Build();
4657
4658 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4659 REPORTER_ASSERT(reporter, count == cache.count());
4660 auto found = cache.findParagraph(impl);
4661 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4662 auto added = cache.updateParagraph(impl);
4663 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4664 };
4665
4666 test("text1", 0, false);
4667 test("text1", 1, true);
4668 test("text2", 1, false);
4669 test("text2", 2, true);
4670 test("text3", 2, false);
4671}
4672
4673DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004674 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004675 cache.turnOn(true);
4676 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004677 if (!fontCollection->fontsFound()) return;
4678
4679 ParagraphStyle paragraph_style;
4680 paragraph_style.turnHintingOff();
4681
4682 TextStyle text_style;
4683 text_style.setColor(SK_ColorBLACK);
4684
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004685 const char* text = "text";
4686 const size_t len = strlen(text);
4687
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004688 auto test = [&](int count, bool expectedToBeFound) {
4689 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4690 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004691 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004692 builder.pop();
4693 auto paragraph = builder.Build();
4694 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4695
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004696 REPORTER_ASSERT(reporter, count == cache.count());
4697 auto found = cache.findParagraph(impl);
4698 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4699 auto added = cache.updateParagraph(impl);
4700 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4701 };
4702
4703 text_style.setFontFamilies({SkString("Roboto")});
4704 test(0, false);
4705 test(1, true);
4706 text_style.setFontFamilies({SkString("Homemade Apple")});
4707 test(1, false);
4708 test(2, true);
4709 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4710 test(2, false);
4711}
4712
4713DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004714 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004715 cache.turnOn(true);
4716 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004717 if (!fontCollection->fontsFound()) return;
4718
4719 ParagraphStyle paragraph_style;
4720 paragraph_style.turnHintingOff();
4721
4722 TextStyle text_style;
4723 text_style.setFontFamilies({SkString("Roboto")});
4724 text_style.setColor(SK_ColorBLACK);
4725
4726 auto test = [&](const char* text1,
4727 const char* text2,
4728 const char* font1,
4729 const char* font2,
4730 int count,
4731 bool expectedToBeFound) {
4732 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4733 text_style.setFontFamilies({SkString(font1)});
4734 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004735 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004736 builder.pop();
4737 text_style.setFontFamilies({SkString(font2)});
4738 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004739 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004740 builder.pop();
4741 auto paragraph = builder.Build();
4742 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4743
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004744 REPORTER_ASSERT(reporter, count == cache.count());
4745 auto found = cache.findParagraph(impl);
4746 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4747 auto added = cache.updateParagraph(impl);
4748 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4749 };
4750
4751 test("text", "", "Roboto", "Homemade Apple", 0, false);
4752 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4753 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4754 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4755 test("text", "", "Roboto", "Homemade Apple", 4, true);
4756}
4757
4758DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004759 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004760 cache.turnOn(true);
4761 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004762 if (!fontCollection->fontsFound()) return;
4763
4764 ParagraphStyle paragraph_style;
4765 paragraph_style.turnHintingOff();
4766
4767 TextStyle text_style;
4768 text_style.setFontFamilies({SkString("Roboto")});
4769 text_style.setColor(SK_ColorBLACK);
4770
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004771 const char* text = "text";
4772 const size_t len = strlen(text);
4773
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004774 auto test = [&](int count, bool expectedToBeFound) {
4775 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4776 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004777 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004778 builder.pop();
4779 auto paragraph = builder.Build();
4780 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4781
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004782 REPORTER_ASSERT(reporter, count == cache.count());
4783 auto found = cache.findParagraph(impl);
4784 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4785 auto added = cache.updateParagraph(impl);
4786 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4787 };
4788
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004789 test(0, false);
4790 test(1, true);
4791 text_style.setLetterSpacing(10);
4792 test(1, false);
4793 test(2, true);
4794 text_style.setWordSpacing(10);
4795 test(2, false);
4796}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004797
Julia Lavrova526df262019-08-21 17:49:44 -04004798DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004799 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004800 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004801 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4802 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004803
4804 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004805 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004806 text_style.setFontSize(16);
4807 text_style.setFontFamilies({SkString("Roboto")});
4808 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004809 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004810
4811 auto paragraph = builder.Build();
4812 paragraph->layout(TestCanvasWidth);
4813 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004814 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004815}
4816
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004817DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004818 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004819 if (!fontCollection->fontsFound()) return;
4820 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4821 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4822
4823 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4824
4825 ParagraphStyle paragraph_style;
4826 TextStyle text_style;
4827 text_style.setFontSize(16);
4828 text_style.setFontFamilies({SkString("Roboto")});
4829 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4830 builder.addText(text.c_str(), text.size());
4831
4832 auto paragraph = builder.Build();
4833 paragraph->layout(TestCanvasWidth);
4834 paragraph->paint(canvas.get(), 0, 0);
4835}
4836
Julia Lavrovaa40db422019-08-21 13:49:15 -04004837DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004838 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004839 if (!fontCollection->fontsFound()) return;
4840 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4841
4842 ParagraphStyle paragraph_style;
4843 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4844
Julia Lavrova526df262019-08-21 17:49:44 -04004845 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004846 builder.addPlaceholder(placeholder);
4847
4848 auto paragraph = builder.Build();
4849 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004850 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004851 paragraph->paint(canvas.get(), 0, 0);
4852}
4853
4854DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004855 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004856 if (!fontCollection->fontsFound()) return;
4857 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4858 TestCanvas canvas("SkParagraph_Fallbacks.png");
4859
4860 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004861 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004862
4863 const char* androidFonts[] = {
4864 "sans-serif",
4865 "sans-serif-condensed",
4866 "serif",
4867 "monospace",
4868 "serif-monospace",
4869 "casual",
4870 "cursive",
4871 "sans-serif-smallcaps",
4872 };
4873
4874 for (auto& font : androidFonts) {
4875
4876 ParagraphStyle paragraph_style;
4877 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4878
4879 TextStyle text_style;
4880 text_style.setColor(SK_ColorBLACK);
4881 text_style.setLocale(SkString("en_US"));
4882 text_style.setFontSize(20);
4883
4884 text_style.setFontFamilies({ SkString(font) });
4885 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004886 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004887
4888 builder.pop();
4889
4890 auto paragraph = builder.Build();
4891 paragraph->layout(TestCanvasWidth);
4892 paragraph->paint(canvas.get(), 0, 0);
4893 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4894 }
4895}
4896
4897DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004898 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004899 if (!fontCollection->fontsFound()) return;
4900 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004901 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004902 TestCanvas canvas("SkParagraph_Bidi1.png");
4903
4904 std::u16string abc = u"\u202Dabc";
4905 std::u16string DEF = u"\u202EDEF";
4906 std::u16string ghi = u"\u202Dghi";
4907 std::u16string JKL = u"\u202EJKL";
4908 std::u16string mno = u"\u202Dmno";
4909
4910 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4911
4912 ParagraphStyle paragraph_style;
4913 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4914
4915 TextStyle text_style;
4916 text_style.setFontFamilies({ SkString("sans-serif")});
4917 text_style.setFontSize(40);
4918
4919 text_style.setColor(SK_ColorCYAN);
4920 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4921 builder.pushStyle(text_style);
4922 builder.addText(abc);
4923
4924 text_style.setColor(SK_ColorGREEN);
4925 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4926 builder.pushStyle(text_style);
4927 builder.addText(DEF);
4928
4929 text_style.setColor(SK_ColorYELLOW);
4930 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4931 builder.pushStyle(text_style);
4932 builder.addText(ghi);
4933
4934 text_style.setColor(SK_ColorMAGENTA);
4935 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4936 builder.pushStyle(text_style);
4937 builder.addText(JKL);
4938
4939 text_style.setColor(SK_ColorBLUE);
4940 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4941 builder.pushStyle(text_style);
4942 builder.addText(mno);
4943
4944 auto paragraph = builder.Build();
4945 paragraph->layout(400);
4946 paragraph->paint(canvas.get(), 0, 0);
4947}
4948
4949DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004950 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004951 if (!fontCollection->fontsFound()) return;
4952 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004953 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004954 TestCanvas canvas("SkParagraph_Bidi2.png");
4955
4956 std::u16string abcD = u"\u202Dabc\u202ED";
4957 std::u16string EFgh = u"EF\u202Dgh";
4958 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4959
4960 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4961
4962 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004963 TextStyle text_style;
4964 text_style.setFontFamilies({ SkString("sans-serif")});
4965 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004966
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004967 {
4968 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4969 builder.pushStyle(text_style);
4970 builder.addText(abcD);
4971 builder.pushStyle(text_style);
4972 builder.addText(EFgh);
4973 builder.pushStyle(text_style);
4974 builder.addText(iJKLmno);
4975 auto paragraph = builder.Build();
4976 paragraph->layout(360);
4977 paragraph->paint(canvas.get(), 0, 0);
4978 }
4979 canvas.get()->translate(0, 400);
4980 {
4981 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4982 builder.pushStyle(text_style);
4983 builder.addText(abcDEFghiJKLmno);
4984 auto paragraph = builder.Build();
4985 paragraph->layout(360);
4986 paragraph->paint(canvas.get(), 0, 0);
4987 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04004988}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004989
4990DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004991 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004992 if (!fontCollection->fontsFound()) return;
4993 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4994 TestCanvas canvas("SkParagraph_Newline.png");
4995
4996 TextStyle text_style;
4997 text_style.setFontFamilies({SkString("Ahem")});
4998 text_style.setColor(SK_ColorBLACK);
4999 StrutStyle strut_style;
5000 strut_style.setStrutEnabled(false);
5001 ParagraphStyle paragraph_style;
5002 paragraph_style.setStrutStyle(strut_style);
5003 paragraph_style.setTextStyle(text_style);
5004 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5005 builder.addText("\n");
5006 auto paragraph = builder.Build();
5007 paragraph->layout(1000);
5008 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5009}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005010
Julia Lavrovab30d4812019-11-08 14:51:16 -05005011DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005012 TestCanvas canvas("SkParagraph_FontResolutions.png");
5013
5014 sk_sp<TestFontCollection> fontCollection =
5015 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5016 if (!fontCollection->fontsFound()) return;
5017
5018 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5019 return;
5020 }
5021 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5022 return;
5023 }
5024 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5025 return;
5026 }
5027
5028 TextStyle text_style;
5029 text_style.setFontFamilies({SkString("abc")});
5030 text_style.setFontSize(50);
5031
5032 ParagraphStyle paragraph_style;
5033 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5034
5035 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5036 text_style.setColor(SK_ColorBLUE);
5037 builder.pushStyle(text_style);
5038 builder.addText(u"a\u0300");
5039 text_style.setColor(SK_ColorMAGENTA);
5040 builder.pushStyle(text_style);
5041 builder.addText(u"à");
5042
5043 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5044
5045 text_style.setColor(SK_ColorRED);
5046 builder.pushStyle(text_style);
5047 builder.addText(u"a\u0300");
5048 text_style.setColor(SK_ColorGREEN);
5049 builder.pushStyle(text_style);
5050 builder.addText(u"à");
5051
5052 auto paragraph = builder.Build();
5053 paragraph->layout(TestCanvasWidth);
5054
5055 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5056 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5057
5058 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5059 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5060 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5061
5062 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5063 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5064
5065 paragraph->paint(canvas.get(), 100, 100);
5066}
5067
Julia Lavrovab30d4812019-11-08 14:51:16 -05005068DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005069 TestCanvas canvas("SkParagraph_FontStyle.png");
5070
5071 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5072 if (!fontCollection->fontsFound()) return;
5073
5074 TextStyle text_style;
5075 text_style.setFontFamilies({SkString("Roboto")});
5076 text_style.setColor(SK_ColorBLACK);
5077 text_style.setFontSize(20);
5078 SkFontStyle fs = SkFontStyle(
5079 SkFontStyle::Weight::kLight_Weight,
5080 SkFontStyle::Width::kNormal_Width,
5081 SkFontStyle::Slant::kUpright_Slant
5082 );
5083 text_style.setFontStyle(fs);
5084 ParagraphStyle paragraph_style;
5085 paragraph_style.setTextStyle(text_style);
5086 TextStyle boldItalic;
5087 boldItalic.setFontFamilies({SkString("Roboto")});
5088 boldItalic.setColor(SK_ColorRED);
5089 SkFontStyle bi = SkFontStyle(
5090 SkFontStyle::Weight::kBold_Weight,
5091 SkFontStyle::Width::kNormal_Width,
5092 SkFontStyle::Slant::kItalic_Slant
5093 );
5094 boldItalic.setFontStyle(bi);
5095 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5096 builder.addText("Default text\n");
5097 builder.pushStyle(boldItalic);
5098 builder.addText("Bold and Italic\n");
5099 builder.pop();
5100 builder.addText("back to normal");
5101 auto paragraph = builder.Build();
5102 paragraph->layout(250);
5103 paragraph->paint(canvas.get(), 0, 0);
5104}
5105
Julia Lavrovab30d4812019-11-08 14:51:16 -05005106DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005107 TestCanvas canvas("SkParagraph_Shaping.png");
5108
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005109 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5110 sk_sp<TestFontCollection> fontCollection =
5111 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5112 if (!fontCollection->fontsFound()) return;
5113
5114
5115 TextStyle text_style;
5116 text_style.setFontFamilies({SkString("Roboto")});
5117 text_style.setColor(SK_ColorGRAY);
5118 text_style.setFontSize(14);
5119 SkFontStyle b = SkFontStyle(
5120 SkFontStyle::Weight::kNormal_Weight,
5121 SkFontStyle::Width::kNormal_Width,
5122 SkFontStyle::Slant::kUpright_Slant
5123 );
5124 text_style.setFontStyle(b);
5125 ParagraphStyle paragraph_style;
5126 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5127 builder.pushStyle(text_style);
5128 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5129 auto paragraph = builder.Build();
5130 paragraph->layout(380);
5131 paragraph->paint(canvas.get(), 0, 0);
5132}
Julia Lavrovac028b422019-11-25 10:00:43 -05005133
5134DEF_TEST(SkParagraph_Ellipsis, reporter) {
5135 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5136 if (!fontCollection->fontsFound()) return;
5137 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5138 TestCanvas canvas("SkParagraph_Ellipsis.png");
5139
5140 const char* text = "This\n"
5141 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5142 TextStyle text_style;
5143 text_style.setFontFamilies({SkString("Ahem")});
5144 text_style.setColor(SK_ColorBLACK);
5145 text_style.setFontSize(10);
5146
5147 auto relayout = [&](size_t lines, bool ellipsis,
5148 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5149 ParagraphStyle paragraph_style;
5150 SkPaint paint;
5151 paint.setColor(bg);
5152 text_style.setForegroundColor(paint);
5153 paragraph_style.setTextStyle(text_style);
5154 paragraph_style.setMaxLines(lines);
5155 if (ellipsis) {
5156 paragraph_style.setEllipsis(u"\u2026");
5157 }
5158 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5159 builder.addText(text);
5160 auto paragraph = builder.Build();
5161 paragraph->layout(50);
5162 paragraph->paint(canvas.get(), 0, 0);
5163 canvas.get()->translate(50, paragraph->getHeight() + 10);
5164 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5165 SkPaint background;
5166 background.setColor(SK_ColorRED);
5167 background.setStyle(SkPaint::kStroke_Style);
5168 background.setAntiAlias(true);
5169 background.setStrokeWidth(1);
5170 canvas.get()->drawRect(result.front().rect, background);
5171
5172 SkASSERT(width == paragraph->getMaxWidth());
5173 SkASSERT(height == paragraph->getHeight());
5174 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5175 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5176 };
5177
5178 SkPaint paint;
5179 paint.setColor(SK_ColorLTGRAY);
5180 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5181
5182 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005183 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5184 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005185
5186 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005187 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005188 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5189
5190 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005191 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5192 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005193}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005194
5195DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5196 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5197 if (!fontCollection->fontsFound()) return;
5198 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5199
5200 std::string text;
5201 for (size_t i = 0; i < 10; i++)
5202 {
5203 SkPaint paint;
5204 paint.setAntiAlias(true);
5205 paint.setColor(SK_ColorBLACK);
5206
5207 TextStyle textStyle;
5208 textStyle.setForegroundColor(paint);
5209 textStyle.setFontFamilies({ SkString("Roboto") });
5210
5211 ParagraphStyle paragraphStyle;
5212 paragraphStyle.setTextStyle(textStyle);
5213
5214 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5215 text += "Text ";
5216 builder.addText(text.c_str());
5217
5218 auto paragraph = builder.Build();
5219 paragraph->layout(100);
5220
5221 //used to add a delay so I can monitor memory usage
5222 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5223 }
5224};
Julia Lavrovac0360582020-02-05 10:17:53 -05005225
5226DEF_TEST(SkParagraph_FormattingInfinity, reporter) {
5227 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5228 if (!fontCollection->fontsFound()) return;
5229 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5230 TestCanvas canvas("SkParagraph_FormattingInfinity.png");
5231
5232 const char* text = "Some text\nAnother line";
5233
5234 SkPaint paint;
5235 paint.setAntiAlias(true);
5236 paint.setColor(SK_ColorBLACK);
5237
5238 TextStyle textStyle;
5239 textStyle.setForegroundColor(paint);
5240 textStyle.setFontFamilies({ SkString("Roboto") });
5241 ParagraphStyle paragraphStyle;
5242 paragraphStyle.setTextStyle(textStyle);
5243
5244 auto draw = [&](const char* prefix, TextAlign textAlign) {
5245 paragraphStyle.setTextAlign(textAlign);
5246 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5247 builder.addText(text);
5248 auto paragraph = builder.Build();
5249 paragraph->layout(SK_ScalarInfinity);
5250 paragraph->paint(canvas.get(), 0, 0);
5251 canvas.get()->translate(0, 100);
5252 };
5253
5254 draw("left", TextAlign::kLeft);
5255 draw("right", TextAlign::kRight);
5256 draw("center", TextAlign::kCenter);
5257 draw("justify", TextAlign::kJustify);
5258};
5259
5260DEF_TEST(SkParagraph_Infinity, reporter) {
5261 SkASSERT(nearlyEqual(1, SK_ScalarInfinity) == false);
5262 SkASSERT(nearlyEqual(1, SK_ScalarNegativeInfinity) == false);
5263 SkASSERT(nearlyEqual(1, SK_ScalarNaN) == false);
5264
5265 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarInfinity) == true);
5266 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNegativeInfinity) == false);
5267 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNaN) == false);
5268
5269 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarInfinity) == false);
5270 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity) == true);
5271 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNaN) == false);
5272
5273 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarInfinity) == false);
5274 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNegativeInfinity) == false);
5275 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNaN) == false);
5276};