blob: 116e0df4c9b22cb16712403f1e6c6e8f2886b4af [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 Lavrovaa3552c52019-05-30 16:12:56 -0400110 size_t resolvedFonts() const { return fResolvedFonts; }
111
112 // TODO: temp solution until we check in fonts
113 bool fontsFound() const { return fFontsFound; }
114
115private:
116 bool fFontsFound;
117 size_t fResolvedFonts;
118 std::string fResourceDir;
119 sk_sp<TypefaceFontProvider> fFontProvider;
120};
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400121
122class TestCanvas {
123public:
124 TestCanvas(const char* testName) : name(testName) {
125 bits.allocN32Pixels(TestCanvasWidth, TestCanvasHeight);
126 canvas = new SkCanvas(bits);
127 canvas->clear(SK_ColorWHITE);
128 }
129
130 ~TestCanvas() {
Julia Lavrovaaae845f2019-08-16 16:44:40 -0400131 SkString tmpDir = skiatest::GetTmpDir();
132 if (!tmpDir.isEmpty()) {
133 SkString path = SkOSPath::Join(tmpDir.c_str(), name);
134 SkFILEWStream file(path.c_str());
135 if (!SkEncodeImage(&file, bits, SkEncodedImageFormat::kPNG, 100)) {
136 SkDebugf("Cannot write a picture %s\n", name);
137 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400138 }
139 delete canvas;
140 }
141
142 void drawRects(SkColor color, std::vector<TextBox>& result, bool fill = false) {
143
144 SkPaint paint;
145 if (!fill) {
146 paint.setStyle(SkPaint::kStroke_Style);
147 paint.setAntiAlias(true);
148 paint.setStrokeWidth(1);
149 }
150 paint.setColor(color);
151 for (auto& r : result) {
152 canvas->drawRect(r.rect, paint);
153 }
154 }
155
156 void drawLine(SkColor color, SkRect rect, bool vertical = true) {
157
158 SkPaint paint;
159 paint.setStyle(SkPaint::kStroke_Style);
160 paint.setAntiAlias(true);
161 paint.setStrokeWidth(1);
162 paint.setColor(color);
163 if (vertical) {
164 canvas->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
165 } else {
166 canvas->drawLine(rect.fLeft, rect.fTop, rect.fRight, rect.fTop, paint);
167 }
168 }
169
170 void drawLines(SkColor color, std::vector<TextBox>& result) {
171
172 for (auto& r : result) {
173 drawLine(color, r.rect);
174 }
175 }
176
177 SkCanvas* get() { return canvas; }
178private:
179 SkBitmap bits;
180 SkCanvas* canvas;
181 const char* name;
182};
183
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400184} // namespace
185
186DEF_TEST(SkParagraph_SimpleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400187 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400188 if (!fontCollection->fontsFound()) return;
189 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400190 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400191
192 ParagraphStyle paragraph_style;
193 paragraph_style.turnHintingOff();
194 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
195
196 TextStyle text_style;
197 text_style.setFontFamilies({SkString("Roboto")});
198 text_style.setColor(SK_ColorBLACK);
199 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400200 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400201 builder.pop();
202
203 auto paragraph = builder.Build();
204 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500205 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400206
207 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
208 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
209 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400210 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400211
212 size_t index = 0;
213 for (auto& line : impl->lines()) {
214 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400215 [&index, reporter]
216 (TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400217 REPORTER_ASSERT(reporter, index == 0);
218 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorBLACK);
219 ++index;
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400220 });
221 }
222}
223
Julia Lavrova916a9042019-08-08 16:51:27 -0400224DEF_TEST(SkParagraph_InlinePlaceholderParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400225 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400226 TestCanvas canvas("SkParagraph_InlinePlaceholderParagraph.png");
227 if (!fontCollection->fontsFound()) return;
228
229 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400230 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400231
232 ParagraphStyle paragraph_style;
233 paragraph_style.turnHintingOff();
234 paragraph_style.setMaxLines(14);
235 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
236
237 TextStyle text_style;
238 text_style.setFontFamilies({SkString("Roboto")});
239 text_style.setColor(SK_ColorBLACK);
240 text_style.setFontSize(26);
241 text_style.setWordSpacing(5);
242 text_style.setLetterSpacing(1);
243 text_style.setDecoration(TextDecoration::kUnderline);
244 text_style.setDecorationColor(SK_ColorBLACK);
245 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400246 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400247
248 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
249 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400250 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400251 builder.addPlaceholder(placeholder1);
252
253 PlaceholderStyle placeholder2(5, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
254 builder.addPlaceholder(placeholder2);
255 builder.addPlaceholder(placeholder1);
256 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400257 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400258 builder.addPlaceholder(placeholder2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400259 builder.addText(text, len);
260 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400261 builder.addPlaceholder(placeholder2);
262 builder.addPlaceholder(placeholder2);
263 builder.addPlaceholder(placeholder2);
264 builder.addPlaceholder(placeholder2);
265 builder.addPlaceholder(placeholder2);
266 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400267 builder.addText(text, len);
268 builder.addText(text, len);
269 builder.addText(text, len);
270 builder.addText(text, len);
271 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400272 builder.addPlaceholder(placeholder2);
273 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400274 builder.addText(text, len);
275 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400276
277 builder.pop();
278
279 auto paragraph = builder.Build();
280 paragraph->layout(TestCanvasWidth);
281 paragraph->paint(canvas.get(), 0, 0);
282
283 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
284 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
285
286 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
287 canvas.drawRects(SK_ColorRED, boxes);
288 REPORTER_ASSERT(reporter, boxes.size() == 1);
289
290 boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
291 canvas.drawRects(SK_ColorGREEN, boxes);
292 REPORTER_ASSERT(reporter, boxes.size() == 1);
293
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400294 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400295 canvas.drawRects(SK_ColorRED, boxes);
296
297 boxes = paragraph->getRectsForRange(4, 17, rect_height_style, rect_width_style);
298 canvas.drawRects(SK_ColorBLUE, boxes);
299
300 REPORTER_ASSERT(reporter, boxes.size() == 7);
301
Julia Lavrovac028b422019-11-25 10:00:43 -0500302 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400303 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 90.921f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400305 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 100, EPSILON100));
306
Julia Lavrovac028b422019-11-25 10:00:43 -0500307 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.left(), 231.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400308 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.top(), 50, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500309 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.right(), 231.343f + 50, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400310 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[3].rect.bottom(), 100, EPSILON100));
311
Julia Lavrovac028b422019-11-25 10:00:43 -0500312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.left(), 281.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400313 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500314 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.right(), 281.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400315 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[4].rect.bottom(), 50, EPSILON100));
316
Julia Lavrovac028b422019-11-25 10:00:43 -0500317 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.left(), 336.343f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400318 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500319 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.right(), 336.343f + 5, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[6].rect.bottom(), 50, EPSILON100));
321}
322
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400323DEF_TEST(SkParagraph_InlinePlaceholderBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400324 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400325 TestCanvas canvas("SkParagraph_InlinePlaceholderBaselineParagraph.png");
326 if (!fontCollection->fontsFound()) return;
327
328 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400329 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400330
331 ParagraphStyle paragraph_style;
332 paragraph_style.turnHintingOff();
333 paragraph_style.setMaxLines(14);
334 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
335
336 TextStyle text_style;
337 text_style.setFontFamilies({SkString("Roboto")});
338 text_style.setColor(SK_ColorBLACK);
339 text_style.setFontSize(26);
340 text_style.setWordSpacing(5);
341 text_style.setLetterSpacing(1);
342 text_style.setDecoration(TextDecoration::kUnderline);
343 text_style.setDecorationColor(SK_ColorBLACK);
344 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400345 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400346
347 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 38.347f);
348 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400349 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400350
351 builder.pop();
352
353 auto paragraph = builder.Build();
354 paragraph->layout(TestCanvasWidth);
355 paragraph->paint(canvas.get(), 0, 0);
356
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400357 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400358 canvas.drawRects(SK_ColorRED, boxes);
359
360 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500361 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400362 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500363 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400364 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
365
366 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
367 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
368
369 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
370 canvas.drawRects(SK_ColorBLUE, boxes);
371
372 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500373 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400374 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 14.226f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500375 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400376 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44.694f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400377}
Julia Lavrova916a9042019-08-08 16:51:27 -0400378
Julia Lavrova916a9042019-08-08 16:51:27 -0400379DEF_TEST(SkParagraph_InlinePlaceholderAboveBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400380 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400381 TestCanvas canvas("SkParagraph_InlinePlaceholderAboveBaselineParagraph.png");
382 if (!fontCollection->fontsFound()) return;
383
384 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400385 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400386
387 ParagraphStyle paragraph_style;
388 paragraph_style.turnHintingOff();
389 paragraph_style.setMaxLines(14);
390 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
391
392 TextStyle text_style;
393 text_style.setFontFamilies({SkString("Roboto")});
394 text_style.setColor(SK_ColorBLACK);
395 text_style.setFontSize(26);
396 text_style.setWordSpacing(5);
397 text_style.setLetterSpacing(1);
398 text_style.setDecoration(TextDecoration::kUnderline);
399 text_style.setDecorationColor(SK_ColorBLACK);
400 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400401 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400402
403 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kAboveBaseline, TextBaseline::kAlphabetic, 903129.129308f);
404 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400405 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400406
407 builder.pop();
408
409 auto paragraph = builder.Build();
410 paragraph->layout(TestCanvasWidth);
411 paragraph->paint(canvas.get(), 0, 0);
412
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400413 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400414 canvas.drawRects(SK_ColorRED, boxes);
415
416 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500417 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400418 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.347f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500419 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400420 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 49.652f, EPSILON100));
421
422 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
423 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
424
425 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
426 canvas.drawRects(SK_ColorBLUE, boxes);
427
428 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500429 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400430 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 25.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500431 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400432 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400433}
Julia Lavrova916a9042019-08-08 16:51:27 -0400434
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400435DEF_TEST(SkParagraph_InlinePlaceholderBelowBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400436 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400437 TestCanvas canvas("SkParagraph_InlinePlaceholderBelowBaselineParagraph.png");
438 if (!fontCollection->fontsFound()) return;
439
440 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400441 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400442
443 ParagraphStyle paragraph_style;
444 paragraph_style.turnHintingOff();
445 paragraph_style.setMaxLines(14);
446 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
447
448 TextStyle text_style;
449 text_style.setFontFamilies({SkString("Roboto")});
450 text_style.setColor(SK_ColorBLACK);
451 text_style.setFontSize(26);
452 text_style.setWordSpacing(5);
453 text_style.setLetterSpacing(1);
454 text_style.setDecoration(TextDecoration::kUnderline);
455 text_style.setDecorationColor(SK_ColorBLACK);
456 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400457 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400458
459 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBelowBaseline, TextBaseline::kAlphabetic, 903129.129308f);
460 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400461 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400462
463 builder.pop();
464
465 auto paragraph = builder.Build();
466 paragraph->layout(TestCanvasWidth);
467 paragraph->paint(canvas.get(), 0, 0);
468
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400469 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400470 canvas.drawRects(SK_ColorRED, boxes);
471
472 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500473 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400474 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400476 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
477
478 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
479 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
480
481 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
482 canvas.drawRects(SK_ColorBLUE, boxes);
483
484 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400486 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.121f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500487 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON2));
Julia Lavrova916a9042019-08-08 16:51:27 -0400488 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.347f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400489}
Julia Lavrova916a9042019-08-08 16:51:27 -0400490
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400491DEF_TEST(SkParagraph_InlinePlaceholderBottomParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400492 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400493 TestCanvas canvas("SkParagraph_InlinePlaceholderBottomParagraph.png");
494 if (!fontCollection->fontsFound()) return;
495
496 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400497 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400498
499 ParagraphStyle paragraph_style;
500 paragraph_style.turnHintingOff();
501 paragraph_style.setMaxLines(14);
502 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
503
504 TextStyle text_style;
505 text_style.setFontFamilies({SkString("Roboto")});
506 text_style.setColor(SK_ColorBLACK);
507 text_style.setFontSize(26);
508 text_style.setWordSpacing(5);
509 text_style.setLetterSpacing(1);
510 text_style.setDecoration(TextDecoration::kUnderline);
511 text_style.setDecorationColor(SK_ColorBLACK);
512 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400513 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400514
515 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBottom, TextBaseline::kAlphabetic, 0);
516 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400517 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400518
519 builder.pop();
520
521 auto paragraph = builder.Build();
522 paragraph->layout(TestCanvasWidth);
523 paragraph->paint(canvas.get(), 0, 0);
524
525 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
526 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
527
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400528 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400529 canvas.drawRects(SK_ColorRED, boxes);
530 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500531 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400532 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
535
536 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
537 canvas.drawRects(SK_ColorBLUE, boxes);
538 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500539 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400540 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 19.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500541 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400542 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400543}
Julia Lavrova916a9042019-08-08 16:51:27 -0400544
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400545DEF_TEST(SkParagraph_InlinePlaceholderTopParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400546 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400547 TestCanvas canvas("SkParagraph_InlinePlaceholderTopParagraph.png");
548 if (!fontCollection->fontsFound()) return;
549
550 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400551 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400552
553 ParagraphStyle paragraph_style;
554 paragraph_style.turnHintingOff();
555 paragraph_style.setMaxLines(14);
556 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
557
558 TextStyle text_style;
559 text_style.setFontFamilies({SkString("Roboto")});
560 text_style.setColor(SK_ColorBLACK);
561 text_style.setFontSize(26);
562 text_style.setWordSpacing(5);
563 text_style.setLetterSpacing(1);
564 text_style.setDecoration(TextDecoration::kUnderline);
565 text_style.setDecorationColor(SK_ColorBLACK);
566 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400567 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400568
569 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kTop, TextBaseline::kAlphabetic, 0);
570 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400571 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400572
573 builder.pop();
574
575 auto paragraph = builder.Build();
576 paragraph->layout(TestCanvasWidth);
577 paragraph->paint(canvas.get(), 0, 0);
578
579 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
580 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
581
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400582 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400583 canvas.drawRects(SK_ColorRED, boxes);
584 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500585 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400586 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500587 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400588 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
589
590 boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
591 canvas.drawRects(SK_ColorBLUE, boxes);
592 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500593 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400594 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500595 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 16.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400596 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 30.468f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400597}
Julia Lavrova916a9042019-08-08 16:51:27 -0400598
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400599DEF_TEST(SkParagraph_InlinePlaceholderMiddleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400600 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400601 TestCanvas canvas("SkParagraph_InlinePlaceholderMiddleParagraph.png");
602 if (!fontCollection->fontsFound()) return;
603
604 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400605 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400606
607 ParagraphStyle paragraph_style;
608 paragraph_style.turnHintingOff();
609 paragraph_style.setMaxLines(14);
610 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
611
612 TextStyle text_style;
613 text_style.setFontFamilies({SkString("Roboto")});
614 text_style.setColor(SK_ColorBLACK);
615 text_style.setFontSize(26);
616 text_style.setWordSpacing(5);
617 text_style.setLetterSpacing(1);
618 text_style.setDecoration(TextDecoration::kUnderline);
619 text_style.setDecorationColor(SK_ColorBLACK);
620 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400621 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400622
623 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kMiddle, TextBaseline::kAlphabetic, 0);
624 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400625 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400626
627 builder.pop();
628
629 auto paragraph = builder.Build();
630 paragraph->layout(TestCanvasWidth);
631 paragraph->paint(canvas.get(), 0, 0);
632
633 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
634 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
635
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400636 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400637 canvas.drawRects(SK_ColorRED, boxes);
638 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500639 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400640 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500641 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400642 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
643
644 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
645 canvas.drawRects(SK_ColorBLUE, boxes);
646 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 75.324f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 9.765f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500649 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 40.234f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400651}
Julia Lavrova916a9042019-08-08 16:51:27 -0400652
Julia Lavrova916a9042019-08-08 16:51:27 -0400653DEF_TEST(SkParagraph_InlinePlaceholderIdeographicBaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400654 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400655 TestCanvas canvas("SkParagraph_InlinePlaceholderIdeographicBaselineParagraph.png");
656 if (!fontCollection->fontsFound()) return;
657
658 const char* text = "給能上目秘使";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400659 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400660
661 ParagraphStyle paragraph_style;
662 paragraph_style.turnHintingOff();
663 paragraph_style.setMaxLines(14);
664 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
665
666 TextStyle text_style;
667 text_style.setFontFamilies({SkString("Source Han Serif CN")});
668 text_style.setColor(SK_ColorBLACK);
669 text_style.setFontSize(26);
670 text_style.setWordSpacing(5);
671 text_style.setLetterSpacing(1);
672 text_style.setDecoration(TextDecoration::kUnderline);
673 text_style.setDecorationColor(SK_ColorBLACK);
674 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400675 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400676 PlaceholderStyle placeholder(55, 50, PlaceholderAlignment::kBaseline, TextBaseline::kIdeographic, 38.347f);
677 builder.addPlaceholder(placeholder);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400678 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400679
680 builder.pop();
681
682 auto paragraph = builder.Build();
683 paragraph->layout(TestCanvasWidth);
684 paragraph->paint(canvas.get(), 0, 0);
685
686 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
687 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
688
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400689 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400690 canvas.drawRects(SK_ColorRED, boxes);
691 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500692 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400693 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500694 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f + 55, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400695 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
696
697 boxes = paragraph->getRectsForRange(5, 6, rect_height_style, rect_width_style);
698 canvas.drawRects(SK_ColorBLUE, boxes);
699 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500700 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 135.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400701 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 4.703f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500702 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 162.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400703 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 42.065f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400704}
Julia Lavrova916a9042019-08-08 16:51:27 -0400705
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400706DEF_TEST(SkParagraph_InlinePlaceholderBreakParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400707 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400708 TestCanvas canvas("SkParagraph_InlinePlaceholderBreakParagraph.png");
709 if (!fontCollection->fontsFound()) return;
710
711 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400712 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400713
714 ParagraphStyle paragraph_style;
715 paragraph_style.turnHintingOff();
716 paragraph_style.setMaxLines(14);
717 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
718
719 TextStyle text_style;
720 text_style.setFontFamilies({SkString("Roboto")});
721 text_style.setColor(SK_ColorBLACK);
722 text_style.setFontSize(26);
723 text_style.setWordSpacing(5);
724 text_style.setLetterSpacing(1);
725 text_style.setDecoration(TextDecoration::kUnderline);
726 text_style.setDecorationColor(SK_ColorBLACK);
727 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400728 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400729
730 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
731 PlaceholderStyle placeholder2(25, 25, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 12.5f);
732
733 builder.addPlaceholder(placeholder1);
734 builder.addPlaceholder(placeholder1);
735 builder.addPlaceholder(placeholder1);
736 builder.addPlaceholder(placeholder2);
737 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400738 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400739
740 builder.addPlaceholder(placeholder1);
741 builder.addPlaceholder(placeholder1);
742 builder.addPlaceholder(placeholder1);
743 builder.addPlaceholder(placeholder1);
744 builder.addPlaceholder(placeholder2); // 4 + 1
745 builder.addPlaceholder(placeholder1);
746 builder.addPlaceholder(placeholder1);
747 builder.addPlaceholder(placeholder1);
748 builder.addPlaceholder(placeholder1);
749 builder.addPlaceholder(placeholder1);
750 builder.addPlaceholder(placeholder1);
751 builder.addPlaceholder(placeholder2); // 6 + 1
752 builder.addPlaceholder(placeholder1);
753 builder.addPlaceholder(placeholder1);
754 builder.addPlaceholder(placeholder1);
755 builder.addPlaceholder(placeholder1);
756 builder.addPlaceholder(placeholder1);
757 builder.addPlaceholder(placeholder1);
758 builder.addPlaceholder(placeholder1);
759 builder.addPlaceholder(placeholder2); // 7 + 1
760
761 builder.addPlaceholder(placeholder1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400762 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400763 builder.addPlaceholder(placeholder1);
764 builder.addPlaceholder(placeholder2);
765
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400766 builder.addText(text, len);
767 builder.addText(text, len);
768 builder.addText(text, len);
769 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400770
771 builder.addPlaceholder(placeholder2);
772 builder.addPlaceholder(placeholder1);
773
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400774 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400775
776 builder.addPlaceholder(placeholder2);
777
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400778 builder.addText(text, len);
779 builder.addText(text, len);
780 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);
Julia Lavrova916a9042019-08-08 16:51:27 -0400797
798 builder.pop();
799
800 auto paragraph = builder.Build();
801 paragraph->layout(TestCanvasWidth - 100);
802 paragraph->paint(canvas.get(), 0, 0);
803
804 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
805 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
806
807 auto boxes = paragraph->getRectsForRange(0, 3, rect_height_style, rect_width_style);
808 canvas.drawRects(SK_ColorRED, boxes);
809 REPORTER_ASSERT(reporter, boxes.size() == 1);
810
811 boxes = paragraph->getRectsForRange(175, 176, rect_height_style, rect_width_style);
812 canvas.drawRects(SK_ColorGREEN, boxes);
813 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovac028b422019-11-25 10:00:43 -0500814 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 31.695f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400815 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 218.531f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500816 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 47.292f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400817 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 249, EPSILON100));
818
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400819 boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400820 canvas.drawRects(SK_ColorRED, boxes);
821
822 boxes = paragraph->getRectsForRange(4, 45, rect_height_style, rect_width_style);
823 canvas.drawRects(SK_ColorBLUE, boxes);
824 REPORTER_ASSERT(reporter, boxes.size() == 30);
Julia Lavrovac028b422019-11-25 10:00:43 -0500825 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 59.726f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400826 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.378f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500827 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400828 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 56.847f, EPSILON100));
829
Julia Lavrovac028b422019-11-25 10:00:43 -0500830 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.left(), 606.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400831 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.top(), 38, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500832 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.right(), 631.343f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400833 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[11].rect.bottom(), 63, EPSILON100));
834
Julia Lavrovac028b422019-11-25 10:00:43 -0500835 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.left(), 0.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400836 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.top(), 63.5f, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500837 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.right(), 50.5f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400838 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[17].rect.bottom(), 113.5f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400839}
Julia Lavrova916a9042019-08-08 16:51:27 -0400840
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400841DEF_TEST(SkParagraph_InlinePlaceholderGetRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400842 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova916a9042019-08-08 16:51:27 -0400843 TestCanvas canvas("SkParagraph_InlinePlaceholderGetRectsParagraph.png");
844 if (!fontCollection->fontsFound()) return;
845
846 const char* text = "012 34";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400847 const size_t len = strlen(text);
Julia Lavrova916a9042019-08-08 16:51:27 -0400848
849 ParagraphStyle paragraph_style;
850 paragraph_style.turnHintingOff();
851 paragraph_style.setMaxLines(14);
852 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
853
854 TextStyle text_style;
855 text_style.setFontFamilies({SkString("Roboto")});
856 text_style.setColor(SK_ColorBLACK);
857 text_style.setFontSize(26);
858 text_style.setWordSpacing(5);
859 text_style.setLetterSpacing(1);
860 text_style.setDecoration(TextDecoration::kUnderline);
861 text_style.setDecorationColor(SK_ColorBLACK);
862 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400863 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400864
865 PlaceholderStyle placeholder1(50, 50, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 50);
866 PlaceholderStyle placeholder2(5, 20, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 10);
867
868 builder.addPlaceholder(placeholder1);
869 builder.addPlaceholder(placeholder1);
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(placeholder2); // 8 + 1
877 builder.addPlaceholder(placeholder1);
878 builder.addPlaceholder(placeholder1);
879 builder.addPlaceholder(placeholder1);
880 builder.addPlaceholder(placeholder1);
881 builder.addPlaceholder(placeholder1);
882 builder.addPlaceholder(placeholder2); // 5 + 1
883 builder.addPlaceholder(placeholder1);
884 builder.addPlaceholder(placeholder1);
885 builder.addPlaceholder(placeholder1);
886 builder.addPlaceholder(placeholder1);
887 builder.addPlaceholder(placeholder1);
888 builder.addPlaceholder(placeholder1);
889 builder.addPlaceholder(placeholder1);
890 builder.addPlaceholder(placeholder1); // 8 + 0
891
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400892 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400893
894 builder.addPlaceholder(placeholder1);
895 builder.addPlaceholder(placeholder2);
896 builder.addPlaceholder(placeholder2); // 1 + 2
897 builder.addPlaceholder(placeholder1);
898 builder.addPlaceholder(placeholder2);
899 builder.addPlaceholder(placeholder2); // 1 + 2
900
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400901 builder.addText(text, len);
902 builder.addText(text, len);
903 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); // 11
Julia Lavrova916a9042019-08-08 16:51:27 -0400912
913 builder.addPlaceholder(placeholder2);
914 builder.addPlaceholder(placeholder1);
915 builder.addPlaceholder(placeholder2);
916 builder.addPlaceholder(placeholder1);
917 builder.addPlaceholder(placeholder2);
918
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400919 builder.addText(text, len);
Julia Lavrova916a9042019-08-08 16:51:27 -0400920
921 builder.pop();
922
923 auto paragraph = builder.Build();
924 paragraph->layout(TestCanvasWidth);
925 paragraph->paint(canvas.get(), 0, 0);
926
927 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
928 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
929
Julia Lavrovaf3ed2732019-09-05 14:35:17 -0400930 auto boxes = paragraph->getRectsForPlaceholders();
Julia Lavrova916a9042019-08-08 16:51:27 -0400931 canvas.drawRects(SK_ColorRED, boxes);
932
933 REPORTER_ASSERT(reporter, boxes.size() == 34);
Julia Lavrovac028b422019-11-25 10:00:43 -0500934 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 90.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400935 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500936 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 140.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 50, EPSILON100));
938
Julia Lavrovac028b422019-11-25 10:00:43 -0500939 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.left(), 800.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400940 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.top(), 0, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500941 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.right(), 850.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400942 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[16].rect.bottom(), 50, EPSILON100));
943
Julia Lavrovac028b422019-11-25 10:00:43 -0500944 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.left(), 503.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400945 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.top(), 160, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500946 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.right(), 508.382f, EPSILON10));
Julia Lavrova916a9042019-08-08 16:51:27 -0400947 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[33].rect.bottom(), 180, EPSILON100));
948
949 boxes = paragraph->getRectsForRange(30, 50, rect_height_style, rect_width_style);
950 canvas.drawRects(SK_ColorBLUE, boxes);
951
952 REPORTER_ASSERT(reporter, boxes.size() == 8);
Julia Lavrovac028b422019-11-25 10:00:43 -0500953 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 216.097f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400954 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500955 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 290.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400956 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 120, EPSILON100));
957
Julia Lavrovac028b422019-11-25 10:00:43 -0500958 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 290.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400959 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500960 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 340.921f, EPSILON20));
Julia Lavrova916a9042019-08-08 16:51:27 -0400961 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 120, EPSILON100));
962
Julia Lavrovac028b422019-11-25 10:00:43 -0500963 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.left(), 340.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400964 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.top(), 60, EPSILON100));
Julia Lavrovac028b422019-11-25 10:00:43 -0500965 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.right(), 345.921f, EPSILON50));
Julia Lavrova916a9042019-08-08 16:51:27 -0400966 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[2].rect.bottom(), 120, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -0400967}
968
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400969DEF_TEST(SkParagraph_SimpleRedParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -0400970 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400971 if (!fontCollection->fontsFound()) return;
972 const char* text = "I am RED";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400973 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400974
975 ParagraphStyle paragraph_style;
976 paragraph_style.turnHintingOff();
977 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
978
979 TextStyle text_style;
980 text_style.setFontFamilies({SkString("Roboto")});
981 text_style.setColor(SK_ColorRED);
982 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -0400983 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400984 builder.pop();
985
986 auto paragraph = builder.Build();
987 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -0500988 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400989
990 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
991 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
992 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
Julia Lavrova5207f352019-06-21 12:22:32 -0400993 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -0400994
995 size_t index = 0;
996 for (auto& line : impl->lines()) {
997 line.scanStyles(StyleType::kDecorations,
Julia Lavrova526df262019-08-21 17:49:44 -0400998 [reporter, &index](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
999 REPORTER_ASSERT(reporter, index == 0);
1000 REPORTER_ASSERT(reporter, style.getColor() == SK_ColorRED);
1001 ++index;
1002 return true;
1003 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001004 }
1005}
1006
Julia Lavrovac2228562019-08-08 16:51:27 -04001007// Checked: DIFF+ (Space between 1 & 2 style blocks)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001008DEF_TEST(SkParagraph_RainbowParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001009 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001010 TestCanvas canvas("SkParagraph_RainbowParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001011 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001012 const char* text1 = "Red Roboto"; // [0:10)
1013 const char* text2 = "big Greeen Default"; // [10:28)
1014 const char* text3 = "Defcolor Homemade Apple"; // [28:51)
1015 const char* text4 = "Small Blue Roboto"; // [51:68)
Julia Lavrovac2228562019-08-08 16:51:27 -04001016 const char* text41 = "Small Blue ";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001017 const char* text5 =
1018 "Continue Last Style With lots of words to check if it overlaps "
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001019 "properly or not"; // [68:)
1020 const char* text42 =
1021 "Roboto"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001022 "Continue Last Style With lots of words to check if it overlaps "
1023 "properly or not";
1024
1025 ParagraphStyle paragraph_style;
1026 paragraph_style.turnHintingOff();
1027 paragraph_style.setTextAlign(TextAlign::kLeft);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001028 paragraph_style.setMaxLines(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001029 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1030
1031 TextStyle text_style1;
1032 text_style1.setFontFamilies({SkString("Roboto")});
1033
1034 text_style1.setColor(SK_ColorRED);
1035 builder.pushStyle(text_style1);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001036 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001037
1038 TextStyle text_style2;
1039 text_style2.setFontFamilies({SkString("Roboto")});
1040 text_style2.setFontSize(50);
1041 text_style2.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
1042 SkFontStyle::kUpright_Slant));
1043 text_style2.setLetterSpacing(10);
1044 text_style2.setDecorationColor(SK_ColorBLACK);
1045 text_style2.setDecoration((TextDecoration)(
1046 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1047 text_style2.setWordSpacing(30);
1048 text_style2.setColor(SK_ColorGREEN);
1049 builder.pushStyle(text_style2);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001050 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001051
1052 TextStyle text_style3;
1053 text_style3.setFontFamilies({SkString("Homemade Apple")});
Julia Lavrova526df262019-08-21 17:49:44 -04001054 text_style3.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001055 builder.pushStyle(text_style3);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001056 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001057
1058 TextStyle text_style4;
1059 text_style4.setFontFamilies({SkString("Roboto")});
1060 text_style4.setFontSize(14);
1061 text_style4.setDecorationColor(SK_ColorBLACK);
1062 text_style4.setDecoration((TextDecoration)(
1063 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1064 text_style4.setColor(SK_ColorBLUE);
1065 builder.pushStyle(text_style4);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001066 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001067
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001068 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001069 builder.pop();
1070
1071 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001072 paragraph->layout(1000);
1073 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001074
Julia Lavrova3281b962019-12-02 11:32:25 -05001075 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1076
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001077 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1078 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
1079 REPORTER_ASSERT(reporter, impl->styles().size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001080 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
1081
1082 auto rects = paragraph->getRectsForRange(0, impl->text().size(), RectHeightStyle::kMax, RectWidthStyle::kTight);
1083 canvas.drawRects(SK_ColorMAGENTA, rects);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001084
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001085 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001086 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001087 StyleType::kAllAttributes,
1088 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001089 switch (index) {
1090 case 0:
1091 REPORTER_ASSERT(reporter, style.equals(text_style1));
Julia Lavrova526df262019-08-21 17:49:44 -04001092 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001093 break;
1094 case 1:
1095 REPORTER_ASSERT(reporter, style.equals(text_style2));
Julia Lavrova526df262019-08-21 17:49:44 -04001096 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text2));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001097 break;
1098 case 2:
1099 REPORTER_ASSERT(reporter, style.equals(text_style3));
Julia Lavrova526df262019-08-21 17:49:44 -04001100 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text3));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001101 break;
1102 case 3:
1103 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001104 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text41));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001105 break;
1106 default:
1107 REPORTER_ASSERT(reporter, false);
1108 break;
1109 }
1110 ++index;
1111 return true;
1112 });
1113 impl->lines()[1].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001114 StyleType::kAllAttributes,
1115 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001116 switch (index) {
1117 case 4:
1118 REPORTER_ASSERT(reporter, style.equals(text_style4));
Julia Lavrova526df262019-08-21 17:49:44 -04001119 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text42));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001120 break;
1121 default:
1122 REPORTER_ASSERT(reporter, false);
1123 break;
1124 }
1125 ++index;
1126 return true;
1127 });
1128 REPORTER_ASSERT(reporter, index == 5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001129}
1130
1131DEF_TEST(SkParagraph_DefaultStyleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001132 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001133 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001134 TestCanvas canvas("SkParagraph_DefaultStyleParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001135 const char* text = "No TextStyle! Uh Oh!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001136 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001137
1138 ParagraphStyle paragraph_style;
1139 TextStyle defaultStyle;
1140 defaultStyle.setFontFamilies({SkString("Roboto")});
1141 paragraph_style.setTextStyle(defaultStyle);
1142 paragraph_style.turnHintingOff();
1143 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001144 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001145
1146 auto paragraph = builder.Build();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001147 paragraph->layout(TestCanvasWidth);
1148 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001149
Julia Lavrova3281b962019-12-02 11:32:25 -05001150 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1151
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001152 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1153
1154 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1155 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1156 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1157
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001158 size_t index = 0;
1159 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001160 StyleType::kAllAttributes,
1161 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001162 REPORTER_ASSERT(reporter, style.equals(paragraph_style.getTextStyle()));
Julia Lavrova526df262019-08-21 17:49:44 -04001163 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001164 ++index;
1165 return true;
1166 });
1167 REPORTER_ASSERT(reporter, index == 1);
1168}
1169
1170DEF_TEST(SkParagraph_BoldParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001171 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001172 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001173 TestCanvas canvas("SkParagraph_BoldParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001174 const char* text = "This is Red max bold text!";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001175 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001176
1177 ParagraphStyle paragraph_style;
1178 paragraph_style.turnHintingOff();
1179 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1180
1181 TextStyle text_style;
1182 text_style.setFontFamilies({SkString("Roboto")});
1183 text_style.setColor(SK_ColorRED);
1184 text_style.setFontSize(60);
1185 text_style.setLetterSpacing(0);
1186 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width,
1187 SkFontStyle::kUpright_Slant));
1188 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001189 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001190 builder.pop();
1191
1192 auto paragraph = builder.Build();
1193 paragraph->layout(VeryLongCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001194 paragraph->paint(canvas.get(), 10.0, 60.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001195
Julia Lavrova3281b962019-12-02 11:32:25 -05001196 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
1197
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001198 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1199
1200 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1201 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
1202 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1203
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001204 size_t index = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001205 impl->lines()[0].scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001206 StyleType::kAllAttributes,
1207 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001208 REPORTER_ASSERT(reporter, style.equals(text_style));
Julia Lavrova526df262019-08-21 17:49:44 -04001209 REPORTER_ASSERT(reporter, equal(impl->text().begin(), textRange, text));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001210 ++index;
1211 return true;
1212 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001213 REPORTER_ASSERT(reporter, index == 1);
1214}
1215
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001216DEF_TEST(SkParagraph_HeightOverrideParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001217 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04001218 if (!fontCollection->fontsFound()) return;
1219 TestCanvas canvas("SkParagraph_HeightOverrideParagraph.png");
1220 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001221 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001222
Julia Lavrovac2228562019-08-08 16:51:27 -04001223 ParagraphStyle paragraph_style;
1224 paragraph_style.turnHintingOff();
1225 paragraph_style.setMaxLines(10);
1226 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001227
Julia Lavrovac2228562019-08-08 16:51:27 -04001228 TextStyle text_style;
1229 text_style.setFontFamilies({SkString("Roboto")});
1230 text_style.setFontSize(20);
1231 text_style.setColor(SK_ColorBLACK);
1232 text_style.setHeight(3.6345f);
1233 text_style.setHeightOverride(true);
1234 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001235 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04001236 builder.pop();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001237
Julia Lavrovac2228562019-08-08 16:51:27 -04001238 auto paragraph = builder.Build();
1239 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001240
Julia Lavrovac2228562019-08-08 16:51:27 -04001241 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrova131c5ad2020-07-20 11:05:26 -04001242 REPORTER_ASSERT(reporter, impl->runs().size() == 4);
Julia Lavrovac2228562019-08-08 16:51:27 -04001243 REPORTER_ASSERT(reporter, impl->styles().size() == 1); // paragraph style does not count
1244 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001245
Julia Lavrovac2228562019-08-08 16:51:27 -04001246 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001247
Julia Lavrovac2228562019-08-08 16:51:27 -04001248 SkPaint paint;
1249 paint.setStyle(SkPaint::kStroke_Style);
1250 paint.setAntiAlias(true);
1251 paint.setStrokeWidth(1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001252
Julia Lavrovac2228562019-08-08 16:51:27 -04001253 // Tests for GetRectsForRange()
1254 RectHeightStyle rect_height_style = RectHeightStyle::kIncludeLineSpacingMiddle;
1255 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1256 paint.setColor(SK_ColorRED);
1257 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
1258 canvas.drawRects(SK_ColorRED, boxes);
1259 REPORTER_ASSERT(reporter, boxes.size() == 0ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001260
Julia Lavrovac2228562019-08-08 16:51:27 -04001261 boxes = paragraph->getRectsForRange(0, 40, rect_height_style, rect_width_style);
1262 canvas.drawRects(SK_ColorBLUE, boxes);
1263 REPORTER_ASSERT(reporter, boxes.size() == 3ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001264
Julia Lavrovac2228562019-08-08 16:51:27 -04001265 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.left(), 0, EPSILON100));
1266 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.top(), 92.805f, EPSILON5));
1267 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.right(), 43.843f, EPSILON100));
1268 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[1].rect.bottom(), 165.495f, EPSILON5));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001269}
1270
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001271DEF_TEST(SkParagraph_LeftAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001272 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001273 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001274 TestCanvas canvas("SkParagraph_LeftAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001275 const char* text =
1276 "This is a very long sentence to test if the text will properly wrap "
1277 "around and go to the next line. Sometimes, short sentence. Longer "
1278 "sentences are okay too because they are nessecary. Very short. "
1279 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1280 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1281 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1282 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1283 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1284 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1285 "mollit anim id est laborum. "
1286 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1287 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1288 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1289 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1290 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1291 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1292 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001293 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001294
1295 ParagraphStyle paragraph_style;
1296 paragraph_style.setMaxLines(14);
1297 paragraph_style.setTextAlign(TextAlign::kLeft);
1298 paragraph_style.turnHintingOff();
1299 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1300
1301 TextStyle text_style;
1302 text_style.setFontFamilies({SkString("Roboto")});
1303 text_style.setFontSize(26);
1304 text_style.setLetterSpacing(1);
1305 text_style.setWordSpacing(5);
1306 text_style.setColor(SK_ColorBLACK);
1307 text_style.setHeight(1);
1308 text_style.setDecoration(TextDecoration::kUnderline);
1309 text_style.setDecorationColor(SK_ColorBLACK);
1310 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001311 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001312 builder.pop();
1313
1314 auto paragraph = builder.Build();
1315 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001316 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001317
1318 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001319
1320 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1321 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1322 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001323 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001324 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1325
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001326 double expected_y = 0;
1327 double epsilon = 0.01f;
1328 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1329 REPORTER_ASSERT(reporter,
1330 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1331 expected_y += 30;
1332 REPORTER_ASSERT(reporter,
1333 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1334 expected_y += 30;
1335 REPORTER_ASSERT(reporter,
1336 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1337 expected_y += 30;
1338 REPORTER_ASSERT(reporter,
1339 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1340 expected_y += 30 * 10;
1341 REPORTER_ASSERT(reporter,
1342 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1343
1344 REPORTER_ASSERT(reporter,
1345 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1346
1347 // Tests for GetGlyphPositionAtCoordinate()
1348 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(0, 0).position == 0);
1349 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 1).position == 0);
1350 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 35).position == 68);
1351 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(1, 70).position == 134);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001352 REPORTER_ASSERT(reporter, impl->getGlyphPositionAtCoordinate(2000, 35).position == 134);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001353}
1354
1355DEF_TEST(SkParagraph_RightAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001356 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001357 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001358 TestCanvas canvas("SkParagraph_RightAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001359 const char* text =
1360 "This is a very long sentence to test if the text will properly wrap "
1361 "around and go to the next line. Sometimes, short sentence. Longer "
1362 "sentences are okay too because they are nessecary. Very short. "
1363 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1364 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1365 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1366 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1367 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1368 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1369 "mollit anim id est laborum. "
1370 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1371 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1372 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1373 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1374 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1375 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1376 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001377 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001378
1379 ParagraphStyle paragraph_style;
1380 paragraph_style.setMaxLines(14);
1381 paragraph_style.setTextAlign(TextAlign::kRight);
1382 paragraph_style.turnHintingOff();
1383 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1384
1385 TextStyle text_style;
1386 text_style.setFontFamilies({SkString("Roboto")});
1387 text_style.setFontSize(26);
1388 text_style.setLetterSpacing(1);
1389 text_style.setWordSpacing(5);
1390 text_style.setColor(SK_ColorBLACK);
1391 text_style.setHeight(1);
1392 text_style.setDecoration(TextDecoration::kUnderline);
1393 text_style.setDecorationColor(SK_ColorBLACK);
1394 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001395 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001396 builder.pop();
1397
1398 auto paragraph = builder.Build();
1399 paragraph->layout(TestCanvasWidth - 100);
1400
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001401 paragraph->paint(canvas.get(), 0, 0);
1402
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001403 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001404
1405 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1406 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001407 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001408 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1409
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001410 double expected_y = 0;
1411 double epsilon = 0.01f;
1412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1413 REPORTER_ASSERT(reporter,
1414 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1415 expected_y += 30;
1416 REPORTER_ASSERT(reporter,
1417 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1418 expected_y += 30;
1419 REPORTER_ASSERT(reporter,
1420 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1421 expected_y += 30;
1422 REPORTER_ASSERT(reporter,
1423 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1424 expected_y += 30 * 10;
1425 REPORTER_ASSERT(reporter,
1426 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1427
1428 auto calculate = [](const TextLine& line) -> SkScalar {
1429 return TestCanvasWidth - 100 - line.offset().fX - line.width();
1430 };
1431
1432 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1433 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1434 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1435 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1436 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1437
1438 REPORTER_ASSERT(reporter,
1439 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1440}
1441
1442DEF_TEST(SkParagraph_CenterAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001443 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001444 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001445 TestCanvas canvas("SkParagraph_CenterAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001446 const char* text =
1447 "This is a very long sentence to test if the text will properly wrap "
1448 "around and go to the next line. Sometimes, short sentence. Longer "
1449 "sentences are okay too because they are nessecary. Very short. "
1450 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1451 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1452 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1453 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1454 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1455 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1456 "mollit anim id est laborum. "
1457 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1458 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1459 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1460 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1461 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1462 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1463 "mollit anim id est laborum.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001464 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001465
1466 ParagraphStyle paragraph_style;
1467 paragraph_style.setMaxLines(14);
1468 paragraph_style.setTextAlign(TextAlign::kCenter);
1469 paragraph_style.turnHintingOff();
1470 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1471
1472 TextStyle text_style;
1473 text_style.setFontFamilies({SkString("Roboto")});
1474 text_style.setFontSize(26);
1475 text_style.setLetterSpacing(1);
1476 text_style.setWordSpacing(5);
1477 text_style.setColor(SK_ColorBLACK);
1478 text_style.setHeight(1);
1479 text_style.setDecoration(TextDecoration::kUnderline);
1480 text_style.setDecorationColor(SK_ColorBLACK);
1481 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001482 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001483 builder.pop();
1484
1485 auto paragraph = builder.Build();
1486 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001487 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001488
1489 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001490
1491 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1492 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1493 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001494 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001495 REPORTER_ASSERT(reporter, impl->lines().size() == paragraph_style.getMaxLines());
1496
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001497 double expected_y = 0;
1498 double epsilon = 0.01f;
1499 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, epsilon));
1500 REPORTER_ASSERT(reporter,
1501 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, epsilon));
1502 expected_y += 30;
1503 REPORTER_ASSERT(reporter,
1504 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, epsilon));
1505 expected_y += 30;
1506 REPORTER_ASSERT(reporter,
1507 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, epsilon));
1508 expected_y += 30;
1509 REPORTER_ASSERT(reporter,
1510 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, epsilon));
1511 expected_y += 30 * 10;
1512 REPORTER_ASSERT(reporter,
1513 SkScalarNearlyEqual(impl->lines()[13].offset().fY, expected_y, epsilon));
1514
1515 auto calculate = [](const TextLine& line) -> SkScalar {
1516 return TestCanvasWidth - 100 - (line.offset().fX * 2 + line.width());
1517 };
1518
1519 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, epsilon));
1520 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, epsilon));
1521 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, epsilon));
1522 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, epsilon));
1523 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[13]), 0, epsilon));
1524
1525 REPORTER_ASSERT(reporter,
1526 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1527}
1528
1529DEF_TEST(SkParagraph_JustifyAlignParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001530 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001531 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001532 TestCanvas canvas("SkParagraph_JustifyAlignParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001533 const char* text =
1534 "This is a very long sentence to test if the text will properly wrap "
1535 "around and go to the next line. Sometimes, short sentence. Longer "
1536 "sentences are okay too because they are nessecary. Very short. "
1537 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1538 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1539 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1540 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1541 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1542 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1543 "mollit anim id est laborum. "
1544 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1545 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1546 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1547 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1548 "velit esse cillum dolore eu fugiat.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001549 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001550
1551 ParagraphStyle paragraph_style;
1552 paragraph_style.setMaxLines(14);
1553 paragraph_style.setTextAlign(TextAlign::kJustify);
1554 paragraph_style.turnHintingOff();
1555 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1556
1557 TextStyle text_style;
1558 text_style.setFontFamilies({SkString("Roboto")});
1559 text_style.setFontSize(26);
1560 text_style.setLetterSpacing(0);
1561 text_style.setWordSpacing(5);
1562 text_style.setColor(SK_ColorBLACK);
1563 text_style.setHeight(1);
1564 text_style.setDecoration(TextDecoration::kUnderline);
1565 text_style.setDecorationColor(SK_ColorBLACK);
1566 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001567 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001568 builder.pop();
1569
1570 auto paragraph = builder.Build();
1571 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001572 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001573
Julia Lavrovac2228562019-08-08 16:51:27 -04001574 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1575 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1576 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1577 canvas.drawRects(SK_ColorRED, boxes);
1578
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001579 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001580
1581 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
1582 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
1583 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04001584 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001585
1586 double expected_y = 0;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001587 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].baseline(), 24.121f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001588 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001589 SkScalarNearlyEqual(impl->lines()[0].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001590 expected_y += 30;
1591 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001592 SkScalarNearlyEqual(impl->lines()[1].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001593 expected_y += 30;
1594 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001595 SkScalarNearlyEqual(impl->lines()[2].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001596 expected_y += 30;
1597 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001598 SkScalarNearlyEqual(impl->lines()[3].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001599 expected_y += 30 * 9;
1600 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001601 SkScalarNearlyEqual(impl->lines()[12].offset().fY, expected_y, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001602
1603 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04001604 return line.offset().fX;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001605 };
1606
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001607 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[0]), 0, EPSILON100));
1608 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[1]), 0, EPSILON100));
1609 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[2]), 0, EPSILON100));
1610 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(impl->lines()[3]), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001611
1612 REPORTER_ASSERT(reporter,
1613 paragraph_style.getTextAlign() == impl->paragraphStyle().getTextAlign());
1614}
1615
Julia Lavrovac2228562019-08-08 16:51:27 -04001616// Checked: DIFF (ghost spaces as a separate box in TxtLib)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001617DEF_TEST(SkParagraph_JustifyRTL, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001618 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001619 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001620 TestCanvas canvas("SkParagraph_JustifyRTL.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001621 const char* text =
1622 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1623 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1624 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001625 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001626
1627 ParagraphStyle paragraph_style;
1628 paragraph_style.setMaxLines(14);
1629 paragraph_style.setTextAlign(TextAlign::kJustify);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001630 paragraph_style.setTextDirection(TextDirection::kRtl);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001631 paragraph_style.turnHintingOff();
1632 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1633
1634 TextStyle text_style;
1635 text_style.setFontFamilies({SkString("Ahem")});
1636 text_style.setFontSize(26);
1637 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001638 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001639 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001640 builder.pop();
1641
1642 auto paragraph = builder.Build();
1643 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001644 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001645
1646 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001647
1648 auto calculate = [](const TextLine& line) -> SkScalar {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001649 return TestCanvasWidth - 100 - line.width();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001650 };
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001651 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001652 if (&line == &impl->lines().back()) {
1653 REPORTER_ASSERT(reporter, calculate(line) > EPSILON100);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001654 } else {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(calculate(line), 0, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001656 }
1657 }
1658
1659 // Just make sure the the text is actually RTL
1660 for (auto& run : impl->runs()) {
1661 REPORTER_ASSERT(reporter, !run.leftToRight());
1662 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001663
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001664 // Tests for GetRectsForRange()
1665 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1666 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1667 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1668 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovad3a32c52020-02-03 09:43:52 -05001669 REPORTER_ASSERT(reporter, boxes.size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001670
1671 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1672 canvas.drawRects(SK_ColorBLUE, boxes);
1673 REPORTER_ASSERT(reporter, boxes.size() == 1);
1674
1675 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 588, EPSILON100));
1676 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1677 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 640, EPSILON100));
1678 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1679}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001680
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001681DEF_TEST_DISABLED(SkParagraph_JustifyRTLNewLine, reporter) {
1682 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1683 if (!fontCollection->fontsFound()) return;
1684 TestCanvas canvas("SkParagraph_JustifyRTLNewLine.png");
1685 const char* text =
1686 "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1687 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1688 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001689 const size_t len = strlen(text);
1690
1691 ParagraphStyle paragraph_style;
1692 paragraph_style.setMaxLines(14);
1693 paragraph_style.setTextAlign(TextAlign::kJustify);
1694 paragraph_style.setTextDirection(TextDirection::kRtl);
1695 paragraph_style.turnHintingOff();
1696 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1697
1698 TextStyle text_style;
1699 text_style.setFontFamilies({SkString("Ahem")});
1700 text_style.setFontSize(26);
1701 text_style.setColor(SK_ColorBLACK);
1702 builder.pushStyle(text_style);
1703 builder.addText(text, len);
1704 builder.pop();
1705
1706 auto paragraph = builder.Build();
1707 paragraph->layout(TestCanvasWidth - 100);
1708 paragraph->paint(canvas.get(), 0, 0);
1709
1710 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
1711
1712 SkPaint paint;
1713 paint.setStyle(SkPaint::kStroke_Style);
1714 paint.setAntiAlias(true);
1715 paint.setStrokeWidth(1);
1716
1717 // Tests for GetRectsForRange()
1718 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1719 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1720 paint.setColor(SK_ColorRED);
1721 auto boxes = paragraph->getRectsForRange(0, 30, rect_height_style, rect_width_style);
1722 for (size_t i = 0; i < boxes.size(); ++i) {
1723 canvas.get()->drawRect(boxes[i].rect, paint);
1724 }
1725 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1726 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 562, EPSILON100));
1727 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
1728 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
1729 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 26, EPSILON100));
1730
1731 paint.setColor(SK_ColorBLUE);
1732 boxes = paragraph->getRectsForRange(240, 250, rect_height_style, rect_width_style);
1733 for (size_t i = 0; i < boxes.size(); ++i) {
1734 canvas.get()->drawRect(boxes[i].rect, paint);
1735 }
1736 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
1737 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 68, EPSILON100));
1738 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 130, EPSILON100));
1739 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 120, EPSILON100));
1740 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 156, EPSILON100));
1741
1742 // All lines should be justified to the width of the
1743 // paragraph.
1744 for (auto& line : impl->lines()) {
1745 REPORTER_ASSERT(reporter,
1746 SkScalarNearlyEqual(line.width(), TestCanvasWidth - 100, EPSILON100));
1747 }
1748}
1749
1750DEF_TEST_DISABLED(SkParagraph_LeadingSpaceRTL, reporter) {
1751 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
1752 if (!fontCollection->fontsFound()) return;
1753 TestCanvas canvas("SkParagraph_LeadingSpaceRTL.png");
1754
1755 const char* text = " leading space";
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001756 const size_t len = strlen(text);
1757
1758 ParagraphStyle paragraph_style;
1759 paragraph_style.setMaxLines(14);
1760 paragraph_style.setTextAlign(TextAlign::kJustify);
1761 paragraph_style.setTextDirection(TextDirection::kRtl);
1762 paragraph_style.turnHintingOff();
1763 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1764
1765 TextStyle text_style;
1766 text_style.setFontFamilies({SkString("Ahem")});
1767 text_style.setFontSize(26);
1768 text_style.setColor(SK_ColorBLACK);
1769 builder.pushStyle(text_style);
1770 builder.addText(text, len);
1771 builder.pop();
1772
1773 auto paragraph = builder.Build();
1774 paragraph->layout(TestCanvasWidth - 100);
1775 paragraph->paint(canvas.get(), 0, 0);
1776
1777 SkPaint paint;
1778 paint.setStyle(SkPaint::kStroke_Style);
1779 paint.setAntiAlias(true);
1780 paint.setStrokeWidth(1);
1781
1782 // Tests for GetRectsForRange()
1783 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
1784 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
1785 paint.setColor(SK_ColorRED);
1786 auto boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
1787 for (size_t i = 0; i < boxes.size(); ++i) {
1788 canvas.get()->drawRect(boxes[i].rect, paint);
1789 }
1790 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
1791}
1792
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001793DEF_TEST(SkParagraph_DecorationsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001794 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001795 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001796 TestCanvas canvas("SkParagraph_DecorationsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001797 const char* text1 = "This text should be";
1798 const char* text2 = " decorated even when";
1799 const char* text3 = " wrapped around to";
1800 const char* text4 = " the next line.";
1801 const char* text5 = " Otherwise, bad things happen.";
1802
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001803 ParagraphStyle paragraph_style;
1804 paragraph_style.setMaxLines(14);
1805 paragraph_style.setTextAlign(TextAlign::kLeft);
1806 paragraph_style.turnHintingOff();
1807 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1808
1809 TextStyle text_style;
1810 text_style.setFontFamilies({SkString("Roboto")});
1811 text_style.setFontSize(26);
1812 text_style.setLetterSpacing(0);
1813 text_style.setWordSpacing(5);
1814 text_style.setColor(SK_ColorBLACK);
1815 text_style.setHeight(2);
1816 text_style.setDecoration(TextDecoration::kUnderline);
1817 text_style.setDecorationColor(SK_ColorBLACK);
1818 text_style.setDecoration((TextDecoration)(
1819 TextDecoration::kUnderline | TextDecoration::kOverline | TextDecoration::kLineThrough));
1820 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
1821 text_style.setDecorationColor(SK_ColorBLACK);
1822 text_style.setDecorationThicknessMultiplier(2.0);
1823 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001824 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001825
1826 text_style.setDecorationStyle(TextDecorationStyle::kDouble);
1827 text_style.setDecorationColor(SK_ColorBLUE);
1828 text_style.setDecorationThicknessMultiplier(1.0);
1829 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001830 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001831
1832 text_style.setDecorationStyle(TextDecorationStyle::kDotted);
1833 text_style.setDecorationColor(SK_ColorBLACK);
1834 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001835 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001836
1837 text_style.setDecorationStyle(TextDecorationStyle::kDashed);
1838 text_style.setDecorationColor(SK_ColorBLACK);
1839 text_style.setDecorationThicknessMultiplier(3.0);
1840 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001841 builder.addText(text4, strlen(text4));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001842
1843 text_style.setDecorationStyle(TextDecorationStyle::kWavy);
1844 text_style.setDecorationColor(SK_ColorRED);
1845 text_style.setDecorationThicknessMultiplier(1.0);
1846 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001847 builder.addText(text5, strlen(text5));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001848 builder.pop();
1849
1850 auto paragraph = builder.Build();
1851 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001852 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001853
1854 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001855
1856 size_t index = 0;
1857 for (auto& line : impl->lines()) {
1858 line.scanStyles(
Julia Lavrova526df262019-08-21 17:49:44 -04001859 StyleType::kDecorations,
1860 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001861 auto decoration = (TextDecoration)(TextDecoration::kUnderline |
1862 TextDecoration::kOverline |
1863 TextDecoration::kLineThrough);
1864 REPORTER_ASSERT(reporter, style.getDecorationType() == decoration);
1865 switch (index) {
1866 case 0:
1867 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1868 TextDecorationStyle::kSolid);
1869 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1870 REPORTER_ASSERT(reporter,
1871 style.getDecorationThicknessMultiplier() == 2.0);
1872 break;
1873 case 1: // The style appears on 2 lines so it has 2 pieces
1874 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1875 TextDecorationStyle::kDouble);
1876 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLUE);
1877 REPORTER_ASSERT(reporter,
1878 style.getDecorationThicknessMultiplier() == 1.0);
1879 break;
1880 case 2:
1881 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1882 TextDecorationStyle::kDotted);
1883 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1884 REPORTER_ASSERT(reporter,
1885 style.getDecorationThicknessMultiplier() == 1.0);
1886 break;
1887 case 3:
1888 case 4:
1889 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1890 TextDecorationStyle::kDashed);
1891 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorBLACK);
1892 REPORTER_ASSERT(reporter,
1893 style.getDecorationThicknessMultiplier() == 3.0);
1894 break;
1895 case 5:
1896 REPORTER_ASSERT(reporter, style.getDecorationStyle() ==
1897 TextDecorationStyle::kWavy);
1898 REPORTER_ASSERT(reporter, style.getDecorationColor() == SK_ColorRED);
1899 REPORTER_ASSERT(reporter,
1900 style.getDecorationThicknessMultiplier() == 1.0);
1901 break;
1902 default:
1903 REPORTER_ASSERT(reporter, false);
1904 break;
1905 }
1906 ++index;
1907 return true;
1908 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001909 }
1910}
1911
Julia Lavrovac2228562019-08-08 16:51:27 -04001912DEF_TEST(SkParagraph_WavyDecorationParagraph, reporter) {
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05001913 SkDebugf("TODO: Add test for wavy decorations\n");
Julia Lavrovac2228562019-08-08 16:51:27 -04001914}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001915
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001916DEF_TEST(SkParagraph_ItalicsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001917 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001918 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001919 TestCanvas canvas("SkParagraph_ItalicsParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001920 const char* text1 = "No italic ";
1921 const char* text2 = "Yes Italic ";
1922 const char* text3 = "No Italic again.";
1923
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001924 ParagraphStyle paragraph_style;
1925 paragraph_style.turnHintingOff();
1926 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1927
1928 TextStyle text_style;
1929 text_style.setFontFamilies({SkString("Roboto")});
1930 text_style.setFontSize(10);
1931 text_style.setColor(SK_ColorRED);
1932 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001933 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001934
1935 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
1936 SkFontStyle::kItalic_Slant));
1937 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001938 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001939 builder.pop();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001940 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001941
1942 auto paragraph = builder.Build();
1943 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001944 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001945
1946 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001947
1948 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
1949 REPORTER_ASSERT(reporter, impl->styles().size() == 3);
1950 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
1951 auto& line = impl->lines()[0];
1952 size_t index = 0;
1953 line.scanStyles(
1954 StyleType::kForeground,
Julia Lavrova526df262019-08-21 17:49:44 -04001955 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001956 switch (index) {
1957 case 0:
1958 REPORTER_ASSERT(
1959 reporter,
1960 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1961 break;
1962 case 1:
1963 REPORTER_ASSERT(reporter,
1964 style.getFontStyle().slant() == SkFontStyle::kItalic_Slant);
1965 break;
1966 case 2:
1967 REPORTER_ASSERT(
1968 reporter,
1969 style.getFontStyle().slant() == SkFontStyle::kUpright_Slant);
1970 break;
1971 default:
1972 REPORTER_ASSERT(reporter, false);
1973 break;
1974 }
1975 ++index;
1976 return true;
1977 });
1978}
1979
1980DEF_TEST(SkParagraph_ChineseParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04001981 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001982 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04001983 TestCanvas canvas("SkParagraph_ChineseParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001984 const char* text =
1985 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
1986 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
1987 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
1988 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
1989 "聞条年所在口。";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04001990 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001991
1992 ParagraphStyle paragraph_style;
1993 paragraph_style.setMaxLines(14);
1994 paragraph_style.setTextAlign(TextAlign::kJustify);
1995 paragraph_style.turnHintingOff();
1996 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
1997
1998 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
1999 TextDecoration::kLineThrough);
2000
2001 TextStyle text_style;
2002 text_style.setFontFamilies({SkString("Source Han Serif CN")});
2003 text_style.setFontSize(35);
2004 text_style.setColor(SK_ColorBLACK);
2005 text_style.setLetterSpacing(2);
2006 text_style.setHeight(1);
2007 text_style.setDecoration(decoration);
2008 text_style.setDecorationColor(SK_ColorBLACK);
2009 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2010 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002011 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002012 builder.pop();
2013
2014 auto paragraph = builder.Build();
2015 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002016 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002017
Julia Lavrova3281b962019-12-02 11:32:25 -05002018 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2019
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002020 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002021
2022 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2023 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
2024 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002025 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002026}
2027
Julia Lavrovad3a32c52020-02-03 09:43:52 -05002028// Checked: disabled for TxtLib
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002029DEF_TEST(SkParagraph_ArabicParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002030 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002031 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002032 TestCanvas canvas("SkParagraph_ArabicParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002033 const char* text =
2034 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2035 "بمباركة التقليدية قام عن. تصفح";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002036 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002037
2038 ParagraphStyle paragraph_style;
2039 paragraph_style.setMaxLines(14);
2040 paragraph_style.setTextAlign(TextAlign::kJustify);
2041 paragraph_style.turnHintingOff();
2042 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2043
2044 auto decoration = (TextDecoration)(TextDecoration::kUnderline | TextDecoration::kOverline |
2045 TextDecoration::kLineThrough);
2046
2047 TextStyle text_style;
2048 text_style.setFontFamilies({SkString("Katibeh")});
2049 text_style.setFontSize(35);
2050 text_style.setColor(SK_ColorBLACK);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002051 text_style.setLetterSpacing(2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002052 text_style.setDecoration(decoration);
2053 text_style.setDecorationColor(SK_ColorBLACK);
2054 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
2055 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002056 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002057 builder.pop();
2058
2059 auto paragraph = builder.Build();
2060 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002061 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002062
Julia Lavrova3281b962019-12-02 11:32:25 -05002063 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
2064
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002065 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002066
2067 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2068 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
2069 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04002070 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002071}
2072
Julia Lavrovac2228562019-08-08 16:51:27 -04002073// Checked: DIFF (2 boxes and each space is a word)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002074DEF_TEST(SkParagraph_ArabicRectsParagraph, reporter) {
2075
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002076 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002077 if (!fontCollection->fontsFound()) return;
2078 TestCanvas canvas("SkParagraph_ArabicRectsParagraph.png");
2079 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002080 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002081
2082 ParagraphStyle paragraph_style;
2083 paragraph_style.turnHintingOff();
2084 paragraph_style.setMaxLines(14);
2085 paragraph_style.setTextAlign(TextAlign::kRight);
2086 paragraph_style.setTextDirection(TextDirection::kRtl);
2087 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2088
2089 TextStyle text_style;
2090 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2091 text_style.setFontSize(26);
2092 text_style.setWordSpacing(5);
2093 text_style.setColor(SK_ColorBLACK);
2094 text_style.setDecoration(TextDecoration::kUnderline);
2095 text_style.setDecorationColor(SK_ColorBLACK);
2096 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002097 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002098 builder.pop();
2099
2100 auto paragraph = builder.Build();
2101 paragraph->layout(TestCanvasWidth - 100);
2102
2103 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2104 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
2105
2106 paragraph->paint(canvas.get(), 0, 0);
2107
2108 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2109 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2110 std::vector<TextBox> boxes = paragraph->getRectsForRange(0, 100, rect_height_style, rect_width_style);
2111 canvas.drawRects(SK_ColorRED, boxes);
2112
Julia Lavrovac2228562019-08-08 16:51:27 -04002113 REPORTER_ASSERT(reporter, boxes.size() == 1ull);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002114
Julia Lavrovac2228562019-08-08 16:51:27 -04002115 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 538.548f, EPSILON100)); // DIFF: 510.09375
2116 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.268f, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002117 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 900, EPSILON100));
2118 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002119}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002120
2121// Checked DIFF+
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002122// This test shows now 2 boxes for [36:40) range:
2123// [36:38) for arabic text and [38:39) for the last space
2124// that has default paragraph direction (LTR) and is placed at the end of the paragraph
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002125DEF_TEST(SkParagraph_ArabicRectsLTRLeftAlignParagraph, reporter) {
2126
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002127 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002128 if (!fontCollection->fontsFound()) return;
2129 TestCanvas canvas("SkParagraph_ArabicRectsLTRLeftAlignParagraph.png");
2130 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002131 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002132
2133 ParagraphStyle paragraph_style;
2134 paragraph_style.turnHintingOff();
2135 paragraph_style.setMaxLines(14);
2136 paragraph_style.setTextAlign(TextAlign::kLeft);
2137 paragraph_style.setTextDirection(TextDirection::kLtr);
2138 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2139
2140 TextStyle text_style;
2141 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2142 text_style.setFontSize(26);
2143 text_style.setWordSpacing(5);
2144 text_style.setColor(SK_ColorBLACK);
2145 text_style.setDecoration(TextDecoration::kUnderline);
2146 text_style.setDecorationColor(SK_ColorBLACK);
2147 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002148 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002149 builder.pop();
2150
2151 auto paragraph = builder.Build();
2152 paragraph->layout(TestCanvasWidth - 100);
2153
2154 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2155 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2156
2157 paragraph->paint(canvas.get(), 0, 0);
2158
2159 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2160 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002161 // 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 -04002162 std::vector<TextBox> boxes = paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2163 canvas.drawRects(SK_ColorRED, boxes);
2164
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002165 REPORTER_ASSERT(reporter, boxes.size() == 2ull);
2166 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 83.92f, EPSILON100)); // DIFF: 89.40625
2167 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2168 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 110.16f, EPSILON100)); // DIFF: 121.87891
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002169 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002170}
2171
2172// Checked DIFF+
2173DEF_TEST(SkParagraph_ArabicRectsLTRRightAlignParagraph, reporter) {
2174
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002175 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002176 if (!fontCollection->fontsFound()) return;
2177 TestCanvas canvas("SkParagraph_ArabicRectsLTRRightAlignParagraph.png");
2178 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002179 const size_t len = strlen(text);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002180
2181 ParagraphStyle paragraph_style;
2182 paragraph_style.turnHintingOff();
2183 paragraph_style.setMaxLines(14);
2184 paragraph_style.setTextAlign(TextAlign::kRight);
2185 paragraph_style.setTextDirection(TextDirection::kLtr);
2186 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
2187
2188 TextStyle text_style;
2189 text_style.setFontFamilies({SkString("Noto Naskh Arabic")});
2190 text_style.setFontSize(26);
2191 text_style.setWordSpacing(5);
2192 text_style.setColor(SK_ColorBLACK);
2193 text_style.setDecoration(TextDecoration::kUnderline);
2194 text_style.setDecorationColor(SK_ColorBLACK);
2195 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002196 builder.addText(text, len);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002197 builder.pop();
2198
2199 auto paragraph = builder.Build();
2200 paragraph->layout(TestCanvasWidth - 100);
2201
2202 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
2203 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
2204
2205 paragraph->paint(canvas.get(), 0, 0);
2206
2207 RectHeightStyle rect_height_style = RectHeightStyle::kMax;
2208 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
2209 std::vector<TextBox> boxes =
2210 paragraph->getRectsForRange(36, 40, rect_height_style, rect_width_style);
2211 canvas.drawRects(SK_ColorRED, boxes);
2212
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05002213 REPORTER_ASSERT(reporter, boxes.size() == 2ull); // DIFF
2214 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 561.5f, EPSILON100)); // DIFF
2215 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), -0.27f, EPSILON100));
2216 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 587.74f, EPSILON100)); // DIFF
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002217 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 44, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002218}
2219
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002220DEF_TEST(SkParagraph_GetGlyphPositionAtCoordinateParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002221 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002222 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002223 TestCanvas canvas("SkParagraph_GetGlyphPositionAtCoordinateParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002224 const char* text =
2225 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2226 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002227 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002228
2229 ParagraphStyle paragraphStyle;
2230 paragraphStyle.setTextAlign(TextAlign::kLeft);
2231 paragraphStyle.setMaxLines(10);
2232 paragraphStyle.turnHintingOff();
2233 TextStyle textStyle;
2234 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002235 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
2236 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002237 textStyle.setFontSize(50);
2238 textStyle.setLetterSpacing(1);
2239 textStyle.setWordSpacing(5);
2240 textStyle.setHeight(1);
2241 textStyle.setColor(SK_ColorBLACK);
2242
2243 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2244 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002245 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002246 builder.pop();
2247
2248 auto paragraph = builder.Build();
2249 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002250 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002251
2252 // Tests for getGlyphPositionAtCoordinate()
2253 // NOTE: resulting values can be a few off from their respective positions in
2254 // the original text because the final trailing whitespaces are sometimes not
2255 // drawn (namely, when using "justify" alignment) and therefore are not active
2256 // glyphs.
2257 REPORTER_ASSERT(reporter,
2258 paragraph->getGlyphPositionAtCoordinate(-10000, -10000).position == 0);
2259 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-1, -1).position == 0);
2260 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(0, 0).position == 0);
2261 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(3, 3).position == 0);
2262 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 1).position == 1);
2263 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002264 paragraph->getGlyphPositionAtCoordinate(300, 2).position == 11);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002265 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.2f).position == 11);
2266 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(302, 2.6f).position == 11);
2267 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(301, 2.1f).position == 11);
Julia Lavrovac4d49052020-06-15 10:20:08 -04002268 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 20).position == 18);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002269 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(450, 20).position == 16);
Julia Lavrovac4d49052020-06-15 10:20:08 -04002270 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(100000, 90).position == 36);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002271 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(-100000, 90).position == 18);
2272 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002273 paragraph->getGlyphPositionAtCoordinate(20, -80).position == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002274 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 90).position == 18);
2275 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 170).position == 36);
Julia Lavrovac4d49052020-06-15 10:20:08 -04002276 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 180).position == 72);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002277 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(70, 180).position == 56);
2278 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(1, 270).position == 72);
2279 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(35, 90).position == 19);
Julia Lavrovac4d49052020-06-15 10:20:08 -04002280 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(10000, 10000).position == 77);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002281 REPORTER_ASSERT(reporter, paragraph->getGlyphPositionAtCoordinate(85, 10000).position == 75);
2282}
2283
2284DEF_TEST(SkParagraph_GetRectsForRangeParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002285 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002286 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002287 TestCanvas canvas("SkParagraph_GetRectsForRangeParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002288 const char* text =
2289 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2290 "67890 12345";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002291 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002292
2293 ParagraphStyle paragraphStyle;
2294 paragraphStyle.setTextAlign(TextAlign::kLeft);
2295 paragraphStyle.setMaxLines(10);
2296 paragraphStyle.turnHintingOff();
2297 TextStyle textStyle;
2298 textStyle.setFontFamilies({SkString("Roboto")});
2299 textStyle.setFontSize(50);
2300 textStyle.setColor(SK_ColorBLACK);
2301 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2302 SkFontStyle::kUpright_Slant));
2303
2304 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2305 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002306 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002307 builder.pop();
2308
2309 auto paragraph = builder.Build();
2310 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002311 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002312
2313 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2314 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002315
2316 SkPaint paint;
2317 paint.setStyle(SkPaint::kStroke_Style);
2318 paint.setAntiAlias(true);
2319 paint.setStrokeWidth(1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002320
2321 {
2322 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2323 REPORTER_ASSERT(reporter, result.empty());
2324 }
2325 {
2326 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002327 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002328 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002329 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2330 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 28.417f, EPSILON100));
2332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002333 }
2334 {
2335 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002336 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002337 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002338 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 56.835f, EPSILON100));
2339 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2340 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 177.97f, EPSILON100));
2341 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002342 }
2343 {
2344 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002345 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002346 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002347 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 177.97f, EPSILON100));
2348 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2349 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 507.031f, EPSILON100));
2350 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002351 }
2352 {
2353 auto result = paragraph->getRectsForRange(30, 100, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002354 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002355 REPORTER_ASSERT(reporter, result.size() == 4);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002356 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 211.375f, EPSILON100));
2357 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, EPSILON100));
2358 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 463.623f, EPSILON100));
2359 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
2360 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 0, EPSILON100));
2361 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 236.406f, EPSILON100));
2362 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 142.089f, EPSILON100));
2363 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 295, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002364 }
2365 {
2366 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002367 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002368 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002369 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 450.1875f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002370 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002371 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 519.47266f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002372 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002373 }
2374 {
2375 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2376 REPORTER_ASSERT(reporter, result.empty());
2377 }
2378}
2379
2380DEF_TEST(SkParagraph_GetRectsForRangeTight, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002381 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002382 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002383 TestCanvas canvas("SkParagraph_GetRectsForRangeTight.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002384 const char* text =
2385 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2386 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2387 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002388 const size_t len = strlen(text);
Julia Lavrova149f22d2020-05-27 10:38:35 -04002389/*
2390( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)
2391 S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S
2392 G G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GGG G G G G G GG
2393 W W W W W W W W W W W W W W W W W W W W
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002394
Julia Lavrova149f22d2020-05-27 10:38:35 -04002395 */
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002396 ParagraphStyle paragraphStyle;
2397 paragraphStyle.setTextAlign(TextAlign::kLeft);
2398 paragraphStyle.setMaxLines(10);
2399 paragraphStyle.turnHintingOff();
2400 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002401 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002402 textStyle.setFontSize(50);
2403 textStyle.setColor(SK_ColorBLACK);
2404 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2405 SkFontStyle::kUpright_Slant));
2406
2407 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2408 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002409 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002410 builder.pop();
2411
2412 auto paragraph = builder.Build();
2413 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002414 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002415
2416 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2417 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002418 {
2419 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2420 REPORTER_ASSERT(reporter, result.empty());
2421 }
2422 {
2423 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002424 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002425 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002426 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2427 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2428 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 16.898f, EPSILON100));
2429 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002430 }
2431 {
2432 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002433 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002434 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002435 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 66.899f, EPSILON100));
2436 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2437 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 264.099f, EPSILON100));
2438 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002439 }
2440 {
2441 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002442 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002443 REPORTER_ASSERT(reporter, result.size() == 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002444 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 264.099f, EPSILON100));
2445 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0, EPSILON100));
2446 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 595.085f, EPSILON50));
2447 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002448 }
2449}
2450
Julia Lavrovac2228562019-08-08 16:51:27 -04002451// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002452DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002453 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002454 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002455 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingMiddle.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002456 const char* text =
2457 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2458 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2459 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002460 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002461
2462 ParagraphStyle paragraphStyle;
2463 paragraphStyle.setTextAlign(TextAlign::kLeft);
2464 paragraphStyle.setMaxLines(10);
2465 paragraphStyle.turnHintingOff();
2466 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002467 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002468 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002469 textStyle.setHeight(1.6f);
2470 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002471 textStyle.setColor(SK_ColorBLACK);
2472 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2473 SkFontStyle::kUpright_Slant));
2474
2475 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2476 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002477 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002478 builder.pop();
2479
2480 auto paragraph = builder.Build();
2481 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002482 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002483
2484 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingMiddle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002485 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002486 {
2487 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2488 REPORTER_ASSERT(reporter, result.empty());
2489 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002490
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002491 {
2492 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002493 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002494 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2496 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2497 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2498 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002499 }
2500 {
2501 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002502 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002503 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002504 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2505 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2506 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2507 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002508 }
2509 {
2510 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002511 canvas.drawRects(SK_ColorGREEN, result);
2512 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002513 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002514 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002515 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002516 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002517 }
2518 {
2519 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002520 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002521 REPORTER_ASSERT(reporter, result.size() == 8);
2522
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002523 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002524 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 88.473305f, EPSILON100));
2525 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2526 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 168.47331f, EPSILON100));
2527
2528 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2529 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 88.473305f, EPSILON100));
2530 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2531 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 168.47331f, EPSILON100));
2532
2533 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2534 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 168.47331f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002535 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002536 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 248.47331f, EPSILON100));
2537
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002538 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002539 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 168.47331f, EPSILON100));
2540 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2541 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 248.47331f, EPSILON100));
2542
2543 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2544 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 248.47331f, EPSILON100));
2545 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2546 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 328.47333f, EPSILON100));
2547
2548 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2549 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 328.47333f, EPSILON100));
2550 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2551 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 408.4733f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002552 }
2553 {
2554 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002555 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002556 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002557 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002558 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002559 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002560 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 88.473305f, EPSILON100));
2561
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002562 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002563 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2564 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2565 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 88.473305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002566 }
2567 {
2568 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2569 REPORTER_ASSERT(reporter, result.empty());
2570 }
2571}
2572
Julia Lavrovac2228562019-08-08 16:51:27 -04002573// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002574DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingTop, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002575 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002576 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002577 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingTop.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002578 const char* text =
2579 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2580 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2581 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002582 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002583
2584 ParagraphStyle paragraphStyle;
2585 paragraphStyle.setTextAlign(TextAlign::kLeft);
2586 paragraphStyle.setMaxLines(10);
2587 paragraphStyle.turnHintingOff();
2588 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002589 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002590 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002591 textStyle.setHeight(1.6f);
2592 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002593 textStyle.setColor(SK_ColorBLACK);
2594 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2595 SkFontStyle::kUpright_Slant));
2596
2597 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2598 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002599 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002600 builder.pop();
2601
2602 auto paragraph = builder.Build();
2603 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002604 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002605
2606 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingTop;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002607 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002608 {
2609 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2610 REPORTER_ASSERT(reporter, result.empty());
2611 }
2612
2613 {
2614 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002615 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002616 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002617 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2618 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2619 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.4296889f, EPSILON100));
2620 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002621 }
2622 {
2623 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002624 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002625 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002626 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.429688f, EPSILON100));
2627 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2628 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.00781f, EPSILON100));
2629 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002630 }
2631 {
2632 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002633 canvas.drawRects(SK_ColorGREEN, result);
2634 REPORTER_ASSERT(reporter, result.size() == 1);
2635 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2636 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
2637 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.0625f, EPSILON50));
2638 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002639 }
2640 {
2641 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002642 canvas.drawRects(SK_ColorMAGENTA, result);
2643 REPORTER_ASSERT(reporter, result.size() == 8);
2644
2645 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.00781f, EPSILON100));
2646 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 80, EPSILON100));
2647 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2648 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 160, EPSILON100));
2649
2650 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2651 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 80, EPSILON100));
2652 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2653 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 160, EPSILON100));
2654
2655 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON100));
2656 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 160, EPSILON100));
2657 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2658 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 240, EPSILON100));
2659
2660 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2661 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 160, EPSILON100));
2662 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.02344f, EPSILON20));
2663 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 240, EPSILON100));
2664
2665 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON100));
2666 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 240, EPSILON100));
2667 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.02344f, EPSILON20));
2668 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 320, EPSILON100));
2669
2670 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON100));
2671 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 320, EPSILON100));
2672 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.02344f, EPSILON20));
2673 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 400, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002674 }
2675 {
2676 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002677 canvas.drawRects(SK_ColorBLACK, result);
2678 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002679 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.72656f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002680 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946615f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002681 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.23047f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002682 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 80, EPSILON100));
2683
2684 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.23047f, EPSILON50));
2685 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946615f, EPSILON100));
2686 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.02344f, EPSILON20));
2687 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002688 }
2689 {
2690 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2691 REPORTER_ASSERT(reporter, result.empty());
2692 }
2693}
2694
Julia Lavrovac2228562019-08-08 16:51:27 -04002695// Checked: NO DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002696DEF_TEST(SkParagraph_GetRectsForRangeIncludeLineSpacingBottom, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002697 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002698 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002699 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeLineSpacingBottom.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002700 const char* text =
2701 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2702 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2703 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002704 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002705
2706 ParagraphStyle paragraphStyle;
2707 paragraphStyle.setTextAlign(TextAlign::kLeft);
2708 paragraphStyle.setMaxLines(10);
2709 paragraphStyle.turnHintingOff();
2710 TextStyle textStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002711 textStyle.setFontFamilies({SkString("Roboto")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002712 textStyle.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002713 textStyle.setHeight(1.6f);
2714 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002715 textStyle.setColor(SK_ColorBLACK);
2716 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2717 SkFontStyle::kUpright_Slant));
2718
2719 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2720 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002721 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002722 builder.pop();
2723
2724 auto paragraph = builder.Build();
2725 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002726 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002727
2728 RectHeightStyle heightStyle = RectHeightStyle::kIncludeLineSpacingBottom;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002729 RectWidthStyle widthStyle = RectWidthStyle::kMax;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002730 {
2731 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2732 REPORTER_ASSERT(reporter, result.empty());
2733 }
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002734
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002735 {
2736 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002737 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002738 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002739 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
2740 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2741 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 17.429f, EPSILON100));
2742 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002743 }
2744 {
2745 auto result = paragraph->getRectsForRange(2, 8, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002746 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002747 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002748 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 67.4298f, EPSILON100));
2749 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2750 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 190.007f, EPSILON100));
2751 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002752 }
2753 {
2754 auto result = paragraph->getRectsForRange(8, 21, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002755 canvas.drawRects(SK_ColorGREEN, result);
2756 REPORTER_ASSERT(reporter, result.size() == 1);
2757 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON100));
2758 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
2759 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 508.062f, EPSILON50));
2760 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002761 }
2762 {
2763 auto result = paragraph->getRectsForRange(30, 150, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002764 canvas.drawRects(SK_ColorMAGENTA, result);
2765 REPORTER_ASSERT(reporter, result.size() == 8);
2766
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002767 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 190.007f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002768 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 96.946f, EPSILON100));
2769 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 525.687f, EPSILON20));
2770 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 176.946f, EPSILON100));
2771
2772 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 525.687f, EPSILON20));
2773 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 96.946f, EPSILON100));
2774 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2775 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 176.946f, EPSILON100));
2776
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002777 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002778 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.top(), 176.946f, EPSILON100));
2779 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.right(), 531.574f, EPSILON20));
2780 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[2].rect.bottom(), 256.946f, EPSILON100));
2781
2782 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.left(), 531.574f, EPSILON20));
2783 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.top(), 176.946f, EPSILON100));
2784 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.right(), 570.023f, EPSILON20));
2785 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[3].rect.bottom(), 256.946f, EPSILON100));
2786
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002787 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002788 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.top(), 256.946f, EPSILON100));
2789 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.right(), 570.023f, EPSILON20));
2790 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[4].rect.bottom(), 336.946f, EPSILON100));
2791
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002792 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.left(), 0, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002793 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.top(), 336.946f, EPSILON100));
2794 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.right(), 570.023f, EPSILON20));
2795 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[5].rect.bottom(), 416.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002796 }
2797 {
2798 auto result = paragraph->getRectsForRange(19, 22, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002799 canvas.drawRects(SK_ColorBLACK, result);
2800 REPORTER_ASSERT(reporter, result.size() == 2); // DIFF
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002801 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 463.726f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002802 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 16.946f, EPSILON100));
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002803 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002804 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 96.946f, EPSILON100));
2805
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002806 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.left(), 530.230f, EPSILON20));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002807 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.top(), 16.946f, EPSILON100));
2808 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.right(), 570.023f, EPSILON20));
2809 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[1].rect.bottom(), 96.946f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002810 }
2811 {
2812 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2813 REPORTER_ASSERT(reporter, result.empty());
2814 }
2815}
2816
Julia Lavrova2813d452020-03-03 11:43:40 -05002817// This is the test I cannot accommodate
2818// Any text range gets a smallest glyph rectangle
2819DEF_TEST_DISABLED(SkParagraph_GetRectsForRangeIncludeCombiningCharacter, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002820 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002821 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002822 TestCanvas canvas("SkParagraph_GetRectsForRangeIncludeCombiningCharacter.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002823 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002824 const size_t len = strlen(text);
2825
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002826 ParagraphStyle paragraphStyle;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002827 paragraphStyle.setTextAlign(TextAlign::kLeft);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002828 paragraphStyle.setMaxLines(10);
2829 paragraphStyle.turnHintingOff();
2830 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2831
2832 TextStyle textStyle;
2833 textStyle.setFontFamilies({SkString("Roboto")});
2834 textStyle.setFontSize(50);
2835 textStyle.setLetterSpacing(1);
2836 textStyle.setWordSpacing(5);
2837 textStyle.setHeight(1);
2838 textStyle.setColor(SK_ColorBLACK);
2839
2840 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002841 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002842 builder.pop();
2843
2844 auto paragraph = builder.Build();
2845 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002846 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002847
2848 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002849 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
2850
2851 RectHeightStyle heightStyle = RectHeightStyle::kTight;
2852 RectWidthStyle widthStyle = RectWidthStyle::kTight;
2853 {
2854 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2855 REPORTER_ASSERT(reporter, result.empty());
2856 }
2857 {
2858 auto first = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
2859 auto second = paragraph->getRectsForRange(1, 2, heightStyle, widthStyle);
2860 auto last = paragraph->getRectsForRange(0, 2, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002861 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2862 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002863 }
2864 {
2865 auto first = paragraph->getRectsForRange(3, 4, heightStyle, widthStyle);
2866 auto second = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
2867 auto last = paragraph->getRectsForRange(3, 5, heightStyle, widthStyle);
Julia Lavrovac2228562019-08-08 16:51:27 -04002868 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 1 && last.size() == 1);
2869 REPORTER_ASSERT(reporter, second[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002870 }
2871 {
2872 auto first = paragraph->getRectsForRange(14, 15, heightStyle, widthStyle);
2873 auto second = paragraph->getRectsForRange(15, 16, heightStyle, widthStyle);
2874 auto third = paragraph->getRectsForRange(16, 17, heightStyle, widthStyle);
2875 auto last = paragraph->getRectsForRange(14, 17, heightStyle, widthStyle);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04002876 REPORTER_ASSERT(reporter, first.size() == 0 && second.size() == 0 && third.size() == 1 && last.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04002877 REPORTER_ASSERT(reporter, third[0].rect == last[0].rect);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002878 }
2879}
2880
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002881// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002882DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002883 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002884 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002885 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002886 // Minikin uses a hard coded list of unicode characters that he treats as invisible - as spaces.
2887 // It's absolutely wrong - invisibility is a glyph attribute, not character/grapheme.
2888 // Any attempt to substitute one for another leads to errors
2889 // (for instance, some fonts can use these hard coded characters for something that is visible)
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002890 const char* text = "01234   "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002891 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002892
2893 ParagraphStyle paragraphStyle;
2894 paragraphStyle.setTextAlign(TextAlign::kCenter);
2895 paragraphStyle.setMaxLines(10);
2896 paragraphStyle.turnHintingOff();
2897 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2898
2899 TextStyle textStyle;
2900 textStyle.setFontFamilies({SkString("Roboto")});
2901 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002902 textStyle.setHeight(1);
2903 textStyle.setColor(SK_ColorBLACK);
2904 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2905 SkFontStyle::kUpright_Slant));
2906
2907 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002908 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002909 builder.pop();
2910
2911 auto paragraph = builder.Build();
2912 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002913 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002914
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002915 // Some of the formatting lazily done on paint
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002916 RectHeightStyle heightStyle = RectHeightStyle::kMax;
2917 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002918 {
2919 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
2920 REPORTER_ASSERT(reporter, result.empty());
2921 }
2922
2923 {
2924 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002925 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002926 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002927 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
2928 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2929 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
2930 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002931 }
2932
2933 {
2934 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002935 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002936 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002937 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, EPSILON100));
2938 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2939 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, EPSILON100));
2940 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002941 }
2942
2943 {
2944 auto result = paragraph->getRectsForRange(4, 5, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002945 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002946 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002947 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2948 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2949 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 346.044f, EPSILON100));
2950 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002951 }
2952
2953 {
2954 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002955 canvas.drawRects(SK_ColorBLACK, result);
2956 REPORTER_ASSERT(reporter, result.size() == 1); // DIFF
2957 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, EPSILON100));
2958 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2959 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2960 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002961 }
2962
2963 {
2964 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002965 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002966 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002967 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, EPSILON100));
2968 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
2969 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, EPSILON100));
2970 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002971 }
2972
2973 {
2974 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
2975 REPORTER_ASSERT(reporter, result.empty());
2976 }
2977}
2978
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002979// Checked DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002980DEF_TEST(SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04002981 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002982 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04002983 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterParagraphNewlineCentered.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002984 const char* text = "01234\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04002985 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002986
2987 ParagraphStyle paragraphStyle;
2988 paragraphStyle.setTextAlign(TextAlign::kCenter);
2989 paragraphStyle.setMaxLines(10);
2990 paragraphStyle.turnHintingOff();
2991 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
2992
2993 TextStyle textStyle;
2994 textStyle.setFontFamilies({SkString("Roboto")});
2995 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002996 textStyle.setHeight(1);
2997 textStyle.setColor(SK_ColorBLACK);
2998 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
2999 SkFontStyle::kUpright_Slant));
3000
3001 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003002 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003003 builder.pop();
3004
3005 auto paragraph = builder.Build();
3006 paragraph->layout(550);
3007
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003008 paragraph->paint(canvas.get(), 0, 0);
3009
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003010 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003011 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3012
3013 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3014 RectWidthStyle widthStyle = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003015 {
3016 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3017 REPORTER_ASSERT(reporter, result.empty());
3018 }
3019
3020 {
3021 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrova526df262019-08-21 17:49:44 -04003022 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003023 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003024 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, EPSILON100));
3025 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, EPSILON100));
3026 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, EPSILON100));
3027 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003028 }
3029
3030 {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003031 auto result = paragraph->getRectsForRange(6, 7, heightStyle, widthStyle);
3032 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003033 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003034 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 275.0f, EPSILON100));
3035 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.406f, EPSILON100));
3036 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275.0f, EPSILON100));
3037 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003038 }
3039}
3040
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003041// Checked NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003042DEF_TEST(SkParagraph_GetRectsForRangeCenterMultiLineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003043 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003044 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003045 TestCanvas canvas("SkParagraph_GetRectsForRangeCenterMultiLineParagraph.png");
3046 const char* text = "01234   \n0123  "; // includes ideographic space and english space.
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003047 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003048
3049 ParagraphStyle paragraphStyle;
3050 paragraphStyle.setTextAlign(TextAlign::kCenter);
3051 paragraphStyle.setMaxLines(10);
3052 paragraphStyle.turnHintingOff();
3053 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3054
3055 TextStyle textStyle;
3056 textStyle.setFontFamilies({SkString("Roboto")});
3057 textStyle.setFontSize(50);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003058 textStyle.setHeight(1);
3059 textStyle.setColor(SK_ColorBLACK);
3060 textStyle.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
3061 SkFontStyle::kUpright_Slant));
3062
3063 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003064 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003065 builder.pop();
3066
3067 auto paragraph = builder.Build();
3068 paragraph->layout(550);
3069
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003070 paragraph->paint(canvas.get(), 0, 0);
3071
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003072 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003073
3074 REPORTER_ASSERT(reporter, impl->lines().size() == 2);
3075
3076 RectHeightStyle heightStyle = RectHeightStyle::kMax;
3077 RectWidthStyle widthStyle = RectWidthStyle::kTight;
3078 SkScalar epsilon = 0.01f;
3079 {
3080 auto result = paragraph->getRectsForRange(0, 0, heightStyle, widthStyle);
3081 REPORTER_ASSERT(reporter, result.empty());
3082 }
3083 {
3084 auto result = paragraph->getRectsForRange(0, 1, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003085 canvas.drawRects(SK_ColorRED, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003086 REPORTER_ASSERT(reporter, result.size() == 1);
3087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 203.955f, epsilon));
3088 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 232.373f, epsilon));
3090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3091 }
3092 {
3093 auto result = paragraph->getRectsForRange(2, 4, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003094 canvas.drawRects(SK_ColorBLUE, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003095 REPORTER_ASSERT(reporter, result.size() == 1);
3096 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 260.791f, epsilon));
3097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
3098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 317.626f, epsilon));
3099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3100 }
3101 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003102 auto result = paragraph->getRectsForRange(4, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003103 canvas.drawRects(SK_ColorGREEN, result);
Julia Lavrovac2228562019-08-08 16:51:27 -04003104 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003105 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 317.626f, epsilon));
3106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04003107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3109 }
3110 {
3111 auto result = paragraph->getRectsForRange(5, 6, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003112 canvas.drawRects(SK_ColorYELLOW, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003113 REPORTER_ASSERT(reporter, result.size() == 1);
3114 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 346.044f, epsilon));
3115 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 0.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003116 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 358.494f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003117 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 59, epsilon));
3118 }
3119 {
3120 auto result = paragraph->getRectsForRange(10, 12, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003121 canvas.drawRects(SK_ColorCYAN, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003122 REPORTER_ASSERT(reporter, result.size() == 1);
3123 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 218.164f, epsilon));
3124 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
3125 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 275, epsilon));
3126 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3127 }
3128 {
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003129 auto result = paragraph->getRectsForRange(14, 18, heightStyle, widthStyle);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003130 canvas.drawRects(SK_ColorBLACK, result);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003131 REPORTER_ASSERT(reporter, result.size() == 1);
3132 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 331.835f, epsilon));
3133 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 59.40625f, epsilon));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003134 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 419.189f, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003135 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 118, epsilon));
3136 }
3137 {
3138 auto result = paragraph->getRectsForRange(21, 21, heightStyle, widthStyle);
3139 REPORTER_ASSERT(reporter, result.empty());
3140 }
3141}
3142
Julia Lavrovac2228562019-08-08 16:51:27 -04003143// Checked: DIFF (line height rounding error)
3144DEF_TEST(SkParagraph_GetRectsForRangeStrut, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003145 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003146 if (!fontCollection->fontsFound()) return;
Julia Lavrovac2228562019-08-08 16:51:27 -04003147 TestCanvas canvas("SkParagraph_GetRectsForRangeStrut.png");
3148 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003149 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003150
3151 StrutStyle strutStyle;
3152 strutStyle.setStrutEnabled(true);
3153 strutStyle.setFontFamilies({SkString("Roboto")});
3154 strutStyle.setFontSize(14.0);
3155
3156 ParagraphStyle paragraphStyle;
3157 paragraphStyle.setStrutStyle(strutStyle);
3158
3159 TextStyle textStyle;
3160 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3161 textStyle.setFontSize(20);
3162 textStyle.setColor(SK_ColorBLACK);
3163
3164 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3165 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003166 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003167 builder.pop();
3168
3169 auto paragraph = builder.Build();
3170 paragraph->layout(550);
3171 paragraph->paint(canvas.get(), 0, 0);
3172
3173 {
3174 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3175 canvas.drawRects(SK_ColorGREEN, result);
3176 REPORTER_ASSERT(reporter, result.size() == 1);
3177 }
3178
3179 {
3180 auto result = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3181 canvas.drawRects(SK_ColorRED, result);
3182 REPORTER_ASSERT(reporter, result.size() == 1);
3183 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.left(), 0, EPSILON100));
3184 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.top(), 10.611f, EPSILON2));
3185 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.right(), 118.605f, EPSILON50));
3186 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(result[0].rect.bottom(), 27.017f, EPSILON2));
3187 }
3188}
3189
3190// Checked: NO DIFF
3191DEF_TEST(SkParagraph_GetRectsForRangeStrutFallback, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003192 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003193 if (!fontCollection->fontsFound()) return;
3194 TestCanvas canvas("SkParagraph_GetRectsForRangeStrutFallback.png");
3195 const char* text = "Chinese 字典";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003196 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003197
3198 StrutStyle strutStyle;
3199 strutStyle.setStrutEnabled(false);
3200
3201 ParagraphStyle paragraphStyle;
3202 paragraphStyle.setStrutStyle(strutStyle);
3203
3204 TextStyle textStyle;
3205 textStyle.setFontFamilies({SkString("Noto Sans CJK JP")});
3206 textStyle.setFontSize(20);
3207 textStyle.setColor(SK_ColorBLACK);
3208
3209 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3210 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003211 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003212 builder.pop();
3213
3214 auto paragraph = builder.Build();
3215 paragraph->layout(550);
3216 paragraph->paint(canvas.get(), 0, 0);
3217
3218
3219 auto result1 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kTight, RectWidthStyle::kMax);
3220 canvas.drawRects(SK_ColorGREEN, result1);
3221 REPORTER_ASSERT(reporter, result1.size() == 1);
3222
3223 auto result2 = paragraph->getRectsForRange(0, 10, RectHeightStyle::kStrut, RectWidthStyle::kMax);
3224 canvas.drawRects(SK_ColorRED, result2);
3225 REPORTER_ASSERT(reporter, result2.size() == 1);
3226
3227 REPORTER_ASSERT(reporter, result1[0].rect == result2[0].rect);
3228}
3229
3230// Checked: DIFF (small in numbers)
3231DEF_TEST(SkParagraph_GetWordBoundaryParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003232 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003233 if (!fontCollection->fontsFound()) return;
3234 TestCanvas canvas("SkParagraph_GetWordBoundaryParagraph.png");
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003235 const char* text = "12345 67890 12345 67890 12345 67890 12345 "
3236 "67890 12345 67890 12345 67890 12345";
3237 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003238 ParagraphStyle paragraphStyle;
3239 paragraphStyle.setTextAlign(TextAlign::kLeft);
3240 paragraphStyle.setMaxLines(10);
3241 paragraphStyle.turnHintingOff();
3242 TextStyle textStyle;
3243 textStyle.setFontFamilies({SkString("Roboto")});
3244 textStyle.setFontSize(52);
3245 textStyle.setLetterSpacing(1.19039f);
3246 textStyle.setWordSpacing(5);
3247 textStyle.setHeight(1.5);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003248 textStyle.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003249 textStyle.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003250
3251 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
3252 builder.pushStyle(textStyle);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003253 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003254 builder.pop();
3255
3256 auto paragraph = builder.Build();
3257 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003258 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003259
3260 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(0) == SkRange<size_t>(0, 5));
3261 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(1) == SkRange<size_t>(0, 5));
3262 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(2) == SkRange<size_t>(0, 5));
3263 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(3) == SkRange<size_t>(0, 5));
3264 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(4) == SkRange<size_t>(0, 5));
Julia Lavrovac2228562019-08-08 16:51:27 -04003265 auto boxes = paragraph->getRectsForRange(5, 6, RectHeightStyle::kMax, RectWidthStyle::kTight);
3266 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003267
3268 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(5) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003269 boxes = paragraph->getRectsForRange(6, 7, 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 Lavrovac2228562019-08-08 16:51:27 -04003272 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(6) == SkRange<size_t>(5, 7));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003273 boxes = paragraph->getRectsForRange(7, 8, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003274 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003275
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003276 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(7) == SkRange<size_t>(7, 12));
3277 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(8) == SkRange<size_t>(7, 12));
3278 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(9) == SkRange<size_t>(7, 12));
3279 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(10) == SkRange<size_t>(7, 12));
3280 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(11) == SkRange<size_t>(7, 12));
3281 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(12) == SkRange<size_t>(12, 13));
3282 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(13) == SkRange<size_t>(13, 18));
3283 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(30) == SkRange<size_t>(30, 31));
3284
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003285 boxes = paragraph->getRectsForRange(12, 13, 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(13, 14, 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(18, 19, 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(19, 20, 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(24, 25, 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(25, 26, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003296 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003297 boxes = paragraph->getRectsForRange(30, 31, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003298 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003299 boxes = paragraph->getRectsForRange(31, 32, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovac2228562019-08-08 16:51:27 -04003300 canvas.drawLines(SK_ColorRED, boxes);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003301
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003302 auto outLen = static_cast<ParagraphImpl*>(paragraph.get())->text().size();
3303 REPORTER_ASSERT(reporter, paragraph->getWordBoundary(outLen - 1) == SkRange<size_t>(outLen - 5, outLen));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003304}
3305
Julia Lavrovac2228562019-08-08 16:51:27 -04003306// Checked: DIFF (unclear)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003307DEF_TEST(SkParagraph_SpacingParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003308 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003309 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003310 TestCanvas canvas("SkParagraph_SpacingParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003311 ParagraphStyle paragraph_style;
3312 paragraph_style.setMaxLines(10);
3313 paragraph_style.setTextAlign(TextAlign::kLeft);
3314 paragraph_style.turnHintingOff();
3315 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3316
3317 TextStyle text_style;
3318 text_style.setFontFamilies({SkString("Roboto")});
3319 text_style.setFontSize(50);
3320 text_style.setLetterSpacing(20);
3321 text_style.setWordSpacing(0);
3322 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003323 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003324 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003325 builder.pop();
3326
3327 text_style.setLetterSpacing(10);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003328 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003329 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003330 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003331 builder.pop();
3332
3333 text_style.setLetterSpacing(20);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003334 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003335 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003336 builder.addText("H", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003337 builder.pop();
3338
3339 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003340 text_style.setWordSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003341 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003342 builder.addText("|", 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003343 builder.pop();
3344
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003345 const char* hSpace = "H ";
3346 const size_t len = strlen(hSpace);
3347
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003348 text_style.setLetterSpacing(0);
3349 text_style.setWordSpacing(20);
3350 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003351 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003352 builder.pop();
3353
3354 text_style.setLetterSpacing(0);
3355 text_style.setWordSpacing(0);
3356 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003357 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003358 builder.pop();
3359
3360 text_style.setLetterSpacing(0);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003361 text_style.setLetterSpacing(0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003362 text_style.setWordSpacing(20);
3363 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003364 builder.addText(hSpace, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003365 builder.pop();
3366
3367 auto paragraph = builder.Build();
3368 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003369 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003370
3371 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3372 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3373 size_t index = 0;
3374 impl->lines().begin()->scanStyles(StyleType::kLetterSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003375 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3376 ++index;
3377 return true;
3378 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003379 REPORTER_ASSERT(reporter, index == 4);
3380 index = 0;
3381 impl->lines().begin()->scanStyles(StyleType::kWordSpacing,
Julia Lavrova526df262019-08-21 17:49:44 -04003382 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
3383 ++index;
3384 return true;
3385 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003386 REPORTER_ASSERT(reporter, index == 4);
3387}
3388
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003389// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003390DEF_TEST(SkParagraph_LongWordParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003391 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003392 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003393 TestCanvas canvas("SkParagraph_LongWordParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003394 const char* text =
3395 "A "
3396 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3397 "wouldbeagoodthingbecausethebreakingisworking.";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003398 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003399
3400 ParagraphStyle paragraph_style;
3401 paragraph_style.turnHintingOff();
3402 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3403
3404 TextStyle text_style;
3405 text_style.setFontFamilies({SkString("Roboto")});
3406 text_style.setColor(SK_ColorRED);
3407 text_style.setFontSize(31);
3408 text_style.setLetterSpacing(0);
3409 text_style.setWordSpacing(0);
3410 text_style.setColor(SK_ColorBLACK);
3411 text_style.setHeight(1);
3412 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003413 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003414 builder.pop();
3415
3416 auto paragraph = builder.Build();
3417 paragraph->layout(TestCanvasWidth / 2);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003418 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003419
3420 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3421 REPORTER_ASSERT(reporter, impl->text().size() == std::string{text}.length());
3422 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3423 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
Julia Lavrova5207f352019-06-21 12:22:32 -04003424 REPORTER_ASSERT(reporter, impl->styles()[0].fStyle.equals(text_style));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003425 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
3426
3427 REPORTER_ASSERT(reporter, impl->lines()[0].width() > TestCanvasWidth / 2 - 20);
3428 REPORTER_ASSERT(reporter, impl->lines()[1].width() > TestCanvasWidth / 2 - 20);
3429 REPORTER_ASSERT(reporter, impl->lines()[2].width() > TestCanvasWidth / 2 - 20);
3430}
3431
Julia Lavrovac2228562019-08-08 16:51:27 -04003432// Checked: DIFF?
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003433DEF_TEST(SkParagraph_KernScaleParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003434 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003435 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003436 TestCanvas canvas("SkParagraph_KernScaleParagraph.png");
3437
3438 const char* text1 = "AVAVAWAH A0 V0 VA To The Lo";
3439 const char* text2 = " Dialog Text List lots of words to see "
3440 "if kerning works on a bigger set of characters AVAVAW";
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003441 float scale = 3.0f;
3442 ParagraphStyle paragraph_style;
3443 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3444 TextStyle text_style;
3445 text_style.setFontFamilies({SkString("Droid Serif")});
3446 text_style.setFontSize(100 / scale);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003447 text_style.setColor(SK_ColorBLACK);
3448
3449 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003450 builder.addText(text1, strlen(text1));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003451 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003452 builder.addText("A", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003453 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003454 builder.addText("V", 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003455 text_style.setFontSize(14 / scale);
3456 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003457 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003458 builder.pop();
3459
3460 auto paragraph = builder.Build();
3461 paragraph->layout(TestCanvasWidth / scale);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003462 canvas.get()->scale(scale, scale);
3463 paragraph->paint(canvas.get(), 0, 0);
3464 canvas.get()->scale(1, 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003465
3466 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003467
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003468 // First and second lines must have the same width, the third one must be bigger
Julia Lavrova6e6333f2019-06-17 10:34:10 -04003469 REPORTER_ASSERT(reporter, impl->lines().size() == 3);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003470 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].width(), 285.858f, EPSILON100));
3471 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].width(), 329.709f, EPSILON100));
3472 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].width(), 120.619f, EPSILON100));
3473 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[0].height(), 39.00f, EPSILON100));
3474 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[1].height(), 39.00f, EPSILON100));
3475 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->lines()[2].height(), 05.00f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003476}
3477
Julia Lavrovac2228562019-08-08 16:51:27 -04003478// Checked: DIFF+
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003479DEF_TEST(SkParagraph_NewlineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003480 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003481 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003482 TestCanvas canvas("SkParagraph_NewlineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003483 const char* text =
3484 "line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3485 "test1 test2 test3 test4";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003486 const size_t len = strlen(text);
3487
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003488 ParagraphStyle paragraph_style;
3489 paragraph_style.turnHintingOff();
3490 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3491
3492 TextStyle text_style;
3493 text_style.setFontFamilies({SkString("Roboto")});
3494 text_style.setColor(SK_ColorRED);
3495 text_style.setFontSize(60);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003496 text_style.setColor(SK_ColorBLACK);
3497 text_style.setHeight(1);
3498 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003499 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003500 builder.pop();
3501
3502 auto paragraph = builder.Build();
3503 paragraph->layout(TestCanvasWidth - 300);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003504 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003505
3506 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3507 // Minikin does not count empty lines but SkParagraph does
3508 REPORTER_ASSERT(reporter, impl->lines().size() == 7);
3509
3510 REPORTER_ASSERT(reporter, impl->lines()[0].offset().fY == 0);
3511 REPORTER_ASSERT(reporter, impl->lines()[1].offset().fY == 70);
3512 REPORTER_ASSERT(reporter, impl->lines()[2].offset().fY == 140);
3513 REPORTER_ASSERT(reporter, impl->lines()[3].offset().fY == 210);
3514 REPORTER_ASSERT(reporter, impl->lines()[4].offset().fY == 280); // Empty line
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04003515 REPORTER_ASSERT(reporter, impl->lines()[5].offset().fY == 296);
3516 REPORTER_ASSERT(reporter, impl->lines()[6].offset().fY == 366);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003517}
3518
Julia Lavrova526df262019-08-21 17:49:44 -04003519// TODO: Fix underline
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003520DEF_TEST(SkParagraph_EmojiParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003521 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003522 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003523 TestCanvas canvas("SkParagraph_EmojiParagraph.png");
3524 const char* text =
3525 "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨‍🚀👨‍🚒🙋‍♂️👳👨‍👨‍👧‍👧\
3526 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\
3527 ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\
3528 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003529 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003530
3531 ParagraphStyle paragraph_style;
3532 paragraph_style.turnHintingOff();
3533 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3534
3535 TextStyle text_style;
3536 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3537 text_style.setFontSize(50);
3538 text_style.setDecoration(TextDecoration::kUnderline);
3539 text_style.setColor(SK_ColorBLACK);
3540 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003541 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003542 builder.pop();
3543
3544 auto paragraph = builder.Build();
3545 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003546 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003547
Julia Lavrova3281b962019-12-02 11:32:25 -05003548 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
3549
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003550 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003551
3552 REPORTER_ASSERT(reporter, impl->lines().size() == 8);
3553 for (auto& line : impl->lines()) {
3554 if (&line != impl->lines().end() - 1) {
3555 REPORTER_ASSERT(reporter, line.width() == 998.25f);
3556 } else {
3557 REPORTER_ASSERT(reporter, line.width() < 998.25f);
3558 }
3559 REPORTER_ASSERT(reporter, line.height() == 59);
3560 }
3561}
3562
Julia Lavrovac2228562019-08-08 16:51:27 -04003563// Checked: DIFF+
3564DEF_TEST(SkParagraph_EmojiMultiLineRectsParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003565 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04003566 if (!fontCollection->fontsFound()) return;
3567 TestCanvas canvas("SkParagraph_EmojiMultiLineRectsParagraph.png");
3568 const char* text =
3569 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧i🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3570 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3571 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3572 "👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸👩‍👩‍👦👩‍👩‍👧‍👧🇺🇸"
3573 "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴‍♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓"
3574 "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️‍🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003575 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04003576
3577 ParagraphStyle paragraph_style;
3578 paragraph_style.turnHintingOff();
3579 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3580
3581 TextStyle text_style;
3582 text_style.setFontFamilies({SkString("Noto Color Emoji")});
3583 text_style.setFontSize(50);
3584 text_style.setColor(SK_ColorBLACK);
3585 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003586 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04003587 builder.pop();
3588
3589 auto paragraph = builder.Build();
3590 paragraph->layout(TestCanvasWidth - 300);
3591 paragraph->paint(canvas.get(), 0, 0);
3592
3593 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
3594 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
3595
3596 auto result = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
3597 REPORTER_ASSERT(reporter, result.size() == 0);
3598
3599 result = paragraph->getRectsForRange(0, 119, rect_height_style, rect_width_style);
3600 REPORTER_ASSERT(reporter, result.size() == 2);
3601 canvas.drawRects(SK_ColorRED, result);
3602
3603 result = paragraph->getRectsForRange(122, 132, rect_height_style, rect_width_style);
Julia Lavrova2813d452020-03-03 11:43:40 -05003604 REPORTER_ASSERT(reporter, result.size() == 1);
Julia Lavrovac2228562019-08-08 16:51:27 -04003605 canvas.drawRects(SK_ColorBLUE, result);
3606
3607 auto pos = paragraph->getGlyphPositionAtCoordinate(610, 100).position;
3608 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3609 REPORTER_ASSERT(reporter, result.size() == 2);
3610 canvas.drawRects(SK_ColorGREEN, result);
3611
3612 pos = paragraph->getGlyphPositionAtCoordinate(580, 100).position;
3613 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3614 REPORTER_ASSERT(reporter, result.size() == 2);
3615 canvas.drawRects(SK_ColorGREEN, result);
3616
3617 pos = paragraph->getGlyphPositionAtCoordinate(560, 100).position;
3618 result = paragraph->getRectsForRange(0, pos, rect_height_style, rect_width_style);
3619 REPORTER_ASSERT(reporter, result.size() == 2);
3620 canvas.drawRects(SK_ColorGREEN, result);
3621}
3622
Julia Lavrova916a9042019-08-08 16:51:27 -04003623DEF_TEST(SkParagraph_HyphenBreakParagraph, reporter) {
3624 SkDebugf("Hyphens are not implemented, and will not be implemented soon.\n");
3625}
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003626
Julia Lavrovac2228562019-08-08 16:51:27 -04003627// Checked: DIFF (line breaking)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003628DEF_TEST(SkParagraph_RepeatLayoutParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003629 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003630 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003631 TestCanvas canvas("SkParagraph_RepeatLayoutParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003632 const char* text =
3633 "Sentence to layout at diff widths to get diff line counts. short words "
3634 "short words short words short words short words short words short words "
3635 "short words short words short words short words short words short words "
3636 "end";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003637 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003638
3639 ParagraphStyle paragraph_style;
3640 paragraph_style.turnHintingOff();
3641 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3642
3643 TextStyle text_style;
3644 text_style.setFontFamilies({SkString("Roboto")});
3645 text_style.setFontSize(31);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003646 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003647 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003648 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003649 builder.pop();
3650
3651 auto paragraph = builder.Build();
3652 paragraph->layout(300);
3653
3654 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3655 // Some of the formatting lazily done on paint
3656 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3657 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3658 REPORTER_ASSERT(reporter, impl->lines().size() == 12);
3659
3660 paragraph->layout(600);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003661 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003662 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3663 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3664 REPORTER_ASSERT(reporter, impl->lines().size() == 6);
3665}
3666
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003667// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003668DEF_TEST(SkParagraph_Ellipsize, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003669 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003670 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003671 TestCanvas canvas("SkParagraph_Ellipsize.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003672 const char* text =
3673 "This is a very long sentence to test if the text will properly wrap "
3674 "around and go to the next line. Sometimes, short sentence. Longer "
3675 "sentences are okay too because they are nessecary. Very short. ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003676 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003677
3678 ParagraphStyle paragraph_style;
3679 paragraph_style.setMaxLines(1);
3680 paragraph_style.setEllipsis(u"\u2026");
3681 paragraph_style.turnHintingOff();
3682 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3683
3684 TextStyle text_style;
3685 text_style.setFontFamilies({SkString("Roboto")});
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003686 text_style.setColor(SK_ColorBLACK);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003687 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003688 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003689 builder.pop();
3690
3691 auto paragraph = builder.Build();
3692 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003693 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003694
3695 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003696
3697 // Check that the ellipsizer limited the text to one line and did not wrap to a second line.
3698 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3699
3700 auto& line = impl->lines()[0];
3701 REPORTER_ASSERT(reporter, line.ellipsis() != nullptr);
Julia Lavrova526df262019-08-21 17:49:44 -04003702 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003703}
3704
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003705// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003706DEF_TEST(SkParagraph_UnderlineShiftParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003707 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003708 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003709 TestCanvas canvas("SkParagraph_UnderlineShiftParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003710 const char* text1 = "fluttser ";
3711 const char* text2 = "mdje";
3712 const char* text3 = "fluttser mdje";
3713
3714 ParagraphStyle paragraph_style;
3715 paragraph_style.turnHintingOff();
3716 paragraph_style.setTextAlign(TextAlign::kLeft);
3717 paragraph_style.setMaxLines(2);
3718 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3719
3720 TextStyle text_style;
3721 text_style.setFontFamilies({SkString("Roboto")});
3722 text_style.setColor(SK_ColorBLACK);
3723 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003724 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003725 text_style.setDecoration(TextDecoration::kUnderline);
3726 text_style.setDecorationColor(SK_ColorBLACK);
3727 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003728 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003729 builder.pop();
3730
3731 auto paragraph = builder.Build();
3732 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003733 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003734
3735 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3736
3737 ParagraphBuilderImpl builder1(paragraph_style, fontCollection);
3738 text_style.setDecoration(TextDecoration::kNoDecoration);
3739 builder1.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003740 builder1.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003741 builder1.pop();
3742
3743 auto paragraph1 = builder1.Build();
3744 paragraph1->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003745 paragraph1->paint(canvas.get(), 0, 25);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003746
3747 auto impl1 = static_cast<ParagraphImpl*>(paragraph1.get());
3748
3749 REPORTER_ASSERT(reporter, impl->lines().size() == 1);
3750 REPORTER_ASSERT(reporter, impl1->lines().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003751
3752 auto rect = paragraph->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3753 .front()
3754 .rect;
3755 auto rect1 = paragraph1->getRectsForRange(0, 12, RectHeightStyle::kMax, RectWidthStyle::kTight)
3756 .front()
3757 .rect;
3758 REPORTER_ASSERT(reporter, rect.fLeft == rect1.fLeft);
3759 REPORTER_ASSERT(reporter, rect.fRight == rect1.fRight);
3760
3761 for (size_t i = 0; i < 12; ++i) {
Julia Lavrova2813d452020-03-03 11:43:40 -05003762 // Not all ranges produce a rectangle ("fl" goes into one cluster so [0:1) is empty)
3763 auto r1 = paragraph->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
3764 auto r2 = paragraph1->getRectsForRange(i, i + 1, RectHeightStyle::kMax, RectWidthStyle::kTight);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003765
Julia Lavrova2813d452020-03-03 11:43:40 -05003766 REPORTER_ASSERT(reporter, r1.size() == r2.size());
3767 if (!r1.empty() && !r2.empty()) {
3768 REPORTER_ASSERT(reporter, r1.front().rect.fLeft == r2.front().rect.fLeft);
3769 REPORTER_ASSERT(reporter, r1.front().rect.fRight == r2.front().rect.fRight);
3770 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003771 }
3772}
3773
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003774// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003775DEF_TEST(SkParagraph_SimpleShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003776 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003777 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003778 TestCanvas canvas("SkParagraph_SimpleShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003779 const char* text = "Hello World Text Dialog";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003780 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003781
3782 ParagraphStyle paragraph_style;
3783 paragraph_style.turnHintingOff();
3784 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3785
3786 TextStyle text_style;
3787 text_style.setFontFamilies({SkString("Roboto")});
3788 text_style.setColor(SK_ColorBLACK);
3789 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0));
3790 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003791 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003792
3793 auto paragraph = builder.Build();
3794 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003795 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003796
3797 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3798
3799 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
3800 REPORTER_ASSERT(reporter, impl->styles().size() == 1);
3801 size_t index = 0;
3802 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003803 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003804 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003805 REPORTER_ASSERT(reporter, index == 0 && style.equals(text_style));
3806 ++index;
3807 return true;
3808 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003809 }
3810}
3811
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003812// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003813DEF_TEST(SkParagraph_ComplexShadow, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003814 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003815 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003816 TestCanvas canvas("SkParagraph_ComplexShadow.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003817 const char* text = "Text Chunk ";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003818 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003819
3820 ParagraphStyle paragraph_style;
3821 paragraph_style.turnHintingOff();
3822 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3823
3824 TextStyle text_style;
3825 text_style.setFontFamilies({SkString("Roboto")});
3826 text_style.setColor(SK_ColorBLACK);
3827 text_style.addShadow(TextShadow(SK_ColorBLACK, SkPoint::Make(2.0f, 2.0f), 1.0f));
3828 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003829 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003830
3831 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(2.0f, 2.0f), 5.0f));
3832 text_style.addShadow(TextShadow(SK_ColorGREEN, SkPoint::Make(10.0f, -5.0f), 3.0f));
3833 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003834 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003835 builder.pop();
3836
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003837 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003838
3839 text_style.addShadow(TextShadow(SK_ColorRED, SkPoint::Make(0.0f, 1.0f), 0.0f));
3840 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003841 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003842 builder.pop();
3843
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003844 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003845
3846 auto paragraph = builder.Build();
3847 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003848 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003849
3850 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3851
3852 size_t index = 0;
3853 for (auto& line : impl->lines()) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003854 line.scanStyles(StyleType::kShadow,
Julia Lavrova526df262019-08-21 17:49:44 -04003855 [&](TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003856 ++index;
3857 switch (index) {
3858 case 1:
3859 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3860 break;
3861 case 2:
3862 REPORTER_ASSERT(reporter, style.getShadowNumber() == 3);
3863 break;
3864 case 3:
3865 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3866 break;
3867 case 4:
3868 REPORTER_ASSERT(reporter, style.getShadowNumber() == 4);
3869 REPORTER_ASSERT(reporter, style.equals(text_style));
3870 break;
3871 case 5:
3872 REPORTER_ASSERT(reporter, style.getShadowNumber() == 1);
3873 break;
3874 default:
3875 REPORTER_ASSERT(reporter, false);
3876 }
3877 return true;
3878 });
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003879 }
3880}
3881
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003882// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003883DEF_TEST(SkParagraph_BaselineParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003884 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003885 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003886 TestCanvas canvas("SkParagraph_BaselineParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003887 const char* text =
3888 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
3889 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003890 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003891
3892 ParagraphStyle paragraph_style;
3893 paragraph_style.turnHintingOff();
3894 paragraph_style.setMaxLines(14);
3895 paragraph_style.setTextAlign(TextAlign::kJustify);
3896 paragraph_style.setHeight(1.5);
3897 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3898
3899 TextStyle text_style;
3900 text_style.setFontFamilies({SkString("Source Han Serif CN")});
3901 text_style.setColor(SK_ColorBLACK);
3902 text_style.setFontSize(55);
3903 text_style.setLetterSpacing(2);
3904 text_style.setDecorationStyle(TextDecorationStyle::kSolid);
3905 text_style.setDecorationColor(SK_ColorBLACK);
3906 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003907 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003908 builder.pop();
3909
3910 auto paragraph = builder.Build();
3911 paragraph->layout(TestCanvasWidth - 100);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003912 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003913
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003914 SkRect rect1 = SkRect::MakeXYWH(0, paragraph->getIdeographicBaseline(),
3915 paragraph->getMaxWidth(),
3916 paragraph->getIdeographicBaseline());
3917 SkRect rect2 = SkRect::MakeXYWH(0, paragraph->getAlphabeticBaseline(),
3918 paragraph->getMaxWidth(),
3919 paragraph->getAlphabeticBaseline());
3920 canvas.drawLine(SK_ColorRED, rect1, false);
3921 canvas.drawLine(SK_ColorGREEN, rect2, false);
3922
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003923 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003924 SkScalarNearlyEqual(paragraph->getIdeographicBaseline(), 79.035f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003925 REPORTER_ASSERT(reporter,
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003926 SkScalarNearlyEqual(paragraph->getAlphabeticBaseline(), 63.305f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003927}
3928
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003929// Checked: NO DIFF (number of runs only)
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003930DEF_TEST(SkParagraph_FontFallbackParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04003931 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003932 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003933 TestCanvas canvas("SkParagraph_FontFallbackParagraph.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003934
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003935 const char* text1 = "Roboto 字典 "; // Roboto + unresolved
3936 const char* text2 = "Homemade Apple 字典"; // Homemade Apple + Noto Sans...
3937 const char* text3 = "Chinese 字典"; // Homemade Apple + Source Han
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003938
3939 ParagraphStyle paragraph_style;
3940 paragraph_style.turnHintingOff();
3941 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
3942
3943 TextStyle text_style;
3944 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003945 SkString("Not a real font"),
3946 SkString("Also a fake font"),
3947 SkString("So fake it is obvious"),
3948 SkString("Next one should be a real font..."),
3949 SkString("Roboto"),
3950 SkString("another fake one in between"),
3951 SkString("Homemade Apple"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003952 });
3953 text_style.setColor(SK_ColorBLACK);
3954 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003955 builder.addText(text1, strlen(text1));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003956
3957 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003958 SkString("Not a real font"),
3959 SkString("Also a fake font"),
3960 SkString("So fake it is obvious"),
3961 SkString("Homemade Apple"),
3962 SkString("Next one should be a real font..."),
3963 SkString("Roboto"),
3964 SkString("another fake one in between"),
3965 SkString("Noto Sans CJK JP"),
3966 SkString("Source Han Serif CN"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003967 });
3968 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003969 builder.addText(text2, strlen(text2));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003970
3971 text_style.setFontFamilies({
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003972 SkString("Not a real font"),
3973 SkString("Also a fake font"),
3974 SkString("So fake it is obvious"),
3975 SkString("Homemade Apple"),
3976 SkString("Next one should be a real font..."),
3977 SkString("Roboto"),
3978 SkString("another fake one in between"),
3979 SkString("Source Han Serif CN"),
3980 SkString("Noto Sans CJK JP"),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003981 });
3982 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04003983 builder.addText(text3, strlen(text3));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003984
3985 builder.pop();
3986
3987 auto paragraph = builder.Build();
Julia Lavrova3281b962019-12-02 11:32:25 -05003988 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == -1); // Not shaped yet
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003989 paragraph->layout(TestCanvasWidth);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04003990 paragraph->paint(canvas.get(), 10.0, 15.0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003991
Julia Lavrova131c5ad2020-07-20 11:05:26 -04003992 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 3); // From the text1 ("字典 " - including the last space)
Julia Lavrova3281b962019-12-02 11:32:25 -05003993
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003994 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
3995
Julia Lavrova131c5ad2020-07-20 11:05:26 -04003996 REPORTER_ASSERT(reporter, impl->runs().size() == 6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04003997
Julia Lavrova131c5ad2020-07-20 11:05:26 -04003998 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
3999 // script (Minikin merges the first 2 into one because of unresolved)
4000 // [Apple + Unresolved ] 0, 1
4001 // [Apple + Noto] 2, 3
4002 // [Apple + Han] 4, 5
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004003 auto robotoAdvance = impl->runs()[0].advance().fX +
Julia Lavrova131c5ad2020-07-20 11:05:26 -04004004 impl->runs()[1].advance().fX;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004005 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
Julia Lavrova131c5ad2020-07-20 11:05:26 -04004006 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[2].advance().fX, 139.125f, EPSILON100));
4007 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 27.999f, EPSILON100));
4008 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 62.248f, EPSILON100));
4009 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004010
4011 // When a different font is resolved, then the metrics are different.
Julia Lavrova131c5ad2020-07-20 11:05:26 -04004012 REPORTER_ASSERT(reporter, impl->runs()[3].correctAscent() != impl->runs()[5].correctAscent());
4013 REPORTER_ASSERT(reporter, impl->runs()[3].correctDescent() != impl->runs()[5].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004014}
4015
Julia Lavrovac2228562019-08-08 16:51:27 -04004016// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004017DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004018 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004019 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004020 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004021 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004022 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004023 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004024
4025 ParagraphStyle paragraph_style;
4026 paragraph_style.setMaxLines(10);
4027 paragraph_style.setTextAlign(TextAlign::kLeft);
4028 paragraph_style.turnHintingOff();
4029
4030 StrutStyle strut_style;
4031 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004032 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004033 strut_style.setFontSize(50);
4034 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004035 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004036 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004037 paragraph_style.setStrutStyle(strut_style);
4038
4039 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4040
4041 TextStyle text_style;
4042 text_style.setFontFamilies({SkString("Ahem")});
4043 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004044 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004045 text_style.setColor(SK_ColorBLACK);
4046 text_style.setHeight(0.5f);
4047 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004048 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004049 builder.pop();
4050
4051 auto paragraph = builder.Build();
4052 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004053 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004054
4055 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004056 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4057
4058 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4059 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4060 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004061 {
4062 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4063 REPORTER_ASSERT(reporter, boxes.empty());
4064 }
4065 {
4066 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004067 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004068 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004069 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4070 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4071 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4072 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004073 }
4074 {
4075 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004076 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004077 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004078 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004079 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004080 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4081 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004082 }
4083 {
4084 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004085 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004086 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4088 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004090 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004091 }
4092 {
4093 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004094 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004095 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004096 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004099 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004100 }
4101 {
4102 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004103 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004104 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004105 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004109 }
4110 {
4111 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004112 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004113 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004114 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004115 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004116 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004117 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004118 }
4119}
4120
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004121// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004122DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004123 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004124 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004125 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004126 // The chinese extra height should be absorbed by the strut.
4127 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004128 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004129
4130 ParagraphStyle paragraph_style;
4131 paragraph_style.setMaxLines(10);
4132 paragraph_style.setTextAlign(TextAlign::kLeft);
4133 paragraph_style.turnHintingOff();
4134
4135 StrutStyle strut_style;
4136
4137 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004138 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004139 strut_style.setFontSize(50);
4140 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004141 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004142 paragraph_style.setStrutStyle(strut_style);
4143
4144 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4145
4146 TextStyle text_style;
4147 text_style.setFontFamilies({SkString("Ahem")});
4148 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004149 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4150 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004151 text_style.setColor(SK_ColorBLACK);
4152 text_style.setHeight(1);
4153 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004154 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004155 builder.pop();
4156
4157 auto paragraph = builder.Build();
4158 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004159 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004160
4161 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4162 // Font is not resolved and the first line does not fit
4163 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4164
4165 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4166 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4167 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004168 {
4169 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4170 REPORTER_ASSERT(reporter, boxes.empty());
4171 }
4172 {
4173 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004174 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004175 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004176 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4177 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4178 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4179 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004180 }
4181 {
4182 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004183 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004184 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004185 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004186 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004187 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4188 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004189 }
4190 {
4191 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004192 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004193 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004194 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4195 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4196 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4197 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004198 }
4199 {
4200 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004201 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004202 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004203 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004204 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004205 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4206 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004207 }
4208 {
4209 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004210 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004211 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004212 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004213 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004214 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4215 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004216 }
4217 {
4218 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004219 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004220 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004221 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004222 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004223 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4224 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004225 }
4226}
4227
Julia Lavrovac2228562019-08-08 16:51:27 -04004228// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004229DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004230 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004231 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004232 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4233
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004234 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004235 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004236 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004237
4238 ParagraphStyle paragraph_style;
4239 paragraph_style.setMaxLines(10);
4240 paragraph_style.setTextAlign(TextAlign::kLeft);
4241 paragraph_style.turnHintingOff();
4242
4243 StrutStyle strut_style;
4244 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004245 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004246 strut_style.setFontSize(50);
4247 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004248 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004249 paragraph_style.setStrutStyle(strut_style);
4250
4251 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4252
4253 TextStyle text_style;
4254 text_style.setFontFamilies({SkString("Ahem")});
4255 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004256 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4257 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004258 text_style.setColor(SK_ColorBLACK);
4259 text_style.setHeight(1);
4260 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004261 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004262 builder.pop();
4263
4264 auto paragraph = builder.Build();
4265 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004266 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004267
4268 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4269 // Font is not resolved and the first line does not fit
4270 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4271
4272 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4273 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4274 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4275 SkScalar epsilon = 0.001f;
4276 {
4277 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4278 REPORTER_ASSERT(reporter, boxes.empty());
4279 }
4280 {
4281 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004282 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004283 REPORTER_ASSERT(reporter, boxes.size() == 1);
4284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4287 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4288 }
4289 {
4290 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004291 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004292 REPORTER_ASSERT(reporter, boxes.size() == 1);
4293 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4296 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4297 }
4298 {
4299 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004300 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004301 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004302 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4303 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004305 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4306 }
4307 {
4308 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004309 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004310 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004311 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004313 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004314 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4315 }
4316 {
4317 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004318 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004319 REPORTER_ASSERT(reporter, boxes.size() == 1);
4320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4323 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4324 }
4325 {
4326 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004327 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004328 REPORTER_ASSERT(reporter, boxes.size() == 1);
4329 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004330 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4332 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4333 }
4334}
4335
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004336// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004337DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004338 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004339 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004340 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004341 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004342 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004343
4344 ParagraphStyle paragraph_style;
4345 paragraph_style.setMaxLines(10);
4346 paragraph_style.setTextAlign(TextAlign::kLeft);
4347 paragraph_style.turnHintingOff();
4348
4349 StrutStyle strut_style;
4350 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004351 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004352 strut_style.setFontSize(50);
4353 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004354 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004355 strut_style.setLeading(0.1f);
4356 strut_style.setForceStrutHeight(true);
4357 paragraph_style.setStrutStyle(strut_style);
4358
4359 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4360
4361 TextStyle text_style;
4362 text_style.setFontFamilies({SkString("Ahem")});
4363 text_style.setFontSize(50);
4364 text_style.setLetterSpacing(0);
4365 text_style.setColor(SK_ColorBLACK);
4366 text_style.setHeight(1);
4367 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004368 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004369 builder.pop();
4370
4371 auto paragraph = builder.Build();
4372 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004373 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004374
4375 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4376 // Font is not resolved and the first line does not fit
4377 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4378
4379 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4380 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4381 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004382
4383 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4384 REPORTER_ASSERT(reporter, boxes1.empty());
4385
4386 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004387 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004388 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4392 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004393
4394 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004395 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004396 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4400 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004401
4402 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004403 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004404 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4408 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004409
4410 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004411 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004412 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004413 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4416 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004417
4418 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004419 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004420 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004421 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004423 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4424 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004425
4426 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004427 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004428 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004429 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004430 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004431 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4432 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004433}
4434
Julia Lavrovac2228562019-08-08 16:51:27 -04004435// Checked: NO DIFF
4436DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004437 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004438 if (!fontCollection->fontsFound()) return;
4439 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4440
4441 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004442 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004443
4444 ParagraphStyle paragraph_style;
4445 paragraph_style.setMaxLines(10);
4446 paragraph_style.setTextAlign(TextAlign::kLeft);
4447 paragraph_style.turnHintingOff();
4448
4449 StrutStyle strut_style;
4450 strut_style.setStrutEnabled(true);
4451 strut_style.setFontFamilies({SkString("Ahem")});
4452 strut_style.setFontSize(50);
4453 strut_style.setHeight(1.5f);
4454 strut_style.setLeading(0.1f);
4455 strut_style.setForceStrutHeight(false);
4456 paragraph_style.setStrutStyle(strut_style);
4457
4458 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4459
4460 TextStyle text_style;
4461 text_style.setFontFamilies({SkString("Ahem")});
4462 text_style.setFontSize(20);
4463 text_style.setColor(SK_ColorBLACK);
4464 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004465 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004466 builder.pop();
4467
4468 auto paragraph = builder.Build();
4469 paragraph->layout(550);
4470 paragraph->paint(canvas.get(), 0, 0);
4471
4472 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4473 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4474 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4475 {
4476 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4477 REPORTER_ASSERT(reporter, boxes.empty());
4478 }
4479 {
4480 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4481 canvas.drawRects(SK_ColorRED, boxes);
4482 REPORTER_ASSERT(reporter, boxes.size() == 1);
4483 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4486 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4487 }
4488 {
4489 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4490 canvas.drawRects(SK_ColorRED, boxes);
4491 REPORTER_ASSERT(reporter, boxes.size() == 1);
4492 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4495 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4496 }
4497}
4498
Julia Lavrovac5313e62019-12-10 12:11:17 -05004499DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4500 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4501 if (!fontCollection->fontsFound()) return;
4502 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4503
4504 const char* text = "12ab\n";
4505
4506 ParagraphStyle paragraph_style;
4507 paragraph_style.turnHintingOff();
4508 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4509
4510 TextStyle text_style;
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004511 text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
Julia Lavrovac5313e62019-12-10 12:11:17 -05004512 text_style.setFontFamilies({SkString("Roboto")});
4513 text_style.setColor(SK_ColorBLACK);
4514
4515 text_style.addFontFeature(SkString("tnum"), 1);
4516 builder.pushStyle(text_style);
4517 builder.addText(text);
4518
4519 text_style.resetFontFeatures();
4520 text_style.addFontFeature(SkString("tnum"), 0);
4521 text_style.addFontFeature(SkString("pnum"), 1);
4522 builder.pushStyle(text_style);
4523 builder.addText(text);
4524
4525 builder.pop();
4526 builder.pop();
4527
4528 auto paragraph = builder.Build();
4529 paragraph->layout(TestCanvasWidth);
4530
4531 paragraph->paint(canvas.get(), 10.0, 15.0);
4532
4533 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4534 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4535
4536 auto& tnum_line = impl->lines()[0];
4537 auto& pnum_line = impl->lines()[1];
4538
4539 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4540 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4541 // Tabular numbers should have equal widths.
4542 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4543 // Proportional numbers should have variable widths.
4544 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4545 // Alphabetic characters should be unaffected.
4546 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4547}
4548
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004549// Not in Minikin
4550DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004551 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004552 if (!fontCollection->fontsFound()) return;
4553 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004554 const size_t len = strlen(text);
4555
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004556 ParagraphStyle paragraph_style;
4557 paragraph_style.turnHintingOff();
4558 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4559
4560 TextStyle text_style;
4561 text_style.setFontFamilies(
4562 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4563 text_style.setFontSize(60);
4564 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004565 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004566 builder.pop();
4567
4568 auto paragraph = builder.Build();
4569 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004570
4571 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4572
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004573 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4574 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4575 auto first = impl->runs()[i].textRange();
4576 auto next = impl->runs()[i + 1].textRange();
4577 REPORTER_ASSERT(reporter, first.end == next.start);
4578 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004579}
4580
Julia Lavrova90787fe2020-07-20 17:32:03 +00004581// Disable until I sort out fonts
4582DEF_TEST_DISABLED(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004583 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004584 if (!fontCollection->fontsFound()) return;
4585 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004586 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004587
4588 ParagraphStyle paragraph_style;
4589 paragraph_style.turnHintingOff();
4590 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4591
4592 TextStyle text_style;
4593 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4594 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004595 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004596 builder.pop();
4597
4598 auto paragraph = builder.Build();
4599 paragraph->layout(TestCanvasWidth);
4600
4601 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4602 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004603 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004604
4605 auto cluster = 0;
4606 SkShaperJSONWriter::VisualizeClusters(
4607 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4608 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4609 if (cluster == 0) {
4610 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4611 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4612 SkASSERT(glyph1to1.size() == 1);
4613 SkASSERT(*glyph1to1.begin() == 1611);
4614 }
4615 ++cluster;
4616 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004617 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004618}
4619
Julia Lavrova90787fe2020-07-20 17:32:03 +00004620// Disable until I sort out fonts
4621DEF_TEST_DISABLED(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004622 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004623 if (!fontCollection->fontsFound()) return;
4624 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004625 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004626
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004627 ParagraphStyle paragraph_style;
4628 paragraph_style.turnHintingOff();
4629 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4630
4631 TextStyle text_style;
4632 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4633 text_style.setColor(SK_ColorBLACK);
4634 text_style.setFontSize(50);
4635 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004636 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004637 builder.pop();
4638
4639 auto paragraph = builder.Build();
4640 paragraph->layout(TestCanvasWidth);
4641
4642 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4643 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004644
4645 auto cluster = 0;
4646 for (auto& run : impl->runs()) {
4647 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004648 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4649 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004650 [&](int codePointCount, SkSpan<const char> utf1to1,
4651 SkSpan<const SkGlyphID> glyph1to1) {
4652 if (cluster == 0) {
4653 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4654 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4655 SkASSERT(glyph1to1.size() == 3);
4656 }
4657 ++cluster;
4658 });
4659 }
4660
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004661 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004662}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004663
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004664DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004665 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004666 cache.turnOn(true);
4667 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004668 if (!fontCollection->fontsFound()) return;
4669
4670 ParagraphStyle paragraph_style;
4671 paragraph_style.turnHintingOff();
4672
4673 TextStyle text_style;
4674 text_style.setFontFamilies({SkString("Roboto")});
4675 text_style.setColor(SK_ColorBLACK);
4676
4677 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4678 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4679 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004680 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004681 builder.pop();
4682 auto paragraph = builder.Build();
4683
4684 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4685 REPORTER_ASSERT(reporter, count == cache.count());
4686 auto found = cache.findParagraph(impl);
4687 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4688 auto added = cache.updateParagraph(impl);
4689 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4690 };
4691
4692 test("text1", 0, false);
4693 test("text1", 1, true);
4694 test("text2", 1, false);
4695 test("text2", 2, true);
4696 test("text3", 2, false);
4697}
4698
4699DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004700 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004701 cache.turnOn(true);
4702 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004703 if (!fontCollection->fontsFound()) return;
4704
4705 ParagraphStyle paragraph_style;
4706 paragraph_style.turnHintingOff();
4707
4708 TextStyle text_style;
4709 text_style.setColor(SK_ColorBLACK);
4710
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004711 const char* text = "text";
4712 const size_t len = strlen(text);
4713
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004714 auto test = [&](int count, bool expectedToBeFound) {
4715 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4716 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004717 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004718 builder.pop();
4719 auto paragraph = builder.Build();
4720 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4721
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004722 REPORTER_ASSERT(reporter, count == cache.count());
4723 auto found = cache.findParagraph(impl);
4724 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4725 auto added = cache.updateParagraph(impl);
4726 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4727 };
4728
4729 text_style.setFontFamilies({SkString("Roboto")});
4730 test(0, false);
4731 test(1, true);
4732 text_style.setFontFamilies({SkString("Homemade Apple")});
4733 test(1, false);
4734 test(2, true);
4735 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4736 test(2, false);
4737}
4738
4739DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004740 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004741 cache.turnOn(true);
4742 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004743 if (!fontCollection->fontsFound()) return;
4744
4745 ParagraphStyle paragraph_style;
4746 paragraph_style.turnHintingOff();
4747
4748 TextStyle text_style;
4749 text_style.setFontFamilies({SkString("Roboto")});
4750 text_style.setColor(SK_ColorBLACK);
4751
4752 auto test = [&](const char* text1,
4753 const char* text2,
4754 const char* font1,
4755 const char* font2,
4756 int count,
4757 bool expectedToBeFound) {
4758 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4759 text_style.setFontFamilies({SkString(font1)});
4760 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004761 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004762 builder.pop();
4763 text_style.setFontFamilies({SkString(font2)});
4764 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004765 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004766 builder.pop();
4767 auto paragraph = builder.Build();
4768 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4769
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004770 REPORTER_ASSERT(reporter, count == cache.count());
4771 auto found = cache.findParagraph(impl);
4772 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4773 auto added = cache.updateParagraph(impl);
4774 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4775 };
4776
4777 test("text", "", "Roboto", "Homemade Apple", 0, false);
4778 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4779 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4780 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4781 test("text", "", "Roboto", "Homemade Apple", 4, true);
4782}
4783
4784DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004785 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004786 cache.turnOn(true);
4787 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004788 if (!fontCollection->fontsFound()) return;
4789
4790 ParagraphStyle paragraph_style;
4791 paragraph_style.turnHintingOff();
4792
4793 TextStyle text_style;
4794 text_style.setFontFamilies({SkString("Roboto")});
4795 text_style.setColor(SK_ColorBLACK);
4796
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004797 const char* text = "text";
4798 const size_t len = strlen(text);
4799
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004800 auto test = [&](int count, bool expectedToBeFound) {
4801 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4802 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004803 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004804 builder.pop();
4805 auto paragraph = builder.Build();
4806 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4807
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004808 REPORTER_ASSERT(reporter, count == cache.count());
4809 auto found = cache.findParagraph(impl);
4810 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4811 auto added = cache.updateParagraph(impl);
4812 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4813 };
4814
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004815 test(0, false);
4816 test(1, true);
4817 text_style.setLetterSpacing(10);
4818 test(1, false);
4819 test(2, true);
4820 text_style.setWordSpacing(10);
4821 test(2, false);
4822}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004823
Julia Lavrova526df262019-08-21 17:49:44 -04004824DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004825 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004826 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004827 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4828 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004829
4830 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004831 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004832 text_style.setFontSize(16);
4833 text_style.setFontFamilies({SkString("Roboto")});
4834 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004835 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004836
4837 auto paragraph = builder.Build();
4838 paragraph->layout(TestCanvasWidth);
4839 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004840 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004841}
4842
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004843DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004844 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004845 if (!fontCollection->fontsFound()) return;
4846 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4847 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4848
4849 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4850
4851 ParagraphStyle paragraph_style;
4852 TextStyle text_style;
4853 text_style.setFontSize(16);
4854 text_style.setFontFamilies({SkString("Roboto")});
4855 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4856 builder.addText(text.c_str(), text.size());
4857
4858 auto paragraph = builder.Build();
4859 paragraph->layout(TestCanvasWidth);
4860 paragraph->paint(canvas.get(), 0, 0);
4861}
4862
Julia Lavrovaa40db422019-08-21 13:49:15 -04004863DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004864 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004865 if (!fontCollection->fontsFound()) return;
4866 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4867
4868 ParagraphStyle paragraph_style;
4869 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4870
Julia Lavrova526df262019-08-21 17:49:44 -04004871 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004872 builder.addPlaceholder(placeholder);
4873
4874 auto paragraph = builder.Build();
4875 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004876 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004877 paragraph->paint(canvas.get(), 0, 0);
4878}
4879
4880DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004881 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004882 if (!fontCollection->fontsFound()) return;
4883 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4884 TestCanvas canvas("SkParagraph_Fallbacks.png");
4885
4886 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004887 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004888
4889 const char* androidFonts[] = {
4890 "sans-serif",
4891 "sans-serif-condensed",
4892 "serif",
4893 "monospace",
4894 "serif-monospace",
4895 "casual",
4896 "cursive",
4897 "sans-serif-smallcaps",
4898 };
4899
4900 for (auto& font : androidFonts) {
4901
4902 ParagraphStyle paragraph_style;
4903 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4904
4905 TextStyle text_style;
4906 text_style.setColor(SK_ColorBLACK);
4907 text_style.setLocale(SkString("en_US"));
4908 text_style.setFontSize(20);
4909
4910 text_style.setFontFamilies({ SkString(font) });
4911 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004912 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004913
4914 builder.pop();
4915
4916 auto paragraph = builder.Build();
4917 paragraph->layout(TestCanvasWidth);
4918 paragraph->paint(canvas.get(), 0, 0);
4919 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4920 }
4921}
4922
4923DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004924 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004925 if (!fontCollection->fontsFound()) return;
4926 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004927 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004928 TestCanvas canvas("SkParagraph_Bidi1.png");
4929
4930 std::u16string abc = u"\u202Dabc";
4931 std::u16string DEF = u"\u202EDEF";
4932 std::u16string ghi = u"\u202Dghi";
4933 std::u16string JKL = u"\u202EJKL";
4934 std::u16string mno = u"\u202Dmno";
4935
4936 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4937
4938 ParagraphStyle paragraph_style;
4939 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4940
4941 TextStyle text_style;
4942 text_style.setFontFamilies({ SkString("sans-serif")});
4943 text_style.setFontSize(40);
4944
4945 text_style.setColor(SK_ColorCYAN);
4946 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4947 builder.pushStyle(text_style);
4948 builder.addText(abc);
4949
4950 text_style.setColor(SK_ColorGREEN);
4951 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4952 builder.pushStyle(text_style);
4953 builder.addText(DEF);
4954
4955 text_style.setColor(SK_ColorYELLOW);
4956 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4957 builder.pushStyle(text_style);
4958 builder.addText(ghi);
4959
4960 text_style.setColor(SK_ColorMAGENTA);
4961 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4962 builder.pushStyle(text_style);
4963 builder.addText(JKL);
4964
4965 text_style.setColor(SK_ColorBLUE);
4966 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4967 builder.pushStyle(text_style);
4968 builder.addText(mno);
4969
4970 auto paragraph = builder.Build();
4971 paragraph->layout(400);
4972 paragraph->paint(canvas.get(), 0, 0);
4973}
4974
4975DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004976 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004977 if (!fontCollection->fontsFound()) return;
4978 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004979 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004980 TestCanvas canvas("SkParagraph_Bidi2.png");
4981
4982 std::u16string abcD = u"\u202Dabc\u202ED";
4983 std::u16string EFgh = u"EF\u202Dgh";
4984 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4985
4986 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4987
4988 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004989 TextStyle text_style;
4990 text_style.setFontFamilies({ SkString("sans-serif")});
4991 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004992
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004993 {
4994 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4995 builder.pushStyle(text_style);
4996 builder.addText(abcD);
4997 builder.pushStyle(text_style);
4998 builder.addText(EFgh);
4999 builder.pushStyle(text_style);
5000 builder.addText(iJKLmno);
5001 auto paragraph = builder.Build();
5002 paragraph->layout(360);
5003 paragraph->paint(canvas.get(), 0, 0);
5004 }
5005 canvas.get()->translate(0, 400);
5006 {
5007 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5008 builder.pushStyle(text_style);
5009 builder.addText(abcDEFghiJKLmno);
5010 auto paragraph = builder.Build();
5011 paragraph->layout(360);
5012 paragraph->paint(canvas.get(), 0, 0);
5013 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04005014}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005015
5016DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005017 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005018 if (!fontCollection->fontsFound()) return;
5019 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5020 TestCanvas canvas("SkParagraph_Newline.png");
5021
5022 TextStyle text_style;
5023 text_style.setFontFamilies({SkString("Ahem")});
5024 text_style.setColor(SK_ColorBLACK);
5025 StrutStyle strut_style;
5026 strut_style.setStrutEnabled(false);
5027 ParagraphStyle paragraph_style;
5028 paragraph_style.setStrutStyle(strut_style);
5029 paragraph_style.setTextStyle(text_style);
5030 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5031 builder.addText("\n");
5032 auto paragraph = builder.Build();
5033 paragraph->layout(1000);
5034 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5035}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005036
Julia Lavrovab30d4812019-11-08 14:51:16 -05005037DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005038 TestCanvas canvas("SkParagraph_FontResolutions.png");
5039
5040 sk_sp<TestFontCollection> fontCollection =
5041 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5042 if (!fontCollection->fontsFound()) return;
5043
5044 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5045 return;
5046 }
5047 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5048 return;
5049 }
5050 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5051 return;
5052 }
5053
5054 TextStyle text_style;
5055 text_style.setFontFamilies({SkString("abc")});
5056 text_style.setFontSize(50);
5057
5058 ParagraphStyle paragraph_style;
5059 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5060
5061 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5062 text_style.setColor(SK_ColorBLUE);
5063 builder.pushStyle(text_style);
5064 builder.addText(u"a\u0300");
5065 text_style.setColor(SK_ColorMAGENTA);
5066 builder.pushStyle(text_style);
5067 builder.addText(u"à");
5068
5069 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5070
5071 text_style.setColor(SK_ColorRED);
5072 builder.pushStyle(text_style);
5073 builder.addText(u"a\u0300");
5074 text_style.setColor(SK_ColorGREEN);
5075 builder.pushStyle(text_style);
5076 builder.addText(u"à");
5077
5078 auto paragraph = builder.Build();
5079 paragraph->layout(TestCanvasWidth);
5080
5081 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5082 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5083
5084 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5085 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5086 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5087
5088 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5089 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5090
5091 paragraph->paint(canvas.get(), 100, 100);
5092}
5093
Julia Lavrovab30d4812019-11-08 14:51:16 -05005094DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005095 TestCanvas canvas("SkParagraph_FontStyle.png");
5096
5097 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5098 if (!fontCollection->fontsFound()) return;
5099
5100 TextStyle text_style;
5101 text_style.setFontFamilies({SkString("Roboto")});
5102 text_style.setColor(SK_ColorBLACK);
5103 text_style.setFontSize(20);
5104 SkFontStyle fs = SkFontStyle(
5105 SkFontStyle::Weight::kLight_Weight,
5106 SkFontStyle::Width::kNormal_Width,
5107 SkFontStyle::Slant::kUpright_Slant
5108 );
5109 text_style.setFontStyle(fs);
5110 ParagraphStyle paragraph_style;
5111 paragraph_style.setTextStyle(text_style);
5112 TextStyle boldItalic;
5113 boldItalic.setFontFamilies({SkString("Roboto")});
5114 boldItalic.setColor(SK_ColorRED);
5115 SkFontStyle bi = SkFontStyle(
5116 SkFontStyle::Weight::kBold_Weight,
5117 SkFontStyle::Width::kNormal_Width,
5118 SkFontStyle::Slant::kItalic_Slant
5119 );
5120 boldItalic.setFontStyle(bi);
5121 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5122 builder.addText("Default text\n");
5123 builder.pushStyle(boldItalic);
5124 builder.addText("Bold and Italic\n");
5125 builder.pop();
5126 builder.addText("back to normal");
5127 auto paragraph = builder.Build();
5128 paragraph->layout(250);
5129 paragraph->paint(canvas.get(), 0, 0);
5130}
5131
Julia Lavrovab30d4812019-11-08 14:51:16 -05005132DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005133 TestCanvas canvas("SkParagraph_Shaping.png");
5134
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005135 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5136 sk_sp<TestFontCollection> fontCollection =
5137 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5138 if (!fontCollection->fontsFound()) return;
5139
5140
5141 TextStyle text_style;
5142 text_style.setFontFamilies({SkString("Roboto")});
5143 text_style.setColor(SK_ColorGRAY);
5144 text_style.setFontSize(14);
5145 SkFontStyle b = SkFontStyle(
5146 SkFontStyle::Weight::kNormal_Weight,
5147 SkFontStyle::Width::kNormal_Width,
5148 SkFontStyle::Slant::kUpright_Slant
5149 );
5150 text_style.setFontStyle(b);
5151 ParagraphStyle paragraph_style;
5152 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5153 builder.pushStyle(text_style);
5154 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5155 auto paragraph = builder.Build();
5156 paragraph->layout(380);
5157 paragraph->paint(canvas.get(), 0, 0);
5158}
Julia Lavrovac028b422019-11-25 10:00:43 -05005159
5160DEF_TEST(SkParagraph_Ellipsis, reporter) {
5161 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5162 if (!fontCollection->fontsFound()) return;
5163 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5164 TestCanvas canvas("SkParagraph_Ellipsis.png");
5165
5166 const char* text = "This\n"
5167 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5168 TextStyle text_style;
5169 text_style.setFontFamilies({SkString("Ahem")});
5170 text_style.setColor(SK_ColorBLACK);
5171 text_style.setFontSize(10);
5172
5173 auto relayout = [&](size_t lines, bool ellipsis,
5174 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5175 ParagraphStyle paragraph_style;
5176 SkPaint paint;
5177 paint.setColor(bg);
5178 text_style.setForegroundColor(paint);
5179 paragraph_style.setTextStyle(text_style);
5180 paragraph_style.setMaxLines(lines);
5181 if (ellipsis) {
5182 paragraph_style.setEllipsis(u"\u2026");
5183 }
5184 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5185 builder.addText(text);
5186 auto paragraph = builder.Build();
5187 paragraph->layout(50);
5188 paragraph->paint(canvas.get(), 0, 0);
5189 canvas.get()->translate(50, paragraph->getHeight() + 10);
5190 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5191 SkPaint background;
5192 background.setColor(SK_ColorRED);
5193 background.setStyle(SkPaint::kStroke_Style);
5194 background.setAntiAlias(true);
5195 background.setStrokeWidth(1);
5196 canvas.get()->drawRect(result.front().rect, background);
5197
5198 SkASSERT(width == paragraph->getMaxWidth());
5199 SkASSERT(height == paragraph->getHeight());
5200 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5201 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5202 };
5203
5204 SkPaint paint;
5205 paint.setColor(SK_ColorLTGRAY);
5206 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5207
5208 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005209 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5210 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005211
5212 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005213 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005214 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5215
5216 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005217 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5218 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005219}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005220
5221DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5222 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5223 if (!fontCollection->fontsFound()) return;
5224 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5225
5226 std::string text;
5227 for (size_t i = 0; i < 10; i++)
5228 {
5229 SkPaint paint;
5230 paint.setAntiAlias(true);
5231 paint.setColor(SK_ColorBLACK);
5232
5233 TextStyle textStyle;
5234 textStyle.setForegroundColor(paint);
5235 textStyle.setFontFamilies({ SkString("Roboto") });
5236
5237 ParagraphStyle paragraphStyle;
5238 paragraphStyle.setTextStyle(textStyle);
5239
5240 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5241 text += "Text ";
5242 builder.addText(text.c_str());
5243
5244 auto paragraph = builder.Build();
5245 paragraph->layout(100);
5246
5247 //used to add a delay so I can monitor memory usage
5248 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5249 }
5250};
Julia Lavrovac0360582020-02-05 10:17:53 -05005251
5252DEF_TEST(SkParagraph_FormattingInfinity, reporter) {
5253 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5254 if (!fontCollection->fontsFound()) return;
5255 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5256 TestCanvas canvas("SkParagraph_FormattingInfinity.png");
5257
5258 const char* text = "Some text\nAnother line";
5259
5260 SkPaint paint;
5261 paint.setAntiAlias(true);
5262 paint.setColor(SK_ColorBLACK);
5263
5264 TextStyle textStyle;
5265 textStyle.setForegroundColor(paint);
5266 textStyle.setFontFamilies({ SkString("Roboto") });
5267 ParagraphStyle paragraphStyle;
5268 paragraphStyle.setTextStyle(textStyle);
5269
5270 auto draw = [&](const char* prefix, TextAlign textAlign) {
5271 paragraphStyle.setTextAlign(textAlign);
5272 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5273 builder.addText(text);
5274 auto paragraph = builder.Build();
5275 paragraph->layout(SK_ScalarInfinity);
5276 paragraph->paint(canvas.get(), 0, 0);
5277 canvas.get()->translate(0, 100);
5278 };
5279
5280 draw("left", TextAlign::kLeft);
5281 draw("right", TextAlign::kRight);
5282 draw("center", TextAlign::kCenter);
5283 draw("justify", TextAlign::kJustify);
5284};
5285
5286DEF_TEST(SkParagraph_Infinity, reporter) {
5287 SkASSERT(nearlyEqual(1, SK_ScalarInfinity) == false);
5288 SkASSERT(nearlyEqual(1, SK_ScalarNegativeInfinity) == false);
5289 SkASSERT(nearlyEqual(1, SK_ScalarNaN) == false);
5290
5291 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarInfinity) == true);
5292 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNegativeInfinity) == false);
5293 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNaN) == false);
5294
5295 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarInfinity) == false);
5296 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity) == true);
5297 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNaN) == false);
5298
5299 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarInfinity) == false);
5300 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNegativeInfinity) == false);
5301 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNaN) == false);
5302};
Julia Lavrova2002b862020-06-19 11:17:09 -04005303
5304DEF_TEST(SkParagraph_LineMetrics, reporter) {
5305
5306 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5307 if (!fontCollection->fontsFound()) return;
5308
5309 TestCanvas canvas("SkParagraph_LineMetrics.png");
5310
5311 const char* text = "One line of text\n";
5312 const size_t len = strlen(text);
5313
5314 ParagraphStyle paragraph_style;
5315 paragraph_style.turnHintingOff();
5316 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5317
5318 TextStyle text_style;
5319 text_style.setFontFamilies({SkString("Roboto")});
5320 text_style.setColor(SK_ColorBLACK);
5321
5322 text_style.setFontSize(8);
5323 builder.pushStyle(text_style);
5324 builder.addText(text, len);
5325 builder.pop();
5326
5327 text_style.setFontSize(12);
5328 builder.pushStyle(text_style);
5329 builder.addText(text, len);
5330 builder.pop();
5331
5332 text_style.setFontSize(18);
5333 builder.pushStyle(text_style);
5334 builder.addText(text, len);
5335 builder.pop();
5336
5337 text_style.setFontSize(30);
5338 builder.pushStyle(text_style);
5339 builder.addText(text, len - 1); // Skip the last \n
5340 builder.pop();
5341
5342 auto paragraph = builder.Build();
5343 paragraph->layout(TestCanvasWidth);
5344
5345 std::vector<LineMetrics> metrics;
5346 paragraph->getLineMetrics(metrics);
5347
5348 SkDEBUGCODE(auto impl = static_cast<ParagraphImpl*>(paragraph.get());)
5349 SkASSERT(metrics.size() == impl->lines().size());
5350 for (size_t i = 0; i < metrics.size(); ++i) {
5351 SkDEBUGCODE(auto& line = impl->lines()[i];)
5352 SkDEBUGCODE(auto baseline = metrics[i].fBaseline;)
5353 SkDEBUGCODE(auto top = line.offset().fY;)
5354 SkDEBUGCODE(auto bottom = line.offset().fY + line.height();)
5355 SkASSERT( baseline > top && baseline <= bottom);
5356 }
5357
5358 paragraph->paint(canvas.get(), 0, 0);
5359 auto rects = paragraph->getRectsForRange(0, len * 4, RectHeightStyle::kMax, RectWidthStyle::kTight);
5360
5361 SkPaint red;
5362 red.setColor(SK_ColorRED);
5363 red.setStyle(SkPaint::kStroke_Style);
5364 red.setAntiAlias(true);
5365 red.setStrokeWidth(1);
5366
5367 for (auto& rect : rects) {
5368 canvas.get()->drawRect(rect.rect, red);
5369 }
5370
5371 SkPaint green;
5372 green.setColor(SK_ColorGREEN);
5373 green.setStyle(SkPaint::kStroke_Style);
5374 green.setAntiAlias(true);
5375 green.setStrokeWidth(1);
5376 for (auto& metric : metrics) {
5377 auto x0 = 0.0;
5378 auto x1 = metric.fWidth;
5379 auto y = metric.fBaseline;
5380 canvas.get()->drawLine(x0, y, x1, y, green);
5381 }
5382};
Julia Lavrovace6f24d2020-07-08 10:41:54 -04005383
5384DEF_TEST(SkParagraph_PlaceholderHeightInf, reporter) {
5385 TestCanvas canvas("SkParagraph_PlaceholderHeightInf.png");
5386
5387 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5388 if (!fontCollection->fontsFound()) return;
5389
5390 TextStyle text_style;
5391 text_style.setFontFamilies({SkString("Ahem")});
5392 text_style.setColor(SK_ColorBLACK);
5393 text_style.setFontSize(14);
5394
5395 PlaceholderStyle placeholder_style;
5396 placeholder_style.fWidth = 16.0f;
5397 placeholder_style.fHeight = SK_ScalarInfinity;
5398 placeholder_style.fAlignment = PlaceholderAlignment::kBottom;
5399 placeholder_style.fBaseline = TextBaseline::kAlphabetic;
5400 placeholder_style.fBaselineOffset = SK_ScalarInfinity;
5401
5402 ParagraphStyle paragraph_style;
5403
5404 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5405 builder.pushStyle(text_style);
5406 builder.addText("Limited by budget");
5407 builder.addPlaceholder(placeholder_style);
5408 auto paragraph = builder.Build();
5409 paragraph->layout(SK_ScalarInfinity);
5410
5411 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5412 REPORTER_ASSERT(reporter, SkScalarIsFinite(impl->getBoundaries().height()));
5413 REPORTER_ASSERT(reporter, SkScalarIsFinite(impl->getBoundaries().width()));
5414
5415 paragraph->paint(canvas.get(), 0, 0);
5416}
Julia Lavrova196515c2020-07-08 14:55:17 -04005417
5418DEF_TEST(SkParagraph_LineMetricsTextAlign, reporter) {
5419
5420 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5421 if (!fontCollection->fontsFound()) return;
5422
5423 TestCanvas canvas("SkParagraph_LineMetricsTextAlign.png");
5424
5425 ParagraphStyle paragraph_style;
5426 paragraph_style.turnHintingOff();
5427 TextStyle text_style;
5428 text_style.setFontFamilies({SkString("Roboto")});
5429 text_style.setColor(SK_ColorBLACK);
5430
5431 auto layout = [&](TextAlign text_align) -> std::pair<SkScalar, SkScalar> {
5432 paragraph_style.setTextAlign(text_align);
5433 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5434 builder.pushStyle(text_style);
5435 builder.addText("Some text that takes more than 200 px");
5436 auto paragraph = builder.Build();
5437 paragraph->layout(200);
5438
5439 std::vector<LineMetrics> metrics;
5440 paragraph->getLineMetrics(metrics);
5441 REPORTER_ASSERT(reporter, metrics.size() > 0);
5442 return { metrics[0].fLeft, metrics[0].fWidth };
5443 };
5444
5445 SkScalar left[4];
5446 SkScalar width[4];
5447 std::tie(left[0], width[0]) = layout(TextAlign::kLeft);
5448 std::tie(left[1], width[1]) = layout(TextAlign::kCenter);
5449 std::tie(left[2], width[2]) = layout(TextAlign::kRight);
5450 std::tie(left[3], width[3]) = layout(TextAlign::kJustify);
5451
5452 // delta = line_width - text_width
5453 REPORTER_ASSERT(reporter, left[0] == 0); // Starts from 0
5454 REPORTER_ASSERT(reporter, left[1] > left[0]); // Starts from delta / 2
5455 REPORTER_ASSERT(reporter, left[2] > left[1]); // Starts from delta
5456 REPORTER_ASSERT(reporter, left[3] == left[0]); // Starts from 0
5457 REPORTER_ASSERT(reporter, width[1] == width[0]);
5458 REPORTER_ASSERT(reporter, width[2] == width[0]);
5459 REPORTER_ASSERT(reporter, width[3] > width[0]); // delta == 0
5460}
Julia Lavrova131c5ad2020-07-20 11:05:26 -04005461
5462DEF_TEST(SkParagraph_FontResolutionInRTL, reporter) {
5463 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
5464 if (!fontCollection->fontsFound()) return;
5465 TestCanvas canvas("SkParagraph_FontResolutionInRTL.png");
5466 const char* text = " אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ ";
5467 const size_t len = strlen(text);
5468
5469 ParagraphStyle paragraph_style;
5470 paragraph_style.setMaxLines(14);
5471 paragraph_style.setTextAlign(TextAlign::kRight);
5472 paragraph_style.setTextDirection(TextDirection::kRtl);
5473 paragraph_style.turnHintingOff();
5474 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5475
5476 TextStyle text_style;
5477 text_style.setFontFamilies({SkString("Ahem")});
5478 text_style.setFontSize(26);
5479 text_style.setColor(SK_ColorBLACK);
5480 builder.pushStyle(text_style);
5481 builder.addText(text, len);
5482 builder.pop();
5483
5484 auto paragraph = builder.Build();
5485 paragraph->layout(TestCanvasWidth);
5486 paragraph->paint(canvas.get(), 0, 0);
5487
5488 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5489 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
5490}
5491
5492DEF_TEST(SkParagraph_FontResolutionInLTR, reporter) {
5493 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>(true);
5494 if (!fontCollection->fontsFound()) return;
5495 TestCanvas canvas("SkParagraph_FontResolutionInLTR.png");
5496 auto text = u"abc \u01A2 \u01A2 def";
5497
5498 ParagraphStyle paragraph_style;
5499 paragraph_style.setMaxLines(14);
5500 paragraph_style.turnHintingOff();
5501 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5502
5503 TextStyle text_style;
5504 text_style.setFontFamilies({SkString("Roboto")});
5505 text_style.setFontSize(26);
5506 text_style.setColor(SK_ColorBLACK);
5507 builder.pushStyle(text_style);
5508 builder.addText(text);
5509 builder.pop();
5510
5511 auto paragraph = builder.Build();
5512 paragraph->layout(TestCanvasWidth);
5513 paragraph->paint(canvas.get(), 0, 0);
5514
5515 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5516 REPORTER_ASSERT(reporter, impl->runs().size() == 3);
5517 REPORTER_ASSERT(reporter, impl->runs()[0].textRange().width() == 4); // "abc "
5518 REPORTER_ASSERT(reporter, impl->runs()[1].textRange().width() == 5); // "{unresolved} {unresolved}"
5519 REPORTER_ASSERT(reporter, impl->runs()[2].textRange().width() == 4); // " def"
5520}