blob: bb284b88695044a99a0826519d02281a0fd9aaad [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
2#include <sstream>
Julia Lavrovadb543f62020-01-29 11:43:41 -05003#include <thread>
Julia Lavrova6e6333f2019-06-17 10:34:10 -04004#include "modules/skparagraph/include/TypefaceFontProvider.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04005#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
6#include "modules/skparagraph/src/ParagraphImpl.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -04007#include "modules/skparagraph/utils/TestFontCollection.h"
Julia Lavrovadb543f62020-01-29 11:43:41 -05008#include "src/core/SkFontMgrPriv.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04009#include "src/core/SkOSFile.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -040010#include "src/utils/SkOSPath.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040011#include "src/utils/SkShaperJSONWriter.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040012#include "tests/CodecPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040013#include "tests/Test.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040014#include "tools/Resources.h"
Julia Lavrovadb9f6692019-08-01 16:02:17 -040015#include "tools/ToolUtils.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040016
Julia Lavrovab30d4812019-11-08 14:51:16 -050017#include "third_party/icu/SkLoadICU.h"
18
Julia Lavrovaa3552c52019-05-30 16:12:56 -040019#define VeryLongCanvasWidth 1000000
20#define TestCanvasWidth 1000
21#define TestCanvasHeight 600
22
Julia Lavrova2e30fde2019-10-09 09:43:02 -040023#define DEF_TEST_DISABLED(name, reporter) \
24static void test_##name(skiatest::Reporter* reporter, const GrContextOptions&); \
25skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \
Herb Derby126d7a22019-11-27 11:38:16 -050026void test_##name(skiatest::Reporter* reporter, const GrContextOptions&) { /* SkDebugf("Disabled:"#name "\n"); */ } \
Julia Lavrova2e30fde2019-10-09 09:43:02 -040027void disabled_##name(skiatest::Reporter* reporter, const GrContextOptions&)
28
Julia Lavrovaa3552c52019-05-30 16:12:56 -040029using namespace skia::textlayout;
30namespace {
31
Julia Lavrovadb9f6692019-08-01 16:02:17 -040032SkScalar EPSILON100 = 0.01f;
33SkScalar EPSILON50 = 0.02f;
34SkScalar EPSILON20 = 0.05f;
Julia Lavrova916a9042019-08-08 16:51:27 -040035SkScalar EPSILON10 = 0.1f;
Julia Lavrovac2228562019-08-08 16:51:27 -040036SkScalar EPSILON5 = 0.20f;
37SkScalar EPSILON2 = 0.50f;
Julia Lavrovadb9f6692019-08-01 16:02:17 -040038
Julia Lavrova5207f352019-06-21 12:22:32 -040039bool equal(const char* base, TextRange a, const char* b) {
40 return std::strncmp(b, base + a.start, a.width()) == 0;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040041}
Julia Lavrova3281b962019-12-02 11:32:25 -050042
Julia Lavrova2e30fde2019-10-09 09:43:02 -040043class ResourceFontCollection : public FontCollection {
Julia Lavrovaa3552c52019-05-30 16:12:56 -040044public:
Julia Lavrova2e30fde2019-10-09 09:43:02 -040045 ResourceFontCollection(bool testOnly = false)
Julia Lavrovaa3552c52019-05-30 16:12:56 -040046 : fFontsFound(false)
47 , fResolvedFonts(0)
48 , fResourceDir(GetResourcePath("fonts").c_str())
49 , fFontProvider(sk_make_sp<TypefaceFontProvider>()) {
50 std::vector<SkString> fonts;
51 SkOSFile::Iter iter(fResourceDir.c_str());
Julia Lavrova2e30fde2019-10-09 09:43:02 -040052
Julia Lavrovab30d4812019-11-08 14:51:16 -050053 if (!SkLoadICU()) {
54 SkDebugf("ICU not loaded, skipping all the tests\n");
55 return;
56 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040057 SkString path;
58 while (iter.next(&path)) {
59 if (path.endsWith("Roboto-Italic.ttf")) {
60 fFontsFound = true;
61 }
62 fonts.emplace_back(path);
63 }
64
65 if (!fFontsFound) {
Herb Derby126d7a22019-11-27 11:38:16 -050066 // SkDebugf("Fonts not found, skipping all the tests\n");
Julia Lavrovaa3552c52019-05-30 16:12:56 -040067 return;
68 }
69 // Only register fonts if we have to
70 for (auto& font : fonts) {
71 SkString file_path;
72 file_path.printf("%s/%s", fResourceDir.c_str(), font.c_str());
73 fFontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
74 }
75
Julia Lavrova2e30fde2019-10-09 09:43:02 -040076 if (testOnly) {
77 this->setTestFontManager(std::move(fFontProvider));
78 } else {
79 this->setAssetFontManager(std::move(fFontProvider));
80 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -040081 this->disableFontFallback();
Julia Lavrovaa3552c52019-05-30 16:12:56 -040082 }
83
Julia Lavrova2e30fde2019-10-09 09:43:02 -040084 ~ResourceFontCollection() = default;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040085
86 size_t resolvedFonts() const { return fResolvedFonts; }
87
88 // TODO: temp solution until we check in fonts
89 bool fontsFound() const { return fFontsFound; }
90
91private:
92 bool fFontsFound;
93 size_t fResolvedFonts;
94 std::string fResourceDir;
95 sk_sp<TypefaceFontProvider> fFontProvider;
96};
Julia Lavrovadb9f6692019-08-01 16:02:17 -040097
98class TestCanvas {
99public:
100 TestCanvas(const char* testName) : name(testName) {
101 bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight);
102 canvas = new SkCanvas(bits);
103 canvas->clear(SK_ColorWHITE);
104 }
105
106 ~TestCanvas() {
Julia Lavrovaaae845f2019-08-16 16:44:40 -0400107 SkString tmpDir = skiatest::GetTmpDir();
108 if (!tmpDir.isEmpty()) {
109 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
110 SkFILEWStream file(path.c_str());
111 if (!SkEncodeImage(&file, bits, SkEncodedImageFormat::kPNG, 100)) {
112 SkDebugf("Cannot write a picture %s\n", name);
113 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400114 }
115 delete canvas;
116 }
117
118 void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) {
119
120 SkPaint paint;
121 if (!fill) {
122 paint.setStyle(SkPaint::kStroke_Style);
123 paint.setAntiAlias(true);
124 paint.setStrokeWidth(1);
125 }
126 paint.setColor(color);
127 for (auto& r : result) {
128 canvas->drawRect(r.rect, paint);
129 }
130 }
131
132 void drawLine(SkColor color, SkRect rect, bool vertical = true) {
133
134 SkPaint paint;
135 paint.setStyle(SkPaint::kStroke_Style);
136 paint.setAntiAlias(true);
137 paint.setStrokeWidth(1);
138 paint.setColor(color);
139 if (vertical) {
140 canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
141 } else {
142 canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint);
143 }
144 }
145
146 void drawLines(SkColor color, std::vector<TextBox>& result) {
147
148 for (auto& r : result) {
149 drawLine(color, r.rect);
150 }
151 }
152
153 SkCanvas* get() { return canvas; }
154private:
155 SkBitmap bits;
156 SkCanvas* canvas;
157 const char* name;
158};
159
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400160} // namespace
161
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400162// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400163DEF_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
946// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400947DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400948 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400949 if (!fontCollection->fontsFound()) return;
950 const char* text = "I am RED";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400951 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400952
953 ParagraphStyle paragraph_style;
954 paragraph_style.turnHintingOff();
955 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
956
957 TextStyle text_style;
958 text_style.setFontFamilies({SkString("Roboto")});
959 text_style.setColor(SK_ColorRED);
960 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400961 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400962 builder.pop();
963
964 auto paragraph = builder.Build();
965 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500966 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400967
968 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
969 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
970 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400971 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400972
973 size_t index = 0;
974 for (auto& line : impl->lines()) {
975 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400976 [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
977 REPORTER_ASSERT(reporter, index == 0);
978 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED);
979 ++index;
980 return true;
981 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400982 }
983}
984
Julia Lavrovac2228562019-08-08 16:51:27 -0400985// Checked: DIFF+ (Space between 1 & 2 style blocks)
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400986DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400987 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400988 TestCanvas canvas("SkParagraph_RainbowParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400989 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400990 const char* text1 = "Red Roboto"; // [0:10)
991 const char* text2 = "big Greeen Default"; // [10:28)
992 const char* text3 = "Defcolor Homemade Apple"; // [28:51)
993 const char* text4 = "Small Blue Roboto"; // [51:68)
Julia Lavrovac2228562019-08-08 16:51:27 -0400994 const char* text41 = "Small Blue ";
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400995 const char* text5 =
996 "Continue Last Style With lots of words to check if it overlaps "
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400997 "properly or not"; // [68:)
998 const char* text42 =
999 "Roboto"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001000 "Continue Last Style With lots of words to check if it overlaps "
1001 "properly or not";
1002
1003 ParagraphStyle paragraph_style;
1004 paragraph_style.turnHintingOff();
1005 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001006 paragraph_style.setMaxLines(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001007 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1008
1009 TextStyle text_style1;
1010 text_style1.setFontFamilies({SkString("Roboto")});
1011
1012 text_style1.setColor(SK_ColorRED);
1013 builder.pushStyle(text_style1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001014 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001015
1016 TextStyle text_style2;
1017 text_style2.setFontFamilies({SkString("Roboto")});
1018 text_style2.setFontSize(50);
1019 text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1020 SkFontStyle::kUpright_Slant));
1021 text_style2.setLetterSpacing(10);
1022 text_style2.setDecorationColor(SK_ColorBLACK);
1023 text_style2.setDecoration((TextDecoration)(
1024 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1025 text_style2.setWordSpacing(30);
1026 text_style2.setColor(SK_ColorGREEN);
1027 builder.pushStyle(text_style2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001028 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001029
1030 TextStyle text_style3;
1031 text_style3.setFontFamilies({SkString("Homemade Apple")});
Julia Lavrova526df262019-08-21 17:49:44 -04001032 text_style3.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001033 builder.pushStyle(text_style3);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001034 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001035
1036 TextStyle text_style4;
1037 text_style4.setFontFamilies({SkString("Roboto")});
1038 text_style4.setFontSize(14);
1039 text_style4.setDecorationColor(SK_ColorBLACK);
1040 text_style4.setDecoration((TextDecoration)(
1041 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1042 text_style4.setColor(SK_ColorBLUE);
1043 builder.pushStyle(text_style4);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001044 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001045
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001046 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001047 builder.pop();
1048
1049 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001050 paragraph->layout(1000);
1051 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001052
Julia Lavrova3281b962019-12-02 11:32:25 -05001053 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1054
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001055 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1056 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
1057 REPORTER_ASSERT(reporter, impl->styles().size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001058 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1059
1060 auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight);
1061 canvas.drawRects(SK_ColorMAGENTA, rects);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001062
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001063 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001064 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001065 StyleType::kAllAttributes,
1066 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001067 switch (index) {
1068 case 0:
1069 REPORTER_ASSERT(reporter, style.equals(text_style1));
Julia Lavrova526df262019-08-21 17:49:44 -04001070 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001071 break;
1072 case 1:
1073 REPORTER_ASSERT(reporter, style.equals(text_style2));
Julia Lavrova526df262019-08-21 17:49:44 -04001074 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001075 break;
1076 case 2:
1077 REPORTER_ASSERT(reporter, style.equals(text_style3));
Julia Lavrova526df262019-08-21 17:49:44 -04001078 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001079 break;
1080 case 3:
1081 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001082 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001083 break;
1084 default:
1085 REPORTER_ASSERT(reporter, false);
1086 break;
1087 }
1088 ++index;
1089 return true;
1090 });
1091 impl->lines()[1].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001092 StyleType::kAllAttributes,
1093 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001094 switch (index) {
1095 case 4:
1096 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001097 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001098 break;
1099 default:
1100 REPORTER_ASSERT(reporter, false);
1101 break;
1102 }
1103 ++index;
1104 return true;
1105 });
1106 REPORTER_ASSERT(reporter, index == 5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001107}
1108
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001109// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001110DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001111 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001112 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001113 TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001114 const char* text = "No TextStyle! Uh Oh!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001115 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001116
1117 ParagraphStyle paragraph_style;
1118 TextStyle defaultStyle;
1119 defaultStyle.setFontFamilies({SkString("Roboto")});
1120 paragraph_style.setTextStyle(defaultStyle);
1121 paragraph_style.turnHintingOff();
1122 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001123 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001124
1125 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001126 paragraph->layout(TestCanvasWidth);
1127 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001128
Julia Lavrova3281b962019-12-02 11:32:25 -05001129 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1130
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001131 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1132
1133 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1134 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1135 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1136
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001137 size_t index = 0;
1138 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001139 StyleType::kAllAttributes,
1140 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001141 REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle()));
Julia Lavrova526df262019-08-21 17:49:44 -04001142 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001143 ++index;
1144 return true;
1145 });
1146 REPORTER_ASSERT(reporter, index == 1);
1147}
1148
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001149// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001150DEF_TEST(SkParagraph_BoldParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001151 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001152 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001153 TestCanvas canvas("SkParagraph_BoldParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001154 const char* text = "This is Red max bold text!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001155 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001156
1157 ParagraphStyle paragraph_style;
1158 paragraph_style.turnHintingOff();
1159 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1160
1161 TextStyle text_style;
1162 text_style.setFontFamilies({SkString("Roboto")});
1163 text_style.setColor(SK_ColorRED);
1164 text_style.setFontSize(60);
1165 text_style.setLetterSpacing(0);
1166 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width,
1167 SkFontStyle::kUpright_Slant));
1168 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001169 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001170 builder.pop();
1171
1172 auto paragraph = builder.Build();
1173 paragraph->layout(VeryLongCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001174 paragraph->paint(canvas.get(), 10.0, 60.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001175
Julia Lavrova3281b962019-12-02 11:32:25 -05001176 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1177
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001178 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1179
1180 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1181 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1182 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1183
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001184 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001185 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001186 StyleType::kAllAttributes,
1187 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001188 REPORTER_ASSERT(reporter, style.equals(text_style));
Julia Lavrova526df262019-08-21 17:49:44 -04001189 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001190 ++index;
1191 return true;
1192 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001193 REPORTER_ASSERT(reporter, index == 1);
1194}
1195
Julia Lavrovac2228562019-08-08 16:51:27 -04001196// Checked: NO DIFF (line height rounding error)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001197DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001198 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04001199 if (!fontCollection->fontsFound()) return;
1200 TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png");
1201 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001202 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001203
Julia Lavrovac2228562019-08-08 16:51:27 -04001204 ParagraphStyle paragraph_style;
1205 paragraph_style.turnHintingOff();
1206 paragraph_style.setMaxLines(10);
1207 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001208
Julia Lavrovac2228562019-08-08 16:51:27 -04001209 TextStyle text_style;
1210 text_style.setFontFamilies({SkString("Roboto")});
1211 text_style.setFontSize(20);
1212 text_style.setColor(SK_ColorBLACK);
1213 text_style.setHeight(3.6345f);
1214 text_style.setHeightOverride(true);
1215 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001216 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04001217 builder.pop();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001218
Julia Lavrovac2228562019-08-08 16:51:27 -04001219 auto paragraph = builder.Build();
1220 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001221
Julia Lavrovac2228562019-08-08 16:51:27 -04001222 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001223 REPORTER_ASSERT(reporter, impl->runs().size() == 5);
Julia Lavrovac2228562019-08-08 16:51:27 -04001224 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
1225 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001226
Julia Lavrovac2228562019-08-08 16:51:27 -04001227 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001228
Julia Lavrovac2228562019-08-08 16:51:27 -04001229 SkPaint paint;
1230 paint.setStyle(SkPaint::kStroke_Style);
1231 paint.setAntiAlias(true);
1232 paint.setStrokeWidth(1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001233
Julia Lavrovac2228562019-08-08 16:51:27 -04001234 // Tests for GetRectsForRange()
1235 RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle;
1236 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1237 paint.setColor(SK_ColorRED);
1238 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
1239 canvas.drawRects(SK_ColorRED, boxes);
1240 REPORTER_ASSERT(reporter, boxes.size() == 0ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001241
Julia Lavrovac2228562019-08-08 16:51:27 -04001242 boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style);
1243 canvas.drawRects(SK_ColorBLUE, boxes);
1244 REPORTER_ASSERT(reporter, boxes.size() == 3ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001245
Julia Lavrovac2228562019-08-08 16:51:27 -04001246 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100));
1247 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5));
1248 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100));
1249 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001250}
1251
Julia Lavrovac2228562019-08-08 16:51:27 -04001252// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001253DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001254 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001255 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001256 TestCanvas canvas("SkParagraph_LeftAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001257 const char* text =
1258 "This is a very long sentence to test if the text will properly wrap "
1259 "around and go to the next line. Sometimes, short sentence. Longer "
1260 "sentences are okay too because they are nessecary. Very short. "
1261 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1262 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1263 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1264 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1265 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1266 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1267 "mollit anim id est laborum. "
1268 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1269 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1270 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1271 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1272 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1273 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1274 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001275 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001276
1277 ParagraphStyle paragraph_style;
1278 paragraph_style.setMaxLines(14);
1279 paragraph_style.setTextAlign(TextAlign::kLeft);
1280 paragraph_style.turnHintingOff();
1281 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1282
1283 TextStyle text_style;
1284 text_style.setFontFamilies({SkString("Roboto")});
1285 text_style.setFontSize(26);
1286 text_style.setLetterSpacing(1);
1287 text_style.setWordSpacing(5);
1288 text_style.setColor(SK_ColorBLACK);
1289 text_style.setHeight(1);
1290 text_style.setDecoration(TextDecoration::kUnderline);
1291 text_style.setDecorationColor(SK_ColorBLACK);
1292 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001293 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001294 builder.pop();
1295
1296 auto paragraph = builder.Build();
1297 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001298 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001299
1300 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001301
1302 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1303 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1304 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001305 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001306 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1307
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001308 double expected_y = 0;
1309 double epsilon = 0.01f;
1310 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1311 REPORTER_ASSERT(reporter,
1312 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1313 expected_y += 30;
1314 REPORTER_ASSERT(reporter,
1315 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1316 expected_y += 30;
1317 REPORTER_ASSERT(reporter,
1318 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1319 expected_y += 30;
1320 REPORTER_ASSERT(reporter,
1321 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1322 expected_y += 30 * 10;
1323 REPORTER_ASSERT(reporter,
1324 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1325
1326 REPORTER_ASSERT(reporter,
1327 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1328
1329 // Tests for GetGlyphPositionAtCoordinate()
1330 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0);
1331 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
1332 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
1333 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001334 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001335}
1336
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001337// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001338DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001339 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001340 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001341 TestCanvas canvas("SkParagraph_RightAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001342 const char* text =
1343 "This is a very long sentence to test if the text will properly wrap "
1344 "around and go to the next line. Sometimes, short sentence. Longer "
1345 "sentences are okay too because they are nessecary. Very short. "
1346 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1347 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1348 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1349 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1350 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1351 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1352 "mollit anim id est laborum. "
1353 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1354 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1355 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1356 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1357 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1358 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1359 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001360 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001361
1362 ParagraphStyle paragraph_style;
1363 paragraph_style.setMaxLines(14);
1364 paragraph_style.setTextAlign(TextAlign::kRight);
1365 paragraph_style.turnHintingOff();
1366 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1367
1368 TextStyle text_style;
1369 text_style.setFontFamilies({SkString("Roboto")});
1370 text_style.setFontSize(26);
1371 text_style.setLetterSpacing(1);
1372 text_style.setWordSpacing(5);
1373 text_style.setColor(SK_ColorBLACK);
1374 text_style.setHeight(1);
1375 text_style.setDecoration(TextDecoration::kUnderline);
1376 text_style.setDecorationColor(SK_ColorBLACK);
1377 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001378 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001379 builder.pop();
1380
1381 auto paragraph = builder.Build();
1382 paragraph->layout(TestCanvasWidth - 100);
1383
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001384 paragraph->paint(canvas.get(), 0, 0);
1385
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001386 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001387
1388 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1389 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001390 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001391 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1392
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001393 double expected_y = 0;
1394 double epsilon = 0.01f;
1395 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1396 REPORTER_ASSERT(reporter,
1397 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1398 expected_y += 30;
1399 REPORTER_ASSERT(reporter,
1400 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1401 expected_y += 30;
1402 REPORTER_ASSERT(reporter,
1403 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1404 expected_y += 30;
1405 REPORTER_ASSERT(reporter,
1406 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1407 expected_y += 30 * 10;
1408 REPORTER_ASSERT(reporter,
1409 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1410
1411 auto calculate = [](const TextLine& line) -> SkScalar {
1412 return TestCanvasWidth - 100 - line.offset().fX - line.width();
1413 };
1414
1415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1416 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1417 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1418 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1419 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1420
1421 REPORTER_ASSERT(reporter,
1422 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1423}
1424
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001425// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001426DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001427 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001428 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001429 TestCanvas canvas("SkParagraph_CenterAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001430 const char* text =
1431 "This is a very long sentence to test if the text will properly wrap "
1432 "around and go to the next line. Sometimes, short sentence. Longer "
1433 "sentences are okay too because they are nessecary. Very short. "
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. "
1441 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1442 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1443 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1444 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1445 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1446 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1447 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001448 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001449
1450 ParagraphStyle paragraph_style;
1451 paragraph_style.setMaxLines(14);
1452 paragraph_style.setTextAlign(TextAlign::kCenter);
1453 paragraph_style.turnHintingOff();
1454 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1455
1456 TextStyle text_style;
1457 text_style.setFontFamilies({SkString("Roboto")});
1458 text_style.setFontSize(26);
1459 text_style.setLetterSpacing(1);
1460 text_style.setWordSpacing(5);
1461 text_style.setColor(SK_ColorBLACK);
1462 text_style.setHeight(1);
1463 text_style.setDecoration(TextDecoration::kUnderline);
1464 text_style.setDecorationColor(SK_ColorBLACK);
1465 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001466 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001467 builder.pop();
1468
1469 auto paragraph = builder.Build();
1470 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001471 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001472
1473 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001474
1475 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1476 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1477 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001478 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001479 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1480
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001481 double expected_y = 0;
1482 double epsilon = 0.01f;
1483 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1484 REPORTER_ASSERT(reporter,
1485 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1486 expected_y += 30;
1487 REPORTER_ASSERT(reporter,
1488 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1489 expected_y += 30;
1490 REPORTER_ASSERT(reporter,
1491 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1492 expected_y += 30;
1493 REPORTER_ASSERT(reporter,
1494 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1495 expected_y += 30 * 10;
1496 REPORTER_ASSERT(reporter,
1497 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1498
1499 auto calculate = [](const TextLine& line) -> SkScalar {
1500 return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width());
1501 };
1502
1503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1506 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1508
1509 REPORTER_ASSERT(reporter,
1510 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1511}
1512
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001513// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001514DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001515 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001516 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001517 TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001518 const char* text =
1519 "This is a very long sentence to test if the text will properly wrap "
1520 "around and go to the next line. Sometimes, short sentence. Longer "
1521 "sentences are okay too because they are nessecary. Very short. "
1522 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1523 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1524 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1525 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1526 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1527 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1528 "mollit anim id est laborum. "
1529 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1530 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1531 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1532 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1533 "velit esse cillum dolore eu fugiat.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001534 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001535
1536 ParagraphStyle paragraph_style;
1537 paragraph_style.setMaxLines(14);
1538 paragraph_style.setTextAlign(TextAlign::kJustify);
1539 paragraph_style.turnHintingOff();
1540 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1541
1542 TextStyle text_style;
1543 text_style.setFontFamilies({SkString("Roboto")});
1544 text_style.setFontSize(26);
1545 text_style.setLetterSpacing(0);
1546 text_style.setWordSpacing(5);
1547 text_style.setColor(SK_ColorBLACK);
1548 text_style.setHeight(1);
1549 text_style.setDecoration(TextDecoration::kUnderline);
1550 text_style.setDecorationColor(SK_ColorBLACK);
1551 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001552 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001553 builder.pop();
1554
1555 auto paragraph = builder.Build();
1556 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001557 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001558
Julia Lavrovac2228562019-08-08 16:51:27 -04001559 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1560 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1561 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1562 canvas.drawRects(SK_ColorRED, boxes);
1563
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001564 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001565
1566 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1567 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1568 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001569 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001570
1571 double expected_y = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001572 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001573 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001574 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001575 expected_y += 30;
1576 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001577 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001578 expected_y += 30;
1579 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001580 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001581 expected_y += 30;
1582 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001583 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001584 expected_y += 30 * 9;
1585 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001586 SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001587
1588 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001589 return line.offset().fX;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001590 };
1591
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001592 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100));
1593 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100));
1594 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100));
1595 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001596
1597 REPORTER_ASSERT(reporter,
1598 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1599}
1600
Julia Lavrovac2228562019-08-08 16:51:27 -04001601// Checked: DIFF (ghost spaces as a separate box in TxtLib)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001602DEF_TEST(SkParagraph_JustifyRTL, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001603 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001604 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001605 TestCanvas canvas("SkParagraph_JustifyRTL.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001606 const char* text =
1607 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1608 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1609 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001610 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001611
1612 ParagraphStyle paragraph_style;
1613 paragraph_style.setMaxLines(14);
1614 paragraph_style.setTextAlign(TextAlign::kJustify);
1615 paragraph_style.turnHintingOff();
1616 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1617
1618 TextStyle text_style;
1619 text_style.setFontFamilies({SkString("Ahem")});
1620 text_style.setFontSize(26);
1621 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001622 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001623 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001624 builder.pop();
1625
1626 auto paragraph = builder.Build();
1627 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001628 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001629
1630 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001631
1632 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001633 return TestCanvasWidth - 100 - line.width();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001634 };
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001635 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001636 if (&line == &impl->lines().back()) {
1637 REPORTER_ASSERT(reporter, calculate(line) > EPSILON100);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001638 } else {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001639 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001640 }
1641 }
1642
1643 // Just make sure the the text is actually RTL
1644 for (auto& run : impl->runs()) {
1645 REPORTER_ASSERT(reporter, !run.leftToRight());
1646 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001647
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001648 // Tests for GetRectsForRange()
1649 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1650 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1651 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1652 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001653 REPORTER_ASSERT(reporter, boxes.size() == 5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001654
1655 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1656 canvas.drawRects(SK_ColorBLUE, boxes);
1657 REPORTER_ASSERT(reporter, boxes.size() == 1);
1658
1659 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100));
1660 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1661 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100));
1662 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1663}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001664
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001665DEF_TEST_DISABLED(SkParagraph_JustifyRTLNewLine, reporter) {
1666 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1667 if (!fontCollection->fontsFound()) return;
1668 TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png");
1669 const char* text =
1670 "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1671 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1672 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
1673
1674 auto icu_text = icu::UnicodeString::fromUTF8(text);
1675 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1676 const size_t len = strlen(text);
1677
1678 ParagraphStyle paragraph_style;
1679 paragraph_style.setMaxLines(14);
1680 paragraph_style.setTextAlign(TextAlign::kJustify);
1681 paragraph_style.setTextDirection(TextDirection::kRtl);
1682 paragraph_style.turnHintingOff();
1683 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1684
1685 TextStyle text_style;
1686 text_style.setFontFamilies({SkString("Ahem")});
1687 text_style.setFontSize(26);
1688 text_style.setColor(SK_ColorBLACK);
1689 builder.pushStyle(text_style);
1690 builder.addText(text, len);
1691 builder.pop();
1692
1693 auto paragraph = builder.Build();
1694 paragraph->layout(TestCanvasWidth - 100);
1695 paragraph->paint(canvas.get(), 0, 0);
1696
1697 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1698
1699 SkPaint paint;
1700 paint.setStyle(SkPaint::kStroke_Style);
1701 paint.setAntiAlias(true);
1702 paint.setStrokeWidth(1);
1703
1704 // Tests for GetRectsForRange()
1705 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1706 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1707 paint.setColor(SK_ColorRED);
1708 auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
1709 for (size_t i = 0; i < boxes.size(); ++i) {
1710 canvas.get()->drawRect(boxes[i].rect, paint);
1711 }
1712 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1713 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
1714 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
1715 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1716 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
1717
1718 paint.setColor(SK_ColorBLUE);
1719 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1720 for (size_t i = 0; i < boxes.size(); ++i) {
1721 canvas.get()->drawRect(boxes[i].rect, paint);
1722 }
1723 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
1724 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
1725 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1726 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
1727 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1728
1729 // All lines should be justified to the width of the
1730 // paragraph.
1731 for (auto& line : impl->lines()) {
1732 REPORTER_ASSERT(reporter,
1733 SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
1734 }
1735}
1736
1737DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
1738 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1739 if (!fontCollection->fontsFound()) return;
1740 TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
1741
1742 const char* text = " leading space";
1743
1744 auto icu_text = icu::UnicodeString::fromUTF8(text);
1745 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1746 const size_t len = strlen(text);
1747
1748 ParagraphStyle paragraph_style;
1749 paragraph_style.setMaxLines(14);
1750 paragraph_style.setTextAlign(TextAlign::kJustify);
1751 paragraph_style.setTextDirection(TextDirection::kRtl);
1752 paragraph_style.turnHintingOff();
1753 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1754
1755 TextStyle text_style;
1756 text_style.setFontFamilies({SkString("Ahem")});
1757 text_style.setFontSize(26);
1758 text_style.setColor(SK_ColorBLACK);
1759 builder.pushStyle(text_style);
1760 builder.addText(text, len);
1761 builder.pop();
1762
1763 auto paragraph = builder.Build();
1764 paragraph->layout(TestCanvasWidth - 100);
1765 paragraph->paint(canvas.get(), 0, 0);
1766
1767 SkPaint paint;
1768 paint.setStyle(SkPaint::kStroke_Style);
1769 paint.setAntiAlias(true);
1770 paint.setStrokeWidth(1);
1771
1772 // Tests for GetRectsForRange()
1773 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1774 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1775 paint.setColor(SK_ColorRED);
1776 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1777 for (size_t i = 0; i < boxes.size(); ++i) {
1778 canvas.get()->drawRect(boxes[i].rect, paint);
1779 }
1780 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1781}
1782
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001783// Checked: NO DIFF (some minor decoration differences, probably)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001784DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001785 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001786 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001787 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001788 const char* text1 = "This text should be";
1789 const char* text2 = " decorated even when";
1790 const char* text3 = " wrapped around to";
1791 const char* text4 = " the next line.";
1792 const char* text5 = " Otherwise, bad things happen.";
1793
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001794 ParagraphStyle paragraph_style;
1795 paragraph_style.setMaxLines(14);
1796 paragraph_style.setTextAlign(TextAlign::kLeft);
1797 paragraph_style.turnHintingOff();
1798 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1799
1800 TextStyle text_style;
1801 text_style.setFontFamilies({SkString("Roboto")});
1802 text_style.setFontSize(26);
1803 text_style.setLetterSpacing(0);
1804 text_style.setWordSpacing(5);
1805 text_style.setColor(SK_ColorBLACK);
1806 text_style.setHeight(2);
1807 text_style.setDecoration(TextDecoration::kUnderline);
1808 text_style.setDecorationColor(SK_ColorBLACK);
1809 text_style.setDecoration((TextDecoration)(
1810 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1811 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1812 text_style.setDecorationColor(SK_ColorBLACK);
1813 text_style.setDecorationThicknessMultiplier(2.0);
1814 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001815 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001816
1817 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1818 text_style.setDecorationColor(SK_ColorBLUE);
1819 text_style.setDecorationThicknessMultiplier(1.0);
1820 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001821 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001822
1823 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1824 text_style.setDecorationColor(SK_ColorBLACK);
1825 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001826 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001827
1828 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1829 text_style.setDecorationColor(SK_ColorBLACK);
1830 text_style.setDecorationThicknessMultiplier(3.0);
1831 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001832 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001833
1834 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1835 text_style.setDecorationColor(SK_ColorRED);
1836 text_style.setDecorationThicknessMultiplier(1.0);
1837 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001838 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001839 builder.pop();
1840
1841 auto paragraph = builder.Build();
1842 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001843 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001844
1845 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001846
1847 size_t index = 0;
1848 for (auto& line : impl->lines()) {
1849 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001850 StyleType::kDecorations,
1851 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001852 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1853 TextDecoration::kOverline |
1854 TextDecoration::kLineThrough);
1855 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1856 switch (index) {
1857 case 0:
1858 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1859 TextDecorationStyle::kSolid);
1860 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1861 REPORTER_ASSERT(reporter,
1862 style.getDecorationThicknessMultiplier() == 2.0);
1863 break;
1864 case 1: // The style appears on 2 lines so it has 2 pieces
1865 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1866 TextDecorationStyle::kDouble);
1867 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1868 REPORTER_ASSERT(reporter,
1869 style.getDecorationThicknessMultiplier() == 1.0);
1870 break;
1871 case 2:
1872 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1873 TextDecorationStyle::kDotted);
1874 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1875 REPORTER_ASSERT(reporter,
1876 style.getDecorationThicknessMultiplier() == 1.0);
1877 break;
1878 case 3:
1879 case 4:
1880 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1881 TextDecorationStyle::kDashed);
1882 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1883 REPORTER_ASSERT(reporter,
1884 style.getDecorationThicknessMultiplier() == 3.0);
1885 break;
1886 case 5:
1887 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1888 TextDecorationStyle::kWavy);
1889 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1890 REPORTER_ASSERT(reporter,
1891 style.getDecorationThicknessMultiplier() == 1.0);
1892 break;
1893 default:
1894 REPORTER_ASSERT(reporter, false);
1895 break;
1896 }
1897 ++index;
1898 return true;
1899 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001900 }
1901}
1902
Julia Lavrovac2228562019-08-08 16:51:27 -04001903DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001904 SkDebugf("TODO: Add test for wavy decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001905}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001906
1907// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001908DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001909 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001910 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001911 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001912 const char* text1 = "No italic ";
1913 const char* text2 = "Yes Italic ";
1914 const char* text3 = "No Italic again.";
1915
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001916 ParagraphStyle paragraph_style;
1917 paragraph_style.turnHintingOff();
1918 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1919
1920 TextStyle text_style;
1921 text_style.setFontFamilies({SkString("Roboto")});
1922 text_style.setFontSize(10);
1923 text_style.setColor(SK_ColorRED);
1924 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001925 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001926
1927 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1928 SkFontStyle::kItalic_Slant));
1929 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001930 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001931 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001932 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001933
1934 auto paragraph = builder.Build();
1935 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001936 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001937
1938 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001939
1940 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1941 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1942 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1943 auto& line = impl->lines()[0];
1944 size_t index = 0;
1945 line.scanStyles(
1946 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001947 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001948 switch (index) {
1949 case 0:
1950 REPORTER_ASSERT(
1951 reporter,
1952 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1953 break;
1954 case 1:
1955 REPORTER_ASSERT(reporter,
1956 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1957 break;
1958 case 2:
1959 REPORTER_ASSERT(
1960 reporter,
1961 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1962 break;
1963 default:
1964 REPORTER_ASSERT(reporter, false);
1965 break;
1966 }
1967 ++index;
1968 return true;
1969 });
1970}
1971
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001972// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001973DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001974 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001975 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001976 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001977 const char* text =
1978 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1979 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1980 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1981 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1982 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001983 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001984
1985 ParagraphStyle paragraph_style;
1986 paragraph_style.setMaxLines(14);
1987 paragraph_style.setTextAlign(TextAlign::kJustify);
1988 paragraph_style.turnHintingOff();
1989 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1990
1991 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
1992 TextDecoration::kLineThrough);
1993
1994 TextStyle text_style;
1995 text_style.setFontFamilies({SkString("Source Han Serif CN")});
1996 text_style.setFontSize(35);
1997 text_style.setColor(SK_ColorBLACK);
1998 text_style.setLetterSpacing(2);
1999 text_style.setHeight(1);
2000 text_style.setDecoration(decoration);
2001 text_style.setDecorationColor(SK_ColorBLACK);
2002 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2003 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002004 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002005 builder.pop();
2006
2007 auto paragraph = builder.Build();
2008 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002009 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002010
Julia Lavrova3281b962019-12-02 11:32:25 -05002011 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2012
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002013 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002014
2015 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2016 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
2017 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002018 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002019}
2020
Julia Lavrovac2228562019-08-08 16:51:27 -04002021// Checked: NO DIFF (disabled)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002022DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002023 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002024 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002025 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002026 const char* text =
2027 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2028 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002029 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002030
2031 ParagraphStyle paragraph_style;
2032 paragraph_style.setMaxLines(14);
2033 paragraph_style.setTextAlign(TextAlign::kJustify);
2034 paragraph_style.turnHintingOff();
2035 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2036
2037 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2038 TextDecoration::kLineThrough);
2039
2040 TextStyle text_style;
2041 text_style.setFontFamilies({SkString("Katibeh")});
2042 text_style.setFontSize(35);
2043 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002044 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002045 text_style.setDecoration(decoration);
2046 text_style.setDecorationColor(SK_ColorBLACK);
2047 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2048 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002049 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002050 builder.pop();
2051
2052 auto paragraph = builder.Build();
2053 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002054 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002055
Julia Lavrova3281b962019-12-02 11:32:25 -05002056 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2057
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002058 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002059
2060 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2061 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2062 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002063 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002064}
2065
Julia Lavrovac2228562019-08-08 16:51:27 -04002066// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002067DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
2068
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002069 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002070 if (!fontCollection->fontsFound()) return;
2071 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
2072 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002073 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002074
2075 ParagraphStyle paragraph_style;
2076 paragraph_style.turnHintingOff();
2077 paragraph_style.setMaxLines(14);
2078 paragraph_style.setTextAlign(TextAlign::kRight);
2079 paragraph_style.setTextDirection(TextDirection::kRtl);
2080 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2081
2082 TextStyle text_style;
2083 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2084 text_style.setFontSize(26);
2085 text_style.setWordSpacing(5);
2086 text_style.setColor(SK_ColorBLACK);
2087 text_style.setDecoration(TextDecoration::kUnderline);
2088 text_style.setDecorationColor(SK_ColorBLACK);
2089 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002090 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002091 builder.pop();
2092
2093 auto paragraph = builder.Build();
2094 paragraph->layout(TestCanvasWidth - 100);
2095
2096 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2097 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2098
2099 paragraph->paint(canvas.get(), 0, 0);
2100
2101 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2102 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2103 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
2104 canvas.drawRects(SK_ColorRED, boxes);
2105
Julia Lavrovac2228562019-08-08 16:51:27 -04002106 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002107
Julia Lavrovac2228562019-08-08 16:51:27 -04002108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
2109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
2111 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002112}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002113
2114// Checked DIFF+
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002115// This test shows now 2 boxes for [36:40) range:
2116// [36:38) for arabic text and [38:39) for the last space
2117// that has default paragraph direction (LTR) and is placed at the end of the paragraph
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002118DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
2119
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002120 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002121 if (!fontCollection->fontsFound()) return;
2122 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
2123 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002124 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002125
2126 ParagraphStyle paragraph_style;
2127 paragraph_style.turnHintingOff();
2128 paragraph_style.setMaxLines(14);
2129 paragraph_style.setTextAlign(TextAlign::kLeft);
2130 paragraph_style.setTextDirection(TextDirection::kLtr);
2131 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2132
2133 TextStyle text_style;
2134 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2135 text_style.setFontSize(26);
2136 text_style.setWordSpacing(5);
2137 text_style.setColor(SK_ColorBLACK);
2138 text_style.setDecoration(TextDecoration::kUnderline);
2139 text_style.setDecorationColor(SK_ColorBLACK);
2140 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002141 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002142 builder.pop();
2143
2144 auto paragraph = builder.Build();
2145 paragraph->layout(TestCanvasWidth - 100);
2146
2147 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2148 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2149
2150 paragraph->paint(canvas.get(), 0, 0);
2151
2152 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2153 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002154 // 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 -04002155 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2156 canvas.drawRects(SK_ColorRED, boxes);
2157
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002158 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
2159 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.92f, EPSILON100)); // DIFF: 89.40625
2160 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2161 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 110.16f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002162 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002163}
2164
2165// Checked DIFF+
2166DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2167
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002168 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002169 if (!fontCollection->fontsFound()) return;
2170 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2171 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002172 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002173
2174 ParagraphStyle paragraph_style;
2175 paragraph_style.turnHintingOff();
2176 paragraph_style.setMaxLines(14);
2177 paragraph_style.setTextAlign(TextAlign::kRight);
2178 paragraph_style.setTextDirection(TextDirection::kLtr);
2179 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2180
2181 TextStyle text_style;
2182 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2183 text_style.setFontSize(26);
2184 text_style.setWordSpacing(5);
2185 text_style.setColor(SK_ColorBLACK);
2186 text_style.setDecoration(TextDecoration::kUnderline);
2187 text_style.setDecorationColor(SK_ColorBLACK);
2188 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002189 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002190 builder.pop();
2191
2192 auto paragraph = builder.Build();
2193 paragraph->layout(TestCanvasWidth - 100);
2194
2195 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2196 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2197
2198 paragraph->paint(canvas.get(), 0, 0);
2199
2200 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2201 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2202 std::vector<TextBox> boxes =
2203 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2204 canvas.drawRects(SK_ColorRED, boxes);
2205
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002206 REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF
2207 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.5f, EPSILON100)); // DIFF
2208 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2209 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 587.74f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002210 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002211}
2212
2213// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002214DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002215 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002216 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002217 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002218 const char* text =
2219 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2220 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002221 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002222
2223 ParagraphStyle paragraphStyle;
2224 paragraphStyle.setTextAlign(TextAlign::kLeft);
2225 paragraphStyle.setMaxLines(10);
2226 paragraphStyle.turnHintingOff();
2227 TextStyle textStyle;
2228 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002229 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2230 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002231 textStyle.setFontSize(50);
2232 textStyle.setLetterSpacing(1);
2233 textStyle.setWordSpacing(5);
2234 textStyle.setHeight(1);
2235 textStyle.setColor(SK_ColorBLACK);
2236
2237 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2238 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002239 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002240 builder.pop();
2241
2242 auto paragraph = builder.Build();
2243 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002244 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002245
2246 // Tests for getGlyphPositionAtCoordinate()
2247 // NOTE: resulting values can be a few off from their respective positions in
2248 // the original text because the final trailing whitespaces are sometimes not
2249 // drawn (namely, when using "justify" alignment) and therefore are not active
2250 // glyphs.
2251 REPORTER_ASSERT(reporter,
2252 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2253 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2254 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2255 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2256 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2257 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002258 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002259 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2260 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2261 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002262 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002263 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002264 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002265 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2266 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002267 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002268 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2269 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002270 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002271 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2272 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2273 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002274 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002275 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2276}
2277
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002278// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002279DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002280 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002281 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002282 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002283 const char* text =
2284 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2285 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002286 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002287
2288 ParagraphStyle paragraphStyle;
2289 paragraphStyle.setTextAlign(TextAlign::kLeft);
2290 paragraphStyle.setMaxLines(10);
2291 paragraphStyle.turnHintingOff();
2292 TextStyle textStyle;
2293 textStyle.setFontFamilies({SkString("Roboto")});
2294 textStyle.setFontSize(50);
2295 textStyle.setColor(SK_ColorBLACK);
2296 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2297 SkFontStyle::kUpright_Slant));
2298
2299 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2300 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002301 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002302 builder.pop();
2303
2304 auto paragraph = builder.Build();
2305 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002306 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002307
2308 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2309 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002310
2311 SkPaint paint;
2312 paint.setStyle(SkPaint::kStroke_Style);
2313 paint.setAntiAlias(true);
2314 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002315
2316 {
2317 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2318 REPORTER_ASSERT(reporter, result.empty());
2319 }
2320 {
2321 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002322 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002323 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002324 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2325 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2326 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2327 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002328 }
2329 {
2330 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002331 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002332 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002333 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2334 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2335 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2336 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002337 }
2338 {
2339 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002340 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002341 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002342 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2343 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2344 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2345 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002346 }
2347 {
2348 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002349 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002350 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002351 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2353 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2354 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2355 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2356 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2357 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2358 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002359 }
2360 {
2361 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002362 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002363 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002364 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002365 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002366 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002367 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002368 }
2369 {
2370 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2371 REPORTER_ASSERT(reporter, result.empty());
2372 }
2373}
2374
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002375// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002376DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002377 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002378 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002379 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002380 const char* text =
2381 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2382 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2383 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002384 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002385
2386 ParagraphStyle paragraphStyle;
2387 paragraphStyle.setTextAlign(TextAlign::kLeft);
2388 paragraphStyle.setMaxLines(10);
2389 paragraphStyle.turnHintingOff();
2390 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002391 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002392 textStyle.setFontSize(50);
2393 textStyle.setColor(SK_ColorBLACK);
2394 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2395 SkFontStyle::kUpright_Slant));
2396
2397 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2398 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002399 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002400 builder.pop();
2401
2402 auto paragraph = builder.Build();
2403 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002404 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002405
2406 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2407 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002408 {
2409 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2410 REPORTER_ASSERT(reporter, result.empty());
2411 }
2412 {
2413 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002414 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002415 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002416 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2417 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2418 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2419 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002420 }
2421 {
2422 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002423 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002424 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002425 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2426 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2427 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2428 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002429 }
2430 {
2431 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002432 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002433 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002434 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2435 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2436 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2437 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002438 }
2439}
2440
Julia Lavrovac2228562019-08-08 16:51:27 -04002441// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002442DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002443 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002444 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002445 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002446 const char* text =
2447 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2448 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2449 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002450 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002451
2452 ParagraphStyle paragraphStyle;
2453 paragraphStyle.setTextAlign(TextAlign::kLeft);
2454 paragraphStyle.setMaxLines(10);
2455 paragraphStyle.turnHintingOff();
2456 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002457 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002458 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002459 textStyle.setHeight(1.6f);
2460 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002461 textStyle.setColor(SK_ColorBLACK);
2462 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2463 SkFontStyle::kUpright_Slant));
2464
2465 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2466 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002467 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002468 builder.pop();
2469
2470 auto paragraph = builder.Build();
2471 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002472 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002473
2474 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002475 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002476 {
2477 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2478 REPORTER_ASSERT(reporter, result.empty());
2479 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002480
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002481 {
2482 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002483 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002484 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2486 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2487 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2488 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002489 }
2490 {
2491 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002492 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002493 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2496 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2497 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002498 }
2499 {
2500 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002501 canvas.drawRects(SK_ColorGREEN, result);
2502 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002506 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002507 }
2508 {
2509 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002510 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002511 REPORTER_ASSERT(reporter, result.size() == 8);
2512
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002513 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002514 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2517
2518 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2519 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2520 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2521 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2522
2523 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2524 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002525 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002526 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2527
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002528 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002529 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2530 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2531 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2532
2533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2536 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2537
2538 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2539 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2540 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2541 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002542 }
2543 {
2544 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002545 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002546 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002547 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002548 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002549 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002550 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2551
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002552 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002553 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2554 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2555 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002556 }
2557 {
2558 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2559 REPORTER_ASSERT(reporter, result.empty());
2560 }
2561}
2562
Julia Lavrovac2228562019-08-08 16:51:27 -04002563// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002564DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002565 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002566 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002567 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002568 const char* text =
2569 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2570 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2571 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002572 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002573
2574 ParagraphStyle paragraphStyle;
2575 paragraphStyle.setTextAlign(TextAlign::kLeft);
2576 paragraphStyle.setMaxLines(10);
2577 paragraphStyle.turnHintingOff();
2578 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002579 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002580 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002581 textStyle.setHeight(1.6f);
2582 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002583 textStyle.setColor(SK_ColorBLACK);
2584 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2585 SkFontStyle::kUpright_Slant));
2586
2587 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2588 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002589 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002590 builder.pop();
2591
2592 auto paragraph = builder.Build();
2593 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002594 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002595
2596 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002597 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002598 {
2599 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2600 REPORTER_ASSERT(reporter, result.empty());
2601 }
2602
2603 {
2604 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002605 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002606 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002607 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2608 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2609 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2610 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002611 }
2612 {
2613 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002614 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002615 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002616 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2617 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2618 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2619 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002620 }
2621 {
2622 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002623 canvas.drawRects(SK_ColorGREEN, result);
2624 REPORTER_ASSERT(reporter, result.size() == 1);
2625 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2627 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2628 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002629 }
2630 {
2631 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002632 canvas.drawRects(SK_ColorMAGENTA, result);
2633 REPORTER_ASSERT(reporter, result.size() == 8);
2634
2635 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2636 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2637 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2638 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2639
2640 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2641 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2643 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2644
2645 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2646 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2649
2650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2651 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2653 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2654
2655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2659
2660 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2661 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2662 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2663 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002664 }
2665 {
2666 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002667 canvas.drawRects(SK_ColorBLACK, result);
2668 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002669 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002670 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002671 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002672 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2673
2674 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2675 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2676 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2677 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002678 }
2679 {
2680 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2681 REPORTER_ASSERT(reporter, result.empty());
2682 }
2683}
2684
Julia Lavrovac2228562019-08-08 16:51:27 -04002685// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002686DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002687 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002688 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002689 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002690 const char* text =
2691 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2692 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2693 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002694 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002695
2696 ParagraphStyle paragraphStyle;
2697 paragraphStyle.setTextAlign(TextAlign::kLeft);
2698 paragraphStyle.setMaxLines(10);
2699 paragraphStyle.turnHintingOff();
2700 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002701 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002702 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002703 textStyle.setHeight(1.6f);
2704 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002705 textStyle.setColor(SK_ColorBLACK);
2706 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2707 SkFontStyle::kUpright_Slant));
2708
2709 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2710 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002711 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002712 builder.pop();
2713
2714 auto paragraph = builder.Build();
2715 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002716 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002717
2718 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002719 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002720 {
2721 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2722 REPORTER_ASSERT(reporter, result.empty());
2723 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002724
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002725 {
2726 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002727 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002728 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002729 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2730 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2731 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2732 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002733 }
2734 {
2735 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002736 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002737 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002738 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2739 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2740 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2741 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002742 }
2743 {
2744 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002745 canvas.drawRects(SK_ColorGREEN, result);
2746 REPORTER_ASSERT(reporter, result.size() == 1);
2747 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2748 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2749 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
2750 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002751 }
2752 {
2753 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002754 canvas.drawRects(SK_ColorMAGENTA, result);
2755 REPORTER_ASSERT(reporter, result.size() == 8);
2756
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002757 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002758 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2759 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2760 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2761
2762 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2763 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2764 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2765 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2766
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002767 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002768 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2769 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2770 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2771
2772 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2773 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2774 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2775 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2776
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002777 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002778 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2780 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2781
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002782 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002783 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2784 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2785 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002786 }
2787 {
2788 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002789 canvas.drawRects(SK_ColorBLACK, result);
2790 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002791 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002792 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002793 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002794 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2795
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002796 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002797 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2798 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2799 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002800 }
2801 {
2802 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2803 REPORTER_ASSERT(reporter, result.empty());
2804 }
2805}
2806
Julia Lavrovac2228562019-08-08 16:51:27 -04002807// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002808DEF_TEST(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002809 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002810 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002811 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002812 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002813 const size_t len = strlen(text);
2814
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002815 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002816 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002817 paragraphStyle.setMaxLines(10);
2818 paragraphStyle.turnHintingOff();
2819 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2820
2821 TextStyle textStyle;
2822 textStyle.setFontFamilies({SkString("Roboto")});
2823 textStyle.setFontSize(50);
2824 textStyle.setLetterSpacing(1);
2825 textStyle.setWordSpacing(5);
2826 textStyle.setHeight(1);
2827 textStyle.setColor(SK_ColorBLACK);
2828
2829 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002830 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002831 builder.pop();
2832
2833 auto paragraph = builder.Build();
2834 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002835 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002836
2837 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002838 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2839
2840 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2841 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2842 {
2843 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2844 REPORTER_ASSERT(reporter, result.empty());
2845 }
2846 {
2847 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2848 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2849 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002850 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2851 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002852 }
2853 {
2854 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2855 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2856 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002857 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2858 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002859 }
2860 {
2861 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2862 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2863 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2864 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002865 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002866 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002867 }
2868}
2869
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002870// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002871DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002872 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002873 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002874 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002875 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2876 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2877 // Any attempt to substitute one for another leads to errors
2878 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002879 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002880 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002881
2882 ParagraphStyle paragraphStyle;
2883 paragraphStyle.setTextAlign(TextAlign::kCenter);
2884 paragraphStyle.setMaxLines(10);
2885 paragraphStyle.turnHintingOff();
2886 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2887
2888 TextStyle textStyle;
2889 textStyle.setFontFamilies({SkString("Roboto")});
2890 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002891 textStyle.setHeight(1);
2892 textStyle.setColor(SK_ColorBLACK);
2893 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2894 SkFontStyle::kUpright_Slant));
2895
2896 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002897 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002898 builder.pop();
2899
2900 auto paragraph = builder.Build();
2901 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002902 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002903
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002904 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002905 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2906 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002907 {
2908 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2909 REPORTER_ASSERT(reporter, result.empty());
2910 }
2911
2912 {
2913 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002914 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002915 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002916 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2917 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2918 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2919 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002920 }
2921
2922 {
2923 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002924 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002925 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002926 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2927 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2928 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2929 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002930 }
2931
2932 {
2933 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002934 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002935 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2938 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2939 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002940 }
2941
2942 {
2943 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002944 canvas.drawRects(SK_ColorBLACK, result);
2945 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2946 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2947 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2948 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2949 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002950 }
2951
2952 {
2953 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002954 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002955 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002956 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2957 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2958 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2959 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002960 }
2961
2962 {
2963 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2964 REPORTER_ASSERT(reporter, result.empty());
2965 }
2966}
2967
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002968// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002969DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002970 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002971 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002972 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002973 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002974 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002975
2976 ParagraphStyle paragraphStyle;
2977 paragraphStyle.setTextAlign(TextAlign::kCenter);
2978 paragraphStyle.setMaxLines(10);
2979 paragraphStyle.turnHintingOff();
2980 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2981
2982 TextStyle textStyle;
2983 textStyle.setFontFamilies({SkString("Roboto")});
2984 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002985 textStyle.setHeight(1);
2986 textStyle.setColor(SK_ColorBLACK);
2987 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2988 SkFontStyle::kUpright_Slant));
2989
2990 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002991 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002992 builder.pop();
2993
2994 auto paragraph = builder.Build();
2995 paragraph->layout(550);
2996
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002997 paragraph->paint(canvas.get(), 0, 0);
2998
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002999 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003000 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3001
3002 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3003 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003004 {
3005 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3006 REPORTER_ASSERT(reporter, result.empty());
3007 }
3008
3009 {
3010 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04003011 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003012 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003013 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
3014 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
3015 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
3016 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003017 }
3018
3019 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003020 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3021 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003022 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003023 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3024 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3025 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3026 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003027 }
3028}
3029
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003030// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003031DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003032 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003033 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003034 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3035 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003036 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003037
3038 ParagraphStyle paragraphStyle;
3039 paragraphStyle.setTextAlign(TextAlign::kCenter);
3040 paragraphStyle.setMaxLines(10);
3041 paragraphStyle.turnHintingOff();
3042 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3043
3044 TextStyle textStyle;
3045 textStyle.setFontFamilies({SkString("Roboto")});
3046 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003047 textStyle.setHeight(1);
3048 textStyle.setColor(SK_ColorBLACK);
3049 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3050 SkFontStyle::kUpright_Slant));
3051
3052 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003053 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003054 builder.pop();
3055
3056 auto paragraph = builder.Build();
3057 paragraph->layout(550);
3058
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003059 paragraph->paint(canvas.get(), 0, 0);
3060
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003061 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003062
3063 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3064
3065 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3066 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3067 SkScalar epsilon = 0.01f;
3068 {
3069 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3070 REPORTER_ASSERT(reporter, result.empty());
3071 }
3072 {
3073 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003074 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003075 REPORTER_ASSERT(reporter, result.size() == 1);
3076 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3077 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3078 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3079 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3080 }
3081 {
3082 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003083 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003084 REPORTER_ASSERT(reporter, result.size() == 1);
3085 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3086 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3088 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3089 }
3090 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003091 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003092 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003093 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003094 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3095 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003096 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3098 }
3099 {
3100 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003101 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003102 REPORTER_ASSERT(reporter, result.size() == 1);
3103 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3104 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003105 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3107 }
3108 {
3109 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003110 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003111 REPORTER_ASSERT(reporter, result.size() == 1);
3112 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3113 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3114 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3115 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3116 }
3117 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003118 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003119 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003120 REPORTER_ASSERT(reporter, result.size() == 1);
3121 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3122 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003123 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003124 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3125 }
3126 {
3127 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3128 REPORTER_ASSERT(reporter, result.empty());
3129 }
3130}
3131
Julia Lavrovac2228562019-08-08 16:51:27 -04003132// Checked: DIFF (line height rounding error)
3133DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003134 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003135 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003136 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3137 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003138 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003139
3140 StrutStyle strutStyle;
3141 strutStyle.setStrutEnabled(true);
3142 strutStyle.setFontFamilies({SkString("Roboto")});
3143 strutStyle.setFontSize(14.0);
3144
3145 ParagraphStyle paragraphStyle;
3146 paragraphStyle.setStrutStyle(strutStyle);
3147
3148 TextStyle textStyle;
3149 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3150 textStyle.setFontSize(20);
3151 textStyle.setColor(SK_ColorBLACK);
3152
3153 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3154 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003155 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003156 builder.pop();
3157
3158 auto paragraph = builder.Build();
3159 paragraph->layout(550);
3160 paragraph->paint(canvas.get(), 0, 0);
3161
3162 {
3163 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3164 canvas.drawRects(SK_ColorGREEN, result);
3165 REPORTER_ASSERT(reporter, result.size() == 1);
3166 }
3167
3168 {
3169 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3170 canvas.drawRects(SK_ColorRED, result);
3171 REPORTER_ASSERT(reporter, result.size() == 1);
3172 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3173 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3174 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3175 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3176 }
3177}
3178
3179// Checked: NO DIFF
3180DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003181 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003182 if (!fontCollection->fontsFound()) return;
3183 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3184 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003185 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003186
3187 StrutStyle strutStyle;
3188 strutStyle.setStrutEnabled(false);
3189
3190 ParagraphStyle paragraphStyle;
3191 paragraphStyle.setStrutStyle(strutStyle);
3192
3193 TextStyle textStyle;
3194 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3195 textStyle.setFontSize(20);
3196 textStyle.setColor(SK_ColorBLACK);
3197
3198 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3199 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003200 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003201 builder.pop();
3202
3203 auto paragraph = builder.Build();
3204 paragraph->layout(550);
3205 paragraph->paint(canvas.get(), 0, 0);
3206
3207
3208 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3209 canvas.drawRects(SK_ColorGREEN, result1);
3210 REPORTER_ASSERT(reporter, result1.size() == 1);
3211
3212 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3213 canvas.drawRects(SK_ColorRED, result2);
3214 REPORTER_ASSERT(reporter, result2.size() == 1);
3215
3216 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3217}
3218
3219// Checked: DIFF (small in numbers)
3220DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003221 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003222 if (!fontCollection->fontsFound()) return;
3223 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003224 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3225 "67890 12345 67890 12345 67890 12345";
3226 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003227 ParagraphStyle paragraphStyle;
3228 paragraphStyle.setTextAlign(TextAlign::kLeft);
3229 paragraphStyle.setMaxLines(10);
3230 paragraphStyle.turnHintingOff();
3231 TextStyle textStyle;
3232 textStyle.setFontFamilies({SkString("Roboto")});
3233 textStyle.setFontSize(52);
3234 textStyle.setLetterSpacing(1.19039f);
3235 textStyle.setWordSpacing(5);
3236 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003237 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003238 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003239
3240 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3241 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003242 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003243 builder.pop();
3244
3245 auto paragraph = builder.Build();
3246 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003247 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003248
3249 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3250 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3251 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3252 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3253 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003254 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3255 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003256
3257 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003258 boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003259 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003260
Julia Lavrovac2228562019-08-08 16:51:27 -04003261 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003262 boxes = paragraph->getRectsForRange(7, 8, 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
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003265 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3266 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3267 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3268 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3269 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3270 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3271 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3272 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3273
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003274 boxes = paragraph->getRectsForRange(12, 13, 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(13, 14, 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 boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003279 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003280 boxes = paragraph->getRectsForRange(19, 20, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003281 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003282 boxes = paragraph->getRectsForRange(24, 25, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003283 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003284 boxes = paragraph->getRectsForRange(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003285 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003286 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003287 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003288 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003289 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003290
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003291 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3292 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003293}
3294
Julia Lavrovac2228562019-08-08 16:51:27 -04003295// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003296DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003297 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003298 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003299 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003300 ParagraphStyle paragraph_style;
3301 paragraph_style.setMaxLines(10);
3302 paragraph_style.setTextAlign(TextAlign::kLeft);
3303 paragraph_style.turnHintingOff();
3304 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3305
3306 TextStyle text_style;
3307 text_style.setFontFamilies({SkString("Roboto")});
3308 text_style.setFontSize(50);
3309 text_style.setLetterSpacing(20);
3310 text_style.setWordSpacing(0);
3311 text_style.setColor(SK_ColorBLACK);
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(10);
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("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003320 builder.pop();
3321
3322 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003323 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003324 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003325 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003326 builder.pop();
3327
3328 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003329 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003330 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003331 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003332 builder.pop();
3333
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003334 const char* hSpace = "H ";
3335 const size_t len = strlen(hSpace);
3336
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003337 text_style.setLetterSpacing(0);
3338 text_style.setWordSpacing(20);
3339 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003340 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003341 builder.pop();
3342
3343 text_style.setLetterSpacing(0);
3344 text_style.setWordSpacing(0);
3345 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003346 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003347 builder.pop();
3348
3349 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003350 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003351 text_style.setWordSpacing(20);
3352 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003353 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003354 builder.pop();
3355
3356 auto paragraph = builder.Build();
3357 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003358 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003359
3360 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3361 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3362 size_t index = 0;
3363 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003364 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3365 ++index;
3366 return true;
3367 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003368 REPORTER_ASSERT(reporter, index == 4);
3369 index = 0;
3370 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003371 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3372 ++index;
3373 return true;
3374 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003375 REPORTER_ASSERT(reporter, index == 4);
3376}
3377
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003378// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003379DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003380 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003381 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003382 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003383 const char* text =
3384 "A "
3385 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3386 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003387 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003388
3389 ParagraphStyle paragraph_style;
3390 paragraph_style.turnHintingOff();
3391 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3392
3393 TextStyle text_style;
3394 text_style.setFontFamilies({SkString("Roboto")});
3395 text_style.setColor(SK_ColorRED);
3396 text_style.setFontSize(31);
3397 text_style.setLetterSpacing(0);
3398 text_style.setWordSpacing(0);
3399 text_style.setColor(SK_ColorBLACK);
3400 text_style.setHeight(1);
3401 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003402 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003403 builder.pop();
3404
3405 auto paragraph = builder.Build();
3406 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003407 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003408
3409 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3410 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3411 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3412 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003413 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003414 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3415
3416 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3417 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3418 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3419}
3420
Julia Lavrovac2228562019-08-08 16:51:27 -04003421// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003422DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003423 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003424 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003425 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3426
3427 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3428 const char* text2 = " Dialog Text List lots of words to see "
3429 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003430 float scale = 3.0f;
3431 ParagraphStyle paragraph_style;
3432 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3433 TextStyle text_style;
3434 text_style.setFontFamilies({SkString("Droid Serif")});
3435 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003436 text_style.setColor(SK_ColorBLACK);
3437
3438 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003439 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003440 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003441 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003442 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003443 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003444 text_style.setFontSize(14 / scale);
3445 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003446 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003447 builder.pop();
3448
3449 auto paragraph = builder.Build();
3450 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003451 canvas.get()->scale(scale, scale);
3452 paragraph->paint(canvas.get(), 0, 0);
3453 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003454
3455 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003456
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003457 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003458 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003459 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3460 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3461 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3462 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3463 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3464 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003465}
3466
Julia Lavrovac2228562019-08-08 16:51:27 -04003467// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003468DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003469 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003470 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003471 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003472 const char* text =
3473 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3474 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003475 const size_t len = strlen(text);
3476
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003477 ParagraphStyle paragraph_style;
3478 paragraph_style.turnHintingOff();
3479 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3480
3481 TextStyle text_style;
3482 text_style.setFontFamilies({SkString("Roboto")});
3483 text_style.setColor(SK_ColorRED);
3484 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003485 text_style.setColor(SK_ColorBLACK);
3486 text_style.setHeight(1);
3487 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003488 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003489 builder.pop();
3490
3491 auto paragraph = builder.Build();
3492 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003493 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003494
3495 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3496 // Minikin does not count empty lines but SkParagraph does
3497 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3498
3499 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3500 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3501 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3502 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3503 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003504 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3505 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003506}
3507
Julia Lavrova526df262019-08-21 17:49:44 -04003508// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003509DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003510 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003511 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003512 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3513 const char* text =
3514 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3515 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3516 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3517 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003518 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003519
3520 ParagraphStyle paragraph_style;
3521 paragraph_style.turnHintingOff();
3522 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3523
3524 TextStyle text_style;
3525 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3526 text_style.setFontSize(50);
3527 text_style.setDecoration(TextDecoration::kUnderline);
3528 text_style.setColor(SK_ColorBLACK);
3529 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003530 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003531 builder.pop();
3532
3533 auto paragraph = builder.Build();
3534 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003535 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003536
Julia Lavrova3281b962019-12-02 11:32:25 -05003537 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3538
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003539 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003540
3541 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3542 for (auto& line : impl->lines()) {
3543 if (&line != impl->lines().end() - 1) {
3544 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3545 } else {
3546 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3547 }
3548 REPORTER_ASSERT(reporter, line.height() == 59);
3549 }
3550}
3551
Julia Lavrovac2228562019-08-08 16:51:27 -04003552// Checked: DIFF+
3553DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003554 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003555 if (!fontCollection->fontsFound()) return;
3556 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3557 const char* text =
3558 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3559 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3560 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3561 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3562 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3563 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003564 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003565
3566 ParagraphStyle paragraph_style;
3567 paragraph_style.turnHintingOff();
3568 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3569
3570 TextStyle text_style;
3571 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3572 text_style.setFontSize(50);
3573 text_style.setColor(SK_ColorBLACK);
3574 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003575 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003576 builder.pop();
3577
3578 auto paragraph = builder.Build();
3579 paragraph->layout(TestCanvasWidth - 300);
3580 paragraph->paint(canvas.get(), 0, 0);
3581
3582 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3583 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3584
3585 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3586 REPORTER_ASSERT(reporter, result.size() == 0);
3587
3588 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3589 REPORTER_ASSERT(reporter, result.size() == 2);
3590 canvas.drawRects(SK_ColorRED, result);
3591
3592 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003593 REPORTER_ASSERT(reporter, result.size() == 0); // There is no single glyph
Julia Lavrovac2228562019-08-08 16:51:27 -04003594 canvas.drawRects(SK_ColorBLUE, result);
3595
3596 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3597 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3598 REPORTER_ASSERT(reporter, result.size() == 2);
3599 canvas.drawRects(SK_ColorGREEN, result);
3600
3601 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3602 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3603 REPORTER_ASSERT(reporter, result.size() == 2);
3604 canvas.drawRects(SK_ColorGREEN, result);
3605
3606 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3607 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3608 REPORTER_ASSERT(reporter, result.size() == 2);
3609 canvas.drawRects(SK_ColorGREEN, result);
3610}
3611
Julia Lavrova916a9042019-08-08 16:51:27 -04003612DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3613 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3614}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003615
Julia Lavrovac2228562019-08-08 16:51:27 -04003616// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003617DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003618 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003619 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003620 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003621 const char* text =
3622 "Sentence to layout at diff widths to get diff line counts. short words "
3623 "short words short words short words short words short words short words "
3624 "short words short words short words short words short words short words "
3625 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003626 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003627
3628 ParagraphStyle paragraph_style;
3629 paragraph_style.turnHintingOff();
3630 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3631
3632 TextStyle text_style;
3633 text_style.setFontFamilies({SkString("Roboto")});
3634 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003635 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003636 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003637 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003638 builder.pop();
3639
3640 auto paragraph = builder.Build();
3641 paragraph->layout(300);
3642
3643 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3644 // Some of the formatting lazily done on paint
3645 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3646 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3647 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3648
3649 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003650 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003651 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3652 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3653 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3654}
3655
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003656// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003657DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003658 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003659 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003660 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003661 const char* text =
3662 "This is a very long sentence to test if the text will properly wrap "
3663 "around and go to the next line. Sometimes, short sentence. Longer "
3664 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003665 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003666
3667 ParagraphStyle paragraph_style;
3668 paragraph_style.setMaxLines(1);
3669 paragraph_style.setEllipsis(u"\u2026");
3670 paragraph_style.turnHintingOff();
3671 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3672
3673 TextStyle text_style;
3674 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003675 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003676 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003677 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003678 builder.pop();
3679
3680 auto paragraph = builder.Build();
3681 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003682 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003683
3684 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003685
3686 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3687 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3688
3689 auto& line = impl->lines()[0];
3690 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003691 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003692}
3693
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003694// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003695DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003696 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003697 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003698 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003699 const char* text1 = "fluttser ";
3700 const char* text2 = "mdje";
3701 const char* text3 = "fluttser mdje";
3702
3703 ParagraphStyle paragraph_style;
3704 paragraph_style.turnHintingOff();
3705 paragraph_style.setTextAlign(TextAlign::kLeft);
3706 paragraph_style.setMaxLines(2);
3707 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3708
3709 TextStyle text_style;
3710 text_style.setFontFamilies({SkString("Roboto")});
3711 text_style.setColor(SK_ColorBLACK);
3712 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003713 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003714 text_style.setDecoration(TextDecoration::kUnderline);
3715 text_style.setDecorationColor(SK_ColorBLACK);
3716 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003717 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003718 builder.pop();
3719
3720 auto paragraph = builder.Build();
3721 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003722 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003723
3724 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3725
3726 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3727 text_style.setDecoration(TextDecoration::kNoDecoration);
3728 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003729 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003730 builder1.pop();
3731
3732 auto paragraph1 = builder1.Build();
3733 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003734 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003735
3736 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3737
3738 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3739 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003740
3741 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3742 .front()
3743 .rect;
3744 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3745 .front()
3746 .rect;
3747 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3748 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3749
3750 for (size_t i = 0; i < 12; ++i) {
3751 auto r =
3752 paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
3753 .front()
3754 .rect;
3755 auto r1 =
3756 paragraph1
3757 ->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight)
3758 .front()
3759 .rect;
3760
3761 REPORTER_ASSERT(reporter, r.fLeft == r1.fLeft);
3762 REPORTER_ASSERT(reporter, r.fRight == r1.fRight);
3763 }
3764}
3765
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003766// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003767DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003768 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003769 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003770 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003771 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003772 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003773
3774 ParagraphStyle paragraph_style;
3775 paragraph_style.turnHintingOff();
3776 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3777
3778 TextStyle text_style;
3779 text_style.setFontFamilies({SkString("Roboto")});
3780 text_style.setColor(SK_ColorBLACK);
3781 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3782 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003783 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003784
3785 auto paragraph = builder.Build();
3786 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003787 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003788
3789 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3790
3791 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3792 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3793 size_t index = 0;
3794 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003795 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003796 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003797 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3798 ++index;
3799 return true;
3800 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003801 }
3802}
3803
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003804// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003805DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003806 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003807 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003808 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003809 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003810 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003811
3812 ParagraphStyle paragraph_style;
3813 paragraph_style.turnHintingOff();
3814 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3815
3816 TextStyle text_style;
3817 text_style.setFontFamilies({SkString("Roboto")});
3818 text_style.setColor(SK_ColorBLACK);
3819 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3820 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003821 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003822
3823 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3824 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3825 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003826 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003827 builder.pop();
3828
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003829 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003830
3831 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3832 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003833 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003834 builder.pop();
3835
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003836 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003837
3838 auto paragraph = builder.Build();
3839 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003840 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003841
3842 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3843
3844 size_t index = 0;
3845 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003846 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003847 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003848 ++index;
3849 switch (index) {
3850 case 1:
3851 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3852 break;
3853 case 2:
3854 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3855 break;
3856 case 3:
3857 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3858 break;
3859 case 4:
3860 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3861 REPORTER_ASSERT(reporter, style.equals(text_style));
3862 break;
3863 case 5:
3864 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3865 break;
3866 default:
3867 REPORTER_ASSERT(reporter, false);
3868 }
3869 return true;
3870 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003871 }
3872}
3873
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003874// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003875DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003876 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003877 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003878 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003879 const char* text =
3880 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3881 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003882 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003883
3884 ParagraphStyle paragraph_style;
3885 paragraph_style.turnHintingOff();
3886 paragraph_style.setMaxLines(14);
3887 paragraph_style.setTextAlign(TextAlign::kJustify);
3888 paragraph_style.setHeight(1.5);
3889 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3890
3891 TextStyle text_style;
3892 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3893 text_style.setColor(SK_ColorBLACK);
3894 text_style.setFontSize(55);
3895 text_style.setLetterSpacing(2);
3896 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3897 text_style.setDecorationColor(SK_ColorBLACK);
3898 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003899 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003900 builder.pop();
3901
3902 auto paragraph = builder.Build();
3903 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003904 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003905
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003906 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3907 paragraph->getMaxWidth(),
3908 paragraph->getIdeographicBaseline());
3909 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3910 paragraph->getMaxWidth(),
3911 paragraph->getAlphabeticBaseline());
3912 canvas.drawLine(SK_ColorRED, rect1, false);
3913 canvas.drawLine(SK_ColorGREEN, rect2, false);
3914
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003915 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003916 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003917 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003918 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003919}
3920
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003921// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003922DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003923 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003924 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003925 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003926
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003927 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3928 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3929 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003930
3931 ParagraphStyle paragraph_style;
3932 paragraph_style.turnHintingOff();
3933 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3934
3935 TextStyle text_style;
3936 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003937 SkString("Not a real font"),
3938 SkString("Also a fake font"),
3939 SkString("So fake it is obvious"),
3940 SkString("Next one should be a real font..."),
3941 SkString("Roboto"),
3942 SkString("another fake one in between"),
3943 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003944 });
3945 text_style.setColor(SK_ColorBLACK);
3946 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003947 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003948
3949 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003950 SkString("Not a real font"),
3951 SkString("Also a fake font"),
3952 SkString("So fake it is obvious"),
3953 SkString("Homemade Apple"),
3954 SkString("Next one should be a real font..."),
3955 SkString("Roboto"),
3956 SkString("another fake one in between"),
3957 SkString("Noto Sans CJK JP"),
3958 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003959 });
3960 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003961 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003962
3963 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003964 SkString("Not a real font"),
3965 SkString("Also a fake font"),
3966 SkString("So fake it is obvious"),
3967 SkString("Homemade Apple"),
3968 SkString("Next one should be a real font..."),
3969 SkString("Roboto"),
3970 SkString("another fake one in between"),
3971 SkString("Source Han Serif CN"),
3972 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003973 });
3974 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003975 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003976
3977 builder.pop();
3978
3979 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003980 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003981 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003982 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003983
Julia Lavrova3281b962019-12-02 11:32:25 -05003984 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
3985
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003986 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3987
3988 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3989 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3990 // [Apple + Noto] [Apple + Han]
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003991 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003992
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003993 auto robotoAdvance = impl->runs()[0].advance().fX +
3994 impl->runs()[1].advance().fX +
3995 impl->runs()[2].advance().fX;
3996 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
3997 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
3998 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
3999 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
4000 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004001
4002 // When a different font is resolved, then the metrics are different.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004003 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
4004 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004005}
4006
Julia Lavrovac2228562019-08-08 16:51:27 -04004007// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004008DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004009 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004010 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004011 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004012 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004013 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004014 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004015
4016 ParagraphStyle paragraph_style;
4017 paragraph_style.setMaxLines(10);
4018 paragraph_style.setTextAlign(TextAlign::kLeft);
4019 paragraph_style.turnHintingOff();
4020
4021 StrutStyle strut_style;
4022 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004023 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004024 strut_style.setFontSize(50);
4025 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004026 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004027 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004028 paragraph_style.setStrutStyle(strut_style);
4029
4030 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4031
4032 TextStyle text_style;
4033 text_style.setFontFamilies({SkString("Ahem")});
4034 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004035 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004036 text_style.setColor(SK_ColorBLACK);
4037 text_style.setHeight(0.5f);
4038 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004039 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004040 builder.pop();
4041
4042 auto paragraph = builder.Build();
4043 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004044 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004045
4046 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004047 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4048
4049 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4050 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4051 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004052 {
4053 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4054 REPORTER_ASSERT(reporter, boxes.empty());
4055 }
4056 {
4057 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004058 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004059 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004060 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4061 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4062 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4063 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004064 }
4065 {
4066 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004067 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004068 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004069 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4070 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4071 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4072 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004073 }
4074 {
4075 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004076 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004077 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004078 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4079 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004080 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004081 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004082 }
4083 {
4084 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004085 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004086 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4088 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004091 }
4092 {
4093 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004094 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004095 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004096 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 224.5f, EPSILON100));
4098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004100 }
4101 {
4102 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004103 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004104 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004105 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
4106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 319.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004109 }
4110}
4111
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004112// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004113DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004114 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004115 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004116 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004117 // The chinese extra height should be absorbed by the strut.
4118 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004119 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004120
4121 ParagraphStyle paragraph_style;
4122 paragraph_style.setMaxLines(10);
4123 paragraph_style.setTextAlign(TextAlign::kLeft);
4124 paragraph_style.turnHintingOff();
4125
4126 StrutStyle strut_style;
4127
4128 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004129 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004130 strut_style.setFontSize(50);
4131 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004132 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004133 paragraph_style.setStrutStyle(strut_style);
4134
4135 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4136
4137 TextStyle text_style;
4138 text_style.setFontFamilies({SkString("Ahem")});
4139 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004140 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4141 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004142 text_style.setColor(SK_ColorBLACK);
4143 text_style.setHeight(1);
4144 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004145 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004146 builder.pop();
4147
4148 auto paragraph = builder.Build();
4149 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004150 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004151
4152 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4153 // Font is not resolved and the first line does not fit
4154 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4155
4156 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4157 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4158 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004159 {
4160 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4161 REPORTER_ASSERT(reporter, boxes.empty());
4162 }
4163 {
4164 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004165 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004166 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004167 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4168 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4169 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4170 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004171 }
4172 {
4173 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004174 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004175 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004176 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4177 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4178 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4179 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004180 }
4181 {
4182 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004183 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004184 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004185 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4186 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4187 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4188 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004189 }
4190 {
4191 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004192 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004193 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004194 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4195 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4196 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4197 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004198 }
4199 {
4200 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004201 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004202 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004203 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4204 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 184, EPSILON100));
4205 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4206 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004207 }
4208 {
4209 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004210 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004211 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004212 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
4213 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 264, EPSILON100));
4214 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4215 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004216 }
4217}
4218
Julia Lavrovac2228562019-08-08 16:51:27 -04004219// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004220DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004221 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004222 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004223 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4224
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004225 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004226 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004227 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004228
4229 ParagraphStyle paragraph_style;
4230 paragraph_style.setMaxLines(10);
4231 paragraph_style.setTextAlign(TextAlign::kLeft);
4232 paragraph_style.turnHintingOff();
4233
4234 StrutStyle strut_style;
4235 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004236 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004237 strut_style.setFontSize(50);
4238 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004239 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004240 paragraph_style.setStrutStyle(strut_style);
4241
4242 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4243
4244 TextStyle text_style;
4245 text_style.setFontFamilies({SkString("Ahem")});
4246 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004247 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4248 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004249 text_style.setColor(SK_ColorBLACK);
4250 text_style.setHeight(1);
4251 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004252 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004253 builder.pop();
4254
4255 auto paragraph = builder.Build();
4256 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004257 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004258
4259 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4260 // Font is not resolved and the first line does not fit
4261 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4262
4263 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4264 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4265 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4266 SkScalar epsilon = 0.001f;
4267 {
4268 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4269 REPORTER_ASSERT(reporter, boxes.empty());
4270 }
4271 {
4272 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004273 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004274 REPORTER_ASSERT(reporter, boxes.size() == 1);
4275 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4276 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4277 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4278 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4279 }
4280 {
4281 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004282 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004283 REPORTER_ASSERT(reporter, boxes.size() == 1);
4284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4287 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4288 }
4289 {
4290 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004291 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004292 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004293 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004296 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4297 }
4298 {
4299 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004300 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004301 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004302 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004303 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004305 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4306 }
4307 {
4308 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004309 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004310 REPORTER_ASSERT(reporter, boxes.size() == 1);
4311 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 128, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004313 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4314 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4315 }
4316 {
4317 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004318 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004319 REPORTER_ASSERT(reporter, boxes.size() == 1);
4320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 188, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4323 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4324 }
4325}
4326
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004327// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004328DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004329 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004330 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004331 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004332 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004333 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004334
4335 ParagraphStyle paragraph_style;
4336 paragraph_style.setMaxLines(10);
4337 paragraph_style.setTextAlign(TextAlign::kLeft);
4338 paragraph_style.turnHintingOff();
4339
4340 StrutStyle strut_style;
4341 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004342 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004343 strut_style.setFontSize(50);
4344 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004345 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004346 strut_style.setLeading(0.1f);
4347 strut_style.setForceStrutHeight(true);
4348 paragraph_style.setStrutStyle(strut_style);
4349
4350 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4351
4352 TextStyle text_style;
4353 text_style.setFontFamilies({SkString("Ahem")});
4354 text_style.setFontSize(50);
4355 text_style.setLetterSpacing(0);
4356 text_style.setColor(SK_ColorBLACK);
4357 text_style.setHeight(1);
4358 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004359 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004360 builder.pop();
4361
4362 auto paragraph = builder.Build();
4363 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004364 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004365
4366 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4367 // Font is not resolved and the first line does not fit
4368 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4369
4370 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4371 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4372 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004373
4374 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4375 REPORTER_ASSERT(reporter, boxes1.empty());
4376
4377 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004378 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004379 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004380 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4381 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4382 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4383 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004384
4385 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004386 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004387 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004388 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
4389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 22.5f, EPSILON100));
4390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004392
4393 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004394 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004395 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004396 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004400
4401 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004402 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004403 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004404 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
4405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 22.5f, EPSILON100));
4406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004408
4409 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004410 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004411 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
4413 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 182.5f, EPSILON100));
4414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004416
4417 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004418 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004419 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004420 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
4421 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 262.5f, EPSILON100));
4422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4423 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004424}
4425
Julia Lavrovac2228562019-08-08 16:51:27 -04004426// Checked: NO DIFF
4427DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004428 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004429 if (!fontCollection->fontsFound()) return;
4430 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4431
4432 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004433 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004434
4435 ParagraphStyle paragraph_style;
4436 paragraph_style.setMaxLines(10);
4437 paragraph_style.setTextAlign(TextAlign::kLeft);
4438 paragraph_style.turnHintingOff();
4439
4440 StrutStyle strut_style;
4441 strut_style.setStrutEnabled(true);
4442 strut_style.setFontFamilies({SkString("Ahem")});
4443 strut_style.setFontSize(50);
4444 strut_style.setHeight(1.5f);
4445 strut_style.setLeading(0.1f);
4446 strut_style.setForceStrutHeight(false);
4447 paragraph_style.setStrutStyle(strut_style);
4448
4449 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4450
4451 TextStyle text_style;
4452 text_style.setFontFamilies({SkString("Ahem")});
4453 text_style.setFontSize(20);
4454 text_style.setColor(SK_ColorBLACK);
4455 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004456 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004457 builder.pop();
4458
4459 auto paragraph = builder.Build();
4460 paragraph->layout(550);
4461 paragraph->paint(canvas.get(), 0, 0);
4462
4463 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4464 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4465 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4466 {
4467 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4468 REPORTER_ASSERT(reporter, boxes.empty());
4469 }
4470 {
4471 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4472 canvas.drawRects(SK_ColorRED, boxes);
4473 REPORTER_ASSERT(reporter, boxes.size() == 1);
4474 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4476 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4477 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4478 }
4479 {
4480 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4481 canvas.drawRects(SK_ColorRED, boxes);
4482 REPORTER_ASSERT(reporter, boxes.size() == 1);
4483 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4486 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4487 }
4488}
4489
Julia Lavrovac5313e62019-12-10 12:11:17 -05004490DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4491 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4492 if (!fontCollection->fontsFound()) return;
4493 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4494
4495 const char* text = "12ab\n";
4496
4497 ParagraphStyle paragraph_style;
4498 paragraph_style.turnHintingOff();
4499 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4500
4501 TextStyle text_style;
4502 text_style.setFontStyle(SkFontStyle::Italic());
4503 text_style.setFontFamilies({SkString("Roboto")});
4504 text_style.setColor(SK_ColorBLACK);
4505
4506 text_style.addFontFeature(SkString("tnum"), 1);
4507 builder.pushStyle(text_style);
4508 builder.addText(text);
4509
4510 text_style.resetFontFeatures();
4511 text_style.addFontFeature(SkString("tnum"), 0);
4512 text_style.addFontFeature(SkString("pnum"), 1);
4513 builder.pushStyle(text_style);
4514 builder.addText(text);
4515
4516 builder.pop();
4517 builder.pop();
4518
4519 auto paragraph = builder.Build();
4520 paragraph->layout(TestCanvasWidth);
4521
4522 paragraph->paint(canvas.get(), 10.0, 15.0);
4523
4524 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4525 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4526
4527 auto& tnum_line = impl->lines()[0];
4528 auto& pnum_line = impl->lines()[1];
4529
4530 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4531 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4532 // Tabular numbers should have equal widths.
4533 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4534 // Proportional numbers should have variable widths.
4535 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4536 // Alphabetic characters should be unaffected.
4537 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4538}
4539
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004540// Not in Minikin
4541DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004542 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004543 if (!fontCollection->fontsFound()) return;
4544 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004545 const size_t len = strlen(text);
4546
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004547 ParagraphStyle paragraph_style;
4548 paragraph_style.turnHintingOff();
4549 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4550
4551 TextStyle text_style;
4552 text_style.setFontFamilies(
4553 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4554 text_style.setFontSize(60);
4555 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004556 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004557 builder.pop();
4558
4559 auto paragraph = builder.Build();
4560 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004561
4562 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4563
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004564 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4565 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4566 auto first = impl->runs()[i].textRange();
4567 auto next = impl->runs()[i + 1].textRange();
4568 REPORTER_ASSERT(reporter, first.end == next.start);
4569 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004570}
4571
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004572DEF_TEST(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004573 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004574 if (!fontCollection->fontsFound()) return;
4575 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004576 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004577
4578 ParagraphStyle paragraph_style;
4579 paragraph_style.turnHintingOff();
4580 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4581
4582 TextStyle text_style;
4583 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4584 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004585 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004586 builder.pop();
4587
4588 auto paragraph = builder.Build();
4589 paragraph->layout(TestCanvasWidth);
4590
4591 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4592 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004593 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004594
4595 auto cluster = 0;
4596 SkShaperJSONWriter::VisualizeClusters(
4597 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4598 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4599 if (cluster == 0) {
4600 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4601 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4602 SkASSERT(glyph1to1.size() == 1);
4603 SkASSERT(*glyph1to1.begin() == 1611);
4604 }
4605 ++cluster;
4606 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004607 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004608}
4609
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004610DEF_TEST(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004611 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004612 if (!fontCollection->fontsFound()) return;
4613 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004614 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004615
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004616 ParagraphStyle paragraph_style;
4617 paragraph_style.turnHintingOff();
4618 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4619
4620 TextStyle text_style;
4621 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4622 text_style.setColor(SK_ColorBLACK);
4623 text_style.setFontSize(50);
4624 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004625 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004626 builder.pop();
4627
4628 auto paragraph = builder.Build();
4629 paragraph->layout(TestCanvasWidth);
4630
4631 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4632 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004633
4634 auto cluster = 0;
4635 for (auto& run : impl->runs()) {
4636 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004637 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4638 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004639 [&](int codePointCount, SkSpan<const char> utf1to1,
4640 SkSpan<const SkGlyphID> glyph1to1) {
4641 if (cluster == 0) {
4642 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4643 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4644 SkASSERT(glyph1to1.size() == 3);
4645 }
4646 ++cluster;
4647 });
4648 }
4649
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004650 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004651}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004652
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004653DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004654 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004655 cache.turnOn(true);
4656 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004657 if (!fontCollection->fontsFound()) return;
4658
4659 ParagraphStyle paragraph_style;
4660 paragraph_style.turnHintingOff();
4661
4662 TextStyle text_style;
4663 text_style.setFontFamilies({SkString("Roboto")});
4664 text_style.setColor(SK_ColorBLACK);
4665
4666 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4667 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4668 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004669 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004670 builder.pop();
4671 auto paragraph = builder.Build();
4672
4673 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4674 REPORTER_ASSERT(reporter, count == cache.count());
4675 auto found = cache.findParagraph(impl);
4676 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4677 auto added = cache.updateParagraph(impl);
4678 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4679 };
4680
4681 test("text1", 0, false);
4682 test("text1", 1, true);
4683 test("text2", 1, false);
4684 test("text2", 2, true);
4685 test("text3", 2, false);
4686}
4687
4688DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004689 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004690 cache.turnOn(true);
4691 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004692 if (!fontCollection->fontsFound()) return;
4693
4694 ParagraphStyle paragraph_style;
4695 paragraph_style.turnHintingOff();
4696
4697 TextStyle text_style;
4698 text_style.setColor(SK_ColorBLACK);
4699
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004700 const char* text = "text";
4701 const size_t len = strlen(text);
4702
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004703 auto test = [&](int count, bool expectedToBeFound) {
4704 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4705 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004706 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004707 builder.pop();
4708 auto paragraph = builder.Build();
4709 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4710
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004711 REPORTER_ASSERT(reporter, count == cache.count());
4712 auto found = cache.findParagraph(impl);
4713 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4714 auto added = cache.updateParagraph(impl);
4715 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4716 };
4717
4718 text_style.setFontFamilies({SkString("Roboto")});
4719 test(0, false);
4720 test(1, true);
4721 text_style.setFontFamilies({SkString("Homemade Apple")});
4722 test(1, false);
4723 test(2, true);
4724 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4725 test(2, false);
4726}
4727
4728DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004729 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004730 cache.turnOn(true);
4731 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004732 if (!fontCollection->fontsFound()) return;
4733
4734 ParagraphStyle paragraph_style;
4735 paragraph_style.turnHintingOff();
4736
4737 TextStyle text_style;
4738 text_style.setFontFamilies({SkString("Roboto")});
4739 text_style.setColor(SK_ColorBLACK);
4740
4741 auto test = [&](const char* text1,
4742 const char* text2,
4743 const char* font1,
4744 const char* font2,
4745 int count,
4746 bool expectedToBeFound) {
4747 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4748 text_style.setFontFamilies({SkString(font1)});
4749 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004750 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004751 builder.pop();
4752 text_style.setFontFamilies({SkString(font2)});
4753 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004754 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004755 builder.pop();
4756 auto paragraph = builder.Build();
4757 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4758
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004759 REPORTER_ASSERT(reporter, count == cache.count());
4760 auto found = cache.findParagraph(impl);
4761 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4762 auto added = cache.updateParagraph(impl);
4763 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4764 };
4765
4766 test("text", "", "Roboto", "Homemade Apple", 0, false);
4767 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4768 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4769 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4770 test("text", "", "Roboto", "Homemade Apple", 4, true);
4771}
4772
4773DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004774 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004775 cache.turnOn(true);
4776 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004777 if (!fontCollection->fontsFound()) return;
4778
4779 ParagraphStyle paragraph_style;
4780 paragraph_style.turnHintingOff();
4781
4782 TextStyle text_style;
4783 text_style.setFontFamilies({SkString("Roboto")});
4784 text_style.setColor(SK_ColorBLACK);
4785
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004786 const char* text = "text";
4787 const size_t len = strlen(text);
4788
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004789 auto test = [&](int count, bool expectedToBeFound) {
4790 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4791 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004792 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004793 builder.pop();
4794 auto paragraph = builder.Build();
4795 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4796
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004797 REPORTER_ASSERT(reporter, count == cache.count());
4798 auto found = cache.findParagraph(impl);
4799 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4800 auto added = cache.updateParagraph(impl);
4801 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4802 };
4803
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004804 test(0, false);
4805 test(1, true);
4806 text_style.setLetterSpacing(10);
4807 test(1, false);
4808 test(2, true);
4809 text_style.setWordSpacing(10);
4810 test(2, false);
4811}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004812
Julia Lavrova526df262019-08-21 17:49:44 -04004813DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004814 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004815 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004816 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4817 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004818
4819 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004820 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004821 text_style.setFontSize(16);
4822 text_style.setFontFamilies({SkString("Roboto")});
4823 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004824 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004825
4826 auto paragraph = builder.Build();
4827 paragraph->layout(TestCanvasWidth);
4828 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004829 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004830}
4831
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004832DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004833 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004834 if (!fontCollection->fontsFound()) return;
4835 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4836 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4837
4838 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4839
4840 ParagraphStyle paragraph_style;
4841 TextStyle text_style;
4842 text_style.setFontSize(16);
4843 text_style.setFontFamilies({SkString("Roboto")});
4844 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4845 builder.addText(text.c_str(), text.size());
4846
4847 auto paragraph = builder.Build();
4848 paragraph->layout(TestCanvasWidth);
4849 paragraph->paint(canvas.get(), 0, 0);
4850}
4851
Julia Lavrovaa40db422019-08-21 13:49:15 -04004852DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004853 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004854 if (!fontCollection->fontsFound()) return;
4855 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4856
4857 ParagraphStyle paragraph_style;
4858 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4859
Julia Lavrova526df262019-08-21 17:49:44 -04004860 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004861 builder.addPlaceholder(placeholder);
4862
4863 auto paragraph = builder.Build();
4864 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004865 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004866 paragraph->paint(canvas.get(), 0, 0);
4867}
4868
4869DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004870 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004871 if (!fontCollection->fontsFound()) return;
4872 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4873 TestCanvas canvas("SkParagraph_Fallbacks.png");
4874
4875 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004876 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004877
4878 const char* androidFonts[] = {
4879 "sans-serif",
4880 "sans-serif-condensed",
4881 "serif",
4882 "monospace",
4883 "serif-monospace",
4884 "casual",
4885 "cursive",
4886 "sans-serif-smallcaps",
4887 };
4888
4889 for (auto& font : androidFonts) {
4890
4891 ParagraphStyle paragraph_style;
4892 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4893
4894 TextStyle text_style;
4895 text_style.setColor(SK_ColorBLACK);
4896 text_style.setLocale(SkString("en_US"));
4897 text_style.setFontSize(20);
4898
4899 text_style.setFontFamilies({ SkString(font) });
4900 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004901 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004902
4903 builder.pop();
4904
4905 auto paragraph = builder.Build();
4906 paragraph->layout(TestCanvasWidth);
4907 paragraph->paint(canvas.get(), 0, 0);
4908 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4909 }
4910}
4911
4912DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004913 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004914 if (!fontCollection->fontsFound()) return;
4915 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004916 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004917 TestCanvas canvas("SkParagraph_Bidi1.png");
4918
4919 std::u16string abc = u"\u202Dabc";
4920 std::u16string DEF = u"\u202EDEF";
4921 std::u16string ghi = u"\u202Dghi";
4922 std::u16string JKL = u"\u202EJKL";
4923 std::u16string mno = u"\u202Dmno";
4924
4925 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4926
4927 ParagraphStyle paragraph_style;
4928 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4929
4930 TextStyle text_style;
4931 text_style.setFontFamilies({ SkString("sans-serif")});
4932 text_style.setFontSize(40);
4933
4934 text_style.setColor(SK_ColorCYAN);
4935 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4936 builder.pushStyle(text_style);
4937 builder.addText(abc);
4938
4939 text_style.setColor(SK_ColorGREEN);
4940 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4941 builder.pushStyle(text_style);
4942 builder.addText(DEF);
4943
4944 text_style.setColor(SK_ColorYELLOW);
4945 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4946 builder.pushStyle(text_style);
4947 builder.addText(ghi);
4948
4949 text_style.setColor(SK_ColorMAGENTA);
4950 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4951 builder.pushStyle(text_style);
4952 builder.addText(JKL);
4953
4954 text_style.setColor(SK_ColorBLUE);
4955 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4956 builder.pushStyle(text_style);
4957 builder.addText(mno);
4958
4959 auto paragraph = builder.Build();
4960 paragraph->layout(400);
4961 paragraph->paint(canvas.get(), 0, 0);
4962}
4963
4964DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004965 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004966 if (!fontCollection->fontsFound()) return;
4967 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004968 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004969 TestCanvas canvas("SkParagraph_Bidi2.png");
4970
4971 std::u16string abcD = u"\u202Dabc\u202ED";
4972 std::u16string EFgh = u"EF\u202Dgh";
4973 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4974
4975 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4976
4977 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004978 TextStyle text_style;
4979 text_style.setFontFamilies({ SkString("sans-serif")});
4980 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004981
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004982 {
4983 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4984 builder.pushStyle(text_style);
4985 builder.addText(abcD);
4986 builder.pushStyle(text_style);
4987 builder.addText(EFgh);
4988 builder.pushStyle(text_style);
4989 builder.addText(iJKLmno);
4990 auto paragraph = builder.Build();
4991 paragraph->layout(360);
4992 paragraph->paint(canvas.get(), 0, 0);
4993 }
4994 canvas.get()->translate(0, 400);
4995 {
4996 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4997 builder.pushStyle(text_style);
4998 builder.addText(abcDEFghiJKLmno);
4999 auto paragraph = builder.Build();
5000 paragraph->layout(360);
5001 paragraph->paint(canvas.get(), 0, 0);
5002 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04005003}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005004
5005DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005006 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005007 if (!fontCollection->fontsFound()) return;
5008 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5009 TestCanvas canvas("SkParagraph_Newline.png");
5010
5011 TextStyle text_style;
5012 text_style.setFontFamilies({SkString("Ahem")});
5013 text_style.setColor(SK_ColorBLACK);
5014 StrutStyle strut_style;
5015 strut_style.setStrutEnabled(false);
5016 ParagraphStyle paragraph_style;
5017 paragraph_style.setStrutStyle(strut_style);
5018 paragraph_style.setTextStyle(text_style);
5019 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5020 builder.addText("\n");
5021 auto paragraph = builder.Build();
5022 paragraph->layout(1000);
5023 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5024}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005025
Julia Lavrovab30d4812019-11-08 14:51:16 -05005026DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005027 TestCanvas canvas("SkParagraph_FontResolutions.png");
5028
5029 sk_sp<TestFontCollection> fontCollection =
5030 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5031 if (!fontCollection->fontsFound()) return;
5032
5033 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5034 return;
5035 }
5036 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5037 return;
5038 }
5039 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5040 return;
5041 }
5042
5043 TextStyle text_style;
5044 text_style.setFontFamilies({SkString("abc")});
5045 text_style.setFontSize(50);
5046
5047 ParagraphStyle paragraph_style;
5048 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5049
5050 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5051 text_style.setColor(SK_ColorBLUE);
5052 builder.pushStyle(text_style);
5053 builder.addText(u"a\u0300");
5054 text_style.setColor(SK_ColorMAGENTA);
5055 builder.pushStyle(text_style);
5056 builder.addText(u"à");
5057
5058 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5059
5060 text_style.setColor(SK_ColorRED);
5061 builder.pushStyle(text_style);
5062 builder.addText(u"a\u0300");
5063 text_style.setColor(SK_ColorGREEN);
5064 builder.pushStyle(text_style);
5065 builder.addText(u"à");
5066
5067 auto paragraph = builder.Build();
5068 paragraph->layout(TestCanvasWidth);
5069
5070 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5071 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5072
5073 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5074 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5075 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5076
5077 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5078 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5079
5080 paragraph->paint(canvas.get(), 100, 100);
5081}
5082
Julia Lavrovab30d4812019-11-08 14:51:16 -05005083DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005084 TestCanvas canvas("SkParagraph_FontStyle.png");
5085
5086 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5087 if (!fontCollection->fontsFound()) return;
5088
5089 TextStyle text_style;
5090 text_style.setFontFamilies({SkString("Roboto")});
5091 text_style.setColor(SK_ColorBLACK);
5092 text_style.setFontSize(20);
5093 SkFontStyle fs = SkFontStyle(
5094 SkFontStyle::Weight::kLight_Weight,
5095 SkFontStyle::Width::kNormal_Width,
5096 SkFontStyle::Slant::kUpright_Slant
5097 );
5098 text_style.setFontStyle(fs);
5099 ParagraphStyle paragraph_style;
5100 paragraph_style.setTextStyle(text_style);
5101 TextStyle boldItalic;
5102 boldItalic.setFontFamilies({SkString("Roboto")});
5103 boldItalic.setColor(SK_ColorRED);
5104 SkFontStyle bi = SkFontStyle(
5105 SkFontStyle::Weight::kBold_Weight,
5106 SkFontStyle::Width::kNormal_Width,
5107 SkFontStyle::Slant::kItalic_Slant
5108 );
5109 boldItalic.setFontStyle(bi);
5110 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5111 builder.addText("Default text\n");
5112 builder.pushStyle(boldItalic);
5113 builder.addText("Bold and Italic\n");
5114 builder.pop();
5115 builder.addText("back to normal");
5116 auto paragraph = builder.Build();
5117 paragraph->layout(250);
5118 paragraph->paint(canvas.get(), 0, 0);
5119}
5120
Julia Lavrovab30d4812019-11-08 14:51:16 -05005121DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005122 TestCanvas canvas("SkParagraph_Shaping.png");
5123
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005124 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5125 sk_sp<TestFontCollection> fontCollection =
5126 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5127 if (!fontCollection->fontsFound()) return;
5128
5129
5130 TextStyle text_style;
5131 text_style.setFontFamilies({SkString("Roboto")});
5132 text_style.setColor(SK_ColorGRAY);
5133 text_style.setFontSize(14);
5134 SkFontStyle b = SkFontStyle(
5135 SkFontStyle::Weight::kNormal_Weight,
5136 SkFontStyle::Width::kNormal_Width,
5137 SkFontStyle::Slant::kUpright_Slant
5138 );
5139 text_style.setFontStyle(b);
5140 ParagraphStyle paragraph_style;
5141 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5142 builder.pushStyle(text_style);
5143 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5144 auto paragraph = builder.Build();
5145 paragraph->layout(380);
5146 paragraph->paint(canvas.get(), 0, 0);
5147}
Julia Lavrovac028b422019-11-25 10:00:43 -05005148
5149DEF_TEST(SkParagraph_Ellipsis, reporter) {
5150 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5151 if (!fontCollection->fontsFound()) return;
5152 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5153 TestCanvas canvas("SkParagraph_Ellipsis.png");
5154
5155 const char* text = "This\n"
5156 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5157 TextStyle text_style;
5158 text_style.setFontFamilies({SkString("Ahem")});
5159 text_style.setColor(SK_ColorBLACK);
5160 text_style.setFontSize(10);
5161
5162 auto relayout = [&](size_t lines, bool ellipsis,
5163 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5164 ParagraphStyle paragraph_style;
5165 SkPaint paint;
5166 paint.setColor(bg);
5167 text_style.setForegroundColor(paint);
5168 paragraph_style.setTextStyle(text_style);
5169 paragraph_style.setMaxLines(lines);
5170 if (ellipsis) {
5171 paragraph_style.setEllipsis(u"\u2026");
5172 }
5173 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5174 builder.addText(text);
5175 auto paragraph = builder.Build();
5176 paragraph->layout(50);
5177 paragraph->paint(canvas.get(), 0, 0);
5178 canvas.get()->translate(50, paragraph->getHeight() + 10);
5179 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5180 SkPaint background;
5181 background.setColor(SK_ColorRED);
5182 background.setStyle(SkPaint::kStroke_Style);
5183 background.setAntiAlias(true);
5184 background.setStrokeWidth(1);
5185 canvas.get()->drawRect(result.front().rect, background);
5186
5187 SkASSERT(width == paragraph->getMaxWidth());
5188 SkASSERT(height == paragraph->getHeight());
5189 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5190 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5191 };
5192
5193 SkPaint paint;
5194 paint.setColor(SK_ColorLTGRAY);
5195 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5196
5197 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005198 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5199 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005200
5201 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005202 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005203 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5204
5205 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005206 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5207 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005208}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005209
5210DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5211 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5212 if (!fontCollection->fontsFound()) return;
5213 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5214
5215 std::string text;
5216 for (size_t i = 0; i < 10; i++)
5217 {
5218 SkPaint paint;
5219 paint.setAntiAlias(true);
5220 paint.setColor(SK_ColorBLACK);
5221
5222 TextStyle textStyle;
5223 textStyle.setForegroundColor(paint);
5224 textStyle.setFontFamilies({ SkString("Roboto") });
5225
5226 ParagraphStyle paragraphStyle;
5227 paragraphStyle.setTextStyle(textStyle);
5228
5229 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5230 text += "Text ";
5231 builder.addText(text.c_str());
5232
5233 auto paragraph = builder.Build();
5234 paragraph->layout(100);
5235
5236 //used to add a delay so I can monitor memory usage
5237 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5238 }
5239};