blob: 6ebc4ce332ea3712a1e78e816337a2ca03a88b41 [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());
Robert Phillips14364622020-07-24 19:48:09 +00001242 REPORTER_ASSERT(reporter, impl->runs().size() == 5);
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
Robert Phillips14364622020-07-24 19:48:09 +00003992 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 2); // From the text1
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 // Font resolution in Skia produces 6 runs because 2 parts of "Roboto 字典 " have different
Robert Phillips14364622020-07-24 19:48:09 +00003997 // script (Minikin merges the first 2 into one because of unresolved) [Apple + Unresolved ]
3998 // [Apple + Noto] [Apple + Han]
3999 REPORTER_ASSERT(reporter, impl->runs().size() == 7);
4000
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004001 auto robotoAdvance = impl->runs()[0].advance().fX +
Robert Phillips14364622020-07-24 19:48:09 +00004002 impl->runs()[1].advance().fX +
4003 impl->runs()[2].advance().fX;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004004 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(robotoAdvance, 64.199f, EPSILON50));
Robert Phillips14364622020-07-24 19:48:09 +00004005 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[3].advance().fX, 139.125f, EPSILON100));
4006 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[4].advance().fX, 27.999f, EPSILON100));
4007 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[5].advance().fX, 62.248f, EPSILON100));
4008 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(impl->runs()[6].advance().fX, 27.999f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004009
4010 // When a different font is resolved, then the metrics are different.
Robert Phillips14364622020-07-24 19:48:09 +00004011 REPORTER_ASSERT(reporter, impl->runs()[4].correctAscent() != impl->runs()[6].correctAscent());
4012 REPORTER_ASSERT(reporter, impl->runs()[4].correctDescent() != impl->runs()[6].correctDescent());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004013}
4014
Julia Lavrovac2228562019-08-08 16:51:27 -04004015// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004016DEF_TEST(SkParagraph_StrutParagraph1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004017 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004018 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004019 TestCanvas canvas("SkParagraph_StrutParagraph1.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004020 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004021 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004022 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004023
4024 ParagraphStyle paragraph_style;
4025 paragraph_style.setMaxLines(10);
4026 paragraph_style.setTextAlign(TextAlign::kLeft);
4027 paragraph_style.turnHintingOff();
4028
4029 StrutStyle strut_style;
4030 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004031 strut_style.setFontFamilies({SkString("BlahFake"), SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004032 strut_style.setFontSize(50);
4033 strut_style.setHeight(1.8f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004034 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004035 strut_style.setLeading(0.1f);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004036 paragraph_style.setStrutStyle(strut_style);
4037
4038 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4039
4040 TextStyle text_style;
4041 text_style.setFontFamilies({SkString("Ahem")});
4042 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004043 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004044 text_style.setColor(SK_ColorBLACK);
4045 text_style.setHeight(0.5f);
4046 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004047 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004048 builder.pop();
4049
4050 auto paragraph = builder.Build();
4051 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004052 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004053
4054 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004055 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4056
4057 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4058 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4059 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004060 {
4061 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4062 REPORTER_ASSERT(reporter, boxes.empty());
4063 }
4064 {
4065 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004066 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004067 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004068 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4069 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
4070 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4071 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004072 }
4073 {
4074 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004075 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004076 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004077 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004078 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004079 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4080 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004081 }
4082 {
4083 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004084 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004085 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004086 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4087 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 34.5f, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004088 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004089 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 84.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004090 }
4091 {
4092 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004093 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004094 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004095 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004096 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004097 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004098 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 95, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004099 }
4100 {
4101 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004102 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004103 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004104 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004105 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 190, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 285, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004108 }
4109 {
4110 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004111 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004112 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004113 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004114 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 285, EPSILON100));
Julia Lavrovac2228562019-08-08 16:51:27 -04004115 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004116 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 380, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004117 }
4118}
4119
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004120// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004121DEF_TEST(SkParagraph_StrutParagraph2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004122 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004123 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004124 TestCanvas canvas("SkParagraph_StrutParagraph2.png");
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004125 // The chinese extra height should be absorbed by the strut.
4126 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004127 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004128
4129 ParagraphStyle paragraph_style;
4130 paragraph_style.setMaxLines(10);
4131 paragraph_style.setTextAlign(TextAlign::kLeft);
4132 paragraph_style.turnHintingOff();
4133
4134 StrutStyle strut_style;
4135
4136 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004137 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004138 strut_style.setFontSize(50);
4139 strut_style.setHeight(1.6f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004140 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004141 paragraph_style.setStrutStyle(strut_style);
4142
4143 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4144
4145 TextStyle text_style;
4146 text_style.setFontFamilies({SkString("Ahem")});
4147 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004148 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4149 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004150 text_style.setColor(SK_ColorBLACK);
4151 text_style.setHeight(1);
4152 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004153 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004154 builder.pop();
4155
4156 auto paragraph = builder.Build();
4157 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004158 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004159
4160 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4161 // Font is not resolved and the first line does not fit
4162 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4163
4164 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4165 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4166 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004167 {
4168 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4169 REPORTER_ASSERT(reporter, boxes.empty());
4170 }
4171 {
4172 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004173 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004174 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004175 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4176 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4177 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4178 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004179 }
4180 {
4181 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004182 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004183 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004184 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004185 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004186 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, EPSILON100));
4187 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004188 }
4189 {
4190 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004191 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004192 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004193 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
4194 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 24, EPSILON100));
4195 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4196 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 74, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004197 }
4198 {
4199 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004200 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004201 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004202 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004203 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004204 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, EPSILON100));
4205 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004206 }
4207 {
4208 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004209 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004210 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004211 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004212 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004213 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, EPSILON100));
4214 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004215 }
4216 {
4217 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004218 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004219 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004220 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004221 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004222 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, EPSILON100));
4223 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004224 }
4225}
4226
Julia Lavrovac2228562019-08-08 16:51:27 -04004227// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004228DEF_TEST(SkParagraph_StrutParagraph3, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004229 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004230 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004231 TestCanvas canvas("SkParagraph_StrutParagraph3.png");
4232
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004233 // The chinese extra height should be absorbed by the strut.
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004234 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004235 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004236
4237 ParagraphStyle paragraph_style;
4238 paragraph_style.setMaxLines(10);
4239 paragraph_style.setTextAlign(TextAlign::kLeft);
4240 paragraph_style.turnHintingOff();
4241
4242 StrutStyle strut_style;
4243 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004244 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004245 strut_style.setFontSize(50);
4246 strut_style.setHeight(1.2f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004247 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004248 paragraph_style.setStrutStyle(strut_style);
4249
4250 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4251
4252 TextStyle text_style;
4253 text_style.setFontFamilies({SkString("Ahem")});
4254 text_style.setFontSize(50);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004255 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width,
4256 SkFontStyle::kUpright_Slant));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004257 text_style.setColor(SK_ColorBLACK);
4258 text_style.setHeight(1);
4259 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004260 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004261 builder.pop();
4262
4263 auto paragraph = builder.Build();
4264 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004265 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004266
4267 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4268 // Font is not resolved and the first line does not fit
4269 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4270
4271 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4272 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4273 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4274 SkScalar epsilon = 0.001f;
4275 {
4276 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4277 REPORTER_ASSERT(reporter, boxes.empty());
4278 }
4279 {
4280 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004281 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004282 REPORTER_ASSERT(reporter, boxes.size() == 1);
4283 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
4284 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
4285 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4286 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4287 }
4288 {
4289 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004290 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004291 REPORTER_ASSERT(reporter, boxes.size() == 1);
4292 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004293 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004294 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 50, epsilon));
4295 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4296 }
4297 {
4298 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004299 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004300 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004301 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
4302 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 8, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004303 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004304 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 58, epsilon));
4305 }
4306 {
4307 auto boxes = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004308 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovac2228562019-08-08 16:51:27 -04004309 REPORTER_ASSERT(reporter, boxes.size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004310 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 300, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004311 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 0, epsilon));
Julia Lavrovac2228562019-08-08 16:51:27 -04004312 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 500, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004313 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 60, epsilon));
4314 }
4315 {
4316 auto boxes = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004317 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004318 REPORTER_ASSERT(reporter, boxes.size() == 1);
4319 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004320 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 120, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004321 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 100, epsilon));
4322 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 180, epsilon));
4323 }
4324 {
4325 auto boxes = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004326 canvas.drawRects(SK_ColorRED, boxes);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004327 REPORTER_ASSERT(reporter, boxes.size() == 1);
4328 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 50, epsilon));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004329 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 180, epsilon));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004330 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 300, epsilon));
4331 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 240, epsilon));
4332 }
4333}
4334
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004335// Checked: NO DIFF
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004336DEF_TEST(SkParagraph_StrutForceParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004337 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004338 if (!fontCollection->fontsFound()) return;
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004339 TestCanvas canvas("SkParagraph_StrutForceParagraph.png");
Julia Lavrova526df262019-08-21 17:49:44 -04004340 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004341 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004342
4343 ParagraphStyle paragraph_style;
4344 paragraph_style.setMaxLines(10);
4345 paragraph_style.setTextAlign(TextAlign::kLeft);
4346 paragraph_style.turnHintingOff();
4347
4348 StrutStyle strut_style;
4349 strut_style.setStrutEnabled(true);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004350 strut_style.setFontFamilies({SkString("Ahem")});
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004351 strut_style.setFontSize(50);
4352 strut_style.setHeight(1.5f);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004353 strut_style.setHeightOverride(true);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004354 strut_style.setLeading(0.1f);
4355 strut_style.setForceStrutHeight(true);
4356 paragraph_style.setStrutStyle(strut_style);
4357
4358 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4359
4360 TextStyle text_style;
4361 text_style.setFontFamilies({SkString("Ahem")});
4362 text_style.setFontSize(50);
4363 text_style.setLetterSpacing(0);
4364 text_style.setColor(SK_ColorBLACK);
4365 text_style.setHeight(1);
4366 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004367 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004368 builder.pop();
4369
4370 auto paragraph = builder.Build();
4371 paragraph->layout(550);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004372 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004373
4374 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4375 // Font is not resolved and the first line does not fit
4376 REPORTER_ASSERT(reporter, impl->lines().size() == 4);
4377
4378 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4379 RectHeightStyle rect_height_max_style = RectHeightStyle::kMax;
4380 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004381
4382 auto boxes1 = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4383 REPORTER_ASSERT(reporter, boxes1.empty());
4384
4385 auto boxes2 = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004386 canvas.drawRects(SK_ColorRED, boxes2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004387 REPORTER_ASSERT(reporter, boxes2.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004388 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.left(), 0, EPSILON100));
4389 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.top(), 22.5f, EPSILON100));
4390 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.right(), 50, EPSILON100));
4391 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes2[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004392
4393 auto boxes3 = paragraph->getRectsForRange(0, 1, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004394 canvas.drawRects(SK_ColorRED, boxes3);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004395 REPORTER_ASSERT(reporter, boxes3.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004396 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004397 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004398 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.right(), 50, EPSILON100));
4399 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes3[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004400
4401 auto boxes4 = paragraph->getRectsForRange(6, 10, rect_height_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004402 canvas.drawRects(SK_ColorRED, boxes4);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004403 REPORTER_ASSERT(reporter, boxes4.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004404 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.left(), 300, EPSILON100));
4405 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.top(), 22.5f, EPSILON100));
4406 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.right(), 500, EPSILON100));
4407 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes4[0].rect.bottom(), 72.5f, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004408
4409 auto boxes5 = paragraph->getRectsForRange(6, 10, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004410 canvas.drawRects(SK_ColorRED, boxes5);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004411 REPORTER_ASSERT(reporter, boxes5.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004412 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.left(), 300, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004413 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.top(), 0, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004414 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.right(), 500, EPSILON100));
4415 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes5[0].rect.bottom(), 80, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004416
4417 auto boxes6 = paragraph->getRectsForRange(14, 16, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004418 canvas.drawRects(SK_ColorRED, boxes6);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004419 REPORTER_ASSERT(reporter, boxes6.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004420 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.left(), 0, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004421 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.top(), 160, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004422 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.right(), 100, EPSILON100));
4423 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes6[0].rect.bottom(), 240, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004424
4425 auto boxes7 = paragraph->getRectsForRange(20, 25, rect_height_max_style, rect_width_style);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004426 canvas.drawRects(SK_ColorRED, boxes7);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004427 REPORTER_ASSERT(reporter, boxes7.size() == 1);
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004428 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.left(), 50, EPSILON100));
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004429 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.top(), 240, EPSILON100));
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004430 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.right(), 300, EPSILON100));
4431 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes7[0].rect.bottom(), 320, EPSILON100));
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004432}
4433
Julia Lavrovac2228562019-08-08 16:51:27 -04004434// Checked: NO DIFF
4435DEF_TEST(SkParagraph_StrutDefaultParagraph, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004436 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovac2228562019-08-08 16:51:27 -04004437 if (!fontCollection->fontsFound()) return;
4438 TestCanvas canvas("SkParagraph_StrutDefaultParagraph.png");
4439
4440 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004441 const size_t len = strlen(text);
Julia Lavrovac2228562019-08-08 16:51:27 -04004442
4443 ParagraphStyle paragraph_style;
4444 paragraph_style.setMaxLines(10);
4445 paragraph_style.setTextAlign(TextAlign::kLeft);
4446 paragraph_style.turnHintingOff();
4447
4448 StrutStyle strut_style;
4449 strut_style.setStrutEnabled(true);
4450 strut_style.setFontFamilies({SkString("Ahem")});
4451 strut_style.setFontSize(50);
4452 strut_style.setHeight(1.5f);
4453 strut_style.setLeading(0.1f);
4454 strut_style.setForceStrutHeight(false);
4455 paragraph_style.setStrutStyle(strut_style);
4456
4457 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4458
4459 TextStyle text_style;
4460 text_style.setFontFamilies({SkString("Ahem")});
4461 text_style.setFontSize(20);
4462 text_style.setColor(SK_ColorBLACK);
4463 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004464 builder.addText(text, len);
Julia Lavrovac2228562019-08-08 16:51:27 -04004465 builder.pop();
4466
4467 auto paragraph = builder.Build();
4468 paragraph->layout(550);
4469 paragraph->paint(canvas.get(), 0, 0);
4470
4471 RectHeightStyle rect_height_style = RectHeightStyle::kTight;
4472 RectHeightStyle rect_height_strut_style = RectHeightStyle::kStrut;
4473 RectWidthStyle rect_width_style = RectWidthStyle::kTight;
4474 {
4475 auto boxes = paragraph->getRectsForRange(0, 0, rect_height_style, rect_width_style);
4476 REPORTER_ASSERT(reporter, boxes.empty());
4477 }
4478 {
4479 auto boxes = paragraph->getRectsForRange(0, 1, rect_height_style, rect_width_style);
4480 canvas.drawRects(SK_ColorRED, boxes);
4481 REPORTER_ASSERT(reporter, boxes.size() == 1);
4482 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4483 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 26.5f, EPSILON100));
4484 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 20, EPSILON100));
4485 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 46.5f, EPSILON100));
4486 }
4487 {
4488 auto boxes = paragraph->getRectsForRange(0, 2, rect_height_strut_style, rect_width_style);
4489 canvas.drawRects(SK_ColorRED, boxes);
4490 REPORTER_ASSERT(reporter, boxes.size() == 1);
4491 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.left(), 0, EPSILON100));
4492 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.top(), 2.5f, EPSILON100));
4493 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.right(), 40, EPSILON100));
4494 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(boxes[0].rect.bottom(), 52.5f, EPSILON100));
4495 }
4496}
4497
Julia Lavrovac5313e62019-12-10 12:11:17 -05004498DEF_TEST(SkParagraph_FontFeaturesParagraph, reporter) {
4499 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
4500 if (!fontCollection->fontsFound()) return;
4501 TestCanvas canvas("SkParagraph_FontFeaturesParagraph.png");
4502
4503 const char* text = "12ab\n";
4504
4505 ParagraphStyle paragraph_style;
4506 paragraph_style.turnHintingOff();
4507 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4508
4509 TextStyle text_style;
Julia Lavrovad3a32c52020-02-03 09:43:52 -05004510 text_style.setFontStyle(SkFontStyle::Italic()); // Regular Roboto doesn't have font features
Julia Lavrovac5313e62019-12-10 12:11:17 -05004511 text_style.setFontFamilies({SkString("Roboto")});
4512 text_style.setColor(SK_ColorBLACK);
4513
4514 text_style.addFontFeature(SkString("tnum"), 1);
4515 builder.pushStyle(text_style);
4516 builder.addText(text);
4517
4518 text_style.resetFontFeatures();
4519 text_style.addFontFeature(SkString("tnum"), 0);
4520 text_style.addFontFeature(SkString("pnum"), 1);
4521 builder.pushStyle(text_style);
4522 builder.addText(text);
4523
4524 builder.pop();
4525 builder.pop();
4526
4527 auto paragraph = builder.Build();
4528 paragraph->layout(TestCanvasWidth);
4529
4530 paragraph->paint(canvas.get(), 10.0, 15.0);
4531
4532 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4533 REPORTER_ASSERT(reporter, paragraph->lineNumber() == 3ull);
4534
4535 auto& tnum_line = impl->lines()[0];
4536 auto& pnum_line = impl->lines()[1];
4537
4538 REPORTER_ASSERT(reporter, tnum_line.clusters().width() == 4ull);
4539 REPORTER_ASSERT(reporter, pnum_line.clusters().width() == 4ull);
4540 // Tabular numbers should have equal widths.
4541 REPORTER_ASSERT(reporter, impl->clusters()[0].width() == impl->clusters()[1].width());
4542 // Proportional numbers should have variable widths.
4543 REPORTER_ASSERT(reporter, impl->clusters()[5].width() != impl->clusters()[6].width());
4544 // Alphabetic characters should be unaffected.
4545 REPORTER_ASSERT(reporter, impl->clusters()[2].width() == impl->clusters()[7].width());
4546}
4547
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004548// Not in Minikin
4549DEF_TEST(SkParagraph_WhitespacesInMultipleFonts, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004550 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004551 if (!fontCollection->fontsFound()) return;
4552 const char* text = "English English 字典 字典 😀😃😄 😀😃😄";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004553 const size_t len = strlen(text);
4554
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004555 ParagraphStyle paragraph_style;
4556 paragraph_style.turnHintingOff();
4557 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4558
4559 TextStyle text_style;
4560 text_style.setFontFamilies(
4561 {SkString("Roboto"), SkString("Noto Color Emoji"), SkString("Source Han Serif CN")});
4562 text_style.setFontSize(60);
4563 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004564 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004565 builder.pop();
4566
4567 auto paragraph = builder.Build();
4568 paragraph->layout(TestCanvasWidth);
Julia Lavrova3281b962019-12-02 11:32:25 -05004569
4570 REPORTER_ASSERT(reporter, paragraph->unresolvedGlyphs() == 0);
4571
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004572 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4573 for (size_t i = 0; i < impl->runs().size() - 1; ++i) {
4574 auto first = impl->runs()[i].textRange();
4575 auto next = impl->runs()[i + 1].textRange();
4576 REPORTER_ASSERT(reporter, first.end == next.start);
4577 }
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004578}
4579
Julia Lavrova90787fe2020-07-20 17:32:03 +00004580// Disable until I sort out fonts
4581DEF_TEST_DISABLED(SkParagraph_JSON1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004582 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004583 if (!fontCollection->fontsFound()) return;
4584 const char* text = "👨‍👩‍👧‍👦";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004585 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004586
4587 ParagraphStyle paragraph_style;
4588 paragraph_style.turnHintingOff();
4589 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4590
4591 TextStyle text_style;
4592 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4593 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004594 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004595 builder.pop();
4596
4597 auto paragraph = builder.Build();
4598 paragraph->layout(TestCanvasWidth);
4599
4600 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4601 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004602 auto& run = impl->runs().front();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004603
4604 auto cluster = 0;
4605 SkShaperJSONWriter::VisualizeClusters(
4606 text, 0, std::strlen(text), run.glyphs(), run.clusterIndexes(),
4607 [&](int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
4608 if (cluster == 0) {
4609 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4610 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4611 SkASSERT(glyph1to1.size() == 1);
4612 SkASSERT(*glyph1to1.begin() == 1611);
4613 }
4614 ++cluster;
4615 });
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004616 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004617}
4618
Julia Lavrova90787fe2020-07-20 17:32:03 +00004619// Disable until I sort out fonts
4620DEF_TEST_DISABLED(SkParagraph_JSON2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004621 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004622 if (!fontCollection->fontsFound()) return;
4623 const char* text = "p〠q";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004624 const size_t len = strlen(text);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004625
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004626 ParagraphStyle paragraph_style;
4627 paragraph_style.turnHintingOff();
4628 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4629
4630 TextStyle text_style;
4631 text_style.setFontFamilies({SkString("Noto Sans CJK JP")});
4632 text_style.setColor(SK_ColorBLACK);
4633 text_style.setFontSize(50);
4634 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004635 builder.addText(text, len);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004636 builder.pop();
4637
4638 auto paragraph = builder.Build();
4639 paragraph->layout(TestCanvasWidth);
4640
4641 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4642 REPORTER_ASSERT(reporter, impl->runs().size() == 1);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004643
4644 auto cluster = 0;
4645 for (auto& run : impl->runs()) {
4646 SkShaperJSONWriter::VisualizeClusters(
Julia Lavrovadb9f6692019-08-01 16:02:17 -04004647 impl->text().begin() + run.textRange().start, 0, run.textRange().width(),
4648 run.glyphs(), run.clusterIndexes(),
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004649 [&](int codePointCount, SkSpan<const char> utf1to1,
4650 SkSpan<const SkGlyphID> glyph1to1) {
4651 if (cluster == 0) {
4652 std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
4653 SkASSERT(std::strcmp(text, utf1to1.data()) == 0);
4654 SkASSERT(glyph1to1.size() == 3);
4655 }
4656 ++cluster;
4657 });
4658 }
4659
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004660 REPORTER_ASSERT(reporter, cluster <= 2);
Julia Lavrovaa3552c52019-05-30 16:12:56 -04004661}
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004662
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004663DEF_TEST(SkParagraph_CacheText, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004664 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004665 cache.turnOn(true);
4666 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004667 if (!fontCollection->fontsFound()) return;
4668
4669 ParagraphStyle paragraph_style;
4670 paragraph_style.turnHintingOff();
4671
4672 TextStyle text_style;
4673 text_style.setFontFamilies({SkString("Roboto")});
4674 text_style.setColor(SK_ColorBLACK);
4675
4676 auto test = [&](const char* text, int count, bool expectedToBeFound) {
4677 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4678 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004679 builder.addText(text, strlen(text));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004680 builder.pop();
4681 auto paragraph = builder.Build();
4682
4683 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4684 REPORTER_ASSERT(reporter, count == cache.count());
4685 auto found = cache.findParagraph(impl);
4686 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4687 auto added = cache.updateParagraph(impl);
4688 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4689 };
4690
4691 test("text1", 0, false);
4692 test("text1", 1, true);
4693 test("text2", 1, false);
4694 test("text2", 2, true);
4695 test("text3", 2, false);
4696}
4697
4698DEF_TEST(SkParagraph_CacheFonts, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004699 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004700 cache.turnOn(true);
4701 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004702 if (!fontCollection->fontsFound()) return;
4703
4704 ParagraphStyle paragraph_style;
4705 paragraph_style.turnHintingOff();
4706
4707 TextStyle text_style;
4708 text_style.setColor(SK_ColorBLACK);
4709
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004710 const char* text = "text";
4711 const size_t len = strlen(text);
4712
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004713 auto test = [&](int count, bool expectedToBeFound) {
4714 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4715 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004716 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004717 builder.pop();
4718 auto paragraph = builder.Build();
4719 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4720
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004721 REPORTER_ASSERT(reporter, count == cache.count());
4722 auto found = cache.findParagraph(impl);
4723 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4724 auto added = cache.updateParagraph(impl);
4725 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4726 };
4727
4728 text_style.setFontFamilies({SkString("Roboto")});
4729 test(0, false);
4730 test(1, true);
4731 text_style.setFontFamilies({SkString("Homemade Apple")});
4732 test(1, false);
4733 test(2, true);
4734 text_style.setFontFamilies({SkString("Noto Color Emoji")});
4735 test(2, false);
4736}
4737
4738DEF_TEST(SkParagraph_CacheFontRanges, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004739 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004740 cache.turnOn(true);
4741 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004742 if (!fontCollection->fontsFound()) return;
4743
4744 ParagraphStyle paragraph_style;
4745 paragraph_style.turnHintingOff();
4746
4747 TextStyle text_style;
4748 text_style.setFontFamilies({SkString("Roboto")});
4749 text_style.setColor(SK_ColorBLACK);
4750
4751 auto test = [&](const char* text1,
4752 const char* text2,
4753 const char* font1,
4754 const char* font2,
4755 int count,
4756 bool expectedToBeFound) {
4757 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4758 text_style.setFontFamilies({SkString(font1)});
4759 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004760 builder.addText(text1, strlen(text1));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004761 builder.pop();
4762 text_style.setFontFamilies({SkString(font2)});
4763 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004764 builder.addText(text2, strlen(text2));
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004765 builder.pop();
4766 auto paragraph = builder.Build();
4767 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4768
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004769 REPORTER_ASSERT(reporter, count == cache.count());
4770 auto found = cache.findParagraph(impl);
4771 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4772 auto added = cache.updateParagraph(impl);
4773 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4774 };
4775
4776 test("text", "", "Roboto", "Homemade Apple", 0, false);
4777 test("t", "ext", "Roboto", "Homemade Apple", 1, false);
4778 test("te", "xt", "Roboto", "Homemade Apple", 2, false);
4779 test("tex", "t", "Roboto", "Homemade Apple", 3, false);
4780 test("text", "", "Roboto", "Homemade Apple", 4, true);
4781}
4782
4783DEF_TEST(SkParagraph_CacheStyles, reporter) {
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004784 ParagraphCache cache;
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004785 cache.turnOn(true);
4786 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004787 if (!fontCollection->fontsFound()) return;
4788
4789 ParagraphStyle paragraph_style;
4790 paragraph_style.turnHintingOff();
4791
4792 TextStyle text_style;
4793 text_style.setFontFamilies({SkString("Roboto")});
4794 text_style.setColor(SK_ColorBLACK);
4795
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004796 const char* text = "text";
4797 const size_t len = strlen(text);
4798
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004799 auto test = [&](int count, bool expectedToBeFound) {
4800 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4801 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004802 builder.addText(text, len);
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004803 builder.pop();
4804 auto paragraph = builder.Build();
4805 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
4806
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004807 REPORTER_ASSERT(reporter, count == cache.count());
4808 auto found = cache.findParagraph(impl);
4809 REPORTER_ASSERT(reporter, found == expectedToBeFound);
4810 auto added = cache.updateParagraph(impl);
4811 REPORTER_ASSERT(reporter, added != expectedToBeFound);
4812 };
4813
Julia Lavrovab7b0b3a2019-07-30 13:32:08 -04004814 test(0, false);
4815 test(1, true);
4816 text_style.setLetterSpacing(10);
4817 test(1, false);
4818 test(2, true);
4819 text_style.setWordSpacing(10);
4820 test(2, false);
4821}
Julia Lavrovaa40db422019-08-21 13:49:15 -04004822
Julia Lavrova526df262019-08-21 17:49:44 -04004823DEF_TEST(SkParagraph_EmptyParagraphWithLineBreak, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004824 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004825 if (!fontCollection->fontsFound()) return;
Julia Lavrova526df262019-08-21 17:49:44 -04004826 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4827 TestCanvas canvas("SkParagraph_EmptyParagraphWithLineBreak.png");
Julia Lavrovaa40db422019-08-21 13:49:15 -04004828
4829 ParagraphStyle paragraph_style;
Julia Lavrovaa40db422019-08-21 13:49:15 -04004830 TextStyle text_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004831 text_style.setFontSize(16);
4832 text_style.setFontFamilies({SkString("Roboto")});
4833 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004834 builder.addText("\n", 1);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004835
4836 auto paragraph = builder.Build();
4837 paragraph->layout(TestCanvasWidth);
4838 paragraph->paint(canvas.get(), 0, 0);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004839 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004840}
4841
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004842DEF_TEST(SkParagraph_NullInMiddleOfText, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004843 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004844 if (!fontCollection->fontsFound()) return;
4845 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
4846 TestCanvas canvas("SkParagraph_NullInMiddleOfText.png");
4847
4848 const SkString text("null terminator ->\u0000<- on purpose did you see it?");
4849
4850 ParagraphStyle paragraph_style;
4851 TextStyle text_style;
4852 text_style.setFontSize(16);
4853 text_style.setFontFamilies({SkString("Roboto")});
4854 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4855 builder.addText(text.c_str(), text.size());
4856
4857 auto paragraph = builder.Build();
4858 paragraph->layout(TestCanvasWidth);
4859 paragraph->paint(canvas.get(), 0, 0);
4860}
4861
Julia Lavrovaa40db422019-08-21 13:49:15 -04004862DEF_TEST(SkParagraph_PlaceholderOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004863 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaa40db422019-08-21 13:49:15 -04004864 if (!fontCollection->fontsFound()) return;
4865 TestCanvas canvas("SkParagraph_PlaceholderOnly.png");
4866
4867 ParagraphStyle paragraph_style;
4868 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4869
Julia Lavrova526df262019-08-21 17:49:44 -04004870 PlaceholderStyle placeholder(0, 0, PlaceholderAlignment::kBaseline, TextBaseline::kAlphabetic, 0);
Julia Lavrovaa40db422019-08-21 13:49:15 -04004871 builder.addPlaceholder(placeholder);
4872
4873 auto paragraph = builder.Build();
4874 paragraph->layout(TestCanvasWidth);
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04004875 auto result = paragraph->getRectsForPlaceholders();
Julia Lavrova526df262019-08-21 17:49:44 -04004876 paragraph->paint(canvas.get(), 0, 0);
4877}
4878
4879DEF_TEST(SkParagraph_Fallbacks, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004880 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004881 if (!fontCollection->fontsFound()) return;
4882 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault(), "Arial");
4883 TestCanvas canvas("SkParagraph_Fallbacks.png");
4884
4885 const char* multiScript = "A1!aÀàĀāƁƀḂⱠꜲꬰəͲἀἏЀЖԠꙐꙮՁخ‎ࡔࠇܦআਉઐଘஇఘಧൺඣᭆᯔᮯ᳇ꠈᜅᩌꪈ༇ꥄꡙꫤ᧰៘꧁꧂ᜰᨏᯤᢆᣭᗗꗃⵞ𐒎߷ጩꬤ𖠺‡₩℻Ⅷ↹⋇⏳ⓖ╋▒◛⚧⑆שׁ🅕㊼龜ポ䷤🂡\n";
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004886 const size_t len = strlen(multiScript);
Julia Lavrova526df262019-08-21 17:49:44 -04004887
4888 const char* androidFonts[] = {
4889 "sans-serif",
4890 "sans-serif-condensed",
4891 "serif",
4892 "monospace",
4893 "serif-monospace",
4894 "casual",
4895 "cursive",
4896 "sans-serif-smallcaps",
4897 };
4898
4899 for (auto& font : androidFonts) {
4900
4901 ParagraphStyle paragraph_style;
4902 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4903
4904 TextStyle text_style;
4905 text_style.setColor(SK_ColorBLACK);
4906 text_style.setLocale(SkString("en_US"));
4907 text_style.setFontSize(20);
4908
4909 text_style.setFontFamilies({ SkString(font) });
4910 builder.pushStyle(text_style);
Kevin Lubick7aeabcf2019-09-27 15:16:13 -04004911 builder.addText(multiScript, len);
Julia Lavrova526df262019-08-21 17:49:44 -04004912
4913 builder.pop();
4914
4915 auto paragraph = builder.Build();
4916 paragraph->layout(TestCanvasWidth);
4917 paragraph->paint(canvas.get(), 0, 0);
4918 canvas.get()->translate(0, paragraph.get()->getHeight() + 10);
4919 }
4920}
4921
4922DEF_TEST(SkParagraph_Bidi1, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004923 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004924 if (!fontCollection->fontsFound()) return;
4925 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004926 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004927 TestCanvas canvas("SkParagraph_Bidi1.png");
4928
4929 std::u16string abc = u"\u202Dabc";
4930 std::u16string DEF = u"\u202EDEF";
4931 std::u16string ghi = u"\u202Dghi";
4932 std::u16string JKL = u"\u202EJKL";
4933 std::u16string mno = u"\u202Dmno";
4934
4935 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4936
4937 ParagraphStyle paragraph_style;
4938 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4939
4940 TextStyle text_style;
4941 text_style.setFontFamilies({ SkString("sans-serif")});
4942 text_style.setFontSize(40);
4943
4944 text_style.setColor(SK_ColorCYAN);
4945 text_style.setFontStyle(SkFontStyle(SkFontStyle::kThin_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4946 builder.pushStyle(text_style);
4947 builder.addText(abc);
4948
4949 text_style.setColor(SK_ColorGREEN);
4950 text_style.setFontStyle(SkFontStyle(SkFontStyle::kLight_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4951 builder.pushStyle(text_style);
4952 builder.addText(DEF);
4953
4954 text_style.setColor(SK_ColorYELLOW);
4955 text_style.setFontStyle(SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4956 builder.pushStyle(text_style);
4957 builder.addText(ghi);
4958
4959 text_style.setColor(SK_ColorMAGENTA);
4960 text_style.setFontStyle(SkFontStyle(SkFontStyle::kMedium_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4961 builder.pushStyle(text_style);
4962 builder.addText(JKL);
4963
4964 text_style.setColor(SK_ColorBLUE);
4965 text_style.setFontStyle(SkFontStyle(SkFontStyle::kBlack_Weight, SkFontStyle::kNormal_Width, SkFontStyle::kUpright_Slant));
4966 builder.pushStyle(text_style);
4967 builder.addText(mno);
4968
4969 auto paragraph = builder.Build();
4970 paragraph->layout(400);
4971 paragraph->paint(canvas.get(), 0, 0);
4972}
4973
4974DEF_TEST(SkParagraph_Bidi2, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004975 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrova526df262019-08-21 17:49:44 -04004976 if (!fontCollection->fontsFound()) return;
4977 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
Julia Lavrova2e30fde2019-10-09 09:43:02 -04004978 fontCollection->enableFontFallback();
Julia Lavrova526df262019-08-21 17:49:44 -04004979 TestCanvas canvas("SkParagraph_Bidi2.png");
4980
4981 std::u16string abcD = u"\u202Dabc\u202ED";
4982 std::u16string EFgh = u"EF\u202Dgh";
4983 std::u16string iJKLmno = u"i\u202EJKL\u202Dmno";
4984
4985 std::u16string abcDEFghiJKLmno = u"\u202Dabc\u202EDEF\u202Dghi\u202EJKL\u202Dmno";
4986
4987 ParagraphStyle paragraph_style;
Julia Lavrova526df262019-08-21 17:49:44 -04004988 TextStyle text_style;
4989 text_style.setFontFamilies({ SkString("sans-serif")});
4990 text_style.setFontSize(40);
Julia Lavrova526df262019-08-21 17:49:44 -04004991
Julia Lavrovac88a3bc2020-01-23 10:16:26 -05004992 {
4993 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
4994 builder.pushStyle(text_style);
4995 builder.addText(abcD);
4996 builder.pushStyle(text_style);
4997 builder.addText(EFgh);
4998 builder.pushStyle(text_style);
4999 builder.addText(iJKLmno);
5000 auto paragraph = builder.Build();
5001 paragraph->layout(360);
5002 paragraph->paint(canvas.get(), 0, 0);
5003 }
5004 canvas.get()->translate(0, 400);
5005 {
5006 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5007 builder.pushStyle(text_style);
5008 builder.addText(abcDEFghiJKLmno);
5009 auto paragraph = builder.Build();
5010 paragraph->layout(360);
5011 paragraph->paint(canvas.get(), 0, 0);
5012 }
Julia Lavrovaa40db422019-08-21 13:49:15 -04005013}
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005014
5015DEF_TEST(SkParagraph_NewlineOnly, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005016 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
Julia Lavrovaf3ed2732019-09-05 14:35:17 -04005017 if (!fontCollection->fontsFound()) return;
5018 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5019 TestCanvas canvas("SkParagraph_Newline.png");
5020
5021 TextStyle text_style;
5022 text_style.setFontFamilies({SkString("Ahem")});
5023 text_style.setColor(SK_ColorBLACK);
5024 StrutStyle strut_style;
5025 strut_style.setStrutEnabled(false);
5026 ParagraphStyle paragraph_style;
5027 paragraph_style.setStrutStyle(strut_style);
5028 paragraph_style.setTextStyle(text_style);
5029 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5030 builder.addText("\n");
5031 auto paragraph = builder.Build();
5032 paragraph->layout(1000);
5033 REPORTER_ASSERT(reporter, paragraph->getHeight() == 28);
5034}
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005035
Julia Lavrovab30d4812019-11-08 14:51:16 -05005036DEF_TEST_DISABLED(SkParagraph_FontResolutions, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005037 TestCanvas canvas("SkParagraph_FontResolutions.png");
5038
5039 sk_sp<TestFontCollection> fontCollection =
5040 sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false);
5041 if (!fontCollection->fontsFound()) return;
5042
5043 if (!fontCollection->addFontFromFile("abc/abc.ttf", "abc")) {
5044 return;
5045 }
5046 if (!fontCollection->addFontFromFile("abc/abc+grave.ttf", "abc+grave")) {
5047 return;
5048 }
5049 if (!fontCollection->addFontFromFile("abc/abc_agrave.ttf", "abc_agrave")) {
5050 return;
5051 }
5052
5053 TextStyle text_style;
5054 text_style.setFontFamilies({SkString("abc")});
5055 text_style.setFontSize(50);
5056
5057 ParagraphStyle paragraph_style;
5058 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5059
5060 text_style.setFontFamilies({SkString("abc"), SkString("abc+grave")});
5061 text_style.setColor(SK_ColorBLUE);
5062 builder.pushStyle(text_style);
5063 builder.addText(u"a\u0300");
5064 text_style.setColor(SK_ColorMAGENTA);
5065 builder.pushStyle(text_style);
5066 builder.addText(u"à");
5067
5068 text_style.setFontFamilies({SkString("abc"), SkString("abc_agrave")});
5069
5070 text_style.setColor(SK_ColorRED);
5071 builder.pushStyle(text_style);
5072 builder.addText(u"a\u0300");
5073 text_style.setColor(SK_ColorGREEN);
5074 builder.pushStyle(text_style);
5075 builder.addText(u"à");
5076
5077 auto paragraph = builder.Build();
5078 paragraph->layout(TestCanvasWidth);
5079
5080 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5081 REPORTER_ASSERT(reporter, impl->runs().size() == 2);
5082
5083 REPORTER_ASSERT(reporter, impl->runs().front().size() == 4);
5084 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[0] == impl->runs().front().glyphs()[2]);
5085 REPORTER_ASSERT(reporter, impl->runs().front().glyphs()[1] == impl->runs().front().glyphs()[3]);
5086
5087 REPORTER_ASSERT(reporter, impl->runs().back().size() == 2);
5088 REPORTER_ASSERT(reporter, impl->runs().back().glyphs()[0] == impl->runs().back().glyphs()[1]);
5089
5090 paragraph->paint(canvas.get(), 100, 100);
5091}
5092
Julia Lavrovab30d4812019-11-08 14:51:16 -05005093DEF_TEST_DISABLED(SkParagraph_FontStyle, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005094 TestCanvas canvas("SkParagraph_FontStyle.png");
5095
5096 sk_sp<TestFontCollection> fontCollection = sk_make_sp<TestFontCollection>(GetResourcePath("fonts").c_str(), false, true);
5097 if (!fontCollection->fontsFound()) return;
5098
5099 TextStyle text_style;
5100 text_style.setFontFamilies({SkString("Roboto")});
5101 text_style.setColor(SK_ColorBLACK);
5102 text_style.setFontSize(20);
5103 SkFontStyle fs = SkFontStyle(
5104 SkFontStyle::Weight::kLight_Weight,
5105 SkFontStyle::Width::kNormal_Width,
5106 SkFontStyle::Slant::kUpright_Slant
5107 );
5108 text_style.setFontStyle(fs);
5109 ParagraphStyle paragraph_style;
5110 paragraph_style.setTextStyle(text_style);
5111 TextStyle boldItalic;
5112 boldItalic.setFontFamilies({SkString("Roboto")});
5113 boldItalic.setColor(SK_ColorRED);
5114 SkFontStyle bi = SkFontStyle(
5115 SkFontStyle::Weight::kBold_Weight,
5116 SkFontStyle::Width::kNormal_Width,
5117 SkFontStyle::Slant::kItalic_Slant
5118 );
5119 boldItalic.setFontStyle(bi);
5120 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5121 builder.addText("Default text\n");
5122 builder.pushStyle(boldItalic);
5123 builder.addText("Bold and Italic\n");
5124 builder.pop();
5125 builder.addText("back to normal");
5126 auto paragraph = builder.Build();
5127 paragraph->layout(250);
5128 paragraph->paint(canvas.get(), 0, 0);
5129}
5130
Julia Lavrovab30d4812019-11-08 14:51:16 -05005131DEF_TEST_DISABLED(SkParagraph_Shaping, reporter) {
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005132 TestCanvas canvas("SkParagraph_Shaping.png");
5133
Julia Lavrova2e30fde2019-10-09 09:43:02 -04005134 auto dir = "/usr/local/google/home/jlavrova/Sources/flutter/engine/src/out/host_debug_unopt_x86/gen/flutter/third_party/txt/assets";
5135 sk_sp<TestFontCollection> fontCollection =
5136 sk_make_sp<TestFontCollection>(dir, /*GetResourcePath("fonts").c_str(), */ false);
5137 if (!fontCollection->fontsFound()) return;
5138
5139
5140 TextStyle text_style;
5141 text_style.setFontFamilies({SkString("Roboto")});
5142 text_style.setColor(SK_ColorGRAY);
5143 text_style.setFontSize(14);
5144 SkFontStyle b = SkFontStyle(
5145 SkFontStyle::Weight::kNormal_Weight,
5146 SkFontStyle::Width::kNormal_Width,
5147 SkFontStyle::Slant::kUpright_Slant
5148 );
5149 text_style.setFontStyle(b);
5150 ParagraphStyle paragraph_style;
5151 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5152 builder.pushStyle(text_style);
5153 builder.addText("Eat0 apple0 pies0 | Eat1 apple1 pies1 | Eat2 apple2 pies2");
5154 auto paragraph = builder.Build();
5155 paragraph->layout(380);
5156 paragraph->paint(canvas.get(), 0, 0);
5157}
Julia Lavrovac028b422019-11-25 10:00:43 -05005158
5159DEF_TEST(SkParagraph_Ellipsis, reporter) {
5160 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5161 if (!fontCollection->fontsFound()) return;
5162 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5163 TestCanvas canvas("SkParagraph_Ellipsis.png");
5164
5165 const char* text = "This\n"
5166 "is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.";
5167 TextStyle text_style;
5168 text_style.setFontFamilies({SkString("Ahem")});
5169 text_style.setColor(SK_ColorBLACK);
5170 text_style.setFontSize(10);
5171
5172 auto relayout = [&](size_t lines, bool ellipsis,
5173 SkScalar width, SkScalar height, SkScalar minWidth, SkScalar maxWidth, SkColor bg) {
5174 ParagraphStyle paragraph_style;
5175 SkPaint paint;
5176 paint.setColor(bg);
5177 text_style.setForegroundColor(paint);
5178 paragraph_style.setTextStyle(text_style);
5179 paragraph_style.setMaxLines(lines);
5180 if (ellipsis) {
5181 paragraph_style.setEllipsis(u"\u2026");
5182 }
5183 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5184 builder.addText(text);
5185 auto paragraph = builder.Build();
5186 paragraph->layout(50);
5187 paragraph->paint(canvas.get(), 0, 0);
5188 canvas.get()->translate(50, paragraph->getHeight() + 10);
5189 auto result = paragraph->getRectsForRange(0, strlen(text), RectHeightStyle::kTight, RectWidthStyle::kTight);
5190 SkPaint background;
5191 background.setColor(SK_ColorRED);
5192 background.setStyle(SkPaint::kStroke_Style);
5193 background.setAntiAlias(true);
5194 background.setStrokeWidth(1);
5195 canvas.get()->drawRect(result.front().rect, background);
5196
5197 SkASSERT(width == paragraph->getMaxWidth());
5198 SkASSERT(height == paragraph->getHeight());
5199 SkASSERT(minWidth == paragraph->getMinIntrinsicWidth());
5200 SkASSERT(maxWidth == paragraph->getMaxIntrinsicWidth());
5201 };
5202
5203 SkPaint paint;
5204 paint.setColor(SK_ColorLTGRAY);
5205 canvas.get()->drawRect(SkRect::MakeXYWH(0, 0, 50, 500), paint);
5206
5207 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005208 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5209 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005210
5211 relayout(1, true, 50, 10, 950, 950, SK_ColorYELLOW);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005212 relayout(3, true, 50, 30, 90, 950, SK_ColorMAGENTA);
Julia Lavrovac028b422019-11-25 10:00:43 -05005213 relayout(std::numeric_limits<size_t>::max(), true, 50, 20, 950, 950, SK_ColorCYAN);
5214
5215 relayout(1, false, 50, 10, 950, 950, SK_ColorRED);
Julia Lavrova90bfd1c2019-12-04 11:43:32 -05005216 relayout(3, false, 50, 30, 90, 950, SK_ColorBLUE);
5217 relayout(std::numeric_limits<size_t>::max(), false, 50, 200, 90, 950, SK_ColorGREEN);
Julia Lavrovac028b422019-11-25 10:00:43 -05005218}
Julia Lavrovadb543f62020-01-29 11:43:41 -05005219
5220DEF_TEST(SkParagraph_MemoryLeak, reporter) {
5221 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5222 if (!fontCollection->fontsFound()) return;
5223 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5224
5225 std::string text;
5226 for (size_t i = 0; i < 10; i++)
5227 {
5228 SkPaint paint;
5229 paint.setAntiAlias(true);
5230 paint.setColor(SK_ColorBLACK);
5231
5232 TextStyle textStyle;
5233 textStyle.setForegroundColor(paint);
5234 textStyle.setFontFamilies({ SkString("Roboto") });
5235
5236 ParagraphStyle paragraphStyle;
5237 paragraphStyle.setTextStyle(textStyle);
5238
5239 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5240 text += "Text ";
5241 builder.addText(text.c_str());
5242
5243 auto paragraph = builder.Build();
5244 paragraph->layout(100);
5245
5246 //used to add a delay so I can monitor memory usage
5247 //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
5248 }
5249};
Julia Lavrovac0360582020-02-05 10:17:53 -05005250
5251DEF_TEST(SkParagraph_FormattingInfinity, reporter) {
5252 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5253 if (!fontCollection->fontsFound()) return;
5254 fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
5255 TestCanvas canvas("SkParagraph_FormattingInfinity.png");
5256
5257 const char* text = "Some text\nAnother line";
5258
5259 SkPaint paint;
5260 paint.setAntiAlias(true);
5261 paint.setColor(SK_ColorBLACK);
5262
5263 TextStyle textStyle;
5264 textStyle.setForegroundColor(paint);
5265 textStyle.setFontFamilies({ SkString("Roboto") });
5266 ParagraphStyle paragraphStyle;
5267 paragraphStyle.setTextStyle(textStyle);
5268
5269 auto draw = [&](const char* prefix, TextAlign textAlign) {
5270 paragraphStyle.setTextAlign(textAlign);
5271 ParagraphBuilderImpl builder(paragraphStyle, fontCollection);
5272 builder.addText(text);
5273 auto paragraph = builder.Build();
5274 paragraph->layout(SK_ScalarInfinity);
5275 paragraph->paint(canvas.get(), 0, 0);
5276 canvas.get()->translate(0, 100);
5277 };
5278
5279 draw("left", TextAlign::kLeft);
5280 draw("right", TextAlign::kRight);
5281 draw("center", TextAlign::kCenter);
5282 draw("justify", TextAlign::kJustify);
5283};
5284
5285DEF_TEST(SkParagraph_Infinity, reporter) {
5286 SkASSERT(nearlyEqual(1, SK_ScalarInfinity) == false);
5287 SkASSERT(nearlyEqual(1, SK_ScalarNegativeInfinity) == false);
5288 SkASSERT(nearlyEqual(1, SK_ScalarNaN) == false);
5289
5290 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarInfinity) == true);
5291 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNegativeInfinity) == false);
5292 SkASSERT(nearlyEqual(SK_ScalarInfinity, SK_ScalarNaN) == false);
5293
5294 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarInfinity) == false);
5295 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity) == true);
5296 SkASSERT(nearlyEqual(SK_ScalarNegativeInfinity, SK_ScalarNaN) == false);
5297
5298 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarInfinity) == false);
5299 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNegativeInfinity) == false);
5300 SkASSERT(nearlyEqual(SK_ScalarNaN, SK_ScalarNaN) == false);
5301};
Julia Lavrova2002b862020-06-19 11:17:09 -04005302
5303DEF_TEST(SkParagraph_LineMetrics, reporter) {
5304
5305 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5306 if (!fontCollection->fontsFound()) return;
5307
5308 TestCanvas canvas("SkParagraph_LineMetrics.png");
5309
5310 const char* text = "One line of text\n";
5311 const size_t len = strlen(text);
5312
5313 ParagraphStyle paragraph_style;
5314 paragraph_style.turnHintingOff();
5315 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5316
5317 TextStyle text_style;
5318 text_style.setFontFamilies({SkString("Roboto")});
5319 text_style.setColor(SK_ColorBLACK);
5320
5321 text_style.setFontSize(8);
5322 builder.pushStyle(text_style);
5323 builder.addText(text, len);
5324 builder.pop();
5325
5326 text_style.setFontSize(12);
5327 builder.pushStyle(text_style);
5328 builder.addText(text, len);
5329 builder.pop();
5330
5331 text_style.setFontSize(18);
5332 builder.pushStyle(text_style);
5333 builder.addText(text, len);
5334 builder.pop();
5335
5336 text_style.setFontSize(30);
5337 builder.pushStyle(text_style);
5338 builder.addText(text, len - 1); // Skip the last \n
5339 builder.pop();
5340
5341 auto paragraph = builder.Build();
5342 paragraph->layout(TestCanvasWidth);
5343
5344 std::vector<LineMetrics> metrics;
5345 paragraph->getLineMetrics(metrics);
5346
5347 SkDEBUGCODE(auto impl = static_cast<ParagraphImpl*>(paragraph.get());)
5348 SkASSERT(metrics.size() == impl->lines().size());
5349 for (size_t i = 0; i < metrics.size(); ++i) {
5350 SkDEBUGCODE(auto& line = impl->lines()[i];)
5351 SkDEBUGCODE(auto baseline = metrics[i].fBaseline;)
5352 SkDEBUGCODE(auto top = line.offset().fY;)
5353 SkDEBUGCODE(auto bottom = line.offset().fY + line.height();)
5354 SkASSERT( baseline > top && baseline <= bottom);
5355 }
5356
5357 paragraph->paint(canvas.get(), 0, 0);
5358 auto rects = paragraph->getRectsForRange(0, len * 4, RectHeightStyle::kMax, RectWidthStyle::kTight);
5359
5360 SkPaint red;
5361 red.setColor(SK_ColorRED);
5362 red.setStyle(SkPaint::kStroke_Style);
5363 red.setAntiAlias(true);
5364 red.setStrokeWidth(1);
5365
5366 for (auto& rect : rects) {
5367 canvas.get()->drawRect(rect.rect, red);
5368 }
5369
5370 SkPaint green;
5371 green.setColor(SK_ColorGREEN);
5372 green.setStyle(SkPaint::kStroke_Style);
5373 green.setAntiAlias(true);
5374 green.setStrokeWidth(1);
5375 for (auto& metric : metrics) {
5376 auto x0 = 0.0;
5377 auto x1 = metric.fWidth;
5378 auto y = metric.fBaseline;
5379 canvas.get()->drawLine(x0, y, x1, y, green);
5380 }
5381};
Julia Lavrovace6f24d2020-07-08 10:41:54 -04005382
5383DEF_TEST(SkParagraph_PlaceholderHeightInf, reporter) {
5384 TestCanvas canvas("SkParagraph_PlaceholderHeightInf.png");
5385
5386 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5387 if (!fontCollection->fontsFound()) return;
5388
5389 TextStyle text_style;
5390 text_style.setFontFamilies({SkString("Ahem")});
5391 text_style.setColor(SK_ColorBLACK);
5392 text_style.setFontSize(14);
5393
5394 PlaceholderStyle placeholder_style;
5395 placeholder_style.fWidth = 16.0f;
5396 placeholder_style.fHeight = SK_ScalarInfinity;
5397 placeholder_style.fAlignment = PlaceholderAlignment::kBottom;
5398 placeholder_style.fBaseline = TextBaseline::kAlphabetic;
5399 placeholder_style.fBaselineOffset = SK_ScalarInfinity;
5400
5401 ParagraphStyle paragraph_style;
5402
5403 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5404 builder.pushStyle(text_style);
5405 builder.addText("Limited by budget");
5406 builder.addPlaceholder(placeholder_style);
5407 auto paragraph = builder.Build();
5408 paragraph->layout(SK_ScalarInfinity);
5409
5410 auto impl = static_cast<ParagraphImpl*>(paragraph.get());
5411 REPORTER_ASSERT(reporter, SkScalarIsFinite(impl->getBoundaries().height()));
5412 REPORTER_ASSERT(reporter, SkScalarIsFinite(impl->getBoundaries().width()));
5413
5414 paragraph->paint(canvas.get(), 0, 0);
5415}
Julia Lavrova196515c2020-07-08 14:55:17 -04005416
5417DEF_TEST(SkParagraph_LineMetricsTextAlign, reporter) {
5418
5419 sk_sp<ResourceFontCollection> fontCollection = sk_make_sp<ResourceFontCollection>();
5420 if (!fontCollection->fontsFound()) return;
5421
5422 TestCanvas canvas("SkParagraph_LineMetricsTextAlign.png");
5423
5424 ParagraphStyle paragraph_style;
5425 paragraph_style.turnHintingOff();
5426 TextStyle text_style;
5427 text_style.setFontFamilies({SkString("Roboto")});
5428 text_style.setColor(SK_ColorBLACK);
5429
5430 auto layout = [&](TextAlign text_align) -> std::pair<SkScalar, SkScalar> {
5431 paragraph_style.setTextAlign(text_align);
5432 ParagraphBuilderImpl builder(paragraph_style, fontCollection);
5433 builder.pushStyle(text_style);
5434 builder.addText("Some text that takes more than 200 px");
5435 auto paragraph = builder.Build();
5436 paragraph->layout(200);
5437
5438 std::vector<LineMetrics> metrics;
5439 paragraph->getLineMetrics(metrics);
5440 REPORTER_ASSERT(reporter, metrics.size() > 0);
5441 return { metrics[0].fLeft, metrics[0].fWidth };
5442 };
5443
5444 SkScalar left[4];
5445 SkScalar width[4];
5446 std::tie(left[0], width[0]) = layout(TextAlign::kLeft);
5447 std::tie(left[1], width[1]) = layout(TextAlign::kCenter);
5448 std::tie(left[2], width[2]) = layout(TextAlign::kRight);
5449 std::tie(left[3], width[3]) = layout(TextAlign::kJustify);
5450
5451 // delta = line_width - text_width
5452 REPORTER_ASSERT(reporter, left[0] == 0); // Starts from 0
5453 REPORTER_ASSERT(reporter, left[1] > left[0]); // Starts from delta / 2
5454 REPORTER_ASSERT(reporter, left[2] > left[1]); // Starts from delta
5455 REPORTER_ASSERT(reporter, left[3] == left[0]); // Starts from 0
5456 REPORTER_ASSERT(reporter, width[1] == width[0]);
5457 REPORTER_ASSERT(reporter, width[2] == width[0]);
5458 REPORTER_ASSERT(reporter, width[3] > width[0]); // delta == 0
5459}