blob: a3dbe4e93dce5e3ce1f795d4dd7aede6da730db7 [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>
Ben Wagnerb985b4b2020-05-28 15:59:42 -040039#include <algorithm>
Ben Wagner4ca7a812020-05-28 13:48:18 -040040#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 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001691 const size_t len = strlen(text);
1692
1693 ParagraphStyle paragraph_style;
1694 paragraph_style.setMaxLines(14);
1695 paragraph_style.setTextAlign(TextAlign::kJustify);
1696 paragraph_style.setTextDirection(TextDirection::kRtl);
1697 paragraph_style.turnHintingOff();
1698 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1699
1700 TextStyle text_style;
1701 text_style.setFontFamilies({SkString("Ahem")});
1702 text_style.setFontSize(26);
1703 text_style.setColor(SK_ColorBLACK);
1704 builder.pushStyle(text_style);
1705 builder.addText(text, len);
1706 builder.pop();
1707
1708 auto paragraph = builder.Build();
1709 paragraph->layout(TestCanvasWidth - 100);
1710 paragraph->paint(canvas.get(), 0, 0);
1711
1712 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1713
1714 SkPaint paint;
1715 paint.setStyle(SkPaint::kStroke_Style);
1716 paint.setAntiAlias(true);
1717 paint.setStrokeWidth(1);
1718
1719 // Tests for GetRectsForRange()
1720 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1721 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1722 paint.setColor(SK_ColorRED);
1723 auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
1724 for (size_t i = 0; i < boxes.size(); ++i) {
1725 canvas.get()->drawRect(boxes[i].rect, paint);
1726 }
1727 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1728 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
1729 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
1730 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1731 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
1732
1733 paint.setColor(SK_ColorBLUE);
1734 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1735 for (size_t i = 0; i < boxes.size(); ++i) {
1736 canvas.get()->drawRect(boxes[i].rect, paint);
1737 }
1738 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
1739 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
1740 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1741 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
1742 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1743
1744 // All lines should be justified to the width of the
1745 // paragraph.
1746 for (auto& line : impl->lines()) {
1747 REPORTER_ASSERT(reporter,
1748 SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
1749 }
1750}
1751
1752DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
1753 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1754 if (!fontCollection->fontsFound()) return;
1755 TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
1756
1757 const char* text = " leading space";
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001758 const size_t len = strlen(text);
1759
1760 ParagraphStyle paragraph_style;
1761 paragraph_style.setMaxLines(14);
1762 paragraph_style.setTextAlign(TextAlign::kJustify);
1763 paragraph_style.setTextDirection(TextDirection::kRtl);
1764 paragraph_style.turnHintingOff();
1765 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1766
1767 TextStyle text_style;
1768 text_style.setFontFamilies({SkString("Ahem")});
1769 text_style.setFontSize(26);
1770 text_style.setColor(SK_ColorBLACK);
1771 builder.pushStyle(text_style);
1772 builder.addText(text, len);
1773 builder.pop();
1774
1775 auto paragraph = builder.Build();
1776 paragraph->layout(TestCanvasWidth - 100);
1777 paragraph->paint(canvas.get(), 0, 0);
1778
1779 SkPaint paint;
1780 paint.setStyle(SkPaint::kStroke_Style);
1781 paint.setAntiAlias(true);
1782 paint.setStrokeWidth(1);
1783
1784 // Tests for GetRectsForRange()
1785 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1786 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1787 paint.setColor(SK_ColorRED);
1788 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1789 for (size_t i = 0; i < boxes.size(); ++i) {
1790 canvas.get()->drawRect(boxes[i].rect, paint);
1791 }
1792 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1793}
1794
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001795DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001796 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001797 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001798 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001799 const char* text1 = "This text should be";
1800 const char* text2 = " decorated even when";
1801 const char* text3 = " wrapped around to";
1802 const char* text4 = " the next line.";
1803 const char* text5 = " Otherwise, bad things happen.";
1804
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001805 ParagraphStyle paragraph_style;
1806 paragraph_style.setMaxLines(14);
1807 paragraph_style.setTextAlign(TextAlign::kLeft);
1808 paragraph_style.turnHintingOff();
1809 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1810
1811 TextStyle text_style;
1812 text_style.setFontFamilies({SkString("Roboto")});
1813 text_style.setFontSize(26);
1814 text_style.setLetterSpacing(0);
1815 text_style.setWordSpacing(5);
1816 text_style.setColor(SK_ColorBLACK);
1817 text_style.setHeight(2);
1818 text_style.setDecoration(TextDecoration::kUnderline);
1819 text_style.setDecorationColor(SK_ColorBLACK);
1820 text_style.setDecoration((TextDecoration)(
1821 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1822 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1823 text_style.setDecorationColor(SK_ColorBLACK);
1824 text_style.setDecorationThicknessMultiplier(2.0);
1825 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001826 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001827
1828 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1829 text_style.setDecorationColor(SK_ColorBLUE);
1830 text_style.setDecorationThicknessMultiplier(1.0);
1831 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001832 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001833
1834 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1835 text_style.setDecorationColor(SK_ColorBLACK);
1836 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001837 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001838
1839 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1840 text_style.setDecorationColor(SK_ColorBLACK);
1841 text_style.setDecorationThicknessMultiplier(3.0);
1842 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001843 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001844
1845 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1846 text_style.setDecorationColor(SK_ColorRED);
1847 text_style.setDecorationThicknessMultiplier(1.0);
1848 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001849 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001850 builder.pop();
1851
1852 auto paragraph = builder.Build();
1853 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001854 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001855
1856 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001857
1858 size_t index = 0;
1859 for (auto& line : impl->lines()) {
1860 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001861 StyleType::kDecorations,
1862 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001863 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1864 TextDecoration::kOverline |
1865 TextDecoration::kLineThrough);
1866 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1867 switch (index) {
1868 case 0:
1869 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1870 TextDecorationStyle::kSolid);
1871 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1872 REPORTER_ASSERT(reporter,
1873 style.getDecorationThicknessMultiplier() == 2.0);
1874 break;
1875 case 1: // The style appears on 2 lines so it has 2 pieces
1876 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1877 TextDecorationStyle::kDouble);
1878 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1879 REPORTER_ASSERT(reporter,
1880 style.getDecorationThicknessMultiplier() == 1.0);
1881 break;
1882 case 2:
1883 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1884 TextDecorationStyle::kDotted);
1885 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1886 REPORTER_ASSERT(reporter,
1887 style.getDecorationThicknessMultiplier() == 1.0);
1888 break;
1889 case 3:
1890 case 4:
1891 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1892 TextDecorationStyle::kDashed);
1893 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1894 REPORTER_ASSERT(reporter,
1895 style.getDecorationThicknessMultiplier() == 3.0);
1896 break;
1897 case 5:
1898 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1899 TextDecorationStyle::kWavy);
1900 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1901 REPORTER_ASSERT(reporter,
1902 style.getDecorationThicknessMultiplier() == 1.0);
1903 break;
1904 default:
1905 REPORTER_ASSERT(reporter, false);
1906 break;
1907 }
1908 ++index;
1909 return true;
1910 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001911 }
1912}
1913
Julia Lavrovac2228562019-08-08 16:51:27 -04001914DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001915 SkDebugf("TODO: Add test for wavy decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001916}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001917
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001918DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001919 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001920 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001921 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001922 const char* text1 = "No italic ";
1923 const char* text2 = "Yes Italic ";
1924 const char* text3 = "No Italic again.";
1925
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001926 ParagraphStyle paragraph_style;
1927 paragraph_style.turnHintingOff();
1928 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1929
1930 TextStyle text_style;
1931 text_style.setFontFamilies({SkString("Roboto")});
1932 text_style.setFontSize(10);
1933 text_style.setColor(SK_ColorRED);
1934 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001935 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001936
1937 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1938 SkFontStyle::kItalic_Slant));
1939 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001940 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001941 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001942 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001943
1944 auto paragraph = builder.Build();
1945 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001946 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001947
1948 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001949
1950 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1951 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1952 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1953 auto& line = impl->lines()[0];
1954 size_t index = 0;
1955 line.scanStyles(
1956 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001957 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001958 switch (index) {
1959 case 0:
1960 REPORTER_ASSERT(
1961 reporter,
1962 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1963 break;
1964 case 1:
1965 REPORTER_ASSERT(reporter,
1966 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1967 break;
1968 case 2:
1969 REPORTER_ASSERT(
1970 reporter,
1971 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1972 break;
1973 default:
1974 REPORTER_ASSERT(reporter, false);
1975 break;
1976 }
1977 ++index;
1978 return true;
1979 });
1980}
1981
1982DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001983 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001984 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001985 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001986 const char* text =
1987 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1988 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1989 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1990 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1991 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001992 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001993
1994 ParagraphStyle paragraph_style;
1995 paragraph_style.setMaxLines(14);
1996 paragraph_style.setTextAlign(TextAlign::kJustify);
1997 paragraph_style.turnHintingOff();
1998 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1999
2000 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2001 TextDecoration::kLineThrough);
2002
2003 TextStyle text_style;
2004 text_style.setFontFamilies({SkString("Source Han Serif CN")});
2005 text_style.setFontSize(35);
2006 text_style.setColor(SK_ColorBLACK);
2007 text_style.setLetterSpacing(2);
2008 text_style.setHeight(1);
2009 text_style.setDecoration(decoration);
2010 text_style.setDecorationColor(SK_ColorBLACK);
2011 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2012 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002013 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002014 builder.pop();
2015
2016 auto paragraph = builder.Build();
2017 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002018 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002019
Julia Lavrova3281b962019-12-02 11:32:25 -05002020 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2021
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002022 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002023
2024 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2025 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
2026 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002027 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002028}
2029
Julia Lavrovad3a32c52020-02-03 09:43:52 -05002030// Checked: disabled for TxtLib
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002031DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002032 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002033 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002034 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002035 const char* text =
2036 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2037 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002038 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002039
2040 ParagraphStyle paragraph_style;
2041 paragraph_style.setMaxLines(14);
2042 paragraph_style.setTextAlign(TextAlign::kJustify);
2043 paragraph_style.turnHintingOff();
2044 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2045
2046 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2047 TextDecoration::kLineThrough);
2048
2049 TextStyle text_style;
2050 text_style.setFontFamilies({SkString("Katibeh")});
2051 text_style.setFontSize(35);
2052 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002053 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002054 text_style.setDecoration(decoration);
2055 text_style.setDecorationColor(SK_ColorBLACK);
2056 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2057 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002058 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002059 builder.pop();
2060
2061 auto paragraph = builder.Build();
2062 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002063 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002064
Julia Lavrova3281b962019-12-02 11:32:25 -05002065 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2066
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002067 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002068
2069 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2070 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2071 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002072 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002073}
2074
Julia Lavrovac2228562019-08-08 16:51:27 -04002075// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002076DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
2077
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002078 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002079 if (!fontCollection->fontsFound()) return;
2080 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
2081 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002082 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002083
2084 ParagraphStyle paragraph_style;
2085 paragraph_style.turnHintingOff();
2086 paragraph_style.setMaxLines(14);
2087 paragraph_style.setTextAlign(TextAlign::kRight);
2088 paragraph_style.setTextDirection(TextDirection::kRtl);
2089 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2090
2091 TextStyle text_style;
2092 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2093 text_style.setFontSize(26);
2094 text_style.setWordSpacing(5);
2095 text_style.setColor(SK_ColorBLACK);
2096 text_style.setDecoration(TextDecoration::kUnderline);
2097 text_style.setDecorationColor(SK_ColorBLACK);
2098 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002099 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002100 builder.pop();
2101
2102 auto paragraph = builder.Build();
2103 paragraph->layout(TestCanvasWidth - 100);
2104
2105 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2106 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2107
2108 paragraph->paint(canvas.get(), 0, 0);
2109
2110 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2111 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2112 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
2113 canvas.drawRects(SK_ColorRED, boxes);
2114
Julia Lavrovac2228562019-08-08 16:51:27 -04002115 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002116
Julia Lavrovac2228562019-08-08 16:51:27 -04002117 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
2118 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002119 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
2120 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002121}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002122
2123// Checked DIFF+
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002124// This test shows now 2 boxes for [36:40) range:
2125// [36:38) for arabic text and [38:39) for the last space
2126// that has default paragraph direction (LTR) and is placed at the end of the paragraph
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002127DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
2128
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002129 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002130 if (!fontCollection->fontsFound()) return;
2131 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
2132 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002133 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002134
2135 ParagraphStyle paragraph_style;
2136 paragraph_style.turnHintingOff();
2137 paragraph_style.setMaxLines(14);
2138 paragraph_style.setTextAlign(TextAlign::kLeft);
2139 paragraph_style.setTextDirection(TextDirection::kLtr);
2140 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2141
2142 TextStyle text_style;
2143 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2144 text_style.setFontSize(26);
2145 text_style.setWordSpacing(5);
2146 text_style.setColor(SK_ColorBLACK);
2147 text_style.setDecoration(TextDecoration::kUnderline);
2148 text_style.setDecorationColor(SK_ColorBLACK);
2149 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002150 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002151 builder.pop();
2152
2153 auto paragraph = builder.Build();
2154 paragraph->layout(TestCanvasWidth - 100);
2155
2156 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2157 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2158
2159 paragraph->paint(canvas.get(), 0, 0);
2160
2161 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2162 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002163 // 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 -04002164 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2165 canvas.drawRects(SK_ColorRED, boxes);
2166
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002167 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
2168 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.92f, EPSILON100)); // DIFF: 89.40625
2169 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2170 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 110.16f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002171 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002172}
2173
2174// Checked DIFF+
2175DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2176
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002177 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002178 if (!fontCollection->fontsFound()) return;
2179 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2180 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002181 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002182
2183 ParagraphStyle paragraph_style;
2184 paragraph_style.turnHintingOff();
2185 paragraph_style.setMaxLines(14);
2186 paragraph_style.setTextAlign(TextAlign::kRight);
2187 paragraph_style.setTextDirection(TextDirection::kLtr);
2188 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2189
2190 TextStyle text_style;
2191 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2192 text_style.setFontSize(26);
2193 text_style.setWordSpacing(5);
2194 text_style.setColor(SK_ColorBLACK);
2195 text_style.setDecoration(TextDecoration::kUnderline);
2196 text_style.setDecorationColor(SK_ColorBLACK);
2197 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002198 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002199 builder.pop();
2200
2201 auto paragraph = builder.Build();
2202 paragraph->layout(TestCanvasWidth - 100);
2203
2204 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2205 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2206
2207 paragraph->paint(canvas.get(), 0, 0);
2208
2209 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2210 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2211 std::vector<TextBox> boxes =
2212 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2213 canvas.drawRects(SK_ColorRED, boxes);
2214
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002215 REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF
2216 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.5f, EPSILON100)); // DIFF
2217 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2218 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 587.74f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002219 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002220}
2221
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002222DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002223 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002224 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002225 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002226 const char* text =
2227 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2228 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002229 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002230
2231 ParagraphStyle paragraphStyle;
2232 paragraphStyle.setTextAlign(TextAlign::kLeft);
2233 paragraphStyle.setMaxLines(10);
2234 paragraphStyle.turnHintingOff();
2235 TextStyle textStyle;
2236 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002237 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2238 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002239 textStyle.setFontSize(50);
2240 textStyle.setLetterSpacing(1);
2241 textStyle.setWordSpacing(5);
2242 textStyle.setHeight(1);
2243 textStyle.setColor(SK_ColorBLACK);
2244
2245 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2246 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002247 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002248 builder.pop();
2249
2250 auto paragraph = builder.Build();
2251 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002252 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002253
2254 // Tests for getGlyphPositionAtCoordinate()
2255 // NOTE: resulting values can be a few off from their respective positions in
2256 // the original text because the final trailing whitespaces are sometimes not
2257 // drawn (namely, when using "justify" alignment) and therefore are not active
2258 // glyphs.
2259 REPORTER_ASSERT(reporter,
2260 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2261 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2262 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2263 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2264 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2265 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002266 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002267 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2268 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2269 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002270 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002271 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002272 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002273 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2274 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002275 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002276 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2277 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002278 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002279 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2280 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2281 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002282 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);//
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002283 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2284}
2285
2286DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002287 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002288 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002289 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002290 const char* text =
2291 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2292 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002293 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002294
2295 ParagraphStyle paragraphStyle;
2296 paragraphStyle.setTextAlign(TextAlign::kLeft);
2297 paragraphStyle.setMaxLines(10);
2298 paragraphStyle.turnHintingOff();
2299 TextStyle textStyle;
2300 textStyle.setFontFamilies({SkString("Roboto")});
2301 textStyle.setFontSize(50);
2302 textStyle.setColor(SK_ColorBLACK);
2303 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2304 SkFontStyle::kUpright_Slant));
2305
2306 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2307 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002308 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002309 builder.pop();
2310
2311 auto paragraph = builder.Build();
2312 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002313 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002314
2315 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2316 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002317
2318 SkPaint paint;
2319 paint.setStyle(SkPaint::kStroke_Style);
2320 paint.setAntiAlias(true);
2321 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002322
2323 {
2324 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2325 REPORTER_ASSERT(reporter, result.empty());
2326 }
2327 {
2328 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002329 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002330 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2333 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2334 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002335 }
2336 {
2337 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002338 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002339 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2341 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2342 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2343 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002344 }
2345 {
2346 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002347 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002348 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002349 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2350 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2351 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2352 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002353 }
2354 {
2355 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002356 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002357 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002358 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2359 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2360 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2361 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2362 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2363 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2364 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2365 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002366 }
2367 {
2368 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002369 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002370 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002371 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002372 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002373 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002374 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002375 }
2376 {
2377 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2378 REPORTER_ASSERT(reporter, result.empty());
2379 }
2380}
2381
2382DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002383 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002384 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002385 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002386 const char* text =
2387 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2388 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2389 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002390 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002391
2392 ParagraphStyle paragraphStyle;
2393 paragraphStyle.setTextAlign(TextAlign::kLeft);
2394 paragraphStyle.setMaxLines(10);
2395 paragraphStyle.turnHintingOff();
2396 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002397 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002398 textStyle.setFontSize(50);
2399 textStyle.setColor(SK_ColorBLACK);
2400 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2401 SkFontStyle::kUpright_Slant));
2402
2403 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2404 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002405 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002406 builder.pop();
2407
2408 auto paragraph = builder.Build();
2409 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002410 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002411
2412 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2413 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002414 {
2415 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2416 REPORTER_ASSERT(reporter, result.empty());
2417 }
2418 {
2419 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002420 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002421 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2423 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2424 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2425 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002426 }
2427 {
2428 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002429 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002430 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002431 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2432 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2433 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2434 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002435 }
2436 {
2437 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002438 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002439 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002440 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2441 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2442 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2443 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002444 }
2445}
2446
Julia Lavrovac2228562019-08-08 16:51:27 -04002447// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002448DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002449 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002450 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002451 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002452 const char* text =
2453 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2454 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2455 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002456 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002457
2458 ParagraphStyle paragraphStyle;
2459 paragraphStyle.setTextAlign(TextAlign::kLeft);
2460 paragraphStyle.setMaxLines(10);
2461 paragraphStyle.turnHintingOff();
2462 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002463 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002464 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002465 textStyle.setHeight(1.6f);
2466 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002467 textStyle.setColor(SK_ColorBLACK);
2468 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2469 SkFontStyle::kUpright_Slant));
2470
2471 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2472 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002473 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002474 builder.pop();
2475
2476 auto paragraph = builder.Build();
2477 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002478 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002479
2480 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002481 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002482 {
2483 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2484 REPORTER_ASSERT(reporter, result.empty());
2485 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002486
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002487 {
2488 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002489 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002490 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002491 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2492 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002495 }
2496 {
2497 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002498 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002499 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002500 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2501 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2502 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2503 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002504 }
2505 {
2506 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002507 canvas.drawRects(SK_ColorGREEN, result);
2508 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002509 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002510 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002511 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002512 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002513 }
2514 {
2515 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002516 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002517 REPORTER_ASSERT(reporter, result.size() == 8);
2518
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002519 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002520 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2521 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2522 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2523
2524 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2525 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2526 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2527 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2528
2529 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2530 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002531 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002532 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2533
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2536 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2537 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2538
2539 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2540 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2541 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2542 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2543
2544 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2545 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2546 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2547 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002548 }
2549 {
2550 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002551 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002552 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002553 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002554 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002555 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002556 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2557
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002558 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002559 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2560 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2561 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002562 }
2563 {
2564 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2565 REPORTER_ASSERT(reporter, result.empty());
2566 }
2567}
2568
Julia Lavrovac2228562019-08-08 16:51:27 -04002569// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002570DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002571 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002572 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002573 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002574 const char* text =
2575 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2576 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2577 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002578 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002579
2580 ParagraphStyle paragraphStyle;
2581 paragraphStyle.setTextAlign(TextAlign::kLeft);
2582 paragraphStyle.setMaxLines(10);
2583 paragraphStyle.turnHintingOff();
2584 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002585 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002586 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002587 textStyle.setHeight(1.6f);
2588 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002589 textStyle.setColor(SK_ColorBLACK);
2590 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2591 SkFontStyle::kUpright_Slant));
2592
2593 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2594 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002595 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002596 builder.pop();
2597
2598 auto paragraph = builder.Build();
2599 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002600 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002601
2602 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002603 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002604 {
2605 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2606 REPORTER_ASSERT(reporter, result.empty());
2607 }
2608
2609 {
2610 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002611 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002612 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002613 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2614 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2615 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2616 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002617 }
2618 {
2619 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002620 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002621 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002622 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2623 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2624 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2625 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002626 }
2627 {
2628 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002629 canvas.drawRects(SK_ColorGREEN, result);
2630 REPORTER_ASSERT(reporter, result.size() == 1);
2631 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2632 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2633 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2634 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002635 }
2636 {
2637 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002638 canvas.drawRects(SK_ColorMAGENTA, result);
2639 REPORTER_ASSERT(reporter, result.size() == 8);
2640
2641 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2643 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2644 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2645
2646 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2650
2651 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2653 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2654 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2655
2656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2659 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2660
2661 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2662 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2663 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2664 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2665
2666 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2667 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2668 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2669 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002670 }
2671 {
2672 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002673 canvas.drawRects(SK_ColorBLACK, result);
2674 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002675 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002676 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002677 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002678 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2679
2680 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2681 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2682 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2683 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002684 }
2685 {
2686 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2687 REPORTER_ASSERT(reporter, result.empty());
2688 }
2689}
2690
Julia Lavrovac2228562019-08-08 16:51:27 -04002691// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002692DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002693 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002694 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002695 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002696 const char* text =
2697 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2698 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2699 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002700 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002701
2702 ParagraphStyle paragraphStyle;
2703 paragraphStyle.setTextAlign(TextAlign::kLeft);
2704 paragraphStyle.setMaxLines(10);
2705 paragraphStyle.turnHintingOff();
2706 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002707 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002708 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002709 textStyle.setHeight(1.6f);
2710 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002711 textStyle.setColor(SK_ColorBLACK);
2712 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2713 SkFontStyle::kUpright_Slant));
2714
2715 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2716 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002717 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002718 builder.pop();
2719
2720 auto paragraph = builder.Build();
2721 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002722 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002723
2724 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002725 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002726 {
2727 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2728 REPORTER_ASSERT(reporter, result.empty());
2729 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002730
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002731 {
2732 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002733 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002734 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002735 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2736 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2737 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2738 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002739 }
2740 {
2741 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002742 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002743 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002744 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2745 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2746 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2747 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002748 }
2749 {
2750 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002751 canvas.drawRects(SK_ColorGREEN, result);
2752 REPORTER_ASSERT(reporter, result.size() == 1);
2753 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2754 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2755 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
2756 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002757 }
2758 {
2759 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002760 canvas.drawRects(SK_ColorMAGENTA, result);
2761 REPORTER_ASSERT(reporter, result.size() == 8);
2762
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002763 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002764 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2765 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2766 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2767
2768 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2769 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2770 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2771 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2772
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002773 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002774 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2775 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2776 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2777
2778 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2780 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2781 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2782
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002783 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002784 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2785 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2786 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2787
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002788 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002789 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2790 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2791 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002792 }
2793 {
2794 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002795 canvas.drawRects(SK_ColorBLACK, result);
2796 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002797 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002798 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002799 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002800 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2801
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002802 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002803 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2804 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2805 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002806 }
2807 {
2808 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2809 REPORTER_ASSERT(reporter, result.empty());
2810 }
2811}
2812
Julia Lavrova2813d452020-03-03 11:43:40 -05002813// This is the test I cannot accommodate
2814// Any text range gets a smallest glyph rectangle
2815DEF_TEST_DISABLED(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002816 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002817 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002818 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002819 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002820 const size_t len = strlen(text);
2821
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002822 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002823 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002824 paragraphStyle.setMaxLines(10);
2825 paragraphStyle.turnHintingOff();
2826 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2827
2828 TextStyle textStyle;
2829 textStyle.setFontFamilies({SkString("Roboto")});
2830 textStyle.setFontSize(50);
2831 textStyle.setLetterSpacing(1);
2832 textStyle.setWordSpacing(5);
2833 textStyle.setHeight(1);
2834 textStyle.setColor(SK_ColorBLACK);
2835
2836 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002837 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002838 builder.pop();
2839
2840 auto paragraph = builder.Build();
2841 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002842 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002843
2844 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002845 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2846
2847 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2848 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2849 {
2850 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2851 REPORTER_ASSERT(reporter, result.empty());
2852 }
2853 {
2854 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2855 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2856 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002857 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2858 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002859 }
2860 {
2861 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2862 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2863 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002864 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2865 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002866 }
2867 {
2868 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2869 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2870 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2871 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002872 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002873 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002874 }
2875}
2876
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002877// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002878DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002879 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002880 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002881 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002882 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2883 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2884 // Any attempt to substitute one for another leads to errors
2885 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002886 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002887 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002888
2889 ParagraphStyle paragraphStyle;
2890 paragraphStyle.setTextAlign(TextAlign::kCenter);
2891 paragraphStyle.setMaxLines(10);
2892 paragraphStyle.turnHintingOff();
2893 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2894
2895 TextStyle textStyle;
2896 textStyle.setFontFamilies({SkString("Roboto")});
2897 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002898 textStyle.setHeight(1);
2899 textStyle.setColor(SK_ColorBLACK);
2900 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2901 SkFontStyle::kUpright_Slant));
2902
2903 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002904 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002905 builder.pop();
2906
2907 auto paragraph = builder.Build();
2908 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002909 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002910
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002911 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002912 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2913 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002914 {
2915 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2916 REPORTER_ASSERT(reporter, result.empty());
2917 }
2918
2919 {
2920 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002921 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002922 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002923 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2924 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2925 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2926 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002927 }
2928
2929 {
2930 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002931 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002932 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002933 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002937 }
2938
2939 {
2940 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002941 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002942 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002943 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2944 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2945 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2946 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002947 }
2948
2949 {
2950 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002951 canvas.drawRects(SK_ColorBLACK, result);
2952 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2953 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2954 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2955 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2956 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002957 }
2958
2959 {
2960 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002961 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002962 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002963 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2964 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2965 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2966 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002967 }
2968
2969 {
2970 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2971 REPORTER_ASSERT(reporter, result.empty());
2972 }
2973}
2974
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002975// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002976DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002977 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002978 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002979 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002980 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002981 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002982
2983 ParagraphStyle paragraphStyle;
2984 paragraphStyle.setTextAlign(TextAlign::kCenter);
2985 paragraphStyle.setMaxLines(10);
2986 paragraphStyle.turnHintingOff();
2987 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2988
2989 TextStyle textStyle;
2990 textStyle.setFontFamilies({SkString("Roboto")});
2991 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002992 textStyle.setHeight(1);
2993 textStyle.setColor(SK_ColorBLACK);
2994 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2995 SkFontStyle::kUpright_Slant));
2996
2997 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002998 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002999 builder.pop();
3000
3001 auto paragraph = builder.Build();
3002 paragraph->layout(550);
3003
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003004 paragraph->paint(canvas.get(), 0, 0);
3005
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003006 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003007 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3008
3009 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3010 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003011 {
3012 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3013 REPORTER_ASSERT(reporter, result.empty());
3014 }
3015
3016 {
3017 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04003018 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003019 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003020 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
3021 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
3022 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
3023 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003024 }
3025
3026 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003027 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3028 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003029 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003030 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3031 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3032 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3033 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003034 }
3035}
3036
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003037// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003038DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003039 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003040 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003041 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3042 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003043 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003044
3045 ParagraphStyle paragraphStyle;
3046 paragraphStyle.setTextAlign(TextAlign::kCenter);
3047 paragraphStyle.setMaxLines(10);
3048 paragraphStyle.turnHintingOff();
3049 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3050
3051 TextStyle textStyle;
3052 textStyle.setFontFamilies({SkString("Roboto")});
3053 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003054 textStyle.setHeight(1);
3055 textStyle.setColor(SK_ColorBLACK);
3056 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3057 SkFontStyle::kUpright_Slant));
3058
3059 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003060 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003061 builder.pop();
3062
3063 auto paragraph = builder.Build();
3064 paragraph->layout(550);
3065
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003066 paragraph->paint(canvas.get(), 0, 0);
3067
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003068 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003069
3070 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3071
3072 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3073 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3074 SkScalar epsilon = 0.01f;
3075 {
3076 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3077 REPORTER_ASSERT(reporter, result.empty());
3078 }
3079 {
3080 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003081 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003082 REPORTER_ASSERT(reporter, result.size() == 1);
3083 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3084 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3085 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3086 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3087 }
3088 {
3089 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003090 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003091 REPORTER_ASSERT(reporter, result.size() == 1);
3092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3093 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3094 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3095 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3096 }
3097 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003098 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003099 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003100 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003101 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3102 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003103 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003104 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3105 }
3106 {
3107 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003108 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003109 REPORTER_ASSERT(reporter, result.size() == 1);
3110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3111 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003112 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003113 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3114 }
3115 {
3116 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003117 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003118 REPORTER_ASSERT(reporter, result.size() == 1);
3119 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3120 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3121 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3122 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3123 }
3124 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003125 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003126 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003127 REPORTER_ASSERT(reporter, result.size() == 1);
3128 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3129 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003130 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003131 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3132 }
3133 {
3134 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3135 REPORTER_ASSERT(reporter, result.empty());
3136 }
3137}
3138
Julia Lavrovac2228562019-08-08 16:51:27 -04003139// Checked: DIFF (line height rounding error)
3140DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003141 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003142 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003143 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3144 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003145 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003146
3147 StrutStyle strutStyle;
3148 strutStyle.setStrutEnabled(true);
3149 strutStyle.setFontFamilies({SkString("Roboto")});
3150 strutStyle.setFontSize(14.0);
3151
3152 ParagraphStyle paragraphStyle;
3153 paragraphStyle.setStrutStyle(strutStyle);
3154
3155 TextStyle textStyle;
3156 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3157 textStyle.setFontSize(20);
3158 textStyle.setColor(SK_ColorBLACK);
3159
3160 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3161 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003162 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003163 builder.pop();
3164
3165 auto paragraph = builder.Build();
3166 paragraph->layout(550);
3167 paragraph->paint(canvas.get(), 0, 0);
3168
3169 {
3170 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3171 canvas.drawRects(SK_ColorGREEN, result);
3172 REPORTER_ASSERT(reporter, result.size() == 1);
3173 }
3174
3175 {
3176 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3177 canvas.drawRects(SK_ColorRED, result);
3178 REPORTER_ASSERT(reporter, result.size() == 1);
3179 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3180 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3181 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3182 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3183 }
3184}
3185
3186// Checked: NO DIFF
3187DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003188 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003189 if (!fontCollection->fontsFound()) return;
3190 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3191 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003192 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003193
3194 StrutStyle strutStyle;
3195 strutStyle.setStrutEnabled(false);
3196
3197 ParagraphStyle paragraphStyle;
3198 paragraphStyle.setStrutStyle(strutStyle);
3199
3200 TextStyle textStyle;
3201 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3202 textStyle.setFontSize(20);
3203 textStyle.setColor(SK_ColorBLACK);
3204
3205 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3206 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003207 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003208 builder.pop();
3209
3210 auto paragraph = builder.Build();
3211 paragraph->layout(550);
3212 paragraph->paint(canvas.get(), 0, 0);
3213
3214
3215 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3216 canvas.drawRects(SK_ColorGREEN, result1);
3217 REPORTER_ASSERT(reporter, result1.size() == 1);
3218
3219 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3220 canvas.drawRects(SK_ColorRED, result2);
3221 REPORTER_ASSERT(reporter, result2.size() == 1);
3222
3223 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3224}
3225
3226// Checked: DIFF (small in numbers)
3227DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003228 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003229 if (!fontCollection->fontsFound()) return;
3230 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003231 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3232 "67890 12345 67890 12345 67890 12345";
3233 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003234 ParagraphStyle paragraphStyle;
3235 paragraphStyle.setTextAlign(TextAlign::kLeft);
3236 paragraphStyle.setMaxLines(10);
3237 paragraphStyle.turnHintingOff();
3238 TextStyle textStyle;
3239 textStyle.setFontFamilies({SkString("Roboto")});
3240 textStyle.setFontSize(52);
3241 textStyle.setLetterSpacing(1.19039f);
3242 textStyle.setWordSpacing(5);
3243 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003244 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003245 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003246
3247 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3248 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003249 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003250 builder.pop();
3251
3252 auto paragraph = builder.Build();
3253 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003254 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003255
3256 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3257 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3258 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3259 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3260 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003261 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3262 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003263
3264 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003265 boxes = paragraph->getRectsForRange(6, 7, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003266 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003267
Julia Lavrovac2228562019-08-08 16:51:27 -04003268 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003269 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003270 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003271
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003272 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3273 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3274 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3275 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3276 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3277 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3278 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3279 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3280
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003281 boxes = paragraph->getRectsForRange(12, 13, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003282 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003283 boxes = paragraph->getRectsForRange(13, 14, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003284 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003285 boxes = paragraph->getRectsForRange(18, 19, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003286 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003287 boxes = paragraph->getRectsForRange(19, 20, 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(24, 25, 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(25, 26, 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(30, 31, 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(31, 32, 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
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003298 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3299 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003300}
3301
Julia Lavrovac2228562019-08-08 16:51:27 -04003302// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003303DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003304 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003305 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003306 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003307 ParagraphStyle paragraph_style;
3308 paragraph_style.setMaxLines(10);
3309 paragraph_style.setTextAlign(TextAlign::kLeft);
3310 paragraph_style.turnHintingOff();
3311 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3312
3313 TextStyle text_style;
3314 text_style.setFontFamilies({SkString("Roboto")});
3315 text_style.setFontSize(50);
3316 text_style.setLetterSpacing(20);
3317 text_style.setWordSpacing(0);
3318 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003319 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003320 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003321 builder.pop();
3322
3323 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003324 text_style.setWordSpacing(0);
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(20);
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(0);
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("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003339 builder.pop();
3340
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003341 const char* hSpace = "H ";
3342 const size_t len = strlen(hSpace);
3343
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003344 text_style.setLetterSpacing(0);
3345 text_style.setWordSpacing(20);
3346 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003347 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003348 builder.pop();
3349
3350 text_style.setLetterSpacing(0);
3351 text_style.setWordSpacing(0);
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);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003357 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003358 text_style.setWordSpacing(20);
3359 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003360 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003361 builder.pop();
3362
3363 auto paragraph = builder.Build();
3364 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003365 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003366
3367 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3368 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3369 size_t index = 0;
3370 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003371 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3372 ++index;
3373 return true;
3374 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003375 REPORTER_ASSERT(reporter, index == 4);
3376 index = 0;
3377 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003378 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3379 ++index;
3380 return true;
3381 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003382 REPORTER_ASSERT(reporter, index == 4);
3383}
3384
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003385// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003386DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003387 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003388 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003389 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003390 const char* text =
3391 "A "
3392 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3393 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003394 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003395
3396 ParagraphStyle paragraph_style;
3397 paragraph_style.turnHintingOff();
3398 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3399
3400 TextStyle text_style;
3401 text_style.setFontFamilies({SkString("Roboto")});
3402 text_style.setColor(SK_ColorRED);
3403 text_style.setFontSize(31);
3404 text_style.setLetterSpacing(0);
3405 text_style.setWordSpacing(0);
3406 text_style.setColor(SK_ColorBLACK);
3407 text_style.setHeight(1);
3408 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003409 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003410 builder.pop();
3411
3412 auto paragraph = builder.Build();
3413 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003414 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003415
3416 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3417 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3418 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3419 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003420 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003421 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3422
3423 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3424 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3425 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3426}
3427
Julia Lavrovac2228562019-08-08 16:51:27 -04003428// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003429DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003430 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003431 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003432 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3433
3434 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3435 const char* text2 = " Dialog Text List lots of words to see "
3436 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003437 float scale = 3.0f;
3438 ParagraphStyle paragraph_style;
3439 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3440 TextStyle text_style;
3441 text_style.setFontFamilies({SkString("Droid Serif")});
3442 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003443 text_style.setColor(SK_ColorBLACK);
3444
3445 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003446 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003447 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003448 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003449 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003450 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003451 text_style.setFontSize(14 / scale);
3452 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003453 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003454 builder.pop();
3455
3456 auto paragraph = builder.Build();
3457 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003458 canvas.get()->scale(scale, scale);
3459 paragraph->paint(canvas.get(), 0, 0);
3460 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003461
3462 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003463
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003464 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003465 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003466 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3467 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3468 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3469 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3470 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3471 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003472}
3473
Julia Lavrovac2228562019-08-08 16:51:27 -04003474// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003475DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003476 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003477 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003478 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003479 const char* text =
3480 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3481 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003482 const size_t len = strlen(text);
3483
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003484 ParagraphStyle paragraph_style;
3485 paragraph_style.turnHintingOff();
3486 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3487
3488 TextStyle text_style;
3489 text_style.setFontFamilies({SkString("Roboto")});
3490 text_style.setColor(SK_ColorRED);
3491 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003492 text_style.setColor(SK_ColorBLACK);
3493 text_style.setHeight(1);
3494 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003495 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003496 builder.pop();
3497
3498 auto paragraph = builder.Build();
3499 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003500 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003501
3502 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3503 // Minikin does not count empty lines but SkParagraph does
3504 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3505
3506 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3507 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3508 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3509 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3510 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003511 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3512 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003513}
3514
Julia Lavrova526df262019-08-21 17:49:44 -04003515// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003516DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003517 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003518 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003519 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3520 const char* text =
3521 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3522 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3523 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3524 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003525 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003526
3527 ParagraphStyle paragraph_style;
3528 paragraph_style.turnHintingOff();
3529 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3530
3531 TextStyle text_style;
3532 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3533 text_style.setFontSize(50);
3534 text_style.setDecoration(TextDecoration::kUnderline);
3535 text_style.setColor(SK_ColorBLACK);
3536 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003537 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003538 builder.pop();
3539
3540 auto paragraph = builder.Build();
3541 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003542 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003543
Julia Lavrova3281b962019-12-02 11:32:25 -05003544 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3545
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003546 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003547
3548 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3549 for (auto& line : impl->lines()) {
3550 if (&line != impl->lines().end() - 1) {
3551 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3552 } else {
3553 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3554 }
3555 REPORTER_ASSERT(reporter, line.height() == 59);
3556 }
3557}
3558
Julia Lavrovac2228562019-08-08 16:51:27 -04003559// Checked: DIFF+
3560DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003561 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003562 if (!fontCollection->fontsFound()) return;
3563 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3564 const char* text =
3565 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3566 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3567 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3568 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3569 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3570 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003571 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003572
3573 ParagraphStyle paragraph_style;
3574 paragraph_style.turnHintingOff();
3575 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3576
3577 TextStyle text_style;
3578 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3579 text_style.setFontSize(50);
3580 text_style.setColor(SK_ColorBLACK);
3581 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003582 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003583 builder.pop();
3584
3585 auto paragraph = builder.Build();
3586 paragraph->layout(TestCanvasWidth - 300);
3587 paragraph->paint(canvas.get(), 0, 0);
3588
3589 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3590 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3591
3592 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3593 REPORTER_ASSERT(reporter, result.size() == 0);
3594
3595 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3596 REPORTER_ASSERT(reporter, result.size() == 2);
3597 canvas.drawRects(SK_ColorRED, result);
3598
3599 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrova2813d452020-03-03 11:43:40 -05003600 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04003601 canvas.drawRects(SK_ColorBLUE, result);
3602
3603 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3604 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3605 REPORTER_ASSERT(reporter, result.size() == 2);
3606 canvas.drawRects(SK_ColorGREEN, result);
3607
3608 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3609 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3610 REPORTER_ASSERT(reporter, result.size() == 2);
3611 canvas.drawRects(SK_ColorGREEN, result);
3612
3613 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3614 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3615 REPORTER_ASSERT(reporter, result.size() == 2);
3616 canvas.drawRects(SK_ColorGREEN, result);
3617}
3618
Julia Lavrova916a9042019-08-08 16:51:27 -04003619DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3620 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3621}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003622
Julia Lavrovac2228562019-08-08 16:51:27 -04003623// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003624DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003625 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003626 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003627 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003628 const char* text =
3629 "Sentence to layout at diff widths to get diff line counts. short words "
3630 "short words short words short words short words short words short words "
3631 "short words short words short words short words short words short words "
3632 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003633 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003634
3635 ParagraphStyle paragraph_style;
3636 paragraph_style.turnHintingOff();
3637 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3638
3639 TextStyle text_style;
3640 text_style.setFontFamilies({SkString("Roboto")});
3641 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003642 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003643 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003644 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003645 builder.pop();
3646
3647 auto paragraph = builder.Build();
3648 paragraph->layout(300);
3649
3650 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3651 // Some of the formatting lazily done on paint
3652 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3653 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3654 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3655
3656 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003657 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003658 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3659 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3660 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3661}
3662
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003663// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003664DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003665 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003666 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003667 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003668 const char* text =
3669 "This is a very long sentence to test if the text will properly wrap "
3670 "around and go to the next line. Sometimes, short sentence. Longer "
3671 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003672 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003673
3674 ParagraphStyle paragraph_style;
3675 paragraph_style.setMaxLines(1);
3676 paragraph_style.setEllipsis(u"\u2026");
3677 paragraph_style.turnHintingOff();
3678 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3679
3680 TextStyle text_style;
3681 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003682 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003683 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003684 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003685 builder.pop();
3686
3687 auto paragraph = builder.Build();
3688 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003689 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003690
3691 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003692
3693 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3694 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3695
3696 auto& line = impl->lines()[0];
3697 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003698 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003699}
3700
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003701// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003702DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003703 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003704 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003705 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003706 const char* text1 = "fluttser ";
3707 const char* text2 = "mdje";
3708 const char* text3 = "fluttser mdje";
3709
3710 ParagraphStyle paragraph_style;
3711 paragraph_style.turnHintingOff();
3712 paragraph_style.setTextAlign(TextAlign::kLeft);
3713 paragraph_style.setMaxLines(2);
3714 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3715
3716 TextStyle text_style;
3717 text_style.setFontFamilies({SkString("Roboto")});
3718 text_style.setColor(SK_ColorBLACK);
3719 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003720 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003721 text_style.setDecoration(TextDecoration::kUnderline);
3722 text_style.setDecorationColor(SK_ColorBLACK);
3723 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003724 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003725 builder.pop();
3726
3727 auto paragraph = builder.Build();
3728 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003729 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003730
3731 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3732
3733 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3734 text_style.setDecoration(TextDecoration::kNoDecoration);
3735 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003736 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003737 builder1.pop();
3738
3739 auto paragraph1 = builder1.Build();
3740 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003741 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003742
3743 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3744
3745 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3746 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003747
3748 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3749 .front()
3750 .rect;
3751 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3752 .front()
3753 .rect;
3754 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3755 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3756
3757 for (size_t i = 0; i < 12; ++i) {
Julia Lavrova2813d452020-03-03 11:43:40 -05003758 // Not all ranges produce a rectangle ("fl" goes into one cluster so [0:1) is empty)
3759 auto r1 = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
3760 auto r2 = paragraph1->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003761
Julia Lavrova2813d452020-03-03 11:43:40 -05003762 REPORTER_ASSERT(reporter, r1.size() == r2.size());
3763 if (!r1.empty() && !r2.empty()) {
3764 REPORTER_ASSERT(reporter, r1.front().rect.fLeft == r2.front().rect.fLeft);
3765 REPORTER_ASSERT(reporter, r1.front().rect.fRight == r2.front().rect.fRight);
3766 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003767 }
3768}
3769
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003770// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003771DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003772 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003773 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003774 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003775 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003776 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003777
3778 ParagraphStyle paragraph_style;
3779 paragraph_style.turnHintingOff();
3780 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3781
3782 TextStyle text_style;
3783 text_style.setFontFamilies({SkString("Roboto")});
3784 text_style.setColor(SK_ColorBLACK);
3785 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3786 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003787 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003788
3789 auto paragraph = builder.Build();
3790 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003791 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003792
3793 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3794
3795 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3796 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3797 size_t index = 0;
3798 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003799 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003800 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003801 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3802 ++index;
3803 return true;
3804 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003805 }
3806}
3807
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003808// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003809DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003810 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003811 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003812 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003813 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003814 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003815
3816 ParagraphStyle paragraph_style;
3817 paragraph_style.turnHintingOff();
3818 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3819
3820 TextStyle text_style;
3821 text_style.setFontFamilies({SkString("Roboto")});
3822 text_style.setColor(SK_ColorBLACK);
3823 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3824 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003825 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003826
3827 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3828 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3829 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003830 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003831 builder.pop();
3832
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003833 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003834
3835 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3836 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003837 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003838 builder.pop();
3839
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003840 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003841
3842 auto paragraph = builder.Build();
3843 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003844 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003845
3846 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3847
3848 size_t index = 0;
3849 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003850 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003851 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003852 ++index;
3853 switch (index) {
3854 case 1:
3855 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3856 break;
3857 case 2:
3858 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3859 break;
3860 case 3:
3861 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3862 break;
3863 case 4:
3864 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3865 REPORTER_ASSERT(reporter, style.equals(text_style));
3866 break;
3867 case 5:
3868 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3869 break;
3870 default:
3871 REPORTER_ASSERT(reporter, false);
3872 }
3873 return true;
3874 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003875 }
3876}
3877
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003878// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003879DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003880 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003881 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003882 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003883 const char* text =
3884 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3885 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003886 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003887
3888 ParagraphStyle paragraph_style;
3889 paragraph_style.turnHintingOff();
3890 paragraph_style.setMaxLines(14);
3891 paragraph_style.setTextAlign(TextAlign::kJustify);
3892 paragraph_style.setHeight(1.5);
3893 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3894
3895 TextStyle text_style;
3896 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3897 text_style.setColor(SK_ColorBLACK);
3898 text_style.setFontSize(55);
3899 text_style.setLetterSpacing(2);
3900 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3901 text_style.setDecorationColor(SK_ColorBLACK);
3902 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003903 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003904 builder.pop();
3905
3906 auto paragraph = builder.Build();
3907 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003908 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003909
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003910 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3911 paragraph->getMaxWidth(),
3912 paragraph->getIdeographicBaseline());
3913 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3914 paragraph->getMaxWidth(),
3915 paragraph->getAlphabeticBaseline());
3916 canvas.drawLine(SK_ColorRED, rect1, false);
3917 canvas.drawLine(SK_ColorGREEN, rect2, false);
3918
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003919 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003920 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003921 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003922 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003923}
3924
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003925// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003926DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003927 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003928 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003929 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003930
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003931 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3932 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3933 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003934
3935 ParagraphStyle paragraph_style;
3936 paragraph_style.turnHintingOff();
3937 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3938
3939 TextStyle text_style;
3940 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003941 SkString("Not a real font"),
3942 SkString("Also a fake font"),
3943 SkString("So fake it is obvious"),
3944 SkString("Next one should be a real font..."),
3945 SkString("Roboto"),
3946 SkString("another fake one in between"),
3947 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003948 });
3949 text_style.setColor(SK_ColorBLACK);
3950 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003951 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003952
3953 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003954 SkString("Not a real font"),
3955 SkString("Also a fake font"),
3956 SkString("So fake it is obvious"),
3957 SkString("Homemade Apple"),
3958 SkString("Next one should be a real font..."),
3959 SkString("Roboto"),
3960 SkString("another fake one in between"),
3961 SkString("Noto Sans CJK JP"),
3962 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003963 });
3964 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003965 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003966
3967 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003968 SkString("Not a real font"),
3969 SkString("Also a fake font"),
3970 SkString("So fake it is obvious"),
3971 SkString("Homemade Apple"),
3972 SkString("Next one should be a real font..."),
3973 SkString("Roboto"),
3974 SkString("another fake one in between"),
3975 SkString("Source Han Serif CN"),
3976 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003977 });
3978 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003979 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003980
3981 builder.pop();
3982
3983 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003984 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003985 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003986 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003987
Julia Lavrova3281b962019-12-02 11:32:25 -05003988 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
3989
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003990 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3991
3992 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3993 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3994 // [Apple + Noto] [Apple + Han]
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003995 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003996
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003997 auto robotoAdvance = impl->runs()[0].advance().fX +
3998 impl->runs()[1].advance().fX +
3999 impl->runs()[2].advance().fX;
4000 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
4001 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
4002 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
4003 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
4004 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004005
4006 // When a different font is resolved, then the metrics are different.
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004007 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
4008 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004009}
4010
Julia Lavrovac2228562019-08-08 16:51:27 -04004011// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004012DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004013 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004014 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004015 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004016 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004017 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004018 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004019
4020 ParagraphStyle paragraph_style;
4021 paragraph_style.setMaxLines(10);
4022 paragraph_style.setTextAlign(TextAlign::kLeft);
4023 paragraph_style.turnHintingOff();
4024
4025 StrutStyle strut_style;
4026 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004027 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004028 strut_style.setFontSize(50);
4029 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004030 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004031 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004032 paragraph_style.setStrutStyle(strut_style);
4033
4034 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4035
4036 TextStyle text_style;
4037 text_style.setFontFamilies({SkString("Ahem")});
4038 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004039 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004040 text_style.setColor(SK_ColorBLACK);
4041 text_style.setHeight(0.5f);
4042 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004043 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004044 builder.pop();
4045
4046 auto paragraph = builder.Build();
4047 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004048 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004049
4050 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004051 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4052
4053 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4054 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4055 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004056 {
4057 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4058 REPORTER_ASSERT(reporter, boxes.empty());
4059 }
4060 {
4061 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004062 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004063 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004064 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4065 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4066 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4067 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004068 }
4069 {
4070 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004071 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004072 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004073 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004074 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004075 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4076 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004077 }
4078 {
4079 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004080 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004081 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004082 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4083 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004084 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004085 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004086 }
4087 {
4088 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004089 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004090 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004091 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004092 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004093 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004094 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004095 }
4096 {
4097 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004098 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004099 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004100 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004101 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004102 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4103 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004104 }
4105 {
4106 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004107 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004108 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004111 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004112 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004113 }
4114}
4115
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004116// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004117DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004118 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004119 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004120 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004121 // The chinese extra height should be absorbed by the strut.
4122 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004123 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004124
4125 ParagraphStyle paragraph_style;
4126 paragraph_style.setMaxLines(10);
4127 paragraph_style.setTextAlign(TextAlign::kLeft);
4128 paragraph_style.turnHintingOff();
4129
4130 StrutStyle strut_style;
4131
4132 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004133 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004134 strut_style.setFontSize(50);
4135 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004136 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004137 paragraph_style.setStrutStyle(strut_style);
4138
4139 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4140
4141 TextStyle text_style;
4142 text_style.setFontFamilies({SkString("Ahem")});
4143 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004144 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4145 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004146 text_style.setColor(SK_ColorBLACK);
4147 text_style.setHeight(1);
4148 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004149 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004150 builder.pop();
4151
4152 auto paragraph = builder.Build();
4153 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004154 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004155
4156 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4157 // Font is not resolved and the first line does not fit
4158 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4159
4160 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4161 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4162 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004163 {
4164 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4165 REPORTER_ASSERT(reporter, boxes.empty());
4166 }
4167 {
4168 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004169 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004170 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004171 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4172 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4173 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4174 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004175 }
4176 {
4177 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004178 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004179 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004180 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004181 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004182 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4183 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004184 }
4185 {
4186 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004187 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004188 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004189 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4190 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4191 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4192 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004193 }
4194 {
4195 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004196 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004197 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004198 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004199 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004200 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4201 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004202 }
4203 {
4204 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004205 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004206 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004207 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004208 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004209 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4210 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004211 }
4212 {
4213 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004214 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004215 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004216 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004217 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004218 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4219 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004220 }
4221}
4222
Julia Lavrovac2228562019-08-08 16:51:27 -04004223// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004224DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004225 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004226 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004227 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4228
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004229 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004230 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004231 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004232
4233 ParagraphStyle paragraph_style;
4234 paragraph_style.setMaxLines(10);
4235 paragraph_style.setTextAlign(TextAlign::kLeft);
4236 paragraph_style.turnHintingOff();
4237
4238 StrutStyle strut_style;
4239 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004240 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004241 strut_style.setFontSize(50);
4242 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004243 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004244 paragraph_style.setStrutStyle(strut_style);
4245
4246 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4247
4248 TextStyle text_style;
4249 text_style.setFontFamilies({SkString("Ahem")});
4250 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004251 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4252 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004253 text_style.setColor(SK_ColorBLACK);
4254 text_style.setHeight(1);
4255 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004256 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004257 builder.pop();
4258
4259 auto paragraph = builder.Build();
4260 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004261 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004262
4263 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4264 // Font is not resolved and the first line does not fit
4265 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4266
4267 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4268 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4269 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4270 SkScalar epsilon = 0.001f;
4271 {
4272 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4273 REPORTER_ASSERT(reporter, boxes.empty());
4274 }
4275 {
4276 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004277 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004278 REPORTER_ASSERT(reporter, boxes.size() == 1);
4279 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4280 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4281 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4282 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4283 }
4284 {
4285 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004286 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004287 REPORTER_ASSERT(reporter, boxes.size() == 1);
4288 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004289 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004290 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4291 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4292 }
4293 {
4294 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004295 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004296 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004297 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4298 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004299 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004300 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4301 }
4302 {
4303 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004304 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004305 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004306 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004307 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004308 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004309 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4310 }
4311 {
4312 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004313 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004314 REPORTER_ASSERT(reporter, boxes.size() == 1);
4315 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004316 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004317 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4318 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4319 }
4320 {
4321 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004322 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004323 REPORTER_ASSERT(reporter, boxes.size() == 1);
4324 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004325 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004326 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4327 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4328 }
4329}
4330
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004331// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004332DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004333 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004334 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004335 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004336 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004337 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004338
4339 ParagraphStyle paragraph_style;
4340 paragraph_style.setMaxLines(10);
4341 paragraph_style.setTextAlign(TextAlign::kLeft);
4342 paragraph_style.turnHintingOff();
4343
4344 StrutStyle strut_style;
4345 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004346 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004347 strut_style.setFontSize(50);
4348 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004349 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004350 strut_style.setLeading(0.1f);
4351 strut_style.setForceStrutHeight(true);
4352 paragraph_style.setStrutStyle(strut_style);
4353
4354 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4355
4356 TextStyle text_style;
4357 text_style.setFontFamilies({SkString("Ahem")});
4358 text_style.setFontSize(50);
4359 text_style.setLetterSpacing(0);
4360 text_style.setColor(SK_ColorBLACK);
4361 text_style.setHeight(1);
4362 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004363 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004364 builder.pop();
4365
4366 auto paragraph = builder.Build();
4367 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004368 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004369
4370 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4371 // Font is not resolved and the first line does not fit
4372 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4373
4374 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4375 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4376 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004377
4378 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4379 REPORTER_ASSERT(reporter, boxes1.empty());
4380
4381 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004382 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004383 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004384 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4385 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4386 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4387 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004388
4389 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004390 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004391 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004392 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004393 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004394 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4395 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004396
4397 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004398 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004399 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4401 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4402 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4403 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004404
4405 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004406 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004407 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004409 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004410 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4411 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004412
4413 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004414 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004415 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004416 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004417 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004418 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4419 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004420
4421 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004422 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004423 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004424 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004425 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004426 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4427 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004428}
4429
Julia Lavrovac2228562019-08-08 16:51:27 -04004430// Checked: NO DIFF
4431DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004432 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004433 if (!fontCollection->fontsFound()) return;
4434 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4435
4436 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004437 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004438
4439 ParagraphStyle paragraph_style;
4440 paragraph_style.setMaxLines(10);
4441 paragraph_style.setTextAlign(TextAlign::kLeft);
4442 paragraph_style.turnHintingOff();
4443
4444 StrutStyle strut_style;
4445 strut_style.setStrutEnabled(true);
4446 strut_style.setFontFamilies({SkString("Ahem")});
4447 strut_style.setFontSize(50);
4448 strut_style.setHeight(1.5f);
4449 strut_style.setLeading(0.1f);
4450 strut_style.setForceStrutHeight(false);
4451 paragraph_style.setStrutStyle(strut_style);
4452
4453 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4454
4455 TextStyle text_style;
4456 text_style.setFontFamilies({SkString("Ahem")});
4457 text_style.setFontSize(20);
4458 text_style.setColor(SK_ColorBLACK);
4459 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004460 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004461 builder.pop();
4462
4463 auto paragraph = builder.Build();
4464 paragraph->layout(550);
4465 paragraph->paint(canvas.get(), 0, 0);
4466
4467 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4468 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4469 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4470 {
4471 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4472 REPORTER_ASSERT(reporter, boxes.empty());
4473 }
4474 {
4475 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4476 canvas.drawRects(SK_ColorRED, boxes);
4477 REPORTER_ASSERT(reporter, boxes.size() == 1);
4478 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4479 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4480 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4481 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4482 }
4483 {
4484 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4485 canvas.drawRects(SK_ColorRED, boxes);
4486 REPORTER_ASSERT(reporter, boxes.size() == 1);
4487 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4488 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4489 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4490 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4491 }
4492}
4493
Julia Lavrovac5313e62019-12-10 12:11:17 -05004494DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4495 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4496 if (!fontCollection->fontsFound()) return;
4497 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4498
4499 const char* text = "12ab\n";
4500
4501 ParagraphStyle paragraph_style;
4502 paragraph_style.turnHintingOff();
4503 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4504
4505 TextStyle text_style;
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004506 text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
Julia Lavrovac5313e62019-12-10 12:11:17 -05004507 text_style.setFontFamilies({SkString("Roboto")});
4508 text_style.setColor(SK_ColorBLACK);
4509
4510 text_style.addFontFeature(SkString("tnum"), 1);
4511 builder.pushStyle(text_style);
4512 builder.addText(text);
4513
4514 text_style.resetFontFeatures();
4515 text_style.addFontFeature(SkString("tnum"), 0);
4516 text_style.addFontFeature(SkString("pnum"), 1);
4517 builder.pushStyle(text_style);
4518 builder.addText(text);
4519
4520 builder.pop();
4521 builder.pop();
4522
4523 auto paragraph = builder.Build();
4524 paragraph->layout(TestCanvasWidth);
4525
4526 paragraph->paint(canvas.get(), 10.0, 15.0);
4527
4528 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4529 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4530
4531 auto& tnum_line = impl->lines()[0];
4532 auto& pnum_line = impl->lines()[1];
4533
4534 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4535 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4536 // Tabular numbers should have equal widths.
4537 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4538 // Proportional numbers should have variable widths.
4539 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4540 // Alphabetic characters should be unaffected.
4541 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4542}
4543
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004544// Not in Minikin
4545DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004546 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004547 if (!fontCollection->fontsFound()) return;
4548 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004549 const size_t len = strlen(text);
4550
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004551 ParagraphStyle paragraph_style;
4552 paragraph_style.turnHintingOff();
4553 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4554
4555 TextStyle text_style;
4556 text_style.setFontFamilies(
4557 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4558 text_style.setFontSize(60);
4559 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004560 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004561 builder.pop();
4562
4563 auto paragraph = builder.Build();
4564 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004565
4566 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4567
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004568 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4569 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4570 auto first = impl->runs()[i].textRange();
4571 auto next = impl->runs()[i + 1].textRange();
4572 REPORTER_ASSERT(reporter, first.end == next.start);
4573 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004574}
4575
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004576DEF_TEST(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004577 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004578 if (!fontCollection->fontsFound()) return;
4579 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004580 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004581
4582 ParagraphStyle paragraph_style;
4583 paragraph_style.turnHintingOff();
4584 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4585
4586 TextStyle text_style;
4587 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4588 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004589 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004590 builder.pop();
4591
4592 auto paragraph = builder.Build();
4593 paragraph->layout(TestCanvasWidth);
4594
4595 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4596 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004597 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004598
4599 auto cluster = 0;
4600 SkShaperJSONWriter::VisualizeClusters(
4601 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4602 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4603 if (cluster == 0) {
4604 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4605 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4606 SkASSERT(glyph1to1.size() == 1);
4607 SkASSERT(*glyph1to1.begin() == 1611);
4608 }
4609 ++cluster;
4610 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004611 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004612}
4613
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004614DEF_TEST(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004615 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004616 if (!fontCollection->fontsFound()) return;
4617 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004618 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004619
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004620 ParagraphStyle paragraph_style;
4621 paragraph_style.turnHintingOff();
4622 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4623
4624 TextStyle text_style;
4625 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4626 text_style.setColor(SK_ColorBLACK);
4627 text_style.setFontSize(50);
4628 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004629 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004630 builder.pop();
4631
4632 auto paragraph = builder.Build();
4633 paragraph->layout(TestCanvasWidth);
4634
4635 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4636 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004637
4638 auto cluster = 0;
4639 for (auto& run : impl->runs()) {
4640 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004641 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4642 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004643 [&](int codePointCount, SkSpan<const char> utf1to1,
4644 SkSpan<const SkGlyphID> glyph1to1) {
4645 if (cluster == 0) {
4646 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4647 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4648 SkASSERT(glyph1to1.size() == 3);
4649 }
4650 ++cluster;
4651 });
4652 }
4653
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004654 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004655}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004656
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004657DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004658 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004659 cache.turnOn(true);
4660 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004661 if (!fontCollection->fontsFound()) return;
4662
4663 ParagraphStyle paragraph_style;
4664 paragraph_style.turnHintingOff();
4665
4666 TextStyle text_style;
4667 text_style.setFontFamilies({SkString("Roboto")});
4668 text_style.setColor(SK_ColorBLACK);
4669
4670 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4671 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4672 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004673 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004674 builder.pop();
4675 auto paragraph = builder.Build();
4676
4677 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4678 REPORTER_ASSERT(reporter, count == cache.count());
4679 auto found = cache.findParagraph(impl);
4680 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4681 auto added = cache.updateParagraph(impl);
4682 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4683 };
4684
4685 test("text1", 0, false);
4686 test("text1", 1, true);
4687 test("text2", 1, false);
4688 test("text2", 2, true);
4689 test("text3", 2, false);
4690}
4691
4692DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004693 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004694 cache.turnOn(true);
4695 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004696 if (!fontCollection->fontsFound()) return;
4697
4698 ParagraphStyle paragraph_style;
4699 paragraph_style.turnHintingOff();
4700
4701 TextStyle text_style;
4702 text_style.setColor(SK_ColorBLACK);
4703
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004704 const char* text = "text";
4705 const size_t len = strlen(text);
4706
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004707 auto test = [&](int count, bool expectedToBeFound) {
4708 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4709 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004710 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004711 builder.pop();
4712 auto paragraph = builder.Build();
4713 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4714
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004715 REPORTER_ASSERT(reporter, count == cache.count());
4716 auto found = cache.findParagraph(impl);
4717 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4718 auto added = cache.updateParagraph(impl);
4719 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4720 };
4721
4722 text_style.setFontFamilies({SkString("Roboto")});
4723 test(0, false);
4724 test(1, true);
4725 text_style.setFontFamilies({SkString("Homemade Apple")});
4726 test(1, false);
4727 test(2, true);
4728 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4729 test(2, false);
4730}
4731
4732DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004733 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004734 cache.turnOn(true);
4735 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004736 if (!fontCollection->fontsFound()) return;
4737
4738 ParagraphStyle paragraph_style;
4739 paragraph_style.turnHintingOff();
4740
4741 TextStyle text_style;
4742 text_style.setFontFamilies({SkString("Roboto")});
4743 text_style.setColor(SK_ColorBLACK);
4744
4745 auto test = [&](const char* text1,
4746 const char* text2,
4747 const char* font1,
4748 const char* font2,
4749 int count,
4750 bool expectedToBeFound) {
4751 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4752 text_style.setFontFamilies({SkString(font1)});
4753 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004754 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004755 builder.pop();
4756 text_style.setFontFamilies({SkString(font2)});
4757 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004758 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004759 builder.pop();
4760 auto paragraph = builder.Build();
4761 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4762
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004763 REPORTER_ASSERT(reporter, count == cache.count());
4764 auto found = cache.findParagraph(impl);
4765 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4766 auto added = cache.updateParagraph(impl);
4767 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4768 };
4769
4770 test("text", "", "Roboto", "Homemade Apple", 0, false);
4771 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4772 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4773 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4774 test("text", "", "Roboto", "Homemade Apple", 4, true);
4775}
4776
4777DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004778 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004779 cache.turnOn(true);
4780 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004781 if (!fontCollection->fontsFound()) return;
4782
4783 ParagraphStyle paragraph_style;
4784 paragraph_style.turnHintingOff();
4785
4786 TextStyle text_style;
4787 text_style.setFontFamilies({SkString("Roboto")});
4788 text_style.setColor(SK_ColorBLACK);
4789
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004790 const char* text = "text";
4791 const size_t len = strlen(text);
4792
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004793 auto test = [&](int count, bool expectedToBeFound) {
4794 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4795 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004796 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004797 builder.pop();
4798 auto paragraph = builder.Build();
4799 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4800
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004801 REPORTER_ASSERT(reporter, count == cache.count());
4802 auto found = cache.findParagraph(impl);
4803 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4804 auto added = cache.updateParagraph(impl);
4805 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4806 };
4807
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004808 test(0, false);
4809 test(1, true);
4810 text_style.setLetterSpacing(10);
4811 test(1, false);
4812 test(2, true);
4813 text_style.setWordSpacing(10);
4814 test(2, false);
4815}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004816
Julia Lavrova526df262019-08-21 17:49:44 -04004817DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004818 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004819 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004820 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4821 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004822
4823 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004824 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004825 text_style.setFontSize(16);
4826 text_style.setFontFamilies({SkString("Roboto")});
4827 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004828 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004829
4830 auto paragraph = builder.Build();
4831 paragraph->layout(TestCanvasWidth);
4832 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004833 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004834}
4835
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004836DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004837 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004838 if (!fontCollection->fontsFound()) return;
4839 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4840 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4841
4842 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4843
4844 ParagraphStyle paragraph_style;
4845 TextStyle text_style;
4846 text_style.setFontSize(16);
4847 text_style.setFontFamilies({SkString("Roboto")});
4848 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4849 builder.addText(text.c_str(), text.size());
4850
4851 auto paragraph = builder.Build();
4852 paragraph->layout(TestCanvasWidth);
4853 paragraph->paint(canvas.get(), 0, 0);
4854}
4855
Julia Lavrovaa40db422019-08-21 13:49:15 -04004856DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004857 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004858 if (!fontCollection->fontsFound()) return;
4859 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4860
4861 ParagraphStyle paragraph_style;
4862 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4863
Julia Lavrova526df262019-08-21 17:49:44 -04004864 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004865 builder.addPlaceholder(placeholder);
4866
4867 auto paragraph = builder.Build();
4868 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004869 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004870 paragraph->paint(canvas.get(), 0, 0);
4871}
4872
4873DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004874 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004875 if (!fontCollection->fontsFound()) return;
4876 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4877 TestCanvas canvas("SkParagraph_Fallbacks.png");
4878
4879 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004880 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004881
4882 const char* androidFonts[] = {
4883 "sans-serif",
4884 "sans-serif-condensed",
4885 "serif",
4886 "monospace",
4887 "serif-monospace",
4888 "casual",
4889 "cursive",
4890 "sans-serif-smallcaps",
4891 };
4892
4893 for (auto& font : androidFonts) {
4894
4895 ParagraphStyle paragraph_style;
4896 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4897
4898 TextStyle text_style;
4899 text_style.setColor(SK_ColorBLACK);
4900 text_style.setLocale(SkString("en_US"));
4901 text_style.setFontSize(20);
4902
4903 text_style.setFontFamilies({ SkString(font) });
4904 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004905 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004906
4907 builder.pop();
4908
4909 auto paragraph = builder.Build();
4910 paragraph->layout(TestCanvasWidth);
4911 paragraph->paint(canvas.get(), 0, 0);
4912 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4913 }
4914}
4915
4916DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004917 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004918 if (!fontCollection->fontsFound()) return;
4919 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004920 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004921 TestCanvas canvas("SkParagraph_Bidi1.png");
4922
4923 std::u16string abc = u"\u202Dabc";
4924 std::u16string DEF = u"\u202EDEF";
4925 std::u16string ghi = u"\u202Dghi";
4926 std::u16string JKL = u"\u202EJKL";
4927 std::u16string mno = u"\u202Dmno";
4928
4929 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4930
4931 ParagraphStyle paragraph_style;
4932 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4933
4934 TextStyle text_style;
4935 text_style.setFontFamilies({ SkString("sans-serif")});
4936 text_style.setFontSize(40);
4937
4938 text_style.setColor(SK_ColorCYAN);
4939 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4940 builder.pushStyle(text_style);
4941 builder.addText(abc);
4942
4943 text_style.setColor(SK_ColorGREEN);
4944 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4945 builder.pushStyle(text_style);
4946 builder.addText(DEF);
4947
4948 text_style.setColor(SK_ColorYELLOW);
4949 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4950 builder.pushStyle(text_style);
4951 builder.addText(ghi);
4952
4953 text_style.setColor(SK_ColorMAGENTA);
4954 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4955 builder.pushStyle(text_style);
4956 builder.addText(JKL);
4957
4958 text_style.setColor(SK_ColorBLUE);
4959 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4960 builder.pushStyle(text_style);
4961 builder.addText(mno);
4962
4963 auto paragraph = builder.Build();
4964 paragraph->layout(400);
4965 paragraph->paint(canvas.get(), 0, 0);
4966}
4967
4968DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004969 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004970 if (!fontCollection->fontsFound()) return;
4971 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004972 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004973 TestCanvas canvas("SkParagraph_Bidi2.png");
4974
4975 std::u16string abcD = u"\u202Dabc\u202ED";
4976 std::u16string EFgh = u"EF\u202Dgh";
4977 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4978
4979 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4980
4981 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004982 TextStyle text_style;
4983 text_style.setFontFamilies({ SkString("sans-serif")});
4984 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004985
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004986 {
4987 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4988 builder.pushStyle(text_style);
4989 builder.addText(abcD);
4990 builder.pushStyle(text_style);
4991 builder.addText(EFgh);
4992 builder.pushStyle(text_style);
4993 builder.addText(iJKLmno);
4994 auto paragraph = builder.Build();
4995 paragraph->layout(360);
4996 paragraph->paint(canvas.get(), 0, 0);
4997 }
4998 canvas.get()->translate(0, 400);
4999 {
5000 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5001 builder.pushStyle(text_style);
5002 builder.addText(abcDEFghiJKLmno);
5003 auto paragraph = builder.Build();
5004 paragraph->layout(360);
5005 paragraph->paint(canvas.get(), 0, 0);
5006 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04005007}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005008
5009DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005010 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005011 if (!fontCollection->fontsFound()) return;
5012 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5013 TestCanvas canvas("SkParagraph_Newline.png");
5014
5015 TextStyle text_style;
5016 text_style.setFontFamilies({SkString("Ahem")});
5017 text_style.setColor(SK_ColorBLACK);
5018 StrutStyle strut_style;
5019 strut_style.setStrutEnabled(false);
5020 ParagraphStyle paragraph_style;
5021 paragraph_style.setStrutStyle(strut_style);
5022 paragraph_style.setTextStyle(text_style);
5023 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5024 builder.addText("\n");
5025 auto paragraph = builder.Build();
5026 paragraph->layout(1000);
5027 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5028}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005029
Julia Lavrovab30d4812019-11-08 14:51:16 -05005030DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005031 TestCanvas canvas("SkParagraph_FontResolutions.png");
5032
5033 sk_sp<TestFontCollection> fontCollection =
5034 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5035 if (!fontCollection->fontsFound()) return;
5036
5037 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5038 return;
5039 }
5040 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5041 return;
5042 }
5043 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5044 return;
5045 }
5046
5047 TextStyle text_style;
5048 text_style.setFontFamilies({SkString("abc")});
5049 text_style.setFontSize(50);
5050
5051 ParagraphStyle paragraph_style;
5052 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5053
5054 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5055 text_style.setColor(SK_ColorBLUE);
5056 builder.pushStyle(text_style);
5057 builder.addText(u"a\u0300");
5058 text_style.setColor(SK_ColorMAGENTA);
5059 builder.pushStyle(text_style);
5060 builder.addText(u"à");
5061
5062 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5063
5064 text_style.setColor(SK_ColorRED);
5065 builder.pushStyle(text_style);
5066 builder.addText(u"a\u0300");
5067 text_style.setColor(SK_ColorGREEN);
5068 builder.pushStyle(text_style);
5069 builder.addText(u"à");
5070
5071 auto paragraph = builder.Build();
5072 paragraph->layout(TestCanvasWidth);
5073
5074 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5075 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5076
5077 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5078 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5079 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5080
5081 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5082 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5083
5084 paragraph->paint(canvas.get(), 100, 100);
5085}
5086
Julia Lavrovab30d4812019-11-08 14:51:16 -05005087DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005088 TestCanvas canvas("SkParagraph_FontStyle.png");
5089
5090 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5091 if (!fontCollection->fontsFound()) return;
5092
5093 TextStyle text_style;
5094 text_style.setFontFamilies({SkString("Roboto")});
5095 text_style.setColor(SK_ColorBLACK);
5096 text_style.setFontSize(20);
5097 SkFontStyle fs = SkFontStyle(
5098 SkFontStyle::Weight::kLight_Weight,
5099 SkFontStyle::Width::kNormal_Width,
5100 SkFontStyle::Slant::kUpright_Slant
5101 );
5102 text_style.setFontStyle(fs);
5103 ParagraphStyle paragraph_style;
5104 paragraph_style.setTextStyle(text_style);
5105 TextStyle boldItalic;
5106 boldItalic.setFontFamilies({SkString("Roboto")});
5107 boldItalic.setColor(SK_ColorRED);
5108 SkFontStyle bi = SkFontStyle(
5109 SkFontStyle::Weight::kBold_Weight,
5110 SkFontStyle::Width::kNormal_Width,
5111 SkFontStyle::Slant::kItalic_Slant
5112 );
5113 boldItalic.setFontStyle(bi);
5114 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5115 builder.addText("Default text\n");
5116 builder.pushStyle(boldItalic);
5117 builder.addText("Bold and Italic\n");
5118 builder.pop();
5119 builder.addText("back to normal");
5120 auto paragraph = builder.Build();
5121 paragraph->layout(250);
5122 paragraph->paint(canvas.get(), 0, 0);
5123}
5124
Julia Lavrovab30d4812019-11-08 14:51:16 -05005125DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005126 TestCanvas canvas("SkParagraph_Shaping.png");
5127
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005128 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5129 sk_sp<TestFontCollection> fontCollection =
5130 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5131 if (!fontCollection->fontsFound()) return;
5132
5133
5134 TextStyle text_style;
5135 text_style.setFontFamilies({SkString("Roboto")});
5136 text_style.setColor(SK_ColorGRAY);
5137 text_style.setFontSize(14);
5138 SkFontStyle b = SkFontStyle(
5139 SkFontStyle::Weight::kNormal_Weight,
5140 SkFontStyle::Width::kNormal_Width,
5141 SkFontStyle::Slant::kUpright_Slant
5142 );
5143 text_style.setFontStyle(b);
5144 ParagraphStyle paragraph_style;
5145 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5146 builder.pushStyle(text_style);
5147 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5148 auto paragraph = builder.Build();
5149 paragraph->layout(380);
5150 paragraph->paint(canvas.get(), 0, 0);
5151}
Julia Lavrovac028b422019-11-25 10:00:43 -05005152
5153DEF_TEST(SkParagraph_Ellipsis, reporter) {
5154 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5155 if (!fontCollection->fontsFound()) return;
5156 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5157 TestCanvas canvas("SkParagraph_Ellipsis.png");
5158
5159 const char* text = "This\n"
5160 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5161 TextStyle text_style;
5162 text_style.setFontFamilies({SkString("Ahem")});
5163 text_style.setColor(SK_ColorBLACK);
5164 text_style.setFontSize(10);
5165
5166 auto relayout = [&](size_t lines, bool ellipsis,
5167 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5168 ParagraphStyle paragraph_style;
5169 SkPaint paint;
5170 paint.setColor(bg);
5171 text_style.setForegroundColor(paint);
5172 paragraph_style.setTextStyle(text_style);
5173 paragraph_style.setMaxLines(lines);
5174 if (ellipsis) {
5175 paragraph_style.setEllipsis(u"\u2026");
5176 }
5177 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5178 builder.addText(text);
5179 auto paragraph = builder.Build();
5180 paragraph->layout(50);
5181 paragraph->paint(canvas.get(), 0, 0);
5182 canvas.get()->translate(50, paragraph->getHeight() + 10);
5183 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5184 SkPaint background;
5185 background.setColor(SK_ColorRED);
5186 background.setStyle(SkPaint::kStroke_Style);
5187 background.setAntiAlias(true);
5188 background.setStrokeWidth(1);
5189 canvas.get()->drawRect(result.front().rect, background);
5190
5191 SkASSERT(width == paragraph->getMaxWidth());
5192 SkASSERT(height == paragraph->getHeight());
5193 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5194 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5195 };
5196
5197 SkPaint paint;
5198 paint.setColor(SK_ColorLTGRAY);
5199 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5200
5201 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005202 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5203 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005204
5205 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005206 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005207 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5208
5209 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005210 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5211 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005212}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005213
5214DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5215 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5216 if (!fontCollection->fontsFound()) return;
5217 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5218
5219 std::string text;
5220 for (size_t i = 0; i < 10; i++)
5221 {
5222 SkPaint paint;
5223 paint.setAntiAlias(true);
5224 paint.setColor(SK_ColorBLACK);
5225
5226 TextStyle textStyle;
5227 textStyle.setForegroundColor(paint);
5228 textStyle.setFontFamilies({ SkString("Roboto") });
5229
5230 ParagraphStyle paragraphStyle;
5231 paragraphStyle.setTextStyle(textStyle);
5232
5233 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5234 text += "Text ";
5235 builder.addText(text.c_str());
5236
5237 auto paragraph = builder.Build();
5238 paragraph->layout(100);
5239
5240 //used to add a delay so I can monitor memory usage
5241 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5242 }
5243};
Julia Lavrovac0360582020-02-05 10:17:53 -05005244
5245DEF_TEST(SkParagraph_FormattingInfinity, reporter) {
5246 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5247 if (!fontCollection->fontsFound()) return;
5248 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5249 TestCanvas canvas("SkParagraph_FormattingInfinity.png");
5250
5251 const char* text = "Some text\nAnother line";
5252
5253 SkPaint paint;
5254 paint.setAntiAlias(true);
5255 paint.setColor(SK_ColorBLACK);
5256
5257 TextStyle textStyle;
5258 textStyle.setForegroundColor(paint);
5259 textStyle.setFontFamilies({ SkString("Roboto") });
5260 ParagraphStyle paragraphStyle;
5261 paragraphStyle.setTextStyle(textStyle);
5262
5263 auto draw = [&](const char* prefix, TextAlign textAlign) {
5264 paragraphStyle.setTextAlign(textAlign);
5265 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5266 builder.addText(text);
5267 auto paragraph = builder.Build();
5268 paragraph->layout(SK_ScalarInfinity);
5269 paragraph->paint(canvas.get(), 0, 0);
5270 canvas.get()->translate(0, 100);
5271 };
5272
5273 draw("left", TextAlign::kLeft);
5274 draw("right", TextAlign::kRight);
5275 draw("center", TextAlign::kCenter);
5276 draw("justify", TextAlign::kJustify);
5277};
5278
5279DEF_TEST(SkParagraph_Infinity, reporter) {
5280 SkASSERT(nearlyEqual(1, SK_ScalarInfinity) == false);
5281 SkASSERT(nearlyEqual(1, SK_ScalarNegativeInfinity) == false);
5282 SkASSERT(nearlyEqual(1, SK_ScalarNaN) == false);
5283
5284 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarInfinity) == true);
5285 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNegativeInfinity) == false);
5286 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNaN) == false);
5287
5288 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarInfinity) == false);
5289 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity) == true);
5290 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNaN) == false);
5291
5292 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarInfinity) == false);
5293 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNegativeInfinity) == false);
5294 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNaN) == false);
5295};