blob: 5d6db263c5e9f1a8dfc9d0fec8597e7350e388e3 [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
Ben Wagner4ca7a812020-05-28 13:48:18 -04002#include "include/core/SkBitmap.h"
3#include "include/core/SkCanvas.h"
4#include "include/core/SkColor.h"
5#include "include/core/SkEncodedImageFormat.h"
Julia Lavrovacd2d4e42020-03-27 15:40:37 -04006#include "include/core/SkFontMgr.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -04007#include "include/core/SkFontStyle.h"
8#include "include/core/SkImageEncoder.h"
9#include "include/core/SkPaint.h"
10#include "include/core/SkPoint.h"
11#include "include/core/SkRect.h"
12#include "include/core/SkRefCnt.h"
13#include "include/core/SkScalar.h"
14#include "include/core/SkStream.h"
15#include "include/core/SkString.h"
16#include "include/core/SkTypeface.h"
17#include "include/core/SkTypes.h"
18#include "modules/skparagraph/include/DartTypes.h"
19#include "modules/skparagraph/include/FontCollection.h"
20#include "modules/skparagraph/include/Paragraph.h"
21#include "modules/skparagraph/include/ParagraphCache.h"
22#include "modules/skparagraph/include/ParagraphStyle.h"
23#include "modules/skparagraph/include/TextShadow.h"
24#include "modules/skparagraph/include/TextStyle.h"
Julia Lavrova6e6333f2019-06-17 10:34:10 -040025#include "modules/skparagraph/include/TypefaceFontProvider.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040026#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
27#include "modules/skparagraph/src/ParagraphImpl.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040028#include "modules/skparagraph/src/Run.h"
29#include "modules/skparagraph/src/TextLine.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -040030#include "modules/skparagraph/utils/TestFontCollection.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040031#include "src/core/SkOSFile.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040032#include "src/core/SkSpan.h"
Julia Lavrova2e30fde2019-10-09 09:43:02 -040033#include "src/utils/SkOSPath.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040034#include "src/utils/SkShaperJSONWriter.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040035#include "tests/Test.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -040036#include "tools/Resources.h"
Ben Wagner4ca7a812020-05-28 13:48:18 -040037
38#include <string.h>
39#include <unicode/unistr.h>
40#include <limits>
41#include <memory>
42#include <string>
43#include <utility>
44#include <vector>
45
46struct GrContextOptions;
47
Julia Lavrovaa3552c52019-05-30 16:12:56 -040048
49#define VeryLongCanvasWidth 1000000
50#define TestCanvasWidth 1000
51#define TestCanvasHeight 600
52
Julia Lavrova2e30fde2019-10-09 09:43:02 -040053#define DEF_TEST_DISABLED(name, reporter) \
54static void test_##name(skiatest::Reporter* reporter, const GrContextOptions&); \
55skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \
Herb Derby126d7a22019-11-27 11:38:16 -050056void test_##name(skiatest::Reporter* reporter, const GrContextOptions&) { /* SkDebugf("Disabled:"#name "\n"); */ } \
Julia Lavrova2e30fde2019-10-09 09:43:02 -040057void disabled_##name(skiatest::Reporter* reporter, const GrContextOptions&)
58
Julia Lavrovaa3552c52019-05-30 16:12:56 -040059using namespace skia::textlayout;
60namespace {
61
Julia Lavrovadb9f6692019-08-01 16:02:17 -040062SkScalar EPSILON100 = 0.01f;
63SkScalar EPSILON50 = 0.02f;
64SkScalar EPSILON20 = 0.05f;
Julia Lavrova916a9042019-08-08 16:51:27 -040065SkScalar EPSILON10 = 0.1f;
Julia Lavrovac2228562019-08-08 16:51:27 -040066SkScalar EPSILON5 = 0.20f;
67SkScalar EPSILON2 = 0.50f;
Julia Lavrovadb9f6692019-08-01 16:02:17 -040068
Julia Lavrova5207f352019-06-21 12:22:32 -040069bool equal(const char* base, TextRange a, const char* b) {
70 return std::strncmp(b, base + a.start, a.width()) == 0;
Julia Lavrovaa3552c52019-05-30 16:12:56 -040071}
Julia Lavrova3281b962019-12-02 11:32:25 -050072
Julia Lavrova2e30fde2019-10-09 09:43:02 -040073class ResourceFontCollection : public FontCollection {
Julia Lavrovaa3552c52019-05-30 16:12:56 -040074public:
Julia Lavrova2e30fde2019-10-09 09:43:02 -040075 ResourceFontCollection(bool testOnly = false)
Julia Lavrovaa3552c52019-05-30 16:12:56 -040076 : fFontsFound(false)
77 , fResolvedFonts(0)
78 , fResourceDir(GetResourcePath("fonts").c_str())
79 , fFontProvider(sk_make_sp<TypefaceFontProvider>()) {
80 std::vector<SkString> fonts;
81 SkOSFile::Iter iter(fResourceDir.c_str());
Julia Lavrova2e30fde2019-10-09 09:43:02 -040082
Julia Lavrovaa3552c52019-05-30 16:12:56 -040083 SkString path;
84 while (iter.next(&path)) {
85 if (path.endsWith("Roboto-Italic.ttf")) {
86 fFontsFound = true;
87 }
88 fonts.emplace_back(path);
89 }
90
91 if (!fFontsFound) {
Herb Derby126d7a22019-11-27 11:38:16 -050092 // SkDebugf("Fonts not found, skipping all the tests\n");
Julia Lavrovaa3552c52019-05-30 16:12:56 -040093 return;
94 }
95 // Only register fonts if we have to
96 for (auto& font : fonts) {
97 SkString file_path;
98 file_path.printf("%s/%s", fResourceDir.c_str(), font.c_str());
99 fFontProvider->registerTypeface(SkTypeface::MakeFromFile(file_path.c_str()));
100 }
101
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400102 if (testOnly) {
103 this->setTestFontManager(std::move(fFontProvider));
104 } else {
105 this->setAssetFontManager(std::move(fFontProvider));
106 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400107 this->disableFontFallback();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400108 }
109
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400110 ~ResourceFontCollection() = default;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400111
112 size_t resolvedFonts() const { return fResolvedFonts; }
113
114 // TODO: temp solution until we check in fonts
115 bool fontsFound() const { return fFontsFound; }
116
117private:
118 bool fFontsFound;
119 size_t fResolvedFonts;
120 std::string fResourceDir;
121 sk_sp<TypefaceFontProvider> fFontProvider;
122};
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400123
124class TestCanvas {
125public:
126 TestCanvas(const char* testName) : name(testName) {
127 bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight);
128 canvas = new SkCanvas(bits);
129 canvas->clear(SK_ColorWHITE);
130 }
131
132 ~TestCanvas() {
Julia Lavrovaaae845f2019-08-16 16:44:40 -0400133 SkString tmpDir = skiatest::GetTmpDir();
134 if (!tmpDir.isEmpty()) {
135 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
136 SkFILEWStream file(path.c_str());
137 if (!SkEncodeImage(&file, bits, SkEncodedImageFormat::kPNG, 100)) {
138 SkDebugf("Cannot write a picture %s\n", name);
139 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400140 }
141 delete canvas;
142 }
143
144 void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) {
145
146 SkPaint paint;
147 if (!fill) {
148 paint.setStyle(SkPaint::kStroke_Style);
149 paint.setAntiAlias(true);
150 paint.setStrokeWidth(1);
151 }
152 paint.setColor(color);
153 for (auto& r : result) {
154 canvas->drawRect(r.rect, paint);
155 }
156 }
157
158 void drawLine(SkColor color, SkRect rect, bool vertical = true) {
159
160 SkPaint paint;
161 paint.setStyle(SkPaint::kStroke_Style);
162 paint.setAntiAlias(true);
163 paint.setStrokeWidth(1);
164 paint.setColor(color);
165 if (vertical) {
166 canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
167 } else {
168 canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint);
169 }
170 }
171
172 void drawLines(SkColor color, std::vector<TextBox>& result) {
173
174 for (auto& r : result) {
175 drawLine(color, r.rect);
176 }
177 }
178
179 SkCanvas* get() { return canvas; }
180private:
181 SkBitmap bits;
182 SkCanvas* canvas;
183 const char* name;
184};
185
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400186} // namespace
187
188DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400189 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400190 if (!fontCollection->fontsFound()) return;
191 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400192 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400193
194 ParagraphStyle paragraph_style;
195 paragraph_style.turnHintingOff();
196 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
197
198 TextStyle text_style;
199 text_style.setFontFamilies({SkString("Roboto")});
200 text_style.setColor(SK_ColorBLACK);
201 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400202 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400203 builder.pop();
204
205 auto paragraph = builder.Build();
206 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500207 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400208
209 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
210 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
211 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400212 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400213
214 size_t index = 0;
215 for (auto& line : impl->lines()) {
216 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400217 [&index, reporter]
218 (TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400219 REPORTER_ASSERT(reporter, index == 0);
220 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorBLACK);
221 ++index;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400222 });
223 }
224}
225
Julia Lavrova916a9042019-08-08 16:51:27 -0400226DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400227 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400228 TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png");
229 if (!fontCollection->fontsFound()) return;
230
231 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400232 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400233
234 ParagraphStyle paragraph_style;
235 paragraph_style.turnHintingOff();
236 paragraph_style.setMaxLines(14);
237 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
238
239 TextStyle text_style;
240 text_style.setFontFamilies({SkString("Roboto")});
241 text_style.setColor(SK_ColorBLACK);
242 text_style.setFontSize(26);
243 text_style.setWordSpacing(5);
244 text_style.setLetterSpacing(1);
245 text_style.setDecoration(TextDecoration::kUnderline);
246 text_style.setDecorationColor(SK_ColorBLACK);
247 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400248 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400249
250 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
251 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400252 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400253 builder.addPlaceholder(placeholder1);
254
255 PlaceholderStyle placeholder2(5, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
256 builder.addPlaceholder(placeholder2);
257 builder.addPlaceholder(placeholder1);
258 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400259 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400260 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400261 builder.addText(text, len);
262 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400263 builder.addPlaceholder(placeholder2);
264 builder.addPlaceholder(placeholder2);
265 builder.addPlaceholder(placeholder2);
266 builder.addPlaceholder(placeholder2);
267 builder.addPlaceholder(placeholder2);
268 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400269 builder.addText(text, len);
270 builder.addText(text, len);
271 builder.addText(text, len);
272 builder.addText(text, len);
273 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400274 builder.addPlaceholder(placeholder2);
275 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400276 builder.addText(text, len);
277 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400278
279 builder.pop();
280
281 auto paragraph = builder.Build();
282 paragraph->layout(TestCanvasWidth);
283 paragraph->paint(canvas.get(), 0, 0);
284
285 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
286 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
287
288 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
289 canvas.drawRects(SK_ColorRED, boxes);
290 REPORTER_ASSERT(reporter, boxes.size() == 1);
291
292 boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
293 canvas.drawRects(SK_ColorGREEN, boxes);
294 REPORTER_ASSERT(reporter, boxes.size() == 1);
295
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400296 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400297 canvas.drawRects(SK_ColorRED, boxes);
298
299 boxes = paragraph->getRectsForRange(4, 17, rect_height_style, rect_width_style);
300 canvas.drawRects(SK_ColorBLUE, boxes);
301
302 REPORTER_ASSERT(reporter, boxes.size() == 7);
303
Julia Lavrovac028b422019-11-25 10:00:43 -0500304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400305 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500306 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 90.921f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400307 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 100, EPSILON100));
308
Julia Lavrovac028b422019-11-25 10:00:43 -0500309 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.left(), 231.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400310 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500311 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.right(), 231.343f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.bottom(), 100, EPSILON100));
313
Julia Lavrovac028b422019-11-25 10:00:43 -0500314 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.left(), 281.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400315 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500316 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.right(), 281.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400317 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.bottom(), 50, EPSILON100));
318
Julia Lavrovac028b422019-11-25 10:00:43 -0500319 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.left(), 336.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.right(), 336.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100));
323}
324
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400325DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400326 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400327 TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png");
328 if (!fontCollection->fontsFound()) return;
329
330 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400331 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400332
333 ParagraphStyle paragraph_style;
334 paragraph_style.turnHintingOff();
335 paragraph_style.setMaxLines(14);
336 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
337
338 TextStyle text_style;
339 text_style.setFontFamilies({SkString("Roboto")});
340 text_style.setColor(SK_ColorBLACK);
341 text_style.setFontSize(26);
342 text_style.setWordSpacing(5);
343 text_style.setLetterSpacing(1);
344 text_style.setDecoration(TextDecoration::kUnderline);
345 text_style.setDecorationColor(SK_ColorBLACK);
346 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400347 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400348
349 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 38.347f);
350 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400351 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400352
353 builder.pop();
354
355 auto paragraph = builder.Build();
356 paragraph->layout(TestCanvasWidth);
357 paragraph->paint(canvas.get(), 0, 0);
358
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400359 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400360 canvas.drawRects(SK_ColorRED, boxes);
361
362 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500363 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400364 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500365 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400366 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
367
368 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
369 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
370
371 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
372 canvas.drawRects(SK_ColorBLUE, boxes);
373
374 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500375 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400376 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 14.226f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500377 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400378 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400379}
Julia Lavrova916a9042019-08-08 16:51:27 -0400380
Julia Lavrova916a9042019-08-08 16:51:27 -0400381DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400382 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400383 TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png");
384 if (!fontCollection->fontsFound()) return;
385
386 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400387 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400388
389 ParagraphStyle paragraph_style;
390 paragraph_style.turnHintingOff();
391 paragraph_style.setMaxLines(14);
392 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
393
394 TextStyle text_style;
395 text_style.setFontFamilies({SkString("Roboto")});
396 text_style.setColor(SK_ColorBLACK);
397 text_style.setFontSize(26);
398 text_style.setWordSpacing(5);
399 text_style.setLetterSpacing(1);
400 text_style.setDecoration(TextDecoration::kUnderline);
401 text_style.setDecorationColor(SK_ColorBLACK);
402 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400403 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400404
405 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kAboveBaseline, TextBaseline::kAlphabetic, 903129.129308f);
406 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400407 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400408
409 builder.pop();
410
411 auto paragraph = builder.Build();
412 paragraph->layout(TestCanvasWidth);
413 paragraph->paint(canvas.get(), 0, 0);
414
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400415 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400416 canvas.drawRects(SK_ColorRED, boxes);
417
418 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500419 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400420 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.347f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500421 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 49.652f, EPSILON100));
423
424 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
425 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
426
427 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
428 canvas.drawRects(SK_ColorBLUE, boxes);
429
430 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500431 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400432 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 25.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500433 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400434 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400435}
Julia Lavrova916a9042019-08-08 16:51:27 -0400436
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400437DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400438 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400439 TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png");
440 if (!fontCollection->fontsFound()) return;
441
442 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400443 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400444
445 ParagraphStyle paragraph_style;
446 paragraph_style.turnHintingOff();
447 paragraph_style.setMaxLines(14);
448 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
449
450 TextStyle text_style;
451 text_style.setFontFamilies({SkString("Roboto")});
452 text_style.setColor(SK_ColorBLACK);
453 text_style.setFontSize(26);
454 text_style.setWordSpacing(5);
455 text_style.setLetterSpacing(1);
456 text_style.setDecoration(TextDecoration::kUnderline);
457 text_style.setDecorationColor(SK_ColorBLACK);
458 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400459 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400460
461 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBelowBaseline, TextBaseline::kAlphabetic, 903129.129308f);
462 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400463 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400464
465 builder.pop();
466
467 auto paragraph = builder.Build();
468 paragraph->layout(TestCanvasWidth);
469 paragraph->paint(canvas.get(), 0, 0);
470
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400471 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400472 canvas.drawRects(SK_ColorRED, boxes);
473
474 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400476 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500477 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400478 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
479
480 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
481 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
482
483 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
484 canvas.drawRects(SK_ColorBLUE, boxes);
485
486 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500487 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400488 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.121f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500489 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400490 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400491}
Julia Lavrova916a9042019-08-08 16:51:27 -0400492
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400493DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400494 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400495 TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png");
496 if (!fontCollection->fontsFound()) return;
497
498 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400499 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400500
501 ParagraphStyle paragraph_style;
502 paragraph_style.turnHintingOff();
503 paragraph_style.setMaxLines(14);
504 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
505
506 TextStyle text_style;
507 text_style.setFontFamilies({SkString("Roboto")});
508 text_style.setColor(SK_ColorBLACK);
509 text_style.setFontSize(26);
510 text_style.setWordSpacing(5);
511 text_style.setLetterSpacing(1);
512 text_style.setDecoration(TextDecoration::kUnderline);
513 text_style.setDecorationColor(SK_ColorBLACK);
514 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400515 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400516
517 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBottom, TextBaseline::kAlphabetic, 0);
518 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400519 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400520
521 builder.pop();
522
523 auto paragraph = builder.Build();
524 paragraph->layout(TestCanvasWidth);
525 paragraph->paint(canvas.get(), 0, 0);
526
527 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
528 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
529
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400530 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400531 canvas.drawRects(SK_ColorRED, boxes);
532 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400536 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
537
538 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
539 canvas.drawRects(SK_ColorBLUE, boxes);
540 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500541 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400542 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 19.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500543 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400544 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400545}
Julia Lavrova916a9042019-08-08 16:51:27 -0400546
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400547DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400548 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400549 TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png");
550 if (!fontCollection->fontsFound()) return;
551
552 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400553 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400554
555 ParagraphStyle paragraph_style;
556 paragraph_style.turnHintingOff();
557 paragraph_style.setMaxLines(14);
558 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
559
560 TextStyle text_style;
561 text_style.setFontFamilies({SkString("Roboto")});
562 text_style.setColor(SK_ColorBLACK);
563 text_style.setFontSize(26);
564 text_style.setWordSpacing(5);
565 text_style.setLetterSpacing(1);
566 text_style.setDecoration(TextDecoration::kUnderline);
567 text_style.setDecorationColor(SK_ColorBLACK);
568 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400569 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400570
571 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kTop, TextBaseline::kAlphabetic, 0);
572 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400573 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400574
575 builder.pop();
576
577 auto paragraph = builder.Build();
578 paragraph->layout(TestCanvasWidth);
579 paragraph->paint(canvas.get(), 0, 0);
580
581 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
582 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
583
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400584 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400585 canvas.drawRects(SK_ColorRED, boxes);
586 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500587 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400588 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500589 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400590 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
591
592 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
593 canvas.drawRects(SK_ColorBLUE, boxes);
594 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500595 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400596 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500597 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400598 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400599}
Julia Lavrova916a9042019-08-08 16:51:27 -0400600
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400601DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400602 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400603 TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png");
604 if (!fontCollection->fontsFound()) return;
605
606 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400607 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400608
609 ParagraphStyle paragraph_style;
610 paragraph_style.turnHintingOff();
611 paragraph_style.setMaxLines(14);
612 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
613
614 TextStyle text_style;
615 text_style.setFontFamilies({SkString("Roboto")});
616 text_style.setColor(SK_ColorBLACK);
617 text_style.setFontSize(26);
618 text_style.setWordSpacing(5);
619 text_style.setLetterSpacing(1);
620 text_style.setDecoration(TextDecoration::kUnderline);
621 text_style.setDecorationColor(SK_ColorBLACK);
622 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400623 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400624
625 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kMiddle, TextBaseline::kAlphabetic, 0);
626 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400627 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400628
629 builder.pop();
630
631 auto paragraph = builder.Build();
632 paragraph->layout(TestCanvasWidth);
633 paragraph->paint(canvas.get(), 0, 0);
634
635 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
636 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
637
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400638 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400639 canvas.drawRects(SK_ColorRED, boxes);
640 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500641 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500643 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400644 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
645
646 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
647 canvas.drawRects(SK_ColorBLUE, boxes);
648 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 9.765f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500651 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400653}
Julia Lavrova916a9042019-08-08 16:51:27 -0400654
Julia Lavrova916a9042019-08-08 16:51:27 -0400655DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400656 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400657 TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png");
658 if (!fontCollection->fontsFound()) return;
659
660 const char* text = "給能上目秘使";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400661 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400662
663 ParagraphStyle paragraph_style;
664 paragraph_style.turnHintingOff();
665 paragraph_style.setMaxLines(14);
666 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
667
668 TextStyle text_style;
669 text_style.setFontFamilies({SkString("Source Han Serif CN")});
670 text_style.setColor(SK_ColorBLACK);
671 text_style.setFontSize(26);
672 text_style.setWordSpacing(5);
673 text_style.setLetterSpacing(1);
674 text_style.setDecoration(TextDecoration::kUnderline);
675 text_style.setDecorationColor(SK_ColorBLACK);
676 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400677 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400678 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kIdeographic, 38.347f);
679 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400680 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400681
682 builder.pop();
683
684 auto paragraph = builder.Build();
685 paragraph->layout(TestCanvasWidth);
686 paragraph->paint(canvas.get(), 0, 0);
687
688 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
689 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
690
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400691 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400692 canvas.drawRects(SK_ColorRED, boxes);
693 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500694 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400695 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500696 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400697 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
698
699 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
700 canvas.drawRects(SK_ColorBLUE, boxes);
701 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500702 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 135.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400703 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 4.703f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500704 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400705 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400706}
Julia Lavrova916a9042019-08-08 16:51:27 -0400707
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400708DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400709 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400710 TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png");
711 if (!fontCollection->fontsFound()) return;
712
713 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400714 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400715
716 ParagraphStyle paragraph_style;
717 paragraph_style.turnHintingOff();
718 paragraph_style.setMaxLines(14);
719 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
720
721 TextStyle text_style;
722 text_style.setFontFamilies({SkString("Roboto")});
723 text_style.setColor(SK_ColorBLACK);
724 text_style.setFontSize(26);
725 text_style.setWordSpacing(5);
726 text_style.setLetterSpacing(1);
727 text_style.setDecoration(TextDecoration::kUnderline);
728 text_style.setDecorationColor(SK_ColorBLACK);
729 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400730 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400731
732 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
733 PlaceholderStyle placeholder2(25, 25, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 12.5f);
734
735 builder.addPlaceholder(placeholder1);
736 builder.addPlaceholder(placeholder1);
737 builder.addPlaceholder(placeholder1);
738 builder.addPlaceholder(placeholder2);
739 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400740 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400741
742 builder.addPlaceholder(placeholder1);
743 builder.addPlaceholder(placeholder1);
744 builder.addPlaceholder(placeholder1);
745 builder.addPlaceholder(placeholder1);
746 builder.addPlaceholder(placeholder2); // 4 + 1
747 builder.addPlaceholder(placeholder1);
748 builder.addPlaceholder(placeholder1);
749 builder.addPlaceholder(placeholder1);
750 builder.addPlaceholder(placeholder1);
751 builder.addPlaceholder(placeholder1);
752 builder.addPlaceholder(placeholder1);
753 builder.addPlaceholder(placeholder2); // 6 + 1
754 builder.addPlaceholder(placeholder1);
755 builder.addPlaceholder(placeholder1);
756 builder.addPlaceholder(placeholder1);
757 builder.addPlaceholder(placeholder1);
758 builder.addPlaceholder(placeholder1);
759 builder.addPlaceholder(placeholder1);
760 builder.addPlaceholder(placeholder1);
761 builder.addPlaceholder(placeholder2); // 7 + 1
762
763 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400764 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400765 builder.addPlaceholder(placeholder1);
766 builder.addPlaceholder(placeholder2);
767
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400768 builder.addText(text, len);
769 builder.addText(text, len);
770 builder.addText(text, len);
771 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400772
773 builder.addPlaceholder(placeholder2);
774 builder.addPlaceholder(placeholder1);
775
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400776 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400777
778 builder.addPlaceholder(placeholder2);
779
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400780 builder.addText(text, len);
781 builder.addText(text, len);
782 builder.addText(text, len);
783 builder.addText(text, len);
784 builder.addText(text, len);
785 builder.addText(text, len);
786 builder.addText(text, len);
787 builder.addText(text, len);
788 builder.addText(text, len);
789 builder.addText(text, len);
790 builder.addText(text, len);
791 builder.addText(text, len);
792 builder.addText(text, len);
793 builder.addText(text, len);
794 builder.addText(text, len);
795 builder.addText(text, len);
796 builder.addText(text, len);
797 builder.addText(text, len);
798 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400799
800 builder.pop();
801
802 auto paragraph = builder.Build();
803 paragraph->layout(TestCanvasWidth - 100);
804 paragraph->paint(canvas.get(), 0, 0);
805
806 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
807 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
808
809 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
810 canvas.drawRects(SK_ColorRED, boxes);
811 REPORTER_ASSERT(reporter, boxes.size() == 1);
812
813 boxes = paragraph->getRectsForRange(175, 176, rect_height_style, rect_width_style);
814 canvas.drawRects(SK_ColorGREEN, boxes);
815 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500816 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 31.695f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400817 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 218.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500818 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 47.292f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400819 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 249, EPSILON100));
820
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400821 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400822 canvas.drawRects(SK_ColorRED, boxes);
823
824 boxes = paragraph->getRectsForRange(4, 45, rect_height_style, rect_width_style);
825 canvas.drawRects(SK_ColorBLUE, boxes);
826 REPORTER_ASSERT(reporter, boxes.size() == 30);
Julia Lavrovac028b422019-11-25 10:00:43 -0500827 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 59.726f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400828 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.378f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500829 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400830 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56.847f, EPSILON100));
831
Julia Lavrovac028b422019-11-25 10:00:43 -0500832 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.left(), 606.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400833 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.top(), 38, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500834 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.right(), 631.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400835 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.bottom(), 63, EPSILON100));
836
Julia Lavrovac028b422019-11-25 10:00:43 -0500837 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400838 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.top(), 63.5f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500839 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.right(), 50.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400840 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400841}
Julia Lavrova916a9042019-08-08 16:51:27 -0400842
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400843DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400844 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400845 TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png");
846 if (!fontCollection->fontsFound()) return;
847
848 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400849 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400850
851 ParagraphStyle paragraph_style;
852 paragraph_style.turnHintingOff();
853 paragraph_style.setMaxLines(14);
854 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
855
856 TextStyle text_style;
857 text_style.setFontFamilies({SkString("Roboto")});
858 text_style.setColor(SK_ColorBLACK);
859 text_style.setFontSize(26);
860 text_style.setWordSpacing(5);
861 text_style.setLetterSpacing(1);
862 text_style.setDecoration(TextDecoration::kUnderline);
863 text_style.setDecorationColor(SK_ColorBLACK);
864 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400865 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400866
867 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
868 PlaceholderStyle placeholder2(5, 20, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 10);
869
870 builder.addPlaceholder(placeholder1);
871 builder.addPlaceholder(placeholder1);
872 builder.addPlaceholder(placeholder1);
873 builder.addPlaceholder(placeholder1);
874 builder.addPlaceholder(placeholder1);
875 builder.addPlaceholder(placeholder1);
876 builder.addPlaceholder(placeholder1);
877 builder.addPlaceholder(placeholder1);
878 builder.addPlaceholder(placeholder2); // 8 + 1
879 builder.addPlaceholder(placeholder1);
880 builder.addPlaceholder(placeholder1);
881 builder.addPlaceholder(placeholder1);
882 builder.addPlaceholder(placeholder1);
883 builder.addPlaceholder(placeholder1);
884 builder.addPlaceholder(placeholder2); // 5 + 1
885 builder.addPlaceholder(placeholder1);
886 builder.addPlaceholder(placeholder1);
887 builder.addPlaceholder(placeholder1);
888 builder.addPlaceholder(placeholder1);
889 builder.addPlaceholder(placeholder1);
890 builder.addPlaceholder(placeholder1);
891 builder.addPlaceholder(placeholder1);
892 builder.addPlaceholder(placeholder1); // 8 + 0
893
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400894 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400895
896 builder.addPlaceholder(placeholder1);
897 builder.addPlaceholder(placeholder2);
898 builder.addPlaceholder(placeholder2); // 1 + 2
899 builder.addPlaceholder(placeholder1);
900 builder.addPlaceholder(placeholder2);
901 builder.addPlaceholder(placeholder2); // 1 + 2
902
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400903 builder.addText(text, len);
904 builder.addText(text, len);
905 builder.addText(text, len);
906 builder.addText(text, len);
907 builder.addText(text, len);
908 builder.addText(text, len);
909 builder.addText(text, len);
910 builder.addText(text, len);
911 builder.addText(text, len);
912 builder.addText(text, len);
913 builder.addText(text, len); // 11
Julia Lavrova916a9042019-08-08 16:51:27 -0400914
915 builder.addPlaceholder(placeholder2);
916 builder.addPlaceholder(placeholder1);
917 builder.addPlaceholder(placeholder2);
918 builder.addPlaceholder(placeholder1);
919 builder.addPlaceholder(placeholder2);
920
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400921 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400922
923 builder.pop();
924
925 auto paragraph = builder.Build();
926 paragraph->layout(TestCanvasWidth);
927 paragraph->paint(canvas.get(), 0, 0);
928
929 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
930 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
931
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400932 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400933 canvas.drawRects(SK_ColorRED, boxes);
934
935 REPORTER_ASSERT(reporter, boxes.size() == 34);
Julia Lavrovac028b422019-11-25 10:00:43 -0500936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500938 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 140.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400939 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
940
Julia Lavrovac028b422019-11-25 10:00:43 -0500941 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.left(), 800.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400942 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500943 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.right(), 850.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400944 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.bottom(), 50, EPSILON100));
945
Julia Lavrovac028b422019-11-25 10:00:43 -0500946 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.left(), 503.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400947 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.top(), 160, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500948 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.right(), 508.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400949 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.bottom(), 180, EPSILON100));
950
951 boxes = paragraph->getRectsForRange(30, 50, rect_height_style, rect_width_style);
952 canvas.drawRects(SK_ColorBLUE, boxes);
953
954 REPORTER_ASSERT(reporter, boxes.size() == 8);
Julia Lavrovac028b422019-11-25 10:00:43 -0500955 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 216.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400956 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500957 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 290.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400958 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 120, EPSILON100));
959
Julia Lavrovac028b422019-11-25 10:00:43 -0500960 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 290.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400961 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500962 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 340.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400963 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 120, EPSILON100));
964
Julia Lavrovac028b422019-11-25 10:00:43 -0500965 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.left(), 340.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400966 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500967 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.right(), 345.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400968 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400969}
970
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400971DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400972 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400973 if (!fontCollection->fontsFound()) return;
974 const char* text = "I am RED";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400975 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400976
977 ParagraphStyle paragraph_style;
978 paragraph_style.turnHintingOff();
979 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
980
981 TextStyle text_style;
982 text_style.setFontFamilies({SkString("Roboto")});
983 text_style.setColor(SK_ColorRED);
984 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400985 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400986 builder.pop();
987
988 auto paragraph = builder.Build();
989 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500990 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400991
992 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
993 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
994 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400995 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400996
997 size_t index = 0;
998 for (auto& line : impl->lines()) {
999 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -04001000 [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
1001 REPORTER_ASSERT(reporter, index == 0);
1002 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED);
1003 ++index;
1004 return true;
1005 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001006 }
1007}
1008
Julia Lavrovac2228562019-08-08 16:51:27 -04001009// Checked: DIFF+ (Space between 1 & 2 style blocks)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001010DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001011 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001012 TestCanvas canvas("SkParagraph_RainbowParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001013 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001014 const char* text1 = "Red Roboto"; // [0:10)
1015 const char* text2 = "big Greeen Default"; // [10:28)
1016 const char* text3 = "Defcolor Homemade Apple"; // [28:51)
1017 const char* text4 = "Small Blue Roboto"; // [51:68)
Julia Lavrovac2228562019-08-08 16:51:27 -04001018 const char* text41 = "Small Blue ";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001019 const char* text5 =
1020 "Continue Last Style With lots of words to check if it overlaps "
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001021 "properly or not"; // [68:)
1022 const char* text42 =
1023 "Roboto"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001024 "Continue Last Style With lots of words to check if it overlaps "
1025 "properly or not";
1026
1027 ParagraphStyle paragraph_style;
1028 paragraph_style.turnHintingOff();
1029 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001030 paragraph_style.setMaxLines(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001031 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1032
1033 TextStyle text_style1;
1034 text_style1.setFontFamilies({SkString("Roboto")});
1035
1036 text_style1.setColor(SK_ColorRED);
1037 builder.pushStyle(text_style1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001038 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001039
1040 TextStyle text_style2;
1041 text_style2.setFontFamilies({SkString("Roboto")});
1042 text_style2.setFontSize(50);
1043 text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1044 SkFontStyle::kUpright_Slant));
1045 text_style2.setLetterSpacing(10);
1046 text_style2.setDecorationColor(SK_ColorBLACK);
1047 text_style2.setDecoration((TextDecoration)(
1048 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1049 text_style2.setWordSpacing(30);
1050 text_style2.setColor(SK_ColorGREEN);
1051 builder.pushStyle(text_style2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001052 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001053
1054 TextStyle text_style3;
1055 text_style3.setFontFamilies({SkString("Homemade Apple")});
Julia Lavrova526df262019-08-21 17:49:44 -04001056 text_style3.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001057 builder.pushStyle(text_style3);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001058 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001059
1060 TextStyle text_style4;
1061 text_style4.setFontFamilies({SkString("Roboto")});
1062 text_style4.setFontSize(14);
1063 text_style4.setDecorationColor(SK_ColorBLACK);
1064 text_style4.setDecoration((TextDecoration)(
1065 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1066 text_style4.setColor(SK_ColorBLUE);
1067 builder.pushStyle(text_style4);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001068 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001069
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001070 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001071 builder.pop();
1072
1073 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001074 paragraph->layout(1000);
1075 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001076
Julia Lavrova3281b962019-12-02 11:32:25 -05001077 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1078
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001079 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1080 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
1081 REPORTER_ASSERT(reporter, impl->styles().size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001082 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1083
1084 auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight);
1085 canvas.drawRects(SK_ColorMAGENTA, rects);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001086
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001087 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001088 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001089 StyleType::kAllAttributes,
1090 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001091 switch (index) {
1092 case 0:
1093 REPORTER_ASSERT(reporter, style.equals(text_style1));
Julia Lavrova526df262019-08-21 17:49:44 -04001094 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001095 break;
1096 case 1:
1097 REPORTER_ASSERT(reporter, style.equals(text_style2));
Julia Lavrova526df262019-08-21 17:49:44 -04001098 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001099 break;
1100 case 2:
1101 REPORTER_ASSERT(reporter, style.equals(text_style3));
Julia Lavrova526df262019-08-21 17:49:44 -04001102 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001103 break;
1104 case 3:
1105 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001106 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001107 break;
1108 default:
1109 REPORTER_ASSERT(reporter, false);
1110 break;
1111 }
1112 ++index;
1113 return true;
1114 });
1115 impl->lines()[1].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001116 StyleType::kAllAttributes,
1117 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001118 switch (index) {
1119 case 4:
1120 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001121 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001122 break;
1123 default:
1124 REPORTER_ASSERT(reporter, false);
1125 break;
1126 }
1127 ++index;
1128 return true;
1129 });
1130 REPORTER_ASSERT(reporter, index == 5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001131}
1132
1133DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001134 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001135 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001136 TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001137 const char* text = "No TextStyle! Uh Oh!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001138 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001139
1140 ParagraphStyle paragraph_style;
1141 TextStyle defaultStyle;
1142 defaultStyle.setFontFamilies({SkString("Roboto")});
1143 paragraph_style.setTextStyle(defaultStyle);
1144 paragraph_style.turnHintingOff();
1145 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001146 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001147
1148 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001149 paragraph->layout(TestCanvasWidth);
1150 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001151
Julia Lavrova3281b962019-12-02 11:32:25 -05001152 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1153
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001154 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1155
1156 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1157 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1158 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1159
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001160 size_t index = 0;
1161 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001162 StyleType::kAllAttributes,
1163 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001164 REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle()));
Julia Lavrova526df262019-08-21 17:49:44 -04001165 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001166 ++index;
1167 return true;
1168 });
1169 REPORTER_ASSERT(reporter, index == 1);
1170}
1171
1172DEF_TEST(SkParagraph_BoldParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001173 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001174 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001175 TestCanvas canvas("SkParagraph_BoldParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001176 const char* text = "This is Red max bold text!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001177 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001178
1179 ParagraphStyle paragraph_style;
1180 paragraph_style.turnHintingOff();
1181 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1182
1183 TextStyle text_style;
1184 text_style.setFontFamilies({SkString("Roboto")});
1185 text_style.setColor(SK_ColorRED);
1186 text_style.setFontSize(60);
1187 text_style.setLetterSpacing(0);
1188 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width,
1189 SkFontStyle::kUpright_Slant));
1190 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001191 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001192 builder.pop();
1193
1194 auto paragraph = builder.Build();
1195 paragraph->layout(VeryLongCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001196 paragraph->paint(canvas.get(), 10.0, 60.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001197
Julia Lavrova3281b962019-12-02 11:32:25 -05001198 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1199
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001200 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1201
1202 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1203 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1204 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1205
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001206 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001207 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001208 StyleType::kAllAttributes,
1209 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001210 REPORTER_ASSERT(reporter, style.equals(text_style));
Julia Lavrova526df262019-08-21 17:49:44 -04001211 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001212 ++index;
1213 return true;
1214 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001215 REPORTER_ASSERT(reporter, index == 1);
1216}
1217
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001218DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001219 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04001220 if (!fontCollection->fontsFound()) return;
1221 TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png");
1222 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001223 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001224
Julia Lavrovac2228562019-08-08 16:51:27 -04001225 ParagraphStyle paragraph_style;
1226 paragraph_style.turnHintingOff();
1227 paragraph_style.setMaxLines(10);
1228 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001229
Julia Lavrovac2228562019-08-08 16:51:27 -04001230 TextStyle text_style;
1231 text_style.setFontFamilies({SkString("Roboto")});
1232 text_style.setFontSize(20);
1233 text_style.setColor(SK_ColorBLACK);
1234 text_style.setHeight(3.6345f);
1235 text_style.setHeightOverride(true);
1236 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001237 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04001238 builder.pop();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001239
Julia Lavrovac2228562019-08-08 16:51:27 -04001240 auto paragraph = builder.Build();
1241 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001242
Julia Lavrovac2228562019-08-08 16:51:27 -04001243 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001244 REPORTER_ASSERT(reporter, impl->runs().size() == 5);
Julia Lavrovac2228562019-08-08 16:51:27 -04001245 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
1246 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001247
Julia Lavrovac2228562019-08-08 16:51:27 -04001248 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001249
Julia Lavrovac2228562019-08-08 16:51:27 -04001250 SkPaint paint;
1251 paint.setStyle(SkPaint::kStroke_Style);
1252 paint.setAntiAlias(true);
1253 paint.setStrokeWidth(1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001254
Julia Lavrovac2228562019-08-08 16:51:27 -04001255 // Tests for GetRectsForRange()
1256 RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle;
1257 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1258 paint.setColor(SK_ColorRED);
1259 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
1260 canvas.drawRects(SK_ColorRED, boxes);
1261 REPORTER_ASSERT(reporter, boxes.size() == 0ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001262
Julia Lavrovac2228562019-08-08 16:51:27 -04001263 boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style);
1264 canvas.drawRects(SK_ColorBLUE, boxes);
1265 REPORTER_ASSERT(reporter, boxes.size() == 3ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001266
Julia Lavrovac2228562019-08-08 16:51:27 -04001267 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100));
1268 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5));
1269 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100));
1270 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001271}
1272
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001273DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001274 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001275 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001276 TestCanvas canvas("SkParagraph_LeftAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001277 const char* text =
1278 "This is a very long sentence to test if the text will properly wrap "
1279 "around and go to the next line. Sometimes, short sentence. Longer "
1280 "sentences are okay too because they are nessecary. Very short. "
1281 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1282 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1283 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1284 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1285 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1286 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1287 "mollit anim id est laborum. "
1288 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1289 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1290 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1291 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1292 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1293 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1294 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001295 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001296
1297 ParagraphStyle paragraph_style;
1298 paragraph_style.setMaxLines(14);
1299 paragraph_style.setTextAlign(TextAlign::kLeft);
1300 paragraph_style.turnHintingOff();
1301 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1302
1303 TextStyle text_style;
1304 text_style.setFontFamilies({SkString("Roboto")});
1305 text_style.setFontSize(26);
1306 text_style.setLetterSpacing(1);
1307 text_style.setWordSpacing(5);
1308 text_style.setColor(SK_ColorBLACK);
1309 text_style.setHeight(1);
1310 text_style.setDecoration(TextDecoration::kUnderline);
1311 text_style.setDecorationColor(SK_ColorBLACK);
1312 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001313 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001314 builder.pop();
1315
1316 auto paragraph = builder.Build();
1317 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001318 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001319
1320 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001321
1322 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1323 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1324 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001325 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001326 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1327
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001328 double expected_y = 0;
1329 double epsilon = 0.01f;
1330 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1331 REPORTER_ASSERT(reporter,
1332 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1333 expected_y += 30;
1334 REPORTER_ASSERT(reporter,
1335 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1336 expected_y += 30;
1337 REPORTER_ASSERT(reporter,
1338 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1339 expected_y += 30;
1340 REPORTER_ASSERT(reporter,
1341 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1342 expected_y += 30 * 10;
1343 REPORTER_ASSERT(reporter,
1344 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1345
1346 REPORTER_ASSERT(reporter,
1347 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1348
1349 // Tests for GetGlyphPositionAtCoordinate()
1350 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0);
1351 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
1352 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
1353 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001354 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001355}
1356
1357DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001358 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001359 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001360 TestCanvas canvas("SkParagraph_RightAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001361 const char* text =
1362 "This is a very long sentence to test if the text will properly wrap "
1363 "around and go to the next line. Sometimes, short sentence. Longer "
1364 "sentences are okay too because they are nessecary. Very short. "
1365 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1366 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1367 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1368 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1369 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1370 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1371 "mollit anim id est laborum. "
1372 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1373 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1374 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1375 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1376 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1377 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1378 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001379 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001380
1381 ParagraphStyle paragraph_style;
1382 paragraph_style.setMaxLines(14);
1383 paragraph_style.setTextAlign(TextAlign::kRight);
1384 paragraph_style.turnHintingOff();
1385 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1386
1387 TextStyle text_style;
1388 text_style.setFontFamilies({SkString("Roboto")});
1389 text_style.setFontSize(26);
1390 text_style.setLetterSpacing(1);
1391 text_style.setWordSpacing(5);
1392 text_style.setColor(SK_ColorBLACK);
1393 text_style.setHeight(1);
1394 text_style.setDecoration(TextDecoration::kUnderline);
1395 text_style.setDecorationColor(SK_ColorBLACK);
1396 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001397 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001398 builder.pop();
1399
1400 auto paragraph = builder.Build();
1401 paragraph->layout(TestCanvasWidth - 100);
1402
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001403 paragraph->paint(canvas.get(), 0, 0);
1404
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001405 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001406
1407 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1408 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001409 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001410 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1411
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001412 double expected_y = 0;
1413 double epsilon = 0.01f;
1414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1415 REPORTER_ASSERT(reporter,
1416 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1417 expected_y += 30;
1418 REPORTER_ASSERT(reporter,
1419 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1420 expected_y += 30;
1421 REPORTER_ASSERT(reporter,
1422 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1423 expected_y += 30;
1424 REPORTER_ASSERT(reporter,
1425 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1426 expected_y += 30 * 10;
1427 REPORTER_ASSERT(reporter,
1428 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1429
1430 auto calculate = [](const TextLine& line) -> SkScalar {
1431 return TestCanvasWidth - 100 - line.offset().fX - line.width();
1432 };
1433
1434 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1435 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1436 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1437 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1438 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1439
1440 REPORTER_ASSERT(reporter,
1441 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1442}
1443
1444DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001445 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001446 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001447 TestCanvas canvas("SkParagraph_CenterAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001448 const char* text =
1449 "This is a very long sentence to test if the text will properly wrap "
1450 "around and go to the next line. Sometimes, short sentence. Longer "
1451 "sentences are okay too because they are nessecary. Very short. "
1452 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1453 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1454 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1455 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1456 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1457 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1458 "mollit anim id est laborum. "
1459 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1460 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1461 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1462 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1463 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1464 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1465 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001466 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001467
1468 ParagraphStyle paragraph_style;
1469 paragraph_style.setMaxLines(14);
1470 paragraph_style.setTextAlign(TextAlign::kCenter);
1471 paragraph_style.turnHintingOff();
1472 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1473
1474 TextStyle text_style;
1475 text_style.setFontFamilies({SkString("Roboto")});
1476 text_style.setFontSize(26);
1477 text_style.setLetterSpacing(1);
1478 text_style.setWordSpacing(5);
1479 text_style.setColor(SK_ColorBLACK);
1480 text_style.setHeight(1);
1481 text_style.setDecoration(TextDecoration::kUnderline);
1482 text_style.setDecorationColor(SK_ColorBLACK);
1483 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001484 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001485 builder.pop();
1486
1487 auto paragraph = builder.Build();
1488 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001489 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001490
1491 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001492
1493 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1494 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1495 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001496 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001497 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1498
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001499 double expected_y = 0;
1500 double epsilon = 0.01f;
1501 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1502 REPORTER_ASSERT(reporter,
1503 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1504 expected_y += 30;
1505 REPORTER_ASSERT(reporter,
1506 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1507 expected_y += 30;
1508 REPORTER_ASSERT(reporter,
1509 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1510 expected_y += 30;
1511 REPORTER_ASSERT(reporter,
1512 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1513 expected_y += 30 * 10;
1514 REPORTER_ASSERT(reporter,
1515 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1516
1517 auto calculate = [](const TextLine& line) -> SkScalar {
1518 return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width());
1519 };
1520
1521 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1522 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1523 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1524 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1525 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1526
1527 REPORTER_ASSERT(reporter,
1528 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1529}
1530
1531DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001532 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001533 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001534 TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001535 const char* text =
1536 "This is a very long sentence to test if the text will properly wrap "
1537 "around and go to the next line. Sometimes, short sentence. Longer "
1538 "sentences are okay too because they are nessecary. Very short. "
1539 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1540 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1541 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1542 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1543 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1544 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1545 "mollit anim id est laborum. "
1546 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1547 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1548 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1549 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1550 "velit esse cillum dolore eu fugiat.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001551 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001552
1553 ParagraphStyle paragraph_style;
1554 paragraph_style.setMaxLines(14);
1555 paragraph_style.setTextAlign(TextAlign::kJustify);
1556 paragraph_style.turnHintingOff();
1557 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1558
1559 TextStyle text_style;
1560 text_style.setFontFamilies({SkString("Roboto")});
1561 text_style.setFontSize(26);
1562 text_style.setLetterSpacing(0);
1563 text_style.setWordSpacing(5);
1564 text_style.setColor(SK_ColorBLACK);
1565 text_style.setHeight(1);
1566 text_style.setDecoration(TextDecoration::kUnderline);
1567 text_style.setDecorationColor(SK_ColorBLACK);
1568 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001569 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001570 builder.pop();
1571
1572 auto paragraph = builder.Build();
1573 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001574 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001575
Julia Lavrovac2228562019-08-08 16:51:27 -04001576 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1577 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1578 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1579 canvas.drawRects(SK_ColorRED, boxes);
1580
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001581 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001582
1583 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1584 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1585 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001586 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001587
1588 double expected_y = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001589 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001590 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001591 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001592 expected_y += 30;
1593 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001594 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001595 expected_y += 30;
1596 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001597 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001598 expected_y += 30;
1599 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001600 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001601 expected_y += 30 * 9;
1602 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001603 SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001604
1605 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001606 return line.offset().fX;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001607 };
1608
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001609 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100));
1610 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100));
1611 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100));
1612 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001613
1614 REPORTER_ASSERT(reporter,
1615 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1616}
1617
Julia Lavrovac2228562019-08-08 16:51:27 -04001618// Checked: DIFF (ghost spaces as a separate box in TxtLib)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001619DEF_TEST(SkParagraph_JustifyRTL, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001620 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001621 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001622 TestCanvas canvas("SkParagraph_JustifyRTL.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001623 const char* text =
1624 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1625 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1626 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001627 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001628
1629 ParagraphStyle paragraph_style;
1630 paragraph_style.setMaxLines(14);
1631 paragraph_style.setTextAlign(TextAlign::kJustify);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001632 paragraph_style.setTextDirection(TextDirection::kRtl);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001633 paragraph_style.turnHintingOff();
1634 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1635
1636 TextStyle text_style;
1637 text_style.setFontFamilies({SkString("Ahem")});
1638 text_style.setFontSize(26);
1639 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001640 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001641 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001642 builder.pop();
1643
1644 auto paragraph = builder.Build();
1645 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001646 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001647
1648 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001649
1650 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001651 return TestCanvasWidth - 100 - line.width();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001652 };
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001653 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001654 if (&line == &impl->lines().back()) {
1655 REPORTER_ASSERT(reporter, calculate(line) > EPSILON100);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001656 } else {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001658 }
1659 }
1660
1661 // Just make sure the the text is actually RTL
1662 for (auto& run : impl->runs()) {
1663 REPORTER_ASSERT(reporter, !run.leftToRight());
1664 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001665
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001666 // Tests for GetRectsForRange()
1667 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1668 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1669 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1670 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001671 REPORTER_ASSERT(reporter, boxes.size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001672
1673 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1674 canvas.drawRects(SK_ColorBLUE, boxes);
1675 REPORTER_ASSERT(reporter, boxes.size() == 1);
1676
1677 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100));
1678 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1679 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100));
1680 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1681}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001682
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001683DEF_TEST_DISABLED(SkParagraph_JustifyRTLNewLine, reporter) {
1684 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1685 if (!fontCollection->fontsFound()) return;
1686 TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png");
1687 const char* text =
1688 "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1689 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1690 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
1691
1692 auto icu_text = icu::UnicodeString::fromUTF8(text);
1693 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1694 const size_t len = strlen(text);
1695
1696 ParagraphStyle paragraph_style;
1697 paragraph_style.setMaxLines(14);
1698 paragraph_style.setTextAlign(TextAlign::kJustify);
1699 paragraph_style.setTextDirection(TextDirection::kRtl);
1700 paragraph_style.turnHintingOff();
1701 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1702
1703 TextStyle text_style;
1704 text_style.setFontFamilies({SkString("Ahem")});
1705 text_style.setFontSize(26);
1706 text_style.setColor(SK_ColorBLACK);
1707 builder.pushStyle(text_style);
1708 builder.addText(text, len);
1709 builder.pop();
1710
1711 auto paragraph = builder.Build();
1712 paragraph->layout(TestCanvasWidth - 100);
1713 paragraph->paint(canvas.get(), 0, 0);
1714
1715 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1716
1717 SkPaint paint;
1718 paint.setStyle(SkPaint::kStroke_Style);
1719 paint.setAntiAlias(true);
1720 paint.setStrokeWidth(1);
1721
1722 // Tests for GetRectsForRange()
1723 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1724 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1725 paint.setColor(SK_ColorRED);
1726 auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
1727 for (size_t i = 0; i < boxes.size(); ++i) {
1728 canvas.get()->drawRect(boxes[i].rect, paint);
1729 }
1730 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1731 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
1732 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
1733 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1734 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
1735
1736 paint.setColor(SK_ColorBLUE);
1737 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1738 for (size_t i = 0; i < boxes.size(); ++i) {
1739 canvas.get()->drawRect(boxes[i].rect, paint);
1740 }
1741 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
1742 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
1743 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1744 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
1745 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1746
1747 // All lines should be justified to the width of the
1748 // paragraph.
1749 for (auto& line : impl->lines()) {
1750 REPORTER_ASSERT(reporter,
1751 SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
1752 }
1753}
1754
1755DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
1756 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1757 if (!fontCollection->fontsFound()) return;
1758 TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
1759
1760 const char* text = " leading space";
1761
1762 auto icu_text = icu::UnicodeString::fromUTF8(text);
1763 std::u16string u16_text(icu_text.getBuffer(), icu_text.getBuffer() + icu_text.length());
1764 const size_t len = strlen(text);
1765
1766 ParagraphStyle paragraph_style;
1767 paragraph_style.setMaxLines(14);
1768 paragraph_style.setTextAlign(TextAlign::kJustify);
1769 paragraph_style.setTextDirection(TextDirection::kRtl);
1770 paragraph_style.turnHintingOff();
1771 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1772
1773 TextStyle text_style;
1774 text_style.setFontFamilies({SkString("Ahem")});
1775 text_style.setFontSize(26);
1776 text_style.setColor(SK_ColorBLACK);
1777 builder.pushStyle(text_style);
1778 builder.addText(text, len);
1779 builder.pop();
1780
1781 auto paragraph = builder.Build();
1782 paragraph->layout(TestCanvasWidth - 100);
1783 paragraph->paint(canvas.get(), 0, 0);
1784
1785 SkPaint paint;
1786 paint.setStyle(SkPaint::kStroke_Style);
1787 paint.setAntiAlias(true);
1788 paint.setStrokeWidth(1);
1789
1790 // Tests for GetRectsForRange()
1791 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1792 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1793 paint.setColor(SK_ColorRED);
1794 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1795 for (size_t i = 0; i < boxes.size(); ++i) {
1796 canvas.get()->drawRect(boxes[i].rect, paint);
1797 }
1798 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1799}
1800
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001801DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001802 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001803 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001804 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001805 const char* text1 = "This text should be";
1806 const char* text2 = " decorated even when";
1807 const char* text3 = " wrapped around to";
1808 const char* text4 = " the next line.";
1809 const char* text5 = " Otherwise, bad things happen.";
1810
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001811 ParagraphStyle paragraph_style;
1812 paragraph_style.setMaxLines(14);
1813 paragraph_style.setTextAlign(TextAlign::kLeft);
1814 paragraph_style.turnHintingOff();
1815 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1816
1817 TextStyle text_style;
1818 text_style.setFontFamilies({SkString("Roboto")});
1819 text_style.setFontSize(26);
1820 text_style.setLetterSpacing(0);
1821 text_style.setWordSpacing(5);
1822 text_style.setColor(SK_ColorBLACK);
1823 text_style.setHeight(2);
1824 text_style.setDecoration(TextDecoration::kUnderline);
1825 text_style.setDecorationColor(SK_ColorBLACK);
1826 text_style.setDecoration((TextDecoration)(
1827 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1828 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1829 text_style.setDecorationColor(SK_ColorBLACK);
1830 text_style.setDecorationThicknessMultiplier(2.0);
1831 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001832 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001833
1834 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1835 text_style.setDecorationColor(SK_ColorBLUE);
1836 text_style.setDecorationThicknessMultiplier(1.0);
1837 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001838 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001839
1840 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1841 text_style.setDecorationColor(SK_ColorBLACK);
1842 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001843 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001844
1845 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1846 text_style.setDecorationColor(SK_ColorBLACK);
1847 text_style.setDecorationThicknessMultiplier(3.0);
1848 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001849 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001850
1851 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1852 text_style.setDecorationColor(SK_ColorRED);
1853 text_style.setDecorationThicknessMultiplier(1.0);
1854 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001855 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001856 builder.pop();
1857
1858 auto paragraph = builder.Build();
1859 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001860 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001861
1862 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001863
1864 size_t index = 0;
1865 for (auto& line : impl->lines()) {
1866 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001867 StyleType::kDecorations,
1868 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001869 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1870 TextDecoration::kOverline |
1871 TextDecoration::kLineThrough);
1872 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1873 switch (index) {
1874 case 0:
1875 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1876 TextDecorationStyle::kSolid);
1877 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1878 REPORTER_ASSERT(reporter,
1879 style.getDecorationThicknessMultiplier() == 2.0);
1880 break;
1881 case 1: // The style appears on 2 lines so it has 2 pieces
1882 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1883 TextDecorationStyle::kDouble);
1884 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1885 REPORTER_ASSERT(reporter,
1886 style.getDecorationThicknessMultiplier() == 1.0);
1887 break;
1888 case 2:
1889 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1890 TextDecorationStyle::kDotted);
1891 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1892 REPORTER_ASSERT(reporter,
1893 style.getDecorationThicknessMultiplier() == 1.0);
1894 break;
1895 case 3:
1896 case 4:
1897 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1898 TextDecorationStyle::kDashed);
1899 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1900 REPORTER_ASSERT(reporter,
1901 style.getDecorationThicknessMultiplier() == 3.0);
1902 break;
1903 case 5:
1904 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1905 TextDecorationStyle::kWavy);
1906 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1907 REPORTER_ASSERT(reporter,
1908 style.getDecorationThicknessMultiplier() == 1.0);
1909 break;
1910 default:
1911 REPORTER_ASSERT(reporter, false);
1912 break;
1913 }
1914 ++index;
1915 return true;
1916 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001917 }
1918}
1919
Julia Lavrovac2228562019-08-08 16:51:27 -04001920DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001921 SkDebugf("TODO: Add test for wavy decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001922}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001923
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001924DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001925 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001926 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001927 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001928 const char* text1 = "No italic ";
1929 const char* text2 = "Yes Italic ";
1930 const char* text3 = "No Italic again.";
1931
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001932 ParagraphStyle paragraph_style;
1933 paragraph_style.turnHintingOff();
1934 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1935
1936 TextStyle text_style;
1937 text_style.setFontFamilies({SkString("Roboto")});
1938 text_style.setFontSize(10);
1939 text_style.setColor(SK_ColorRED);
1940 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001941 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001942
1943 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1944 SkFontStyle::kItalic_Slant));
1945 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001946 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001947 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001948 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001949
1950 auto paragraph = builder.Build();
1951 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001952 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001953
1954 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001955
1956 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1957 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1958 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1959 auto& line = impl->lines()[0];
1960 size_t index = 0;
1961 line.scanStyles(
1962 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001963 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001964 switch (index) {
1965 case 0:
1966 REPORTER_ASSERT(
1967 reporter,
1968 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1969 break;
1970 case 1:
1971 REPORTER_ASSERT(reporter,
1972 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1973 break;
1974 case 2:
1975 REPORTER_ASSERT(
1976 reporter,
1977 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1978 break;
1979 default:
1980 REPORTER_ASSERT(reporter, false);
1981 break;
1982 }
1983 ++index;
1984 return true;
1985 });
1986}
1987
1988DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001989 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001990 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001991 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001992 const char* text =
1993 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1994 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1995 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1996 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1997 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001998 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001999
2000 ParagraphStyle paragraph_style;
2001 paragraph_style.setMaxLines(14);
2002 paragraph_style.setTextAlign(TextAlign::kJustify);
2003 paragraph_style.turnHintingOff();
2004 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2005
2006 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2007 TextDecoration::kLineThrough);
2008
2009 TextStyle text_style;
2010 text_style.setFontFamilies({SkString("Source Han Serif CN")});
2011 text_style.setFontSize(35);
2012 text_style.setColor(SK_ColorBLACK);
2013 text_style.setLetterSpacing(2);
2014 text_style.setHeight(1);
2015 text_style.setDecoration(decoration);
2016 text_style.setDecorationColor(SK_ColorBLACK);
2017 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2018 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002019 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002020 builder.pop();
2021
2022 auto paragraph = builder.Build();
2023 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002024 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002025
Julia Lavrova3281b962019-12-02 11:32:25 -05002026 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2027
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002028 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002029
2030 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2031 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
2032 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002033 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002034}
2035
Julia Lavrovad3a32c52020-02-03 09:43:52 -05002036// Checked: disabled for TxtLib
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002037DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002038 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002039 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002040 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002041 const char* text =
2042 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2043 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002044 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002045
2046 ParagraphStyle paragraph_style;
2047 paragraph_style.setMaxLines(14);
2048 paragraph_style.setTextAlign(TextAlign::kJustify);
2049 paragraph_style.turnHintingOff();
2050 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2051
2052 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2053 TextDecoration::kLineThrough);
2054
2055 TextStyle text_style;
2056 text_style.setFontFamilies({SkString("Katibeh")});
2057 text_style.setFontSize(35);
2058 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002059 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002060 text_style.setDecoration(decoration);
2061 text_style.setDecorationColor(SK_ColorBLACK);
2062 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2063 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002064 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002065 builder.pop();
2066
2067 auto paragraph = builder.Build();
2068 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002069 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002070
Julia Lavrova3281b962019-12-02 11:32:25 -05002071 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2072
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002073 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002074
2075 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2076 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2077 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002078 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002079}
2080
Julia Lavrovac2228562019-08-08 16:51:27 -04002081// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002082DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
2083
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002084 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002085 if (!fontCollection->fontsFound()) return;
2086 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
2087 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002088 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002089
2090 ParagraphStyle paragraph_style;
2091 paragraph_style.turnHintingOff();
2092 paragraph_style.setMaxLines(14);
2093 paragraph_style.setTextAlign(TextAlign::kRight);
2094 paragraph_style.setTextDirection(TextDirection::kRtl);
2095 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2096
2097 TextStyle text_style;
2098 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2099 text_style.setFontSize(26);
2100 text_style.setWordSpacing(5);
2101 text_style.setColor(SK_ColorBLACK);
2102 text_style.setDecoration(TextDecoration::kUnderline);
2103 text_style.setDecorationColor(SK_ColorBLACK);
2104 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002105 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002106 builder.pop();
2107
2108 auto paragraph = builder.Build();
2109 paragraph->layout(TestCanvasWidth - 100);
2110
2111 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2112 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2113
2114 paragraph->paint(canvas.get(), 0, 0);
2115
2116 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2117 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2118 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
2119 canvas.drawRects(SK_ColorRED, boxes);
2120
Julia Lavrovac2228562019-08-08 16:51:27 -04002121 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002122
Julia Lavrovac2228562019-08-08 16:51:27 -04002123 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
2124 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002125 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
2126 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002127}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002128
2129// Checked DIFF+
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002130// This test shows now 2 boxes for [36:40) range:
2131// [36:38) for arabic text and [38:39) for the last space
2132// that has default paragraph direction (LTR) and is placed at the end of the paragraph
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002133DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
2134
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002135 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002136 if (!fontCollection->fontsFound()) return;
2137 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
2138 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002139 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002140
2141 ParagraphStyle paragraph_style;
2142 paragraph_style.turnHintingOff();
2143 paragraph_style.setMaxLines(14);
2144 paragraph_style.setTextAlign(TextAlign::kLeft);
2145 paragraph_style.setTextDirection(TextDirection::kLtr);
2146 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2147
2148 TextStyle text_style;
2149 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2150 text_style.setFontSize(26);
2151 text_style.setWordSpacing(5);
2152 text_style.setColor(SK_ColorBLACK);
2153 text_style.setDecoration(TextDecoration::kUnderline);
2154 text_style.setDecorationColor(SK_ColorBLACK);
2155 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002156 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002157 builder.pop();
2158
2159 auto paragraph = builder.Build();
2160 paragraph->layout(TestCanvasWidth - 100);
2161
2162 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2163 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2164
2165 paragraph->paint(canvas.get(), 0, 0);
2166
2167 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2168 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002169 // 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 -04002170 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2171 canvas.drawRects(SK_ColorRED, boxes);
2172
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002173 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
2174 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.92f, EPSILON100)); // DIFF: 89.40625
2175 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2176 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 110.16f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002177 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002178}
2179
2180// Checked DIFF+
2181DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2182
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002183 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002184 if (!fontCollection->fontsFound()) return;
2185 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2186 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002187 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002188
2189 ParagraphStyle paragraph_style;
2190 paragraph_style.turnHintingOff();
2191 paragraph_style.setMaxLines(14);
2192 paragraph_style.setTextAlign(TextAlign::kRight);
2193 paragraph_style.setTextDirection(TextDirection::kLtr);
2194 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2195
2196 TextStyle text_style;
2197 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2198 text_style.setFontSize(26);
2199 text_style.setWordSpacing(5);
2200 text_style.setColor(SK_ColorBLACK);
2201 text_style.setDecoration(TextDecoration::kUnderline);
2202 text_style.setDecorationColor(SK_ColorBLACK);
2203 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002204 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002205 builder.pop();
2206
2207 auto paragraph = builder.Build();
2208 paragraph->layout(TestCanvasWidth - 100);
2209
2210 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2211 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2212
2213 paragraph->paint(canvas.get(), 0, 0);
2214
2215 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2216 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2217 std::vector<TextBox> boxes =
2218 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2219 canvas.drawRects(SK_ColorRED, boxes);
2220
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002221 REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF
2222 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.5f, EPSILON100)); // DIFF
2223 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2224 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 587.74f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002225 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002226}
2227
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002228DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002229 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002230 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002231 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002232 const char* text =
2233 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2234 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002235 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002236
2237 ParagraphStyle paragraphStyle;
2238 paragraphStyle.setTextAlign(TextAlign::kLeft);
2239 paragraphStyle.setMaxLines(10);
2240 paragraphStyle.turnHintingOff();
2241 TextStyle textStyle;
2242 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002243 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2244 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002245 textStyle.setFontSize(50);
2246 textStyle.setLetterSpacing(1);
2247 textStyle.setWordSpacing(5);
2248 textStyle.setHeight(1);
2249 textStyle.setColor(SK_ColorBLACK);
2250
2251 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2252 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002253 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002254 builder.pop();
2255
2256 auto paragraph = builder.Build();
2257 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002258 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002259
2260 // Tests for getGlyphPositionAtCoordinate()
2261 // NOTE: resulting values can be a few off from their respective positions in
2262 // the original text because the final trailing whitespaces are sometimes not
2263 // drawn (namely, when using "justify" alignment) and therefore are not active
2264 // glyphs.
2265 REPORTER_ASSERT(reporter,
2266 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2267 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2268 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2269 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2270 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2271 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002272 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002273 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2274 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2275 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002276 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002277 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002278 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002279 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2280 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002281 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002282 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2283 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002284 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002285 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2286 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2287 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002288 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002289 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2290}
2291
2292DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002293 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002294 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002295 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002296 const char* text =
2297 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2298 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002299 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002300
2301 ParagraphStyle paragraphStyle;
2302 paragraphStyle.setTextAlign(TextAlign::kLeft);
2303 paragraphStyle.setMaxLines(10);
2304 paragraphStyle.turnHintingOff();
2305 TextStyle textStyle;
2306 textStyle.setFontFamilies({SkString("Roboto")});
2307 textStyle.setFontSize(50);
2308 textStyle.setColor(SK_ColorBLACK);
2309 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2310 SkFontStyle::kUpright_Slant));
2311
2312 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2313 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002314 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002315 builder.pop();
2316
2317 auto paragraph = builder.Build();
2318 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002319 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002320
2321 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2322 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002323
2324 SkPaint paint;
2325 paint.setStyle(SkPaint::kStroke_Style);
2326 paint.setAntiAlias(true);
2327 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002328
2329 {
2330 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2331 REPORTER_ASSERT(reporter, result.empty());
2332 }
2333 {
2334 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002335 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002336 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002337 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2338 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002341 }
2342 {
2343 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002344 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002345 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002346 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2347 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2348 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2349 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002350 }
2351 {
2352 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002353 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002354 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002355 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2356 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2357 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2358 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002359 }
2360 {
2361 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002362 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002363 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002364 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2365 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2366 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2367 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2368 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2369 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2370 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2371 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002372 }
2373 {
2374 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002375 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002376 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002377 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002378 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002379 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002380 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002381 }
2382 {
2383 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2384 REPORTER_ASSERT(reporter, result.empty());
2385 }
2386}
2387
2388DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002389 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002390 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002391 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002392 const char* text =
2393 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2394 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2395 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002396 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002397
2398 ParagraphStyle paragraphStyle;
2399 paragraphStyle.setTextAlign(TextAlign::kLeft);
2400 paragraphStyle.setMaxLines(10);
2401 paragraphStyle.turnHintingOff();
2402 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002403 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002404 textStyle.setFontSize(50);
2405 textStyle.setColor(SK_ColorBLACK);
2406 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2407 SkFontStyle::kUpright_Slant));
2408
2409 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2410 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002411 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002412 builder.pop();
2413
2414 auto paragraph = builder.Build();
2415 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002416 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002417
2418 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2419 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002420 {
2421 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2422 REPORTER_ASSERT(reporter, result.empty());
2423 }
2424 {
2425 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002426 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002427 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002428 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2429 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2430 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2431 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002432 }
2433 {
2434 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002435 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002436 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002437 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2438 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2439 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2440 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002441 }
2442 {
2443 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002444 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002445 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002446 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2447 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2448 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2449 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002450 }
2451}
2452
Julia Lavrovac2228562019-08-08 16:51:27 -04002453// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002454DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002455 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002456 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002457 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002458 const char* text =
2459 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2460 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2461 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002462 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002463
2464 ParagraphStyle paragraphStyle;
2465 paragraphStyle.setTextAlign(TextAlign::kLeft);
2466 paragraphStyle.setMaxLines(10);
2467 paragraphStyle.turnHintingOff();
2468 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002469 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002470 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002471 textStyle.setHeight(1.6f);
2472 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002473 textStyle.setColor(SK_ColorBLACK);
2474 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2475 SkFontStyle::kUpright_Slant));
2476
2477 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2478 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002479 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002480 builder.pop();
2481
2482 auto paragraph = builder.Build();
2483 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002484 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002485
2486 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002487 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002488 {
2489 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2490 REPORTER_ASSERT(reporter, result.empty());
2491 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002492
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002493 {
2494 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002495 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002496 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002497 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2498 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2499 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2500 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002501 }
2502 {
2503 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002504 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002505 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002506 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2508 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2509 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002510 }
2511 {
2512 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002513 canvas.drawRects(SK_ColorGREEN, result);
2514 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002517 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002518 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002519 }
2520 {
2521 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002522 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002523 REPORTER_ASSERT(reporter, result.size() == 8);
2524
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002525 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002526 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2527 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2528 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2529
2530 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2531 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2532 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2534
2535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2536 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002537 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002538 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2539
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002540 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002541 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2542 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2543 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2544
2545 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2546 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2547 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2548 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2549
2550 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2551 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2552 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2553 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002554 }
2555 {
2556 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002557 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002558 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002559 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002560 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002561 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002562 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2563
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002564 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002565 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2566 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2567 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002568 }
2569 {
2570 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2571 REPORTER_ASSERT(reporter, result.empty());
2572 }
2573}
2574
Julia Lavrovac2228562019-08-08 16:51:27 -04002575// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002576DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002577 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002578 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002579 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002580 const char* text =
2581 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2582 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2583 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002584 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002585
2586 ParagraphStyle paragraphStyle;
2587 paragraphStyle.setTextAlign(TextAlign::kLeft);
2588 paragraphStyle.setMaxLines(10);
2589 paragraphStyle.turnHintingOff();
2590 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002591 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002592 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002593 textStyle.setHeight(1.6f);
2594 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002595 textStyle.setColor(SK_ColorBLACK);
2596 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2597 SkFontStyle::kUpright_Slant));
2598
2599 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2600 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002601 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002602 builder.pop();
2603
2604 auto paragraph = builder.Build();
2605 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002606 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002607
2608 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002609 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002610 {
2611 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2612 REPORTER_ASSERT(reporter, result.empty());
2613 }
2614
2615 {
2616 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002617 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002618 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002619 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2620 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2621 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2622 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002623 }
2624 {
2625 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002626 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002627 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002628 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2629 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2630 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2631 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002632 }
2633 {
2634 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002635 canvas.drawRects(SK_ColorGREEN, result);
2636 REPORTER_ASSERT(reporter, result.size() == 1);
2637 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2638 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2639 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2640 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002641 }
2642 {
2643 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002644 canvas.drawRects(SK_ColorMAGENTA, result);
2645 REPORTER_ASSERT(reporter, result.size() == 8);
2646
2647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2651
2652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2653 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2654 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2656
2657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2659 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2660 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2661
2662 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2663 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2664 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2665 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2666
2667 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2668 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2669 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2670 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2671
2672 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2673 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2674 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2675 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002676 }
2677 {
2678 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002679 canvas.drawRects(SK_ColorBLACK, result);
2680 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002681 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002682 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002683 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002684 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2685
2686 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2687 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2688 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2689 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002690 }
2691 {
2692 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2693 REPORTER_ASSERT(reporter, result.empty());
2694 }
2695}
2696
Julia Lavrovac2228562019-08-08 16:51:27 -04002697// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002698DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002699 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002700 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002701 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002702 const char* text =
2703 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2704 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2705 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002706 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002707
2708 ParagraphStyle paragraphStyle;
2709 paragraphStyle.setTextAlign(TextAlign::kLeft);
2710 paragraphStyle.setMaxLines(10);
2711 paragraphStyle.turnHintingOff();
2712 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002713 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002714 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002715 textStyle.setHeight(1.6f);
2716 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002717 textStyle.setColor(SK_ColorBLACK);
2718 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2719 SkFontStyle::kUpright_Slant));
2720
2721 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2722 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002723 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002724 builder.pop();
2725
2726 auto paragraph = builder.Build();
2727 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002728 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002729
2730 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002731 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002732 {
2733 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2734 REPORTER_ASSERT(reporter, result.empty());
2735 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002736
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002737 {
2738 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002739 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002740 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002741 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2742 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2743 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2744 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002745 }
2746 {
2747 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002748 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002749 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002750 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2751 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2752 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2753 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002754 }
2755 {
2756 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002757 canvas.drawRects(SK_ColorGREEN, result);
2758 REPORTER_ASSERT(reporter, result.size() == 1);
2759 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2760 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2761 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
2762 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002763 }
2764 {
2765 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002766 canvas.drawRects(SK_ColorMAGENTA, result);
2767 REPORTER_ASSERT(reporter, result.size() == 8);
2768
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002769 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002770 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2771 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2772 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2773
2774 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2775 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2776 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2777 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2778
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002780 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2781 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2782 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2783
2784 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2785 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2786 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2787 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2788
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002789 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002790 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2791 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2792 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2793
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002794 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002795 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2796 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2797 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002798 }
2799 {
2800 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002801 canvas.drawRects(SK_ColorBLACK, result);
2802 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002803 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002804 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002805 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002806 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2807
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002808 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002809 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2810 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2811 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002812 }
2813 {
2814 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2815 REPORTER_ASSERT(reporter, result.empty());
2816 }
2817}
2818
Julia Lavrova2813d452020-03-03 11:43:40 -05002819// This is the test I cannot accommodate
2820// Any text range gets a smallest glyph rectangle
2821DEF_TEST_DISABLED(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002822 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002823 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002824 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002825 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002826 const size_t len = strlen(text);
2827
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002828 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002829 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002830 paragraphStyle.setMaxLines(10);
2831 paragraphStyle.turnHintingOff();
2832 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2833
2834 TextStyle textStyle;
2835 textStyle.setFontFamilies({SkString("Roboto")});
2836 textStyle.setFontSize(50);
2837 textStyle.setLetterSpacing(1);
2838 textStyle.setWordSpacing(5);
2839 textStyle.setHeight(1);
2840 textStyle.setColor(SK_ColorBLACK);
2841
2842 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002843 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002844 builder.pop();
2845
2846 auto paragraph = builder.Build();
2847 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002848 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002849
2850 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002851 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2852
2853 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2854 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2855 {
2856 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2857 REPORTER_ASSERT(reporter, result.empty());
2858 }
2859 {
2860 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2861 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2862 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002863 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2864 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002865 }
2866 {
2867 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2868 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2869 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002870 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2871 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002872 }
2873 {
2874 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2875 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2876 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2877 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002878 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002879 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002880 }
2881}
2882
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002883// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002884DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002885 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002886 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002887 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002888 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2889 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2890 // Any attempt to substitute one for another leads to errors
2891 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002892 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002893 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002894
2895 ParagraphStyle paragraphStyle;
2896 paragraphStyle.setTextAlign(TextAlign::kCenter);
2897 paragraphStyle.setMaxLines(10);
2898 paragraphStyle.turnHintingOff();
2899 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2900
2901 TextStyle textStyle;
2902 textStyle.setFontFamilies({SkString("Roboto")});
2903 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002904 textStyle.setHeight(1);
2905 textStyle.setColor(SK_ColorBLACK);
2906 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2907 SkFontStyle::kUpright_Slant));
2908
2909 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002910 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002911 builder.pop();
2912
2913 auto paragraph = builder.Build();
2914 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002915 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002916
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002917 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002918 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2919 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002920 {
2921 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2922 REPORTER_ASSERT(reporter, result.empty());
2923 }
2924
2925 {
2926 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002927 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002928 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002929 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2930 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2931 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2932 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002933 }
2934
2935 {
2936 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002937 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002938 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002939 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2940 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2941 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2942 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002943 }
2944
2945 {
2946 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002947 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002948 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002949 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2950 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2951 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2952 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002953 }
2954
2955 {
2956 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002957 canvas.drawRects(SK_ColorBLACK, result);
2958 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2959 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2960 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2961 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2962 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002963 }
2964
2965 {
2966 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002967 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002968 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002969 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2970 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2971 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2972 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002973 }
2974
2975 {
2976 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2977 REPORTER_ASSERT(reporter, result.empty());
2978 }
2979}
2980
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002981// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002982DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002983 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002984 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002985 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002986 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002987 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002988
2989 ParagraphStyle paragraphStyle;
2990 paragraphStyle.setTextAlign(TextAlign::kCenter);
2991 paragraphStyle.setMaxLines(10);
2992 paragraphStyle.turnHintingOff();
2993 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2994
2995 TextStyle textStyle;
2996 textStyle.setFontFamilies({SkString("Roboto")});
2997 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002998 textStyle.setHeight(1);
2999 textStyle.setColor(SK_ColorBLACK);
3000 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3001 SkFontStyle::kUpright_Slant));
3002
3003 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003004 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003005 builder.pop();
3006
3007 auto paragraph = builder.Build();
3008 paragraph->layout(550);
3009
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003010 paragraph->paint(canvas.get(), 0, 0);
3011
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003012 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003013 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3014
3015 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3016 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003017 {
3018 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3019 REPORTER_ASSERT(reporter, result.empty());
3020 }
3021
3022 {
3023 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04003024 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003025 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003026 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
3027 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
3028 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
3029 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003030 }
3031
3032 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003033 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3034 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003035 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003036 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3037 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3038 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3039 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003040 }
3041}
3042
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003043// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003044DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003045 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003046 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003047 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3048 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003049 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003050
3051 ParagraphStyle paragraphStyle;
3052 paragraphStyle.setTextAlign(TextAlign::kCenter);
3053 paragraphStyle.setMaxLines(10);
3054 paragraphStyle.turnHintingOff();
3055 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3056
3057 TextStyle textStyle;
3058 textStyle.setFontFamilies({SkString("Roboto")});
3059 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003060 textStyle.setHeight(1);
3061 textStyle.setColor(SK_ColorBLACK);
3062 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3063 SkFontStyle::kUpright_Slant));
3064
3065 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003066 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003067 builder.pop();
3068
3069 auto paragraph = builder.Build();
3070 paragraph->layout(550);
3071
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003072 paragraph->paint(canvas.get(), 0, 0);
3073
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003074 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003075
3076 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3077
3078 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3079 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3080 SkScalar epsilon = 0.01f;
3081 {
3082 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3083 REPORTER_ASSERT(reporter, result.empty());
3084 }
3085 {
3086 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003087 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003088 REPORTER_ASSERT(reporter, result.size() == 1);
3089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3093 }
3094 {
3095 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003096 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003097 REPORTER_ASSERT(reporter, result.size() == 1);
3098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3100 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3101 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3102 }
3103 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003104 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003105 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003106 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3111 }
3112 {
3113 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003114 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003115 REPORTER_ASSERT(reporter, result.size() == 1);
3116 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3117 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003118 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003119 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3120 }
3121 {
3122 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003123 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003124 REPORTER_ASSERT(reporter, result.size() == 1);
3125 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3126 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3127 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3128 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3129 }
3130 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003131 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003132 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003133 REPORTER_ASSERT(reporter, result.size() == 1);
3134 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3135 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003136 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003137 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3138 }
3139 {
3140 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3141 REPORTER_ASSERT(reporter, result.empty());
3142 }
3143}
3144
Julia Lavrovac2228562019-08-08 16:51:27 -04003145// Checked: DIFF (line height rounding error)
3146DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003147 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003148 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003149 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3150 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003151 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003152
3153 StrutStyle strutStyle;
3154 strutStyle.setStrutEnabled(true);
3155 strutStyle.setFontFamilies({SkString("Roboto")});
3156 strutStyle.setFontSize(14.0);
3157
3158 ParagraphStyle paragraphStyle;
3159 paragraphStyle.setStrutStyle(strutStyle);
3160
3161 TextStyle textStyle;
3162 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3163 textStyle.setFontSize(20);
3164 textStyle.setColor(SK_ColorBLACK);
3165
3166 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3167 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003168 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003169 builder.pop();
3170
3171 auto paragraph = builder.Build();
3172 paragraph->layout(550);
3173 paragraph->paint(canvas.get(), 0, 0);
3174
3175 {
3176 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3177 canvas.drawRects(SK_ColorGREEN, result);
3178 REPORTER_ASSERT(reporter, result.size() == 1);
3179 }
3180
3181 {
3182 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3183 canvas.drawRects(SK_ColorRED, result);
3184 REPORTER_ASSERT(reporter, result.size() == 1);
3185 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3186 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3187 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3188 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3189 }
3190}
3191
3192// Checked: NO DIFF
3193DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003194 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003195 if (!fontCollection->fontsFound()) return;
3196 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3197 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003198 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003199
3200 StrutStyle strutStyle;
3201 strutStyle.setStrutEnabled(false);
3202
3203 ParagraphStyle paragraphStyle;
3204 paragraphStyle.setStrutStyle(strutStyle);
3205
3206 TextStyle textStyle;
3207 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3208 textStyle.setFontSize(20);
3209 textStyle.setColor(SK_ColorBLACK);
3210
3211 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3212 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003213 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003214 builder.pop();
3215
3216 auto paragraph = builder.Build();
3217 paragraph->layout(550);
3218 paragraph->paint(canvas.get(), 0, 0);
3219
3220
3221 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3222 canvas.drawRects(SK_ColorGREEN, result1);
3223 REPORTER_ASSERT(reporter, result1.size() == 1);
3224
3225 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3226 canvas.drawRects(SK_ColorRED, result2);
3227 REPORTER_ASSERT(reporter, result2.size() == 1);
3228
3229 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3230}
3231
3232// Checked: DIFF (small in numbers)
3233DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003234 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003235 if (!fontCollection->fontsFound()) return;
3236 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003237 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3238 "67890 12345 67890 12345 67890 12345";
3239 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003240 ParagraphStyle paragraphStyle;
3241 paragraphStyle.setTextAlign(TextAlign::kLeft);
3242 paragraphStyle.setMaxLines(10);
3243 paragraphStyle.turnHintingOff();
3244 TextStyle textStyle;
3245 textStyle.setFontFamilies({SkString("Roboto")});
3246 textStyle.setFontSize(52);
3247 textStyle.setLetterSpacing(1.19039f);
3248 textStyle.setWordSpacing(5);
3249 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003250 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003251 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003252
3253 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3254 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003255 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003256 builder.pop();
3257
3258 auto paragraph = builder.Build();
3259 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003260 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003261
3262 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3263 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3264 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3265 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3266 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003267 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3268 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003269
3270 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003271 boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003272 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003273
Julia Lavrovac2228562019-08-08 16:51:27 -04003274 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003275 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003276 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003277
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003278 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3279 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3280 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3281 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3282 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3283 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3284 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3285 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3286
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003287 boxes = paragraph->getRectsForRange(12, 13, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003288 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003289 boxes = paragraph->getRectsForRange(13, 14, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003290 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003291 boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003292 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003293 boxes = paragraph->getRectsForRange(19, 20, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003294 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003295 boxes = paragraph->getRectsForRange(24, 25, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003296 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003297 boxes = paragraph->getRectsForRange(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003298 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003299 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003300 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003301 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003302 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003303
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003304 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3305 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003306}
3307
Julia Lavrovac2228562019-08-08 16:51:27 -04003308// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003309DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003310 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003311 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003312 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003313 ParagraphStyle paragraph_style;
3314 paragraph_style.setMaxLines(10);
3315 paragraph_style.setTextAlign(TextAlign::kLeft);
3316 paragraph_style.turnHintingOff();
3317 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3318
3319 TextStyle text_style;
3320 text_style.setFontFamilies({SkString("Roboto")});
3321 text_style.setFontSize(50);
3322 text_style.setLetterSpacing(20);
3323 text_style.setWordSpacing(0);
3324 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003325 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003326 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003327 builder.pop();
3328
3329 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003330 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003331 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003332 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003333 builder.pop();
3334
3335 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003336 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003337 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003338 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003339 builder.pop();
3340
3341 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003342 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003343 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003344 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003345 builder.pop();
3346
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003347 const char* hSpace = "H ";
3348 const size_t len = strlen(hSpace);
3349
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003350 text_style.setLetterSpacing(0);
3351 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 text_style.setLetterSpacing(0);
3357 text_style.setWordSpacing(0);
3358 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003359 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003360 builder.pop();
3361
3362 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003363 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003364 text_style.setWordSpacing(20);
3365 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003366 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003367 builder.pop();
3368
3369 auto paragraph = builder.Build();
3370 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003371 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003372
3373 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3374 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3375 size_t index = 0;
3376 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003377 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3378 ++index;
3379 return true;
3380 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003381 REPORTER_ASSERT(reporter, index == 4);
3382 index = 0;
3383 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003384 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3385 ++index;
3386 return true;
3387 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003388 REPORTER_ASSERT(reporter, index == 4);
3389}
3390
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003391// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003392DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003393 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003394 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003395 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003396 const char* text =
3397 "A "
3398 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3399 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003400 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003401
3402 ParagraphStyle paragraph_style;
3403 paragraph_style.turnHintingOff();
3404 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3405
3406 TextStyle text_style;
3407 text_style.setFontFamilies({SkString("Roboto")});
3408 text_style.setColor(SK_ColorRED);
3409 text_style.setFontSize(31);
3410 text_style.setLetterSpacing(0);
3411 text_style.setWordSpacing(0);
3412 text_style.setColor(SK_ColorBLACK);
3413 text_style.setHeight(1);
3414 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003415 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003416 builder.pop();
3417
3418 auto paragraph = builder.Build();
3419 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003420 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003421
3422 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3423 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3424 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3425 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003426 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003427 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3428
3429 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3430 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3431 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3432}
3433
Julia Lavrovac2228562019-08-08 16:51:27 -04003434// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003435DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003436 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003437 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003438 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3439
3440 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3441 const char* text2 = " Dialog Text List lots of words to see "
3442 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003443 float scale = 3.0f;
3444 ParagraphStyle paragraph_style;
3445 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3446 TextStyle text_style;
3447 text_style.setFontFamilies({SkString("Droid Serif")});
3448 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003449 text_style.setColor(SK_ColorBLACK);
3450
3451 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003452 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003453 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003454 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003455 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003456 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003457 text_style.setFontSize(14 / scale);
3458 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003459 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003460 builder.pop();
3461
3462 auto paragraph = builder.Build();
3463 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003464 canvas.get()->scale(scale, scale);
3465 paragraph->paint(canvas.get(), 0, 0);
3466 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003467
3468 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003469
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003470 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003471 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003472 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3473 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3474 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3476 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3477 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003478}
3479
Julia Lavrovac2228562019-08-08 16:51:27 -04003480// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003481DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003482 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003483 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003484 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003485 const char* text =
3486 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3487 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003488 const size_t len = strlen(text);
3489
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003490 ParagraphStyle paragraph_style;
3491 paragraph_style.turnHintingOff();
3492 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3493
3494 TextStyle text_style;
3495 text_style.setFontFamilies({SkString("Roboto")});
3496 text_style.setColor(SK_ColorRED);
3497 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003498 text_style.setColor(SK_ColorBLACK);
3499 text_style.setHeight(1);
3500 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003501 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003502 builder.pop();
3503
3504 auto paragraph = builder.Build();
3505 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003506 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003507
3508 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3509 // Minikin does not count empty lines but SkParagraph does
3510 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3511
3512 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3513 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3514 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3515 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3516 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003517 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3518 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003519}
3520
Julia Lavrova526df262019-08-21 17:49:44 -04003521// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003522DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003523 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003524 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003525 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3526 const char* text =
3527 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3528 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3529 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3530 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003531 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003532
3533 ParagraphStyle paragraph_style;
3534 paragraph_style.turnHintingOff();
3535 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3536
3537 TextStyle text_style;
3538 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3539 text_style.setFontSize(50);
3540 text_style.setDecoration(TextDecoration::kUnderline);
3541 text_style.setColor(SK_ColorBLACK);
3542 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003543 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003544 builder.pop();
3545
3546 auto paragraph = builder.Build();
3547 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003548 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003549
Julia Lavrova3281b962019-12-02 11:32:25 -05003550 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3551
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003552 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003553
3554 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3555 for (auto& line : impl->lines()) {
3556 if (&line != impl->lines().end() - 1) {
3557 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3558 } else {
3559 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3560 }
3561 REPORTER_ASSERT(reporter, line.height() == 59);
3562 }
3563}
3564
Julia Lavrovac2228562019-08-08 16:51:27 -04003565// Checked: DIFF+
3566DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003567 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003568 if (!fontCollection->fontsFound()) return;
3569 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3570 const char* text =
3571 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3572 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3573 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3574 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3575 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3576 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003577 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003578
3579 ParagraphStyle paragraph_style;
3580 paragraph_style.turnHintingOff();
3581 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3582
3583 TextStyle text_style;
3584 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3585 text_style.setFontSize(50);
3586 text_style.setColor(SK_ColorBLACK);
3587 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003588 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003589 builder.pop();
3590
3591 auto paragraph = builder.Build();
3592 paragraph->layout(TestCanvasWidth - 300);
3593 paragraph->paint(canvas.get(), 0, 0);
3594
3595 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3596 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3597
3598 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3599 REPORTER_ASSERT(reporter, result.size() == 0);
3600
3601 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3602 REPORTER_ASSERT(reporter, result.size() == 2);
3603 canvas.drawRects(SK_ColorRED, result);
3604
3605 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrova2813d452020-03-03 11:43:40 -05003606 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04003607 canvas.drawRects(SK_ColorBLUE, result);
3608
3609 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3610 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3611 REPORTER_ASSERT(reporter, result.size() == 2);
3612 canvas.drawRects(SK_ColorGREEN, result);
3613
3614 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3615 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3616 REPORTER_ASSERT(reporter, result.size() == 2);
3617 canvas.drawRects(SK_ColorGREEN, result);
3618
3619 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3620 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3621 REPORTER_ASSERT(reporter, result.size() == 2);
3622 canvas.drawRects(SK_ColorGREEN, result);
3623}
3624
Julia Lavrova916a9042019-08-08 16:51:27 -04003625DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3626 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3627}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003628
Julia Lavrovac2228562019-08-08 16:51:27 -04003629// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003630DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003631 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003632 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003633 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003634 const char* text =
3635 "Sentence to layout at diff widths to get diff line counts. short words "
3636 "short words short words short words short words short words short words "
3637 "short words short words short words short words short words short words "
3638 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003639 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003640
3641 ParagraphStyle paragraph_style;
3642 paragraph_style.turnHintingOff();
3643 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3644
3645 TextStyle text_style;
3646 text_style.setFontFamilies({SkString("Roboto")});
3647 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003648 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003649 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003650 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003651 builder.pop();
3652
3653 auto paragraph = builder.Build();
3654 paragraph->layout(300);
3655
3656 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3657 // Some of the formatting lazily done on paint
3658 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3659 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3660 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3661
3662 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003663 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003664 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3665 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3666 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3667}
3668
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003669// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003670DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003671 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003672 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003673 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003674 const char* text =
3675 "This is a very long sentence to test if the text will properly wrap "
3676 "around and go to the next line. Sometimes, short sentence. Longer "
3677 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003678 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003679
3680 ParagraphStyle paragraph_style;
3681 paragraph_style.setMaxLines(1);
3682 paragraph_style.setEllipsis(u"\u2026");
3683 paragraph_style.turnHintingOff();
3684 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3685
3686 TextStyle text_style;
3687 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003688 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003689 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003690 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003691 builder.pop();
3692
3693 auto paragraph = builder.Build();
3694 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003695 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003696
3697 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003698
3699 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3700 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3701
3702 auto& line = impl->lines()[0];
3703 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003704 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003705}
3706
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003707// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003708DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003709 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003710 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003711 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003712 const char* text1 = "fluttser ";
3713 const char* text2 = "mdje";
3714 const char* text3 = "fluttser mdje";
3715
3716 ParagraphStyle paragraph_style;
3717 paragraph_style.turnHintingOff();
3718 paragraph_style.setTextAlign(TextAlign::kLeft);
3719 paragraph_style.setMaxLines(2);
3720 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3721
3722 TextStyle text_style;
3723 text_style.setFontFamilies({SkString("Roboto")});
3724 text_style.setColor(SK_ColorBLACK);
3725 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003726 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003727 text_style.setDecoration(TextDecoration::kUnderline);
3728 text_style.setDecorationColor(SK_ColorBLACK);
3729 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003730 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003731 builder.pop();
3732
3733 auto paragraph = builder.Build();
3734 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003735 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003736
3737 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3738
3739 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3740 text_style.setDecoration(TextDecoration::kNoDecoration);
3741 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003742 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003743 builder1.pop();
3744
3745 auto paragraph1 = builder1.Build();
3746 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003747 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003748
3749 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3750
3751 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3752 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003753
3754 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3755 .front()
3756 .rect;
3757 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3758 .front()
3759 .rect;
3760 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3761 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3762
3763 for (size_t i = 0; i < 12; ++i) {
Julia Lavrova2813d452020-03-03 11:43:40 -05003764 // Not all ranges produce a rectangle ("fl" goes into one cluster so [0:1) is empty)
3765 auto r1 = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
3766 auto r2 = paragraph1->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003767
Julia Lavrova2813d452020-03-03 11:43:40 -05003768 REPORTER_ASSERT(reporter, r1.size() == r2.size());
3769 if (!r1.empty() && !r2.empty()) {
3770 REPORTER_ASSERT(reporter, r1.front().rect.fLeft == r2.front().rect.fLeft);
3771 REPORTER_ASSERT(reporter, r1.front().rect.fRight == r2.front().rect.fRight);
3772 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003773 }
3774}
3775
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003776// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003777DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003778 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003779 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003780 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003781 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003782 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003783
3784 ParagraphStyle paragraph_style;
3785 paragraph_style.turnHintingOff();
3786 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3787
3788 TextStyle text_style;
3789 text_style.setFontFamilies({SkString("Roboto")});
3790 text_style.setColor(SK_ColorBLACK);
3791 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3792 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003793 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003794
3795 auto paragraph = builder.Build();
3796 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003797 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003798
3799 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3800
3801 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3802 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3803 size_t index = 0;
3804 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003805 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003806 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003807 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3808 ++index;
3809 return true;
3810 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003811 }
3812}
3813
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003814// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003815DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003816 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003817 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003818 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003819 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003820 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003821
3822 ParagraphStyle paragraph_style;
3823 paragraph_style.turnHintingOff();
3824 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3825
3826 TextStyle text_style;
3827 text_style.setFontFamilies({SkString("Roboto")});
3828 text_style.setColor(SK_ColorBLACK);
3829 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3830 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003831 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003832
3833 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3834 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3835 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003836 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003837 builder.pop();
3838
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003839 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003840
3841 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3842 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003843 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003844 builder.pop();
3845
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003846 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003847
3848 auto paragraph = builder.Build();
3849 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003850 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003851
3852 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3853
3854 size_t index = 0;
3855 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003856 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003857 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003858 ++index;
3859 switch (index) {
3860 case 1:
3861 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3862 break;
3863 case 2:
3864 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3865 break;
3866 case 3:
3867 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3868 break;
3869 case 4:
3870 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3871 REPORTER_ASSERT(reporter, style.equals(text_style));
3872 break;
3873 case 5:
3874 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3875 break;
3876 default:
3877 REPORTER_ASSERT(reporter, false);
3878 }
3879 return true;
3880 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003881 }
3882}
3883
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003884// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003885DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003886 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003887 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003888 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003889 const char* text =
3890 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3891 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003892 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003893
3894 ParagraphStyle paragraph_style;
3895 paragraph_style.turnHintingOff();
3896 paragraph_style.setMaxLines(14);
3897 paragraph_style.setTextAlign(TextAlign::kJustify);
3898 paragraph_style.setHeight(1.5);
3899 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3900
3901 TextStyle text_style;
3902 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3903 text_style.setColor(SK_ColorBLACK);
3904 text_style.setFontSize(55);
3905 text_style.setLetterSpacing(2);
3906 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3907 text_style.setDecorationColor(SK_ColorBLACK);
3908 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003909 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003910 builder.pop();
3911
3912 auto paragraph = builder.Build();
3913 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003914 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003915
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003916 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3917 paragraph->getMaxWidth(),
3918 paragraph->getIdeographicBaseline());
3919 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3920 paragraph->getMaxWidth(),
3921 paragraph->getAlphabeticBaseline());
3922 canvas.drawLine(SK_ColorRED, rect1, false);
3923 canvas.drawLine(SK_ColorGREEN, rect2, false);
3924
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003925 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003926 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003927 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003928 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003929}
3930
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003931// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003932DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003933 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003934 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003935 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003936
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003937 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3938 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3939 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003940
3941 ParagraphStyle paragraph_style;
3942 paragraph_style.turnHintingOff();
3943 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3944
3945 TextStyle text_style;
3946 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003947 SkString("Not a real font"),
3948 SkString("Also a fake font"),
3949 SkString("So fake it is obvious"),
3950 SkString("Next one should be a real font..."),
3951 SkString("Roboto"),
3952 SkString("another fake one in between"),
3953 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003954 });
3955 text_style.setColor(SK_ColorBLACK);
3956 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003957 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003958
3959 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003960 SkString("Not a real font"),
3961 SkString("Also a fake font"),
3962 SkString("So fake it is obvious"),
3963 SkString("Homemade Apple"),
3964 SkString("Next one should be a real font..."),
3965 SkString("Roboto"),
3966 SkString("another fake one in between"),
3967 SkString("Noto Sans CJK JP"),
3968 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003969 });
3970 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003971 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003972
3973 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003974 SkString("Not a real font"),
3975 SkString("Also a fake font"),
3976 SkString("So fake it is obvious"),
3977 SkString("Homemade Apple"),
3978 SkString("Next one should be a real font..."),
3979 SkString("Roboto"),
3980 SkString("another fake one in between"),
3981 SkString("Source Han Serif CN"),
3982 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003983 });
3984 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003985 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003986
3987 builder.pop();
3988
3989 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003990 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003991 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003992 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003993
Julia Lavrova3281b962019-12-02 11:32:25 -05003994 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
3995
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003996 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3997
3998 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3999 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
4000 // [Apple + Noto] [Apple + Han]
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004001 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004002
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004003 auto robotoAdvance = impl->runs()[0].advance().fX +
4004 impl->runs()[1].advance().fX +
4005 impl->runs()[2].advance().fX;
4006 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
4007 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
4008 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
4009 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
4010 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004011
4012 // When a different font is resolved, then the metrics are different.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004013 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
4014 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004015}
4016
Julia Lavrovac2228562019-08-08 16:51:27 -04004017// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004018DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004019 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004020 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004021 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004022 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004023 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004024 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004025
4026 ParagraphStyle paragraph_style;
4027 paragraph_style.setMaxLines(10);
4028 paragraph_style.setTextAlign(TextAlign::kLeft);
4029 paragraph_style.turnHintingOff();
4030
4031 StrutStyle strut_style;
4032 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004033 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004034 strut_style.setFontSize(50);
4035 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004036 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004037 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004038 paragraph_style.setStrutStyle(strut_style);
4039
4040 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4041
4042 TextStyle text_style;
4043 text_style.setFontFamilies({SkString("Ahem")});
4044 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004045 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004046 text_style.setColor(SK_ColorBLACK);
4047 text_style.setHeight(0.5f);
4048 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004049 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004050 builder.pop();
4051
4052 auto paragraph = builder.Build();
4053 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004054 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004055
4056 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004057 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4058
4059 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4060 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4061 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004062 {
4063 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4064 REPORTER_ASSERT(reporter, boxes.empty());
4065 }
4066 {
4067 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004068 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004069 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004070 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4071 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4072 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4073 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004074 }
4075 {
4076 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004077 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004078 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004079 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004080 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004081 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4082 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004083 }
4084 {
4085 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004086 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004087 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004088 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004092 }
4093 {
4094 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004095 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004096 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004100 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004101 }
4102 {
4103 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004104 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004105 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004110 }
4111 {
4112 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004113 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004114 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004115 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004116 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004117 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004118 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004119 }
4120}
4121
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004122// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004123DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004124 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004125 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004126 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004127 // The chinese extra height should be absorbed by the strut.
4128 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004129 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004130
4131 ParagraphStyle paragraph_style;
4132 paragraph_style.setMaxLines(10);
4133 paragraph_style.setTextAlign(TextAlign::kLeft);
4134 paragraph_style.turnHintingOff();
4135
4136 StrutStyle strut_style;
4137
4138 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004139 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004140 strut_style.setFontSize(50);
4141 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004142 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004143 paragraph_style.setStrutStyle(strut_style);
4144
4145 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4146
4147 TextStyle text_style;
4148 text_style.setFontFamilies({SkString("Ahem")});
4149 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004150 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4151 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004152 text_style.setColor(SK_ColorBLACK);
4153 text_style.setHeight(1);
4154 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004155 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004156 builder.pop();
4157
4158 auto paragraph = builder.Build();
4159 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004160 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004161
4162 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4163 // Font is not resolved and the first line does not fit
4164 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4165
4166 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4167 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4168 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004169 {
4170 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4171 REPORTER_ASSERT(reporter, boxes.empty());
4172 }
4173 {
4174 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004175 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004176 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004177 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4178 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4179 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4180 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004181 }
4182 {
4183 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004184 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004185 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004186 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004187 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004188 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4189 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004190 }
4191 {
4192 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004193 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004194 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004195 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4196 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4197 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4198 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004199 }
4200 {
4201 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004202 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004203 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004204 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004205 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004206 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4207 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004208 }
4209 {
4210 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004211 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004212 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004213 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004214 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004215 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4216 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004217 }
4218 {
4219 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004220 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004221 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004222 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004223 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004224 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4225 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004226 }
4227}
4228
Julia Lavrovac2228562019-08-08 16:51:27 -04004229// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004230DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004231 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004232 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004233 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4234
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004235 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004236 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004237 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004238
4239 ParagraphStyle paragraph_style;
4240 paragraph_style.setMaxLines(10);
4241 paragraph_style.setTextAlign(TextAlign::kLeft);
4242 paragraph_style.turnHintingOff();
4243
4244 StrutStyle strut_style;
4245 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004246 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004247 strut_style.setFontSize(50);
4248 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004249 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004250 paragraph_style.setStrutStyle(strut_style);
4251
4252 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4253
4254 TextStyle text_style;
4255 text_style.setFontFamilies({SkString("Ahem")});
4256 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004257 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4258 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004259 text_style.setColor(SK_ColorBLACK);
4260 text_style.setHeight(1);
4261 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004262 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004263 builder.pop();
4264
4265 auto paragraph = builder.Build();
4266 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004267 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004268
4269 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4270 // Font is not resolved and the first line does not fit
4271 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4272
4273 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4274 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4275 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4276 SkScalar epsilon = 0.001f;
4277 {
4278 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4279 REPORTER_ASSERT(reporter, boxes.empty());
4280 }
4281 {
4282 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004283 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004284 REPORTER_ASSERT(reporter, boxes.size() == 1);
4285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4287 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4288 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4289 }
4290 {
4291 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004292 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004293 REPORTER_ASSERT(reporter, boxes.size() == 1);
4294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004296 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4297 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4298 }
4299 {
4300 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004301 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004302 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004303 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004305 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004306 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4307 }
4308 {
4309 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004310 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004311 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004313 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004314 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004315 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4316 }
4317 {
4318 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004319 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004320 REPORTER_ASSERT(reporter, boxes.size() == 1);
4321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004323 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4324 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4325 }
4326 {
4327 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004328 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004329 REPORTER_ASSERT(reporter, boxes.size() == 1);
4330 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4333 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4334 }
4335}
4336
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004337// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004338DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004339 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004340 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004341 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004342 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004343 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004344
4345 ParagraphStyle paragraph_style;
4346 paragraph_style.setMaxLines(10);
4347 paragraph_style.setTextAlign(TextAlign::kLeft);
4348 paragraph_style.turnHintingOff();
4349
4350 StrutStyle strut_style;
4351 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004352 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004353 strut_style.setFontSize(50);
4354 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004355 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004356 strut_style.setLeading(0.1f);
4357 strut_style.setForceStrutHeight(true);
4358 paragraph_style.setStrutStyle(strut_style);
4359
4360 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4361
4362 TextStyle text_style;
4363 text_style.setFontFamilies({SkString("Ahem")});
4364 text_style.setFontSize(50);
4365 text_style.setLetterSpacing(0);
4366 text_style.setColor(SK_ColorBLACK);
4367 text_style.setHeight(1);
4368 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004369 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004370 builder.pop();
4371
4372 auto paragraph = builder.Build();
4373 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004374 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004375
4376 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4377 // Font is not resolved and the first line does not fit
4378 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4379
4380 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4381 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4382 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004383
4384 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4385 REPORTER_ASSERT(reporter, boxes1.empty());
4386
4387 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004388 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004389 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4392 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4393 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004394
4395 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004396 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004397 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4401 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004402
4403 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004404 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004405 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4409 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004410
4411 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004412 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004413 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004416 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4417 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004418
4419 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004420 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004421 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004423 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004424 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4425 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004426
4427 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004428 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004429 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004430 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004431 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004432 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4433 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004434}
4435
Julia Lavrovac2228562019-08-08 16:51:27 -04004436// Checked: NO DIFF
4437DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004438 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004439 if (!fontCollection->fontsFound()) return;
4440 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4441
4442 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004443 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004444
4445 ParagraphStyle paragraph_style;
4446 paragraph_style.setMaxLines(10);
4447 paragraph_style.setTextAlign(TextAlign::kLeft);
4448 paragraph_style.turnHintingOff();
4449
4450 StrutStyle strut_style;
4451 strut_style.setStrutEnabled(true);
4452 strut_style.setFontFamilies({SkString("Ahem")});
4453 strut_style.setFontSize(50);
4454 strut_style.setHeight(1.5f);
4455 strut_style.setLeading(0.1f);
4456 strut_style.setForceStrutHeight(false);
4457 paragraph_style.setStrutStyle(strut_style);
4458
4459 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4460
4461 TextStyle text_style;
4462 text_style.setFontFamilies({SkString("Ahem")});
4463 text_style.setFontSize(20);
4464 text_style.setColor(SK_ColorBLACK);
4465 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004466 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004467 builder.pop();
4468
4469 auto paragraph = builder.Build();
4470 paragraph->layout(550);
4471 paragraph->paint(canvas.get(), 0, 0);
4472
4473 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4474 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4475 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4476 {
4477 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4478 REPORTER_ASSERT(reporter, boxes.empty());
4479 }
4480 {
4481 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4482 canvas.drawRects(SK_ColorRED, boxes);
4483 REPORTER_ASSERT(reporter, boxes.size() == 1);
4484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4486 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4487 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4488 }
4489 {
4490 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4491 canvas.drawRects(SK_ColorRED, boxes);
4492 REPORTER_ASSERT(reporter, boxes.size() == 1);
4493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4496 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4497 }
4498}
4499
Julia Lavrovac5313e62019-12-10 12:11:17 -05004500DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4501 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4502 if (!fontCollection->fontsFound()) return;
4503 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4504
4505 const char* text = "12ab\n";
4506
4507 ParagraphStyle paragraph_style;
4508 paragraph_style.turnHintingOff();
4509 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4510
4511 TextStyle text_style;
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004512 text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
Julia Lavrovac5313e62019-12-10 12:11:17 -05004513 text_style.setFontFamilies({SkString("Roboto")});
4514 text_style.setColor(SK_ColorBLACK);
4515
4516 text_style.addFontFeature(SkString("tnum"), 1);
4517 builder.pushStyle(text_style);
4518 builder.addText(text);
4519
4520 text_style.resetFontFeatures();
4521 text_style.addFontFeature(SkString("tnum"), 0);
4522 text_style.addFontFeature(SkString("pnum"), 1);
4523 builder.pushStyle(text_style);
4524 builder.addText(text);
4525
4526 builder.pop();
4527 builder.pop();
4528
4529 auto paragraph = builder.Build();
4530 paragraph->layout(TestCanvasWidth);
4531
4532 paragraph->paint(canvas.get(), 10.0, 15.0);
4533
4534 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4535 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4536
4537 auto& tnum_line = impl->lines()[0];
4538 auto& pnum_line = impl->lines()[1];
4539
4540 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4541 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4542 // Tabular numbers should have equal widths.
4543 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4544 // Proportional numbers should have variable widths.
4545 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4546 // Alphabetic characters should be unaffected.
4547 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4548}
4549
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004550// Not in Minikin
4551DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004552 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004553 if (!fontCollection->fontsFound()) return;
4554 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004555 const size_t len = strlen(text);
4556
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004557 ParagraphStyle paragraph_style;
4558 paragraph_style.turnHintingOff();
4559 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4560
4561 TextStyle text_style;
4562 text_style.setFontFamilies(
4563 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4564 text_style.setFontSize(60);
4565 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004566 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004567 builder.pop();
4568
4569 auto paragraph = builder.Build();
4570 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004571
4572 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4573
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004574 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4575 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4576 auto first = impl->runs()[i].textRange();
4577 auto next = impl->runs()[i + 1].textRange();
4578 REPORTER_ASSERT(reporter, first.end == next.start);
4579 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004580}
4581
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004582DEF_TEST(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004583 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004584 if (!fontCollection->fontsFound()) return;
4585 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004586 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004587
4588 ParagraphStyle paragraph_style;
4589 paragraph_style.turnHintingOff();
4590 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4591
4592 TextStyle text_style;
4593 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4594 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004595 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004596 builder.pop();
4597
4598 auto paragraph = builder.Build();
4599 paragraph->layout(TestCanvasWidth);
4600
4601 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4602 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004603 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004604
4605 auto cluster = 0;
4606 SkShaperJSONWriter::VisualizeClusters(
4607 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4608 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4609 if (cluster == 0) {
4610 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4611 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4612 SkASSERT(glyph1to1.size() == 1);
4613 SkASSERT(*glyph1to1.begin() == 1611);
4614 }
4615 ++cluster;
4616 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004617 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004618}
4619
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004620DEF_TEST(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004621 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004622 if (!fontCollection->fontsFound()) return;
4623 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004624 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004625
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004626 ParagraphStyle paragraph_style;
4627 paragraph_style.turnHintingOff();
4628 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4629
4630 TextStyle text_style;
4631 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4632 text_style.setColor(SK_ColorBLACK);
4633 text_style.setFontSize(50);
4634 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004635 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004636 builder.pop();
4637
4638 auto paragraph = builder.Build();
4639 paragraph->layout(TestCanvasWidth);
4640
4641 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4642 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004643
4644 auto cluster = 0;
4645 for (auto& run : impl->runs()) {
4646 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004647 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4648 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004649 [&](int codePointCount, SkSpan<const char> utf1to1,
4650 SkSpan<const SkGlyphID> glyph1to1) {
4651 if (cluster == 0) {
4652 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4653 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4654 SkASSERT(glyph1to1.size() == 3);
4655 }
4656 ++cluster;
4657 });
4658 }
4659
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004660 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004661}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004662
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004663DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004664 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004665 cache.turnOn(true);
4666 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004667 if (!fontCollection->fontsFound()) return;
4668
4669 ParagraphStyle paragraph_style;
4670 paragraph_style.turnHintingOff();
4671
4672 TextStyle text_style;
4673 text_style.setFontFamilies({SkString("Roboto")});
4674 text_style.setColor(SK_ColorBLACK);
4675
4676 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4677 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4678 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004679 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004680 builder.pop();
4681 auto paragraph = builder.Build();
4682
4683 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4684 REPORTER_ASSERT(reporter, count == cache.count());
4685 auto found = cache.findParagraph(impl);
4686 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4687 auto added = cache.updateParagraph(impl);
4688 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4689 };
4690
4691 test("text1", 0, false);
4692 test("text1", 1, true);
4693 test("text2", 1, false);
4694 test("text2", 2, true);
4695 test("text3", 2, false);
4696}
4697
4698DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004699 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004700 cache.turnOn(true);
4701 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004702 if (!fontCollection->fontsFound()) return;
4703
4704 ParagraphStyle paragraph_style;
4705 paragraph_style.turnHintingOff();
4706
4707 TextStyle text_style;
4708 text_style.setColor(SK_ColorBLACK);
4709
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004710 const char* text = "text";
4711 const size_t len = strlen(text);
4712
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004713 auto test = [&](int count, bool expectedToBeFound) {
4714 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4715 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004716 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004717 builder.pop();
4718 auto paragraph = builder.Build();
4719 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4720
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004721 REPORTER_ASSERT(reporter, count == cache.count());
4722 auto found = cache.findParagraph(impl);
4723 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4724 auto added = cache.updateParagraph(impl);
4725 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4726 };
4727
4728 text_style.setFontFamilies({SkString("Roboto")});
4729 test(0, false);
4730 test(1, true);
4731 text_style.setFontFamilies({SkString("Homemade Apple")});
4732 test(1, false);
4733 test(2, true);
4734 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4735 test(2, false);
4736}
4737
4738DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004739 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004740 cache.turnOn(true);
4741 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004742 if (!fontCollection->fontsFound()) return;
4743
4744 ParagraphStyle paragraph_style;
4745 paragraph_style.turnHintingOff();
4746
4747 TextStyle text_style;
4748 text_style.setFontFamilies({SkString("Roboto")});
4749 text_style.setColor(SK_ColorBLACK);
4750
4751 auto test = [&](const char* text1,
4752 const char* text2,
4753 const char* font1,
4754 const char* font2,
4755 int count,
4756 bool expectedToBeFound) {
4757 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4758 text_style.setFontFamilies({SkString(font1)});
4759 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004760 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004761 builder.pop();
4762 text_style.setFontFamilies({SkString(font2)});
4763 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004764 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004765 builder.pop();
4766 auto paragraph = builder.Build();
4767 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4768
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004769 REPORTER_ASSERT(reporter, count == cache.count());
4770 auto found = cache.findParagraph(impl);
4771 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4772 auto added = cache.updateParagraph(impl);
4773 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4774 };
4775
4776 test("text", "", "Roboto", "Homemade Apple", 0, false);
4777 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4778 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4779 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4780 test("text", "", "Roboto", "Homemade Apple", 4, true);
4781}
4782
4783DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004784 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004785 cache.turnOn(true);
4786 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004787 if (!fontCollection->fontsFound()) return;
4788
4789 ParagraphStyle paragraph_style;
4790 paragraph_style.turnHintingOff();
4791
4792 TextStyle text_style;
4793 text_style.setFontFamilies({SkString("Roboto")});
4794 text_style.setColor(SK_ColorBLACK);
4795
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004796 const char* text = "text";
4797 const size_t len = strlen(text);
4798
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004799 auto test = [&](int count, bool expectedToBeFound) {
4800 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4801 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004802 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004803 builder.pop();
4804 auto paragraph = builder.Build();
4805 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4806
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004807 REPORTER_ASSERT(reporter, count == cache.count());
4808 auto found = cache.findParagraph(impl);
4809 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4810 auto added = cache.updateParagraph(impl);
4811 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4812 };
4813
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004814 test(0, false);
4815 test(1, true);
4816 text_style.setLetterSpacing(10);
4817 test(1, false);
4818 test(2, true);
4819 text_style.setWordSpacing(10);
4820 test(2, false);
4821}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004822
Julia Lavrova526df262019-08-21 17:49:44 -04004823DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004824 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004825 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004826 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4827 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004828
4829 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004830 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004831 text_style.setFontSize(16);
4832 text_style.setFontFamilies({SkString("Roboto")});
4833 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004834 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004835
4836 auto paragraph = builder.Build();
4837 paragraph->layout(TestCanvasWidth);
4838 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004839 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004840}
4841
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004842DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004843 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004844 if (!fontCollection->fontsFound()) return;
4845 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4846 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4847
4848 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4849
4850 ParagraphStyle paragraph_style;
4851 TextStyle text_style;
4852 text_style.setFontSize(16);
4853 text_style.setFontFamilies({SkString("Roboto")});
4854 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4855 builder.addText(text.c_str(), text.size());
4856
4857 auto paragraph = builder.Build();
4858 paragraph->layout(TestCanvasWidth);
4859 paragraph->paint(canvas.get(), 0, 0);
4860}
4861
Julia Lavrovaa40db422019-08-21 13:49:15 -04004862DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004863 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004864 if (!fontCollection->fontsFound()) return;
4865 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4866
4867 ParagraphStyle paragraph_style;
4868 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4869
Julia Lavrova526df262019-08-21 17:49:44 -04004870 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004871 builder.addPlaceholder(placeholder);
4872
4873 auto paragraph = builder.Build();
4874 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004875 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004876 paragraph->paint(canvas.get(), 0, 0);
4877}
4878
4879DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004880 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004881 if (!fontCollection->fontsFound()) return;
4882 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4883 TestCanvas canvas("SkParagraph_Fallbacks.png");
4884
4885 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004886 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004887
4888 const char* androidFonts[] = {
4889 "sans-serif",
4890 "sans-serif-condensed",
4891 "serif",
4892 "monospace",
4893 "serif-monospace",
4894 "casual",
4895 "cursive",
4896 "sans-serif-smallcaps",
4897 };
4898
4899 for (auto& font : androidFonts) {
4900
4901 ParagraphStyle paragraph_style;
4902 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4903
4904 TextStyle text_style;
4905 text_style.setColor(SK_ColorBLACK);
4906 text_style.setLocale(SkString("en_US"));
4907 text_style.setFontSize(20);
4908
4909 text_style.setFontFamilies({ SkString(font) });
4910 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004911 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004912
4913 builder.pop();
4914
4915 auto paragraph = builder.Build();
4916 paragraph->layout(TestCanvasWidth);
4917 paragraph->paint(canvas.get(), 0, 0);
4918 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4919 }
4920}
4921
4922DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004923 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004924 if (!fontCollection->fontsFound()) return;
4925 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004926 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004927 TestCanvas canvas("SkParagraph_Bidi1.png");
4928
4929 std::u16string abc = u"\u202Dabc";
4930 std::u16string DEF = u"\u202EDEF";
4931 std::u16string ghi = u"\u202Dghi";
4932 std::u16string JKL = u"\u202EJKL";
4933 std::u16string mno = u"\u202Dmno";
4934
4935 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4936
4937 ParagraphStyle paragraph_style;
4938 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4939
4940 TextStyle text_style;
4941 text_style.setFontFamilies({ SkString("sans-serif")});
4942 text_style.setFontSize(40);
4943
4944 text_style.setColor(SK_ColorCYAN);
4945 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4946 builder.pushStyle(text_style);
4947 builder.addText(abc);
4948
4949 text_style.setColor(SK_ColorGREEN);
4950 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4951 builder.pushStyle(text_style);
4952 builder.addText(DEF);
4953
4954 text_style.setColor(SK_ColorYELLOW);
4955 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4956 builder.pushStyle(text_style);
4957 builder.addText(ghi);
4958
4959 text_style.setColor(SK_ColorMAGENTA);
4960 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4961 builder.pushStyle(text_style);
4962 builder.addText(JKL);
4963
4964 text_style.setColor(SK_ColorBLUE);
4965 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4966 builder.pushStyle(text_style);
4967 builder.addText(mno);
4968
4969 auto paragraph = builder.Build();
4970 paragraph->layout(400);
4971 paragraph->paint(canvas.get(), 0, 0);
4972}
4973
4974DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004975 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004976 if (!fontCollection->fontsFound()) return;
4977 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004978 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004979 TestCanvas canvas("SkParagraph_Bidi2.png");
4980
4981 std::u16string abcD = u"\u202Dabc\u202ED";
4982 std::u16string EFgh = u"EF\u202Dgh";
4983 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4984
4985 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4986
4987 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004988 TextStyle text_style;
4989 text_style.setFontFamilies({ SkString("sans-serif")});
4990 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004991
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004992 {
4993 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4994 builder.pushStyle(text_style);
4995 builder.addText(abcD);
4996 builder.pushStyle(text_style);
4997 builder.addText(EFgh);
4998 builder.pushStyle(text_style);
4999 builder.addText(iJKLmno);
5000 auto paragraph = builder.Build();
5001 paragraph->layout(360);
5002 paragraph->paint(canvas.get(), 0, 0);
5003 }
5004 canvas.get()->translate(0, 400);
5005 {
5006 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5007 builder.pushStyle(text_style);
5008 builder.addText(abcDEFghiJKLmno);
5009 auto paragraph = builder.Build();
5010 paragraph->layout(360);
5011 paragraph->paint(canvas.get(), 0, 0);
5012 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04005013}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005014
5015DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005016 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005017 if (!fontCollection->fontsFound()) return;
5018 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5019 TestCanvas canvas("SkParagraph_Newline.png");
5020
5021 TextStyle text_style;
5022 text_style.setFontFamilies({SkString("Ahem")});
5023 text_style.setColor(SK_ColorBLACK);
5024 StrutStyle strut_style;
5025 strut_style.setStrutEnabled(false);
5026 ParagraphStyle paragraph_style;
5027 paragraph_style.setStrutStyle(strut_style);
5028 paragraph_style.setTextStyle(text_style);
5029 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5030 builder.addText("\n");
5031 auto paragraph = builder.Build();
5032 paragraph->layout(1000);
5033 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5034}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005035
Julia Lavrovab30d4812019-11-08 14:51:16 -05005036DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005037 TestCanvas canvas("SkParagraph_FontResolutions.png");
5038
5039 sk_sp<TestFontCollection> fontCollection =
5040 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5041 if (!fontCollection->fontsFound()) return;
5042
5043 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5044 return;
5045 }
5046 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5047 return;
5048 }
5049 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5050 return;
5051 }
5052
5053 TextStyle text_style;
5054 text_style.setFontFamilies({SkString("abc")});
5055 text_style.setFontSize(50);
5056
5057 ParagraphStyle paragraph_style;
5058 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5059
5060 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5061 text_style.setColor(SK_ColorBLUE);
5062 builder.pushStyle(text_style);
5063 builder.addText(u"a\u0300");
5064 text_style.setColor(SK_ColorMAGENTA);
5065 builder.pushStyle(text_style);
5066 builder.addText(u"à");
5067
5068 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5069
5070 text_style.setColor(SK_ColorRED);
5071 builder.pushStyle(text_style);
5072 builder.addText(u"a\u0300");
5073 text_style.setColor(SK_ColorGREEN);
5074 builder.pushStyle(text_style);
5075 builder.addText(u"à");
5076
5077 auto paragraph = builder.Build();
5078 paragraph->layout(TestCanvasWidth);
5079
5080 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5081 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5082
5083 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5084 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5085 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5086
5087 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5088 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5089
5090 paragraph->paint(canvas.get(), 100, 100);
5091}
5092
Julia Lavrovab30d4812019-11-08 14:51:16 -05005093DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005094 TestCanvas canvas("SkParagraph_FontStyle.png");
5095
5096 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5097 if (!fontCollection->fontsFound()) return;
5098
5099 TextStyle text_style;
5100 text_style.setFontFamilies({SkString("Roboto")});
5101 text_style.setColor(SK_ColorBLACK);
5102 text_style.setFontSize(20);
5103 SkFontStyle fs = SkFontStyle(
5104 SkFontStyle::Weight::kLight_Weight,
5105 SkFontStyle::Width::kNormal_Width,
5106 SkFontStyle::Slant::kUpright_Slant
5107 );
5108 text_style.setFontStyle(fs);
5109 ParagraphStyle paragraph_style;
5110 paragraph_style.setTextStyle(text_style);
5111 TextStyle boldItalic;
5112 boldItalic.setFontFamilies({SkString("Roboto")});
5113 boldItalic.setColor(SK_ColorRED);
5114 SkFontStyle bi = SkFontStyle(
5115 SkFontStyle::Weight::kBold_Weight,
5116 SkFontStyle::Width::kNormal_Width,
5117 SkFontStyle::Slant::kItalic_Slant
5118 );
5119 boldItalic.setFontStyle(bi);
5120 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5121 builder.addText("Default text\n");
5122 builder.pushStyle(boldItalic);
5123 builder.addText("Bold and Italic\n");
5124 builder.pop();
5125 builder.addText("back to normal");
5126 auto paragraph = builder.Build();
5127 paragraph->layout(250);
5128 paragraph->paint(canvas.get(), 0, 0);
5129}
5130
Julia Lavrovab30d4812019-11-08 14:51:16 -05005131DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005132 TestCanvas canvas("SkParagraph_Shaping.png");
5133
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005134 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5135 sk_sp<TestFontCollection> fontCollection =
5136 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5137 if (!fontCollection->fontsFound()) return;
5138
5139
5140 TextStyle text_style;
5141 text_style.setFontFamilies({SkString("Roboto")});
5142 text_style.setColor(SK_ColorGRAY);
5143 text_style.setFontSize(14);
5144 SkFontStyle b = SkFontStyle(
5145 SkFontStyle::Weight::kNormal_Weight,
5146 SkFontStyle::Width::kNormal_Width,
5147 SkFontStyle::Slant::kUpright_Slant
5148 );
5149 text_style.setFontStyle(b);
5150 ParagraphStyle paragraph_style;
5151 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5152 builder.pushStyle(text_style);
5153 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5154 auto paragraph = builder.Build();
5155 paragraph->layout(380);
5156 paragraph->paint(canvas.get(), 0, 0);
5157}
Julia Lavrovac028b422019-11-25 10:00:43 -05005158
5159DEF_TEST(SkParagraph_Ellipsis, reporter) {
5160 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5161 if (!fontCollection->fontsFound()) return;
5162 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5163 TestCanvas canvas("SkParagraph_Ellipsis.png");
5164
5165 const char* text = "This\n"
5166 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5167 TextStyle text_style;
5168 text_style.setFontFamilies({SkString("Ahem")});
5169 text_style.setColor(SK_ColorBLACK);
5170 text_style.setFontSize(10);
5171
5172 auto relayout = [&](size_t lines, bool ellipsis,
5173 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5174 ParagraphStyle paragraph_style;
5175 SkPaint paint;
5176 paint.setColor(bg);
5177 text_style.setForegroundColor(paint);
5178 paragraph_style.setTextStyle(text_style);
5179 paragraph_style.setMaxLines(lines);
5180 if (ellipsis) {
5181 paragraph_style.setEllipsis(u"\u2026");
5182 }
5183 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5184 builder.addText(text);
5185 auto paragraph = builder.Build();
5186 paragraph->layout(50);
5187 paragraph->paint(canvas.get(), 0, 0);
5188 canvas.get()->translate(50, paragraph->getHeight() + 10);
5189 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5190 SkPaint background;
5191 background.setColor(SK_ColorRED);
5192 background.setStyle(SkPaint::kStroke_Style);
5193 background.setAntiAlias(true);
5194 background.setStrokeWidth(1);
5195 canvas.get()->drawRect(result.front().rect, background);
5196
5197 SkASSERT(width == paragraph->getMaxWidth());
5198 SkASSERT(height == paragraph->getHeight());
5199 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5200 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5201 };
5202
5203 SkPaint paint;
5204 paint.setColor(SK_ColorLTGRAY);
5205 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5206
5207 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005208 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5209 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005210
5211 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005212 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005213 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5214
5215 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005216 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5217 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005218}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005219
5220DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5221 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5222 if (!fontCollection->fontsFound()) return;
5223 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5224
5225 std::string text;
5226 for (size_t i = 0; i < 10; i++)
5227 {
5228 SkPaint paint;
5229 paint.setAntiAlias(true);
5230 paint.setColor(SK_ColorBLACK);
5231
5232 TextStyle textStyle;
5233 textStyle.setForegroundColor(paint);
5234 textStyle.setFontFamilies({ SkString("Roboto") });
5235
5236 ParagraphStyle paragraphStyle;
5237 paragraphStyle.setTextStyle(textStyle);
5238
5239 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5240 text += "Text ";
5241 builder.addText(text.c_str());
5242
5243 auto paragraph = builder.Build();
5244 paragraph->layout(100);
5245
5246 //used to add a delay so I can monitor memory usage
5247 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5248 }
5249};
Julia Lavrovac0360582020-02-05 10:17:53 -05005250
5251DEF_TEST(SkParagraph_FormattingInfinity, reporter) {
5252 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5253 if (!fontCollection->fontsFound()) return;
5254 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5255 TestCanvas canvas("SkParagraph_FormattingInfinity.png");
5256
5257 const char* text = "Some text\nAnother line";
5258
5259 SkPaint paint;
5260 paint.setAntiAlias(true);
5261 paint.setColor(SK_ColorBLACK);
5262
5263 TextStyle textStyle;
5264 textStyle.setForegroundColor(paint);
5265 textStyle.setFontFamilies({ SkString("Roboto") });
5266 ParagraphStyle paragraphStyle;
5267 paragraphStyle.setTextStyle(textStyle);
5268
5269 auto draw = [&](const char* prefix, TextAlign textAlign) {
5270 paragraphStyle.setTextAlign(textAlign);
5271 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5272 builder.addText(text);
5273 auto paragraph = builder.Build();
5274 paragraph->layout(SK_ScalarInfinity);
5275 paragraph->paint(canvas.get(), 0, 0);
5276 canvas.get()->translate(0, 100);
5277 };
5278
5279 draw("left", TextAlign::kLeft);
5280 draw("right", TextAlign::kRight);
5281 draw("center", TextAlign::kCenter);
5282 draw("justify", TextAlign::kJustify);
5283};
5284
5285DEF_TEST(SkParagraph_Infinity, reporter) {
5286 SkASSERT(nearlyEqual(1, SK_ScalarInfinity) == false);
5287 SkASSERT(nearlyEqual(1, SK_ScalarNegativeInfinity) == false);
5288 SkASSERT(nearlyEqual(1, SK_ScalarNaN) == false);
5289
5290 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarInfinity) == true);
5291 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNegativeInfinity) == false);
5292 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNaN) == false);
5293
5294 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarInfinity) == false);
5295 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity) == true);
5296 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNaN) == false);
5297
5298 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarInfinity) == false);
5299 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNegativeInfinity) == false);
5300 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNaN) == false);
5301};