1 /*
2 * Copyright 2017 Google, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <iostream>
18
19 #include "flutter/fml/logging.h"
20 #include "render_test.h"
21 #include "third_party/icu/source/common/unicode/unistr.h"
22 #include "third_party/skia/include/core/SkColor.h"
23 #include "third_party/skia/include/core/SkPath.h"
24 #include "txt/font_style.h"
25 #include "txt/font_weight.h"
26 #include "txt/paragraph_builder_txt.h"
27 #include "txt/paragraph_txt.h"
28 #include "txt/placeholder_run.h"
29 #include "txt_test_utils.h"
30
31 #define DISABLE_ON_WINDOWS(TEST) DISABLE_TEST_WINDOWS(TEST)
32
33 namespace txt {
34
35 using ParagraphTest = RenderTest;
36
TEST_F(ParagraphTest,SimpleParagraph)37 TEST_F(ParagraphTest, SimpleParagraph) {
38 const char* text = "Hello World Text Dialog";
39 auto icu_text = icu::UnicodeString::fromUTF8(text);
40 std::u16string u16_text(icu_text.getBuffer(),
41 icu_text.getBuffer() + icu_text.length());
42
43 txt::ParagraphStyle paragraph_style;
44 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
45
46 txt::TextStyle text_style;
47 // We must supply a font here, as the default is Arial, and we do not
48 // include Arial in our test fonts as it is proprietary. We want it to
49 // be Arial default though as it is one of the most common fonts on host
50 // platforms. On real devices/apps, Arial should be able to be resolved.
51 text_style.font_families = std::vector<std::string>(1, "Roboto");
52 text_style.color = SK_ColorBLACK;
53 builder.PushStyle(text_style);
54 builder.AddText(u16_text);
55
56 builder.Pop();
57
58 auto paragraph = BuildParagraph(builder);
59 paragraph->Layout(GetTestCanvasWidth());
60
61 paragraph->Paint(GetCanvas(), 10.0, 15.0);
62
63 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
64 for (size_t i = 0; i < u16_text.length(); i++) {
65 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
66 }
67 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
68 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
69 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
70 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
71 ASSERT_TRUE(Snapshot());
72 }
73
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderParagraph))74 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderParagraph)) {
75 const char* text = "012 34";
76 auto icu_text = icu::UnicodeString::fromUTF8(text);
77 std::u16string u16_text(icu_text.getBuffer(),
78 icu_text.getBuffer() + icu_text.length());
79
80 txt::ParagraphStyle paragraph_style;
81 paragraph_style.max_lines = 14;
82 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
83
84 txt::TextStyle text_style;
85 text_style.font_families = std::vector<std::string>(1, "Roboto");
86 text_style.font_size = 26;
87 text_style.letter_spacing = 1;
88 text_style.word_spacing = 5;
89 text_style.color = SK_ColorBLACK;
90 text_style.height = 1;
91 text_style.decoration = TextDecoration::kUnderline;
92 text_style.decoration_color = SK_ColorBLACK;
93 builder.PushStyle(text_style);
94
95 builder.AddText(u16_text);
96
97 txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline,
98 TextBaseline::kAlphabetic, 0);
99 builder.AddPlaceholder(placeholder_run);
100
101 builder.AddText(u16_text);
102
103 builder.AddPlaceholder(placeholder_run);
104 txt::PlaceholderRun placeholder_run2(5, 50, PlaceholderAlignment::kBaseline,
105 TextBaseline::kAlphabetic, 50);
106 builder.AddPlaceholder(placeholder_run2);
107 builder.AddPlaceholder(placeholder_run);
108 builder.AddPlaceholder(placeholder_run2);
109 builder.AddText(u16_text);
110 builder.AddPlaceholder(placeholder_run2);
111
112 builder.AddText(u16_text);
113 builder.AddText(u16_text);
114 builder.AddPlaceholder(placeholder_run2);
115 builder.AddPlaceholder(placeholder_run2);
116 builder.AddPlaceholder(placeholder_run2);
117 builder.AddPlaceholder(placeholder_run2);
118 builder.AddPlaceholder(placeholder_run2);
119 builder.AddPlaceholder(placeholder_run);
120 builder.AddText(u16_text);
121 builder.AddText(u16_text);
122 builder.AddText(u16_text);
123 builder.AddText(u16_text);
124 builder.AddText(u16_text);
125 builder.AddPlaceholder(placeholder_run2);
126 builder.AddPlaceholder(placeholder_run);
127 builder.AddText(u16_text);
128 builder.AddText(u16_text);
129
130 builder.Pop();
131
132 auto paragraph = BuildParagraph(builder);
133 paragraph->Layout(GetTestCanvasWidth());
134
135 paragraph->Paint(GetCanvas(), 0, 0);
136
137 SkPaint paint;
138 paint.setStyle(SkPaint::kStroke_Style);
139 paint.setAntiAlias(true);
140 paint.setStrokeWidth(1);
141
142 Paragraph::RectHeightStyle rect_height_style =
143 Paragraph::RectHeightStyle::kTight;
144 Paragraph::RectWidthStyle rect_width_style =
145 Paragraph::RectWidthStyle::kTight;
146 paint.setColor(SK_ColorRED);
147 std::vector<txt::Paragraph::TextBox> boxes =
148 paragraph->GetRectsForRange(0, 3, rect_height_style, rect_width_style);
149 for (size_t i = 0; i < boxes.size(); ++i) {
150 GetCanvas()->drawRect(boxes[i].rect, paint);
151 }
152 // ASSERT_TRUE(Snapshot());
153 EXPECT_EQ(boxes.size(), 1ull);
154
155 paint.setColor(SK_ColorGREEN);
156 boxes =
157 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
158 for (size_t i = 0; i < boxes.size(); ++i) {
159 GetCanvas()->drawRect(boxes[i].rect, paint);
160 }
161 EXPECT_EQ(boxes.size(), 1ull);
162
163 paint.setColor(SK_ColorRED);
164 boxes = paragraph->GetRectsForPlaceholders();
165 for (size_t i = 0; i < boxes.size(); ++i) {
166 GetCanvas()->drawRect(boxes[i].rect, paint);
167 }
168
169 paint.setColor(SK_ColorBLUE);
170 boxes =
171 paragraph->GetRectsForRange(4, 17, rect_height_style, rect_width_style);
172 for (size_t i = 0; i < boxes.size(); ++i) {
173 GetCanvas()->drawRect(boxes[i].rect, paint);
174 }
175 EXPECT_EQ(boxes.size(), 7ull);
176 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 90.921875);
177 EXPECT_FLOAT_EQ(boxes[1].rect.top(), 50);
178 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 140.92188);
179 EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 100);
180
181 EXPECT_FLOAT_EQ(boxes[3].rect.left(), 231.34375);
182 EXPECT_FLOAT_EQ(boxes[3].rect.top(), 50);
183 EXPECT_FLOAT_EQ(boxes[3].rect.right(), 231.34375 + 50);
184 EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 100);
185
186 EXPECT_FLOAT_EQ(boxes[4].rect.left(), 281.34375);
187 EXPECT_FLOAT_EQ(boxes[4].rect.top(), 0);
188 EXPECT_FLOAT_EQ(boxes[4].rect.right(), 281.34375 + 5);
189 EXPECT_FLOAT_EQ(boxes[4].rect.bottom(), 50);
190
191 EXPECT_FLOAT_EQ(boxes[6].rect.left(), 336.34375);
192 EXPECT_FLOAT_EQ(boxes[6].rect.top(), 0);
193 EXPECT_FLOAT_EQ(boxes[6].rect.right(), 336.34375 + 5);
194 EXPECT_FLOAT_EQ(boxes[6].rect.bottom(), 50);
195
196 ASSERT_TRUE(Snapshot());
197 }
198
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderBaselineParagraph))199 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderBaselineParagraph)) {
200 const char* text = "012 34";
201 auto icu_text = icu::UnicodeString::fromUTF8(text);
202 std::u16string u16_text(icu_text.getBuffer(),
203 icu_text.getBuffer() + icu_text.length());
204
205 txt::ParagraphStyle paragraph_style;
206 paragraph_style.max_lines = 14;
207 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
208
209 txt::TextStyle text_style;
210 text_style.font_families = std::vector<std::string>(1, "Roboto");
211 text_style.font_size = 26;
212 text_style.letter_spacing = 1;
213 text_style.word_spacing = 5;
214 text_style.color = SK_ColorBLACK;
215 text_style.height = 1;
216 text_style.decoration = TextDecoration::kUnderline;
217 text_style.decoration_color = SK_ColorBLACK;
218 builder.PushStyle(text_style);
219
220 builder.AddText(u16_text);
221
222 txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kBaseline,
223 TextBaseline::kAlphabetic, 38.34734);
224 builder.AddPlaceholder(placeholder_run);
225
226 builder.AddText(u16_text);
227
228 builder.Pop();
229
230 auto paragraph = BuildParagraph(builder);
231 paragraph->Layout(GetTestCanvasWidth());
232
233 paragraph->Paint(GetCanvas(), 0, 0);
234
235 SkPaint paint;
236 paint.setStyle(SkPaint::kStroke_Style);
237 paint.setAntiAlias(true);
238 paint.setStrokeWidth(1);
239
240 Paragraph::RectHeightStyle rect_height_style =
241 Paragraph::RectHeightStyle::kTight;
242 Paragraph::RectWidthStyle rect_width_style =
243 Paragraph::RectWidthStyle::kTight;
244 paint.setColor(SK_ColorRED);
245 std::vector<txt::Paragraph::TextBox> boxes =
246 paragraph->GetRectsForPlaceholders();
247 for (size_t i = 0; i < boxes.size(); ++i) {
248 GetCanvas()->drawRect(boxes[i].rect, paint);
249 }
250 EXPECT_EQ(boxes.size(), 1ull);
251 // Verify the box is in the right place
252 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.921875);
253 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
254 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.92188);
255 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50);
256
257 paint.setColor(SK_ColorBLUE);
258 boxes =
259 paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style);
260 for (size_t i = 0; i < boxes.size(); ++i) {
261 GetCanvas()->drawRect(boxes[i].rect, paint);
262 }
263 EXPECT_EQ(boxes.size(), 1ull);
264 // Verify the other text didn't just shift to accomodate it.
265 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 75.324219);
266 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 14.226246);
267 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.921875);
268 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 44.694996);
269
270 ASSERT_TRUE(Snapshot());
271 }
272
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderAboveBaselineParagraph))273 TEST_F(ParagraphTest,
274 DISABLE_ON_WINDOWS(InlinePlaceholderAboveBaselineParagraph)) {
275 const char* text = "012 34";
276 auto icu_text = icu::UnicodeString::fromUTF8(text);
277 std::u16string u16_text(icu_text.getBuffer(),
278 icu_text.getBuffer() + icu_text.length());
279
280 txt::ParagraphStyle paragraph_style;
281 paragraph_style.max_lines = 14;
282 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
283
284 txt::TextStyle text_style;
285 text_style.font_families = std::vector<std::string>(1, "Roboto");
286 text_style.font_size = 26;
287 text_style.letter_spacing = 1;
288 text_style.word_spacing = 5;
289 text_style.color = SK_ColorBLACK;
290 text_style.height = 1;
291 text_style.decoration = TextDecoration::kUnderline;
292 text_style.decoration_color = SK_ColorBLACK;
293 builder.PushStyle(text_style);
294
295 builder.AddText(u16_text);
296
297 txt::PlaceholderRun placeholder_run(55, 50,
298 PlaceholderAlignment::kAboveBaseline,
299 TextBaseline::kAlphabetic, 903129.129308);
300 builder.AddPlaceholder(placeholder_run);
301
302 builder.AddText(u16_text);
303
304 builder.Pop();
305
306 auto paragraph = BuildParagraph(builder);
307 paragraph->Layout(GetTestCanvasWidth());
308
309 paragraph->Paint(GetCanvas(), 0, 0);
310
311 SkPaint paint;
312 paint.setStyle(SkPaint::kStroke_Style);
313 paint.setAntiAlias(true);
314 paint.setStrokeWidth(1);
315
316 Paragraph::RectHeightStyle rect_height_style =
317 Paragraph::RectHeightStyle::kTight;
318 Paragraph::RectWidthStyle rect_width_style =
319 Paragraph::RectWidthStyle::kTight;
320 paint.setColor(SK_ColorRED);
321 std::vector<txt::Paragraph::TextBox> boxes =
322 paragraph->GetRectsForPlaceholders();
323 for (size_t i = 0; i < boxes.size(); ++i) {
324 GetCanvas()->drawRect(boxes[i].rect, paint);
325 }
326 EXPECT_EQ(boxes.size(), 1ull);
327 // Verify the box is in the right place
328 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.921875);
329 EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.34765625);
330 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.92188);
331 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 49.652344);
332
333 paint.setColor(SK_ColorBLUE);
334 boxes =
335 paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style);
336 for (size_t i = 0; i < boxes.size(); ++i) {
337 GetCanvas()->drawRect(boxes[i].rect, paint);
338 }
339 EXPECT_EQ(boxes.size(), 1ull);
340 // Verify the other text didn't just shift to accomodate it.
341 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 75.324219);
342 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 25.53125);
343 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.921875);
344 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 56);
345
346 ASSERT_TRUE(Snapshot());
347 }
348
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderBelowBaselineParagraph))349 TEST_F(ParagraphTest,
350 DISABLE_ON_WINDOWS(InlinePlaceholderBelowBaselineParagraph)) {
351 const char* text = "012 34";
352 auto icu_text = icu::UnicodeString::fromUTF8(text);
353 std::u16string u16_text(icu_text.getBuffer(),
354 icu_text.getBuffer() + icu_text.length());
355
356 txt::ParagraphStyle paragraph_style;
357 paragraph_style.max_lines = 14;
358 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
359
360 txt::TextStyle text_style;
361 text_style.font_families = std::vector<std::string>(1, "Roboto");
362 text_style.font_size = 26;
363 text_style.letter_spacing = 1;
364 text_style.word_spacing = 5;
365 text_style.color = SK_ColorBLACK;
366 text_style.height = 1;
367 text_style.decoration = TextDecoration::kUnderline;
368 text_style.decoration_color = SK_ColorBLACK;
369 builder.PushStyle(text_style);
370
371 builder.AddText(u16_text);
372
373 txt::PlaceholderRun placeholder_run(55, 50,
374 PlaceholderAlignment::kBelowBaseline,
375 TextBaseline::kAlphabetic, 903129.129308);
376 builder.AddPlaceholder(placeholder_run);
377
378 builder.AddText(u16_text);
379
380 builder.Pop();
381
382 auto paragraph = BuildParagraph(builder);
383 paragraph->Layout(GetTestCanvasWidth());
384
385 paragraph->Paint(GetCanvas(), 0, 0);
386
387 SkPaint paint;
388 paint.setStyle(SkPaint::kStroke_Style);
389 paint.setAntiAlias(true);
390 paint.setStrokeWidth(1);
391
392 Paragraph::RectHeightStyle rect_height_style =
393 Paragraph::RectHeightStyle::kTight;
394 Paragraph::RectWidthStyle rect_width_style =
395 Paragraph::RectWidthStyle::kTight;
396 paint.setColor(SK_ColorRED);
397 std::vector<txt::Paragraph::TextBox> boxes =
398 paragraph->GetRectsForPlaceholders();
399 for (size_t i = 0; i < boxes.size(); ++i) {
400 GetCanvas()->drawRect(boxes[i].rect, paint);
401 }
402 EXPECT_EQ(boxes.size(), 1ull);
403 // Verify the box is in the right place
404 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.921875);
405 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 24);
406 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.92188);
407 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 74);
408
409 paint.setColor(SK_ColorBLUE);
410 boxes =
411 paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style);
412 for (size_t i = 0; i < boxes.size(); ++i) {
413 GetCanvas()->drawRect(boxes[i].rect, paint);
414 }
415 EXPECT_EQ(boxes.size(), 1ull);
416 // Verify the other text didn't just shift to accomodate it.
417 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 75.324219);
418 EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.12109375);
419 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.921875);
420 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 30.347656);
421
422 ASSERT_TRUE(Snapshot());
423 }
424
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderBottomParagraph))425 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderBottomParagraph)) {
426 const char* text = "012 34";
427 auto icu_text = icu::UnicodeString::fromUTF8(text);
428 std::u16string u16_text(icu_text.getBuffer(),
429 icu_text.getBuffer() + icu_text.length());
430
431 txt::ParagraphStyle paragraph_style;
432 paragraph_style.max_lines = 14;
433 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
434
435 txt::TextStyle text_style;
436 text_style.font_families = std::vector<std::string>(1, "Roboto");
437 text_style.font_size = 26;
438 text_style.letter_spacing = 1;
439 text_style.word_spacing = 5;
440 text_style.color = SK_ColorBLACK;
441 text_style.height = 1;
442 text_style.decoration = TextDecoration::kUnderline;
443 text_style.decoration_color = SK_ColorBLACK;
444 builder.PushStyle(text_style);
445
446 builder.AddText(u16_text);
447
448 txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kBottom,
449 TextBaseline::kAlphabetic, 0);
450 builder.AddPlaceholder(placeholder_run);
451
452 builder.AddText(u16_text);
453
454 builder.Pop();
455
456 auto paragraph = BuildParagraph(builder);
457 paragraph->Layout(GetTestCanvasWidth());
458
459 paragraph->Paint(GetCanvas(), 0, 0);
460
461 SkPaint paint;
462 paint.setStyle(SkPaint::kStroke_Style);
463 paint.setAntiAlias(true);
464 paint.setStrokeWidth(1);
465
466 Paragraph::RectHeightStyle rect_height_style =
467 Paragraph::RectHeightStyle::kTight;
468 Paragraph::RectWidthStyle rect_width_style =
469 Paragraph::RectWidthStyle::kTight;
470 paint.setColor(SK_ColorRED);
471 std::vector<txt::Paragraph::TextBox> boxes =
472 paragraph->GetRectsForPlaceholders();
473 for (size_t i = 0; i < boxes.size(); ++i) {
474 GetCanvas()->drawRect(boxes[i].rect, paint);
475 }
476 EXPECT_EQ(boxes.size(), 1ull);
477 // Verify the box is in the right place
478 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.921875);
479 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
480 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.92188);
481 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50);
482
483 paint.setColor(SK_ColorBLUE);
484 boxes =
485 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
486 for (size_t i = 0; i < boxes.size(); ++i) {
487 GetCanvas()->drawRect(boxes[i].rect, paint);
488 }
489 EXPECT_EQ(boxes.size(), 1ull);
490 // Verify the other text didn't just shift to accomodate it.
491 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0.5);
492 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 19.53125);
493 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 16.097656);
494 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50);
495
496 ASSERT_TRUE(Snapshot());
497 }
498
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderTopParagraph))499 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderTopParagraph)) {
500 const char* text = "012 34";
501 auto icu_text = icu::UnicodeString::fromUTF8(text);
502 std::u16string u16_text(icu_text.getBuffer(),
503 icu_text.getBuffer() + icu_text.length());
504
505 txt::ParagraphStyle paragraph_style;
506 paragraph_style.max_lines = 14;
507 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
508
509 txt::TextStyle text_style;
510 text_style.font_families = std::vector<std::string>(1, "Roboto");
511 text_style.font_size = 26;
512 text_style.letter_spacing = 1;
513 text_style.word_spacing = 5;
514 text_style.color = SK_ColorBLACK;
515 text_style.height = 1;
516 text_style.decoration = TextDecoration::kUnderline;
517 text_style.decoration_color = SK_ColorBLACK;
518 builder.PushStyle(text_style);
519
520 builder.AddText(u16_text);
521
522 txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kTop,
523 TextBaseline::kAlphabetic, 0);
524 builder.AddPlaceholder(placeholder_run);
525
526 builder.AddText(u16_text);
527
528 builder.Pop();
529
530 auto paragraph = BuildParagraph(builder);
531 paragraph->Layout(GetTestCanvasWidth());
532
533 paragraph->Paint(GetCanvas(), 0, 0);
534
535 SkPaint paint;
536 paint.setStyle(SkPaint::kStroke_Style);
537 paint.setAntiAlias(true);
538 paint.setStrokeWidth(1);
539
540 Paragraph::RectHeightStyle rect_height_style =
541 Paragraph::RectHeightStyle::kTight;
542 Paragraph::RectWidthStyle rect_width_style =
543 Paragraph::RectWidthStyle::kTight;
544 paint.setColor(SK_ColorRED);
545 std::vector<txt::Paragraph::TextBox> boxes =
546 paragraph->GetRectsForPlaceholders();
547 for (size_t i = 0; i < boxes.size(); ++i) {
548 GetCanvas()->drawRect(boxes[i].rect, paint);
549 }
550 EXPECT_EQ(boxes.size(), 1ull);
551 // Verify the box is in the right place
552 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.921875);
553 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
554 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.92188);
555 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50);
556
557 paint.setColor(SK_ColorBLUE);
558 boxes =
559 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
560 for (size_t i = 0; i < boxes.size(); ++i) {
561 GetCanvas()->drawRect(boxes[i].rect, paint);
562 }
563 EXPECT_EQ(boxes.size(), 1ull);
564 // Verify the other text didn't just shift to accomodate it.
565 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0.5);
566 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
567 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 16.097656);
568 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 30.46875);
569
570 ASSERT_TRUE(Snapshot());
571 }
572
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderMiddleParagraph))573 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderMiddleParagraph)) {
574 const char* text = "012 34";
575 auto icu_text = icu::UnicodeString::fromUTF8(text);
576 std::u16string u16_text(icu_text.getBuffer(),
577 icu_text.getBuffer() + icu_text.length());
578
579 txt::ParagraphStyle paragraph_style;
580 paragraph_style.max_lines = 14;
581 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
582
583 txt::TextStyle text_style;
584 text_style.font_families = std::vector<std::string>(1, "Roboto");
585 text_style.font_size = 26;
586 text_style.letter_spacing = 1;
587 text_style.word_spacing = 5;
588 text_style.color = SK_ColorBLACK;
589 text_style.height = 1;
590 text_style.decoration = TextDecoration::kUnderline;
591 text_style.decoration_color = SK_ColorBLACK;
592 builder.PushStyle(text_style);
593
594 builder.AddText(u16_text);
595
596 txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kMiddle,
597 TextBaseline::kAlphabetic, 0);
598 builder.AddPlaceholder(placeholder_run);
599
600 builder.AddText(u16_text);
601
602 builder.Pop();
603
604 auto paragraph = BuildParagraph(builder);
605 paragraph->Layout(GetTestCanvasWidth());
606
607 paragraph->Paint(GetCanvas(), 0, 0);
608
609 SkPaint paint;
610 paint.setStyle(SkPaint::kStroke_Style);
611 paint.setAntiAlias(true);
612 paint.setStrokeWidth(1);
613
614 Paragraph::RectHeightStyle rect_height_style =
615 Paragraph::RectHeightStyle::kTight;
616 Paragraph::RectWidthStyle rect_width_style =
617 Paragraph::RectWidthStyle::kTight;
618 paint.setColor(SK_ColorRED);
619 std::vector<txt::Paragraph::TextBox> boxes =
620 paragraph->GetRectsForPlaceholders();
621 for (size_t i = 0; i < boxes.size(); ++i) {
622 GetCanvas()->drawRect(boxes[i].rect, paint);
623 }
624 EXPECT_EQ(boxes.size(), 1ull);
625 // Verify the box is in the right place
626 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.921875);
627 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
628 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.92188);
629 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50);
630
631 paint.setColor(SK_ColorBLUE);
632 boxes =
633 paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style);
634 for (size_t i = 0; i < boxes.size(); ++i) {
635 GetCanvas()->drawRect(boxes[i].rect, paint);
636 }
637 EXPECT_EQ(boxes.size(), 1ull);
638 // Verify the other text didn't just shift to accomodate it.
639 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 75.324219);
640 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 9.765625);
641 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.921875);
642 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 40.234375);
643
644 ASSERT_TRUE(Snapshot());
645 }
646
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderIdeographicBaselineParagraph))647 TEST_F(ParagraphTest,
648 DISABLE_ON_WINDOWS(InlinePlaceholderIdeographicBaselineParagraph)) {
649 const char* text = "給能上目秘使";
650 auto icu_text = icu::UnicodeString::fromUTF8(text);
651 std::u16string u16_text(icu_text.getBuffer(),
652 icu_text.getBuffer() + icu_text.length());
653
654 txt::ParagraphStyle paragraph_style;
655 paragraph_style.max_lines = 14;
656 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
657
658 txt::TextStyle text_style;
659 text_style.font_families = std::vector<std::string>(1, "Source Han Serif CN");
660 text_style.font_size = 26;
661 text_style.letter_spacing = 1;
662 text_style.word_spacing = 5;
663 text_style.color = SK_ColorBLACK;
664 text_style.height = 1;
665 text_style.decoration = TextDecoration::kUnderline;
666 text_style.decoration_color = SK_ColorBLACK;
667 builder.PushStyle(text_style);
668
669 builder.AddText(u16_text);
670
671 txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kBaseline,
672 TextBaseline::kIdeographic, 38.34734);
673 builder.AddPlaceholder(placeholder_run);
674
675 builder.AddText(u16_text);
676
677 builder.Pop();
678
679 auto paragraph = BuildParagraph(builder);
680 paragraph->Layout(GetTestCanvasWidth());
681
682 paragraph->Paint(GetCanvas(), 0, 0);
683
684 SkPaint paint;
685 paint.setStyle(SkPaint::kStroke_Style);
686 paint.setAntiAlias(true);
687 paint.setStrokeWidth(1);
688
689 Paragraph::RectHeightStyle rect_height_style =
690 Paragraph::RectHeightStyle::kTight;
691 Paragraph::RectWidthStyle rect_width_style =
692 Paragraph::RectWidthStyle::kTight;
693 paint.setColor(SK_ColorRED);
694 std::vector<txt::Paragraph::TextBox> boxes =
695 paragraph->GetRectsForPlaceholders();
696 for (size_t i = 0; i < boxes.size(); ++i) {
697 GetCanvas()->drawRect(boxes[i].rect, paint);
698 }
699 EXPECT_EQ(boxes.size(), 1ull);
700 // Verify the box is in the right place
701 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 162.5);
702 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
703 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 217.5);
704 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50);
705
706 paint.setColor(SK_ColorBLUE);
707 boxes =
708 paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style);
709 for (size_t i = 0; i < boxes.size(); ++i) {
710 GetCanvas()->drawRect(boxes[i].rect, paint);
711 }
712 EXPECT_EQ(boxes.size(), 1ull);
713 // Verify the other text didn't just shift to accomodate it.
714 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 135.5);
715 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 4.7033391);
716 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 162.5);
717 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 42.065342);
718
719 ASSERT_TRUE(Snapshot());
720 }
721
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderBreakParagraph))722 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderBreakParagraph)) {
723 const char* text = "012 34";
724 auto icu_text = icu::UnicodeString::fromUTF8(text);
725 std::u16string u16_text(icu_text.getBuffer(),
726 icu_text.getBuffer() + icu_text.length());
727
728 txt::ParagraphStyle paragraph_style;
729 paragraph_style.max_lines = 14;
730 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
731
732 txt::TextStyle text_style;
733 text_style.font_families = std::vector<std::string>(1, "Roboto");
734 text_style.font_size = 26;
735 text_style.letter_spacing = 1;
736 text_style.word_spacing = 5;
737 text_style.color = SK_ColorBLACK;
738 text_style.height = 1;
739 text_style.decoration = TextDecoration::kUnderline;
740 text_style.decoration_color = SK_ColorBLACK;
741 builder.PushStyle(text_style);
742
743 builder.AddText(u16_text);
744
745 txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline,
746 TextBaseline::kAlphabetic, 50);
747 txt::PlaceholderRun placeholder_run2(25, 25, PlaceholderAlignment::kBaseline,
748 TextBaseline::kAlphabetic, 12.5);
749 builder.AddPlaceholder(placeholder_run);
750 builder.AddPlaceholder(placeholder_run);
751 builder.AddPlaceholder(placeholder_run);
752 builder.AddPlaceholder(placeholder_run2);
753 builder.AddPlaceholder(placeholder_run);
754 builder.AddText(u16_text);
755 builder.AddPlaceholder(placeholder_run);
756 builder.AddPlaceholder(placeholder_run);
757 builder.AddPlaceholder(placeholder_run);
758 builder.AddPlaceholder(placeholder_run);
759 builder.AddPlaceholder(placeholder_run2);
760 builder.AddPlaceholder(placeholder_run);
761 builder.AddPlaceholder(placeholder_run);
762 builder.AddPlaceholder(placeholder_run);
763 builder.AddPlaceholder(placeholder_run);
764 builder.AddPlaceholder(placeholder_run);
765 builder.AddPlaceholder(placeholder_run);
766 builder.AddPlaceholder(placeholder_run2);
767 builder.AddPlaceholder(placeholder_run);
768 builder.AddPlaceholder(placeholder_run);
769 builder.AddPlaceholder(placeholder_run);
770 builder.AddPlaceholder(placeholder_run);
771 builder.AddPlaceholder(placeholder_run);
772 builder.AddPlaceholder(placeholder_run);
773 builder.AddPlaceholder(placeholder_run);
774 builder.AddPlaceholder(placeholder_run2);
775 builder.AddPlaceholder(placeholder_run);
776
777 builder.AddText(u16_text);
778
779 builder.AddPlaceholder(placeholder_run);
780 builder.AddPlaceholder(placeholder_run2);
781
782 builder.AddText(u16_text);
783 builder.AddText(u16_text);
784 builder.AddText(u16_text);
785 builder.AddText(u16_text);
786 builder.AddPlaceholder(placeholder_run2);
787 builder.AddPlaceholder(placeholder_run);
788 builder.AddText(u16_text);
789 builder.AddPlaceholder(placeholder_run2);
790 builder.AddText(u16_text);
791 builder.AddText(u16_text);
792 builder.AddText(u16_text);
793 builder.AddText(u16_text);
794 builder.AddText(u16_text);
795 builder.AddText(u16_text);
796 builder.AddText(u16_text);
797 builder.AddText(u16_text);
798 builder.AddText(u16_text);
799 builder.AddText(u16_text);
800 builder.AddText(u16_text);
801 builder.AddText(u16_text);
802 builder.AddText(u16_text);
803 builder.AddText(u16_text);
804 builder.AddText(u16_text);
805 builder.AddText(u16_text);
806 builder.AddText(u16_text);
807 builder.AddText(u16_text);
808 builder.AddText(u16_text);
809
810 builder.Pop();
811
812 auto paragraph = BuildParagraph(builder);
813 paragraph->Layout(GetTestCanvasWidth() - 100);
814
815 paragraph->Paint(GetCanvas(), 0, 0);
816
817 SkPaint paint;
818 paint.setStyle(SkPaint::kStroke_Style);
819 paint.setAntiAlias(true);
820 paint.setStrokeWidth(1);
821
822 Paragraph::RectHeightStyle rect_height_style =
823 Paragraph::RectHeightStyle::kTight;
824 Paragraph::RectWidthStyle rect_width_style =
825 Paragraph::RectWidthStyle::kTight;
826 paint.setColor(SK_ColorRED);
827 std::vector<txt::Paragraph::TextBox> boxes =
828 paragraph->GetRectsForRange(0, 3, rect_height_style, rect_width_style);
829 for (size_t i = 0; i < boxes.size(); ++i) {
830 GetCanvas()->drawRect(boxes[i].rect, paint);
831 }
832 EXPECT_EQ(boxes.size(), 1ull);
833
834 paint.setColor(SK_ColorGREEN);
835 boxes = paragraph->GetRectsForRange(175, 176, rect_height_style,
836 rect_width_style);
837 for (size_t i = 0; i < boxes.size(); ++i) {
838 GetCanvas()->drawRect(boxes[i].rect, paint);
839 }
840 EXPECT_EQ(boxes.size(), 1ull);
841 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 31.695312);
842 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 218.53125);
843 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 47.292969);
844 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 249);
845
846 paint.setColor(SK_ColorRED);
847 boxes = paragraph->GetRectsForPlaceholders();
848 for (size_t i = 0; i < boxes.size(); ++i) {
849 GetCanvas()->drawRect(boxes[i].rect, paint);
850 }
851
852 paint.setColor(SK_ColorBLUE);
853 boxes =
854 paragraph->GetRectsForRange(4, 45, rect_height_style, rect_width_style);
855 for (size_t i = 0; i < boxes.size(); ++i) {
856 GetCanvas()->drawRect(boxes[i].rect, paint);
857 }
858 EXPECT_EQ(boxes.size(), 30ull);
859 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 59.726562);
860 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 26.378906);
861 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.921875);
862 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 56.847656);
863
864 EXPECT_FLOAT_EQ(boxes[11].rect.left(), 606.34375);
865 EXPECT_FLOAT_EQ(boxes[11].rect.top(), 38);
866 EXPECT_FLOAT_EQ(boxes[11].rect.right(), 631.34375);
867 EXPECT_FLOAT_EQ(boxes[11].rect.bottom(), 63);
868
869 EXPECT_FLOAT_EQ(boxes[17].rect.left(), 0.5);
870 EXPECT_FLOAT_EQ(boxes[17].rect.top(), 63.5);
871 EXPECT_FLOAT_EQ(boxes[17].rect.right(), 50.5);
872 EXPECT_FLOAT_EQ(boxes[17].rect.bottom(), 113.5);
873
874 ASSERT_TRUE(Snapshot());
875 }
876
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholderGetRectsParagraph))877 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderGetRectsParagraph)) {
878 const char* text = "012 34";
879 auto icu_text = icu::UnicodeString::fromUTF8(text);
880 std::u16string u16_text(icu_text.getBuffer(),
881 icu_text.getBuffer() + icu_text.length());
882
883 txt::ParagraphStyle paragraph_style;
884 paragraph_style.max_lines = 14;
885 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
886
887 txt::TextStyle text_style;
888 text_style.font_families = std::vector<std::string>(1, "Roboto");
889 text_style.font_size = 26;
890 text_style.letter_spacing = 1;
891 text_style.word_spacing = 5;
892 text_style.color = SK_ColorBLACK;
893 text_style.height = 1;
894 text_style.decoration = TextDecoration::kUnderline;
895 text_style.decoration_color = SK_ColorBLACK;
896 builder.PushStyle(text_style);
897
898 builder.AddText(u16_text);
899
900 txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline,
901 TextBaseline::kAlphabetic, 50);
902 txt::PlaceholderRun placeholder_run2(5, 20, PlaceholderAlignment::kBaseline,
903 TextBaseline::kAlphabetic, 10);
904 builder.AddPlaceholder(placeholder_run);
905 builder.AddPlaceholder(placeholder_run);
906 builder.AddPlaceholder(placeholder_run);
907 builder.AddPlaceholder(placeholder_run);
908 builder.AddPlaceholder(placeholder_run);
909 builder.AddPlaceholder(placeholder_run);
910 builder.AddPlaceholder(placeholder_run);
911 builder.AddPlaceholder(placeholder_run);
912 builder.AddPlaceholder(placeholder_run2);
913 builder.AddPlaceholder(placeholder_run);
914 builder.AddPlaceholder(placeholder_run);
915 builder.AddPlaceholder(placeholder_run);
916 builder.AddPlaceholder(placeholder_run);
917 builder.AddPlaceholder(placeholder_run);
918 builder.AddPlaceholder(placeholder_run2);
919 builder.AddPlaceholder(placeholder_run);
920 builder.AddPlaceholder(placeholder_run);
921 builder.AddPlaceholder(placeholder_run);
922 builder.AddPlaceholder(placeholder_run);
923 builder.AddPlaceholder(placeholder_run);
924 builder.AddPlaceholder(placeholder_run);
925 builder.AddPlaceholder(placeholder_run);
926 builder.AddPlaceholder(placeholder_run);
927
928 builder.AddText(u16_text);
929
930 builder.AddPlaceholder(placeholder_run);
931 builder.AddPlaceholder(placeholder_run2);
932 builder.AddPlaceholder(placeholder_run2);
933 builder.AddPlaceholder(placeholder_run);
934 builder.AddPlaceholder(placeholder_run2);
935 builder.AddPlaceholder(placeholder_run2);
936
937 builder.AddText(u16_text);
938 builder.AddText(u16_text);
939 builder.AddText(u16_text);
940 builder.AddText(u16_text);
941 builder.AddText(u16_text);
942 builder.AddText(u16_text);
943 builder.AddText(u16_text);
944 builder.AddText(u16_text);
945 builder.AddText(u16_text);
946 builder.AddText(u16_text);
947 builder.AddText(u16_text);
948 builder.AddPlaceholder(placeholder_run2);
949 builder.AddPlaceholder(placeholder_run);
950 builder.AddPlaceholder(placeholder_run2);
951 builder.AddPlaceholder(placeholder_run);
952 builder.AddPlaceholder(placeholder_run2);
953 builder.AddText(u16_text);
954
955 builder.Pop();
956
957 auto paragraph = BuildParagraph(builder);
958 paragraph->Layout(GetTestCanvasWidth());
959
960 paragraph->Paint(GetCanvas(), 0, 0);
961
962 SkPaint paint;
963 paint.setStyle(SkPaint::kStroke_Style);
964 paint.setAntiAlias(true);
965 paint.setStrokeWidth(1);
966 paint.setColor(SK_ColorRED);
967 std::vector<txt::Paragraph::TextBox> boxes =
968 paragraph->GetRectsForPlaceholders();
969 for (size_t i = 0; i < boxes.size(); ++i) {
970 GetCanvas()->drawRect(boxes[i].rect, paint);
971 }
972 EXPECT_EQ(boxes.size(), 34ull);
973 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.921875);
974 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
975 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 140.92188);
976 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50);
977
978 EXPECT_FLOAT_EQ(boxes[16].rect.left(), 800.92188);
979 EXPECT_FLOAT_EQ(boxes[16].rect.top(), 0);
980 EXPECT_FLOAT_EQ(boxes[16].rect.right(), 850.92188);
981 EXPECT_FLOAT_EQ(boxes[16].rect.bottom(), 50);
982
983 EXPECT_FLOAT_EQ(boxes[33].rect.left(), 503.38281);
984 EXPECT_FLOAT_EQ(boxes[33].rect.top(), 160);
985 EXPECT_FLOAT_EQ(boxes[33].rect.right(), 508.38281);
986 EXPECT_FLOAT_EQ(boxes[33].rect.bottom(), 180);
987
988 Paragraph::RectHeightStyle rect_height_style =
989 Paragraph::RectHeightStyle::kMax;
990 Paragraph::RectWidthStyle rect_width_style =
991 Paragraph::RectWidthStyle::kTight;
992 paint.setColor(SK_ColorBLUE);
993 boxes =
994 paragraph->GetRectsForRange(30, 50, rect_height_style, rect_width_style);
995 for (size_t i = 0; i < boxes.size(); ++i) {
996 GetCanvas()->drawRect(boxes[i].rect, paint);
997 }
998 EXPECT_EQ(boxes.size(), 8ull);
999 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 216.09766);
1000 // Top should be taller than "tight"
1001 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 60);
1002 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 290.92188);
1003 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 120);
1004
1005 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 290.92188);
1006 EXPECT_FLOAT_EQ(boxes[1].rect.top(), 60);
1007 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 340.92188);
1008 EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 120);
1009
1010 EXPECT_FLOAT_EQ(boxes[2].rect.left(), 340.92188);
1011 EXPECT_FLOAT_EQ(boxes[2].rect.top(), 60);
1012 EXPECT_FLOAT_EQ(boxes[2].rect.right(), 345.92188);
1013 EXPECT_FLOAT_EQ(boxes[2].rect.bottom(), 120);
1014
1015 ASSERT_TRUE(Snapshot());
1016 }
1017
1018 #if OS_LINUX
1019 // Tests if manually inserted 0xFFFC characters are replaced to 0xFFFD in order
1020 // to not interfere with the placeholder box layout.
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (InlinePlaceholder0xFFFCParagraph))1021 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholder0xFFFCParagraph)) {
1022 const char* text = "ab\uFFFCcd";
1023 auto icu_text = icu::UnicodeString::fromUTF8(text);
1024 std::u16string u16_text(icu_text.getBuffer(),
1025 icu_text.getBuffer() + icu_text.length());
1026
1027 // Used to generate the replaced version.
1028 const char* text2 = "ab\uFFFDcd";
1029 auto icu_text2 = icu::UnicodeString::fromUTF8(text2);
1030 std::u16string u16_text2(icu_text2.getBuffer(),
1031 icu_text2.getBuffer() + icu_text2.length());
1032
1033 txt::ParagraphStyle paragraph_style;
1034 paragraph_style.max_lines = 14;
1035 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1036
1037 txt::TextStyle text_style;
1038 text_style.font_families = std::vector<std::string>(1, "Roboto");
1039 text_style.font_size = 26;
1040 text_style.letter_spacing = 1;
1041 text_style.word_spacing = 5;
1042 text_style.color = SK_ColorBLACK;
1043 text_style.height = 1;
1044 text_style.decoration = TextDecoration::kUnderline;
1045 text_style.decoration_color = SK_ColorBLACK;
1046 builder.PushStyle(text_style);
1047
1048 std::vector<uint16_t> truth_text;
1049
1050 builder.AddText(u16_text);
1051 truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end());
1052 builder.AddText(u16_text);
1053 truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end());
1054
1055 txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline,
1056 TextBaseline::kAlphabetic, 25);
1057 builder.AddPlaceholder(placeholder_run);
1058 truth_text.push_back(0xFFFC);
1059
1060 builder.AddText(u16_text);
1061 truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end());
1062 builder.AddText(u16_text);
1063 truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end());
1064
1065 builder.AddPlaceholder(placeholder_run);
1066 truth_text.push_back(0xFFFC);
1067 builder.AddPlaceholder(placeholder_run);
1068 truth_text.push_back(0xFFFC);
1069 builder.AddText(u16_text);
1070 truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end());
1071 builder.AddText(u16_text);
1072 truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end());
1073 builder.AddPlaceholder(placeholder_run);
1074 truth_text.push_back(0xFFFC);
1075
1076 builder.Pop();
1077
1078 auto paragraph = BuildParagraph(builder);
1079 paragraph->Layout(GetTestCanvasWidth());
1080
1081 paragraph->Paint(GetCanvas(), 0, 0);
1082
1083 for (size_t i = 0; i < truth_text.size(); ++i) {
1084 EXPECT_EQ(paragraph->text_[i], truth_text[i]);
1085 }
1086
1087 SkPaint paint;
1088 paint.setStyle(SkPaint::kStroke_Style);
1089 paint.setAntiAlias(true);
1090 paint.setStrokeWidth(1);
1091
1092 paint.setColor(SK_ColorRED);
1093
1094 paint.setColor(SK_ColorRED);
1095 std::vector<txt::Paragraph::TextBox> boxes =
1096 paragraph->GetRectsForPlaceholders();
1097 for (size_t i = 0; i < boxes.size(); ++i) {
1098 GetCanvas()->drawRect(boxes[i].rect, paint);
1099 }
1100 EXPECT_EQ(boxes.size(), 4ull);
1101
1102 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 177.83594);
1103 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
1104 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 227.83594);
1105 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50);
1106
1107 EXPECT_FLOAT_EQ(boxes[3].rect.left(), 682.50781);
1108 EXPECT_FLOAT_EQ(boxes[3].rect.top(), 0);
1109 EXPECT_FLOAT_EQ(boxes[3].rect.right(), 732.50781);
1110 EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 50);
1111
1112 ASSERT_TRUE(Snapshot());
1113 }
1114 #endif
1115
TEST_F(ParagraphTest,SimpleRedParagraph)1116 TEST_F(ParagraphTest, SimpleRedParagraph) {
1117 const char* text = "I am RED";
1118 auto icu_text = icu::UnicodeString::fromUTF8(text);
1119 std::u16string u16_text(icu_text.getBuffer(),
1120 icu_text.getBuffer() + icu_text.length());
1121
1122 txt::ParagraphStyle paragraph_style;
1123 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1124
1125 txt::TextStyle text_style;
1126 text_style.font_families = std::vector<std::string>(1, "Roboto");
1127 text_style.color = SK_ColorRED;
1128 builder.PushStyle(text_style);
1129
1130 builder.AddText(u16_text);
1131
1132 builder.Pop();
1133
1134 auto paragraph = BuildParagraph(builder);
1135 paragraph->Layout(GetTestCanvasWidth());
1136
1137 paragraph->Paint(GetCanvas(), 10.0, 15.0);
1138
1139 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
1140 for (size_t i = 0; i < u16_text.length(); i++) {
1141 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
1142 }
1143 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
1144 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
1145 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
1146 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
1147 ASSERT_TRUE(Snapshot());
1148 }
1149
TEST_F(ParagraphTest,RainbowParagraph)1150 TEST_F(ParagraphTest, RainbowParagraph) {
1151 const char* text1 = "Red Roboto";
1152 auto icu_text1 = icu::UnicodeString::fromUTF8(text1);
1153 std::u16string u16_text1(icu_text1.getBuffer(),
1154 icu_text1.getBuffer() + icu_text1.length());
1155 const char* text2 = "big Greeen Default";
1156 auto icu_text2 = icu::UnicodeString::fromUTF8(text2);
1157 std::u16string u16_text2(icu_text2.getBuffer(),
1158 icu_text2.getBuffer() + icu_text2.length());
1159 const char* text3 = "Defcolor Homemade Apple";
1160 auto icu_text3 = icu::UnicodeString::fromUTF8(text3);
1161 std::u16string u16_text3(icu_text3.getBuffer(),
1162 icu_text3.getBuffer() + icu_text3.length());
1163 const char* text4 = "Small Blue Roboto";
1164 auto icu_text4 = icu::UnicodeString::fromUTF8(text4);
1165 std::u16string u16_text4(icu_text4.getBuffer(),
1166 icu_text4.getBuffer() + icu_text4.length());
1167 const char* text5 =
1168 "Continue Last Style With lots of words to check if it overlaps "
1169 "properly or not";
1170 auto icu_text5 = icu::UnicodeString::fromUTF8(text5);
1171 std::u16string u16_text5(icu_text5.getBuffer(),
1172 icu_text5.getBuffer() + icu_text5.length());
1173
1174 txt::ParagraphStyle paragraph_style;
1175 paragraph_style.max_lines = 2;
1176 paragraph_style.text_align = TextAlign::left;
1177 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1178
1179 txt::TextStyle text_style1;
1180 text_style1.font_families = std::vector<std::string>(1, "Roboto");
1181 text_style1.color = SK_ColorRED;
1182
1183 builder.PushStyle(text_style1);
1184
1185 builder.AddText(u16_text1);
1186
1187 txt::TextStyle text_style2;
1188 text_style2.font_size = 50;
1189 text_style2.letter_spacing = 10;
1190 text_style2.word_spacing = 30;
1191 text_style2.font_weight = txt::FontWeight::w600;
1192 text_style2.color = SK_ColorGREEN;
1193 text_style2.font_families = std::vector<std::string>(1, "Roboto");
1194 text_style2.decoration = TextDecoration::kUnderline |
1195 TextDecoration::kOverline |
1196 TextDecoration::kLineThrough;
1197 text_style2.decoration_color = SK_ColorBLACK;
1198 builder.PushStyle(text_style2);
1199
1200 builder.AddText(u16_text2);
1201
1202 txt::TextStyle text_style3;
1203 text_style3.font_families = std::vector<std::string>(1, "Homemade Apple");
1204 builder.PushStyle(text_style3);
1205
1206 builder.AddText(u16_text3);
1207
1208 txt::TextStyle text_style4;
1209 text_style4.font_size = 14;
1210 text_style4.color = SK_ColorBLUE;
1211 text_style4.font_families = std::vector<std::string>(1, "Roboto");
1212 text_style4.decoration = TextDecoration::kUnderline |
1213 TextDecoration::kOverline |
1214 TextDecoration::kLineThrough;
1215 text_style4.decoration_color = SK_ColorBLACK;
1216 builder.PushStyle(text_style4);
1217
1218 builder.AddText(u16_text4);
1219
1220 // Extra text to see if it goes to default when there is more text chunks than
1221 // styles.
1222 builder.AddText(u16_text5);
1223
1224 builder.Pop();
1225
1226 auto paragraph = BuildParagraph(builder);
1227 paragraph->Layout(GetTestCanvasWidth());
1228 paragraph->Paint(GetCanvas(), 0, 0);
1229
1230 u16_text1 += u16_text2 + u16_text3 + u16_text4;
1231 for (size_t i = 0; i < u16_text1.length(); i++) {
1232 ASSERT_EQ(paragraph->text_[i], u16_text1[i]);
1233 }
1234 ASSERT_TRUE(Snapshot());
1235 ASSERT_EQ(paragraph->runs_.runs_.size(), 4ull);
1236 ASSERT_EQ(paragraph->runs_.styles_.size(), 5ull);
1237 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style1));
1238 ASSERT_TRUE(paragraph->runs_.styles_[2].equals(text_style2));
1239 ASSERT_TRUE(paragraph->runs_.styles_[3].equals(text_style3));
1240 ASSERT_TRUE(paragraph->runs_.styles_[4].equals(text_style4));
1241 ASSERT_EQ(paragraph->records_[0].style().color, text_style1.color);
1242 ASSERT_EQ(paragraph->records_[1].style().color, text_style2.color);
1243 ASSERT_EQ(paragraph->records_[2].style().color, text_style3.color);
1244 ASSERT_EQ(paragraph->records_[3].style().color, text_style4.color);
1245 }
1246
1247 // Currently, this should render nothing without a supplied TextStyle.
TEST_F(ParagraphTest,DefaultStyleParagraph)1248 TEST_F(ParagraphTest, DefaultStyleParagraph) {
1249 const char* text = "No TextStyle! Uh Oh!";
1250 auto icu_text = icu::UnicodeString::fromUTF8(text);
1251 std::u16string u16_text(icu_text.getBuffer(),
1252 icu_text.getBuffer() + icu_text.length());
1253
1254 txt::ParagraphStyle paragraph_style;
1255 paragraph_style.font_family = "Roboto";
1256 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1257
1258 builder.AddText(u16_text);
1259
1260 builder.Pop();
1261
1262 auto paragraph = BuildParagraph(builder);
1263 paragraph->Layout(GetTestCanvasWidth());
1264
1265 paragraph->Paint(GetCanvas(), 10.0, 15.0);
1266
1267 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
1268 for (size_t i = 0; i < u16_text.length(); i++) {
1269 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
1270 }
1271 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
1272 ASSERT_EQ(paragraph->runs_.styles_.size(), 1ull);
1273 ASSERT_TRUE(Snapshot());
1274 }
1275
TEST_F(ParagraphTest,BoldParagraph)1276 TEST_F(ParagraphTest, BoldParagraph) {
1277 const char* text = "This is Red max bold text!";
1278 auto icu_text = icu::UnicodeString::fromUTF8(text);
1279 std::u16string u16_text(icu_text.getBuffer(),
1280 icu_text.getBuffer() + icu_text.length());
1281
1282 txt::ParagraphStyle paragraph_style;
1283 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1284
1285 txt::TextStyle text_style;
1286 text_style.font_families = std::vector<std::string>(1, "Roboto");
1287 text_style.font_size = 60;
1288 text_style.letter_spacing = 0;
1289 text_style.font_weight = txt::FontWeight::w900;
1290 text_style.color = SK_ColorRED;
1291 builder.PushStyle(text_style);
1292
1293 builder.AddText(u16_text);
1294
1295 builder.Pop();
1296
1297 auto paragraph = BuildParagraph(builder);
1298 paragraph->Layout(GetTestCanvasWidth());
1299
1300 paragraph->Paint(GetCanvas(), 10.0, 60.0);
1301
1302 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
1303 for (size_t i = 0; i < u16_text.length(); i++) {
1304 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
1305 }
1306 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
1307 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
1308 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
1309 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
1310 ASSERT_TRUE(Snapshot());
1311
1312 // width_ takes the full available space, but longest_line_ is only the width
1313 // of the text, which is less than one line.
1314 ASSERT_DOUBLE_EQ(paragraph->width_, GetTestCanvasWidth());
1315 ASSERT_TRUE(paragraph->longest_line_ < paragraph->width_);
1316 Paragraph::RectHeightStyle rect_height_style =
1317 Paragraph::RectHeightStyle::kMax;
1318 Paragraph::RectWidthStyle rect_width_style =
1319 Paragraph::RectWidthStyle::kTight;
1320 std::vector<txt::Paragraph::TextBox> boxes = paragraph->GetRectsForRange(
1321 0, strlen(text), rect_height_style, rect_width_style);
1322 ASSERT_DOUBLE_EQ(paragraph->longest_line_,
1323 boxes[boxes.size() - 1].rect.right() - boxes[0].rect.left());
1324 }
1325
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (HeightOverrideParagraph))1326 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideParagraph)) {
1327 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
1328 auto icu_text = icu::UnicodeString::fromUTF8(text);
1329 std::u16string u16_text(icu_text.getBuffer(),
1330 icu_text.getBuffer() + icu_text.length());
1331
1332 txt::ParagraphStyle paragraph_style;
1333 paragraph_style.max_lines = 10;
1334 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1335
1336 txt::TextStyle text_style;
1337 text_style.font_families = std::vector<std::string>(1, "Roboto");
1338 text_style.font_size = 20;
1339 text_style.letter_spacing = 0;
1340 text_style.word_spacing = 0;
1341 text_style.color = SK_ColorBLACK;
1342 text_style.height = 3.6345;
1343 text_style.has_height_override = true;
1344 builder.PushStyle(text_style);
1345
1346 builder.AddText(u16_text);
1347
1348 builder.Pop();
1349
1350 auto paragraph = BuildParagraph(builder);
1351 paragraph->Layout(550);
1352
1353 paragraph->Paint(GetCanvas(), 0, 0);
1354
1355 SkPaint paint;
1356 paint.setStyle(SkPaint::kStroke_Style);
1357 paint.setAntiAlias(true);
1358 paint.setStrokeWidth(1);
1359
1360 // Tests for GetRectsForRange()
1361 Paragraph::RectHeightStyle rect_height_style =
1362 Paragraph::RectHeightStyle::kIncludeLineSpacingMiddle;
1363 Paragraph::RectWidthStyle rect_width_style =
1364 Paragraph::RectWidthStyle::kTight;
1365 paint.setColor(SK_ColorRED);
1366 std::vector<txt::Paragraph::TextBox> boxes =
1367 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
1368 for (size_t i = 0; i < boxes.size(); ++i) {
1369 GetCanvas()->drawRect(boxes[i].rect, paint);
1370 }
1371 EXPECT_EQ(boxes.size(), 0ull);
1372
1373 boxes =
1374 paragraph->GetRectsForRange(0, 40, rect_height_style, rect_width_style);
1375 for (size_t i = 0; i < boxes.size(); ++i) {
1376 GetCanvas()->drawRect(boxes[i].rect, paint);
1377 }
1378 EXPECT_EQ(boxes.size(), 3ull);
1379 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0);
1380 EXPECT_NEAR(boxes[1].rect.top(), 92.805778503417969, 0.0001);
1381 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 43.84375);
1382 EXPECT_NEAR(boxes[1].rect.bottom(), 165.49578857421875, 0.0001);
1383
1384 ASSERT_TRUE(Snapshot());
1385 }
1386
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (LeftAlignParagraph))1387 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(LeftAlignParagraph)) {
1388 const char* text =
1389 "This is a very long sentence to test if the text will properly wrap "
1390 "around and go to the next line. Sometimes, short sentence. Longer "
1391 "sentences are okay too because they are necessary. Very short. "
1392 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1393 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1394 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1395 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1396 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1397 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1398 "mollit anim id est laborum. "
1399 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1400 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1401 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1402 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1403 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1404 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1405 "mollit anim id est laborum.";
1406 auto icu_text = icu::UnicodeString::fromUTF8(text);
1407 std::u16string u16_text(icu_text.getBuffer(),
1408 icu_text.getBuffer() + icu_text.length());
1409
1410 txt::ParagraphStyle paragraph_style;
1411 paragraph_style.max_lines = 14;
1412 paragraph_style.text_align = TextAlign::left;
1413 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1414
1415 txt::TextStyle text_style;
1416 text_style.font_families = std::vector<std::string>(1, "Roboto");
1417 text_style.font_size = 26;
1418 text_style.letter_spacing = 1;
1419 text_style.word_spacing = 5;
1420 text_style.color = SK_ColorBLACK;
1421 text_style.height = 1;
1422 text_style.decoration = TextDecoration::kUnderline;
1423 text_style.decoration_color = SK_ColorBLACK;
1424 builder.PushStyle(text_style);
1425
1426 builder.AddText(u16_text);
1427
1428 builder.Pop();
1429
1430 auto paragraph = BuildParagraph(builder);
1431 paragraph->Layout(GetTestCanvasWidth() - 100);
1432
1433 paragraph->Paint(GetCanvas(), 0, 0);
1434
1435 ASSERT_TRUE(Snapshot());
1436
1437 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
1438 for (size_t i = 0; i < u16_text.length(); i++) {
1439 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
1440 }
1441 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
1442 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
1443 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
1444 ASSERT_EQ(paragraph->records_.size(), paragraph_style.max_lines);
1445 double expected_y = 24;
1446
1447 ASSERT_TRUE(paragraph->records_[0].style().equals(text_style));
1448 ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().y(), expected_y);
1449 expected_y += 30;
1450 ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().x(), 0);
1451
1452 ASSERT_TRUE(paragraph->records_[1].style().equals(text_style));
1453 ASSERT_DOUBLE_EQ(paragraph->records_[1].offset().y(), expected_y);
1454 expected_y += 30;
1455 ASSERT_DOUBLE_EQ(paragraph->records_[1].offset().x(), 0);
1456
1457 ASSERT_TRUE(paragraph->records_[2].style().equals(text_style));
1458 ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().y(), expected_y);
1459 expected_y += 30;
1460 ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().x(), 0);
1461
1462 ASSERT_TRUE(paragraph->records_[3].style().equals(text_style));
1463 ASSERT_DOUBLE_EQ(paragraph->records_[3].offset().y(), expected_y);
1464 expected_y += 30 * 10;
1465 ASSERT_DOUBLE_EQ(paragraph->records_[3].offset().x(), 0);
1466
1467 ASSERT_TRUE(paragraph->records_[13].style().equals(text_style));
1468 ASSERT_DOUBLE_EQ(paragraph->records_[13].offset().y(), expected_y);
1469 ASSERT_DOUBLE_EQ(paragraph->records_[13].offset().x(), 0);
1470
1471 ASSERT_EQ(paragraph_style.text_align,
1472 paragraph->GetParagraphStyle().text_align);
1473
1474 // Tests for GetGlyphPositionAtCoordinate()
1475 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0, 0).position, 0ull);
1476 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 1).position, 0ull);
1477 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 35).position, 68ull);
1478 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 70).position, 134ull);
1479 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(2000, 35).position, 134ull);
1480
1481 ASSERT_TRUE(Snapshot());
1482 }
1483
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (RightAlignParagraph))1484 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(RightAlignParagraph)) {
1485 const char* text =
1486 "This is a very long sentence to test if the text will properly wrap "
1487 "around and go to the next line. Sometimes, short sentence. Longer "
1488 "sentences are okay too because they are necessary. Very short. "
1489 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1490 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1491 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1492 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1493 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1494 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1495 "mollit anim id est laborum. "
1496 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1497 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1498 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1499 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1500 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1501 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1502 "mollit anim id est laborum.";
1503 auto icu_text = icu::UnicodeString::fromUTF8(text);
1504 std::u16string u16_text(icu_text.getBuffer(),
1505 icu_text.getBuffer() + icu_text.length());
1506
1507 txt::ParagraphStyle paragraph_style;
1508 paragraph_style.max_lines = 14;
1509 paragraph_style.text_align = TextAlign::right;
1510 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1511
1512 txt::TextStyle text_style;
1513 text_style.font_families = std::vector<std::string>(1, "Roboto");
1514 text_style.font_size = 26;
1515 text_style.letter_spacing = 1;
1516 text_style.word_spacing = 5;
1517 text_style.color = SK_ColorBLACK;
1518 text_style.height = 1;
1519 text_style.decoration = TextDecoration::kUnderline;
1520 text_style.decoration_color = SK_ColorBLACK;
1521 builder.PushStyle(text_style);
1522
1523 builder.AddText(u16_text);
1524
1525 builder.Pop();
1526
1527 auto paragraph = BuildParagraph(builder);
1528 int available_width = GetTestCanvasWidth() - 100;
1529 paragraph->Layout(available_width);
1530
1531 paragraph->Paint(GetCanvas(), 0, 0);
1532
1533 ASSERT_TRUE(Snapshot());
1534 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
1535 for (size_t i = 0; i < u16_text.length(); i++) {
1536 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
1537 }
1538 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
1539 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
1540 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
1541 // Two records for each due to 'ghost' trailing whitespace run.
1542 ASSERT_EQ(paragraph->records_.size(), paragraph_style.max_lines * 2);
1543 double expected_y = 24;
1544
1545 ASSERT_TRUE(paragraph->records_[0].style().equals(text_style));
1546 ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().y(), expected_y);
1547 expected_y += 30;
1548 ASSERT_NEAR(
1549 paragraph->records_[0].offset().x(),
1550 paragraph->width_ -
1551 paragraph->breaker_.getWidths()[paragraph->records_[0].line()],
1552 2.0);
1553
1554 // width_ takes the full available space, while longest_line_ wraps the glyphs
1555 // as tightly as possible. Even though this text is more than one line long,
1556 // no line perfectly spans the width of the full line, so longest_line_ is
1557 // less than width_.
1558 ASSERT_DOUBLE_EQ(paragraph->width_, available_width);
1559 ASSERT_TRUE(paragraph->longest_line_ < available_width);
1560 ASSERT_DOUBLE_EQ(paragraph->longest_line_, 880.765625);
1561
1562 ASSERT_TRUE(paragraph->records_[2].style().equals(text_style));
1563 ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().y(), expected_y);
1564 expected_y += 30;
1565 ASSERT_NEAR(
1566 paragraph->records_[2].offset().x(),
1567 paragraph->width_ -
1568 paragraph->breaker_.getWidths()[paragraph->records_[2].line()],
1569 2.0);
1570
1571 ASSERT_TRUE(paragraph->records_[4].style().equals(text_style));
1572 ASSERT_DOUBLE_EQ(paragraph->records_[4].offset().y(), expected_y);
1573 expected_y += 30;
1574 ASSERT_NEAR(
1575 paragraph->records_[4].offset().x(),
1576 paragraph->width_ -
1577 paragraph->breaker_.getWidths()[paragraph->records_[4].line()],
1578 2.0);
1579
1580 ASSERT_TRUE(paragraph->records_[6].style().equals(text_style));
1581 ASSERT_DOUBLE_EQ(paragraph->records_[6].offset().y(), expected_y);
1582 expected_y += 30 * 10;
1583 ASSERT_NEAR(
1584 paragraph->records_[6].offset().x(),
1585 paragraph->width_ -
1586 paragraph->breaker_.getWidths()[paragraph->records_[6].line()],
1587 2.0);
1588
1589 ASSERT_TRUE(paragraph->records_[26].style().equals(text_style));
1590 ASSERT_DOUBLE_EQ(paragraph->records_[26].offset().y(), expected_y);
1591 ASSERT_NEAR(
1592 paragraph->records_[26].offset().x(),
1593 paragraph->width_ -
1594 paragraph->breaker_.getWidths()[paragraph->records_[26].line()],
1595 2.0);
1596
1597 ASSERT_EQ(paragraph_style.text_align,
1598 paragraph->GetParagraphStyle().text_align);
1599
1600 ASSERT_TRUE(Snapshot());
1601 }
1602
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (CenterAlignParagraph))1603 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(CenterAlignParagraph)) {
1604 const char* text =
1605 "This is a very long sentence to test if the text will properly wrap "
1606 "around and go to the next line. Sometimes, short sentence. Longer "
1607 "sentences are okay too because they are necessary. Very short. "
1608 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1609 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1610 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1611 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1612 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1613 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1614 "mollit anim id est laborum. "
1615 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1616 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1617 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1618 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1619 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1620 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1621 "mollit anim id est laborum.";
1622 auto icu_text = icu::UnicodeString::fromUTF8(text);
1623 std::u16string u16_text(icu_text.getBuffer(),
1624 icu_text.getBuffer() + icu_text.length());
1625
1626 txt::ParagraphStyle paragraph_style;
1627 paragraph_style.max_lines = 14;
1628 paragraph_style.text_align = TextAlign::center;
1629 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1630
1631 txt::TextStyle text_style;
1632 text_style.font_families = std::vector<std::string>(1, "Roboto");
1633 text_style.font_size = 26;
1634 text_style.letter_spacing = 1;
1635 text_style.word_spacing = 5;
1636 text_style.color = SK_ColorBLACK;
1637 text_style.height = 1;
1638 text_style.decoration = TextDecoration::kUnderline;
1639 text_style.decoration_color = SK_ColorBLACK;
1640 builder.PushStyle(text_style);
1641
1642 builder.AddText(u16_text);
1643
1644 builder.Pop();
1645
1646 auto paragraph = BuildParagraph(builder);
1647 paragraph->Layout(GetTestCanvasWidth() - 100);
1648
1649 paragraph->Paint(GetCanvas(), 0, 0);
1650
1651 ASSERT_TRUE(Snapshot());
1652 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
1653 for (size_t i = 0; i < u16_text.length(); i++) {
1654 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
1655 }
1656 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
1657 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
1658 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
1659 // Two records for each due to 'ghost' trailing whitespace run.
1660 ASSERT_EQ(paragraph->records_.size(), paragraph_style.max_lines * 2);
1661 double expected_y = 24;
1662
1663 ASSERT_TRUE(paragraph->records_[0].style().equals(text_style));
1664 ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().y(), expected_y);
1665 expected_y += 30;
1666 ASSERT_NEAR(paragraph->records_[0].offset().x(),
1667 (paragraph->width_ -
1668 paragraph->breaker_.getWidths()[paragraph->records_[0].line()]) /
1669 2,
1670 2.0);
1671
1672 ASSERT_TRUE(paragraph->records_[2].style().equals(text_style));
1673 ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().y(), expected_y);
1674 expected_y += 30;
1675 ASSERT_NEAR(paragraph->records_[2].offset().x(),
1676 (paragraph->width_ -
1677 paragraph->breaker_.getWidths()[paragraph->records_[2].line()]) /
1678 2,
1679 2.0);
1680
1681 ASSERT_TRUE(paragraph->records_[4].style().equals(text_style));
1682 ASSERT_DOUBLE_EQ(paragraph->records_[4].offset().y(), expected_y);
1683 expected_y += 30;
1684 ASSERT_NEAR(paragraph->records_[4].offset().x(),
1685 (paragraph->width_ -
1686 paragraph->breaker_.getWidths()[paragraph->records_[4].line()]) /
1687 2,
1688 2.0);
1689
1690 ASSERT_TRUE(paragraph->records_[6].style().equals(text_style));
1691 ASSERT_DOUBLE_EQ(paragraph->records_[6].offset().y(), expected_y);
1692 expected_y += 30 * 10;
1693 ASSERT_NEAR(paragraph->records_[6].offset().x(),
1694 (paragraph->width_ -
1695 paragraph->breaker_.getWidths()[paragraph->records_[6].line()]) /
1696 2,
1697 2.0);
1698
1699 ASSERT_TRUE(paragraph->records_[26].style().equals(text_style));
1700 ASSERT_DOUBLE_EQ(paragraph->records_[26].offset().y(), expected_y);
1701 ASSERT_NEAR(
1702 paragraph->records_[26].offset().x(),
1703 (paragraph->width_ -
1704 paragraph->breaker_.getWidths()[paragraph->records_[26].line()]) /
1705 2,
1706 2.0);
1707
1708 ASSERT_EQ(paragraph_style.text_align,
1709 paragraph->GetParagraphStyle().text_align);
1710
1711 ASSERT_TRUE(Snapshot());
1712 }
1713
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (JustifyAlignParagraph))1714 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyAlignParagraph)) {
1715 const char* text =
1716 "This is a very long sentence to test if the text will properly wrap "
1717 "around and go to the next line. Sometimes, short sentence. Longer "
1718 "sentences are okay too because they are necessary. Very short. "
1719 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1720 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1721 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1722 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1723 "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
1724 "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
1725 "mollit anim id est laborum. "
1726 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
1727 "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
1728 "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
1729 "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
1730 "velit esse cillum dolore eu fugiat.";
1731 auto icu_text = icu::UnicodeString::fromUTF8(text);
1732 std::u16string u16_text(icu_text.getBuffer(),
1733 icu_text.getBuffer() + icu_text.length());
1734
1735 txt::ParagraphStyle paragraph_style;
1736 paragraph_style.max_lines = 14;
1737 paragraph_style.text_align = TextAlign::justify;
1738 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1739
1740 txt::TextStyle text_style;
1741 text_style.font_families = std::vector<std::string>(1, "Roboto");
1742 text_style.font_size = 26;
1743 text_style.letter_spacing = 0;
1744 text_style.word_spacing = 5;
1745 text_style.color = SK_ColorBLACK;
1746 text_style.height = 1;
1747 text_style.decoration = TextDecoration::kUnderline;
1748 text_style.decoration_color = SK_ColorBLACK;
1749 builder.PushStyle(text_style);
1750
1751 builder.AddText(u16_text);
1752
1753 builder.Pop();
1754
1755 auto paragraph = BuildParagraph(builder);
1756 paragraph->Layout(GetTestCanvasWidth() - 100);
1757
1758 paragraph->Paint(GetCanvas(), 0, 0);
1759
1760 ASSERT_TRUE(Snapshot());
1761 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
1762 for (size_t i = 0; i < u16_text.length(); i++) {
1763 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
1764 }
1765 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
1766 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
1767 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
1768 ASSERT_EQ(paragraph->records_.size(), 27ull);
1769 double expected_y = 24;
1770
1771 ASSERT_TRUE(paragraph->records_[0].style().equals(text_style));
1772 ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().y(), expected_y);
1773 expected_y += 30;
1774 ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().x(), 0);
1775
1776 ASSERT_TRUE(paragraph->records_[2].style().equals(text_style));
1777 ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().y(), expected_y);
1778 expected_y += 30;
1779 ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().x(), 0);
1780
1781 ASSERT_TRUE(paragraph->records_[4].style().equals(text_style));
1782 ASSERT_DOUBLE_EQ(paragraph->records_[4].offset().y(), expected_y);
1783 expected_y += 30;
1784 ASSERT_DOUBLE_EQ(paragraph->records_[4].offset().x(), 0);
1785
1786 ASSERT_TRUE(paragraph->records_[6].style().equals(text_style));
1787 ASSERT_DOUBLE_EQ(paragraph->records_[6].offset().y(), expected_y);
1788 expected_y += 30 * 10;
1789 ASSERT_DOUBLE_EQ(paragraph->records_[6].offset().x(), 0);
1790
1791 ASSERT_TRUE(paragraph->records_[26].style().equals(text_style));
1792 ASSERT_DOUBLE_EQ(paragraph->records_[26].offset().y(), expected_y);
1793 ASSERT_DOUBLE_EQ(paragraph->records_[26].offset().x(), 0);
1794
1795 ASSERT_EQ(paragraph_style.text_align,
1796 paragraph->GetParagraphStyle().text_align);
1797
1798 ASSERT_TRUE(Snapshot());
1799 }
1800
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (JustifyRTL))1801 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyRTL)) {
1802 const char* text =
1803 "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
1804 "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
1805 "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";
1806
1807 auto icu_text = icu::UnicodeString::fromUTF8(text);
1808 std::u16string u16_text(icu_text.getBuffer(),
1809 icu_text.getBuffer() + icu_text.length());
1810
1811 txt::ParagraphStyle paragraph_style;
1812 paragraph_style.max_lines = 14;
1813 paragraph_style.text_align = TextAlign::justify;
1814 paragraph_style.text_direction = TextDirection::rtl;
1815 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1816
1817 txt::TextStyle text_style;
1818 text_style.font_families = std::vector<std::string>(1, "Ahem");
1819 text_style.font_size = 26;
1820 text_style.color = SK_ColorBLACK;
1821 text_style.height = 1;
1822 builder.PushStyle(text_style);
1823
1824 builder.AddText(u16_text);
1825
1826 builder.Pop();
1827
1828 auto paragraph = BuildParagraph(builder);
1829 size_t paragraph_width = GetTestCanvasWidth() - 100;
1830 paragraph->Layout(paragraph_width);
1831
1832 paragraph->Paint(GetCanvas(), 0, 0);
1833
1834 auto glyph_line_width = [¶graph](int index) {
1835 size_t second_to_last_position_index =
1836 paragraph->glyph_lines_[index].positions.size() - 1;
1837 return paragraph->glyph_lines_[index]
1838 .positions[second_to_last_position_index]
1839 .x_pos.end;
1840 };
1841
1842 SkPaint paint;
1843 paint.setStyle(SkPaint::kStroke_Style);
1844 paint.setAntiAlias(true);
1845 paint.setStrokeWidth(1);
1846
1847 // Tests for GetRectsForRange()
1848 Paragraph::RectHeightStyle rect_height_style =
1849 Paragraph::RectHeightStyle::kMax;
1850 Paragraph::RectWidthStyle rect_width_style =
1851 Paragraph::RectWidthStyle::kTight;
1852 paint.setColor(SK_ColorRED);
1853 std::vector<txt::Paragraph::TextBox> boxes =
1854 paragraph->GetRectsForRange(0, 100, rect_height_style, rect_width_style);
1855 for (size_t i = 0; i < boxes.size(); ++i) {
1856 GetCanvas()->drawRect(boxes[i].rect, paint);
1857 }
1858 ASSERT_EQ(boxes.size(), 5ull);
1859
1860 paint.setColor(SK_ColorBLUE);
1861 boxes = paragraph->GetRectsForRange(240, 250, rect_height_style,
1862 rect_width_style);
1863 for (size_t i = 0; i < boxes.size(); ++i) {
1864 GetCanvas()->drawRect(boxes[i].rect, paint);
1865 }
1866 ASSERT_EQ(boxes.size(), 1ull);
1867 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 588);
1868 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 130);
1869 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 640);
1870 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 156);
1871 ASSERT_TRUE(Snapshot());
1872
1873 // All lines should be justified to the width of the
1874 // paragraph.
1875 for (size_t i = 0; i < paragraph->glyph_lines_.size(); ++i) {
1876 ASSERT_EQ(glyph_line_width(i), paragraph_width);
1877 }
1878 }
1879
TEST_F(ParagraphTest,DecorationsParagraph)1880 TEST_F(ParagraphTest, DecorationsParagraph) {
1881 txt::ParagraphStyle paragraph_style;
1882 paragraph_style.max_lines = 14;
1883 paragraph_style.text_align = TextAlign::left;
1884 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1885
1886 txt::TextStyle text_style;
1887 text_style.font_families = std::vector<std::string>(1, "Roboto");
1888 text_style.font_size = 26;
1889 text_style.letter_spacing = 0;
1890 text_style.word_spacing = 5;
1891 text_style.color = SK_ColorBLACK;
1892 text_style.height = 2;
1893 text_style.decoration = TextDecoration::kUnderline |
1894 TextDecoration::kOverline |
1895 TextDecoration::kLineThrough;
1896 text_style.decoration_style = txt::TextDecorationStyle::kSolid;
1897 text_style.decoration_color = SK_ColorBLACK;
1898 text_style.decoration_thickness_multiplier = 2.0;
1899 builder.PushStyle(text_style);
1900 builder.AddText(u"This text should be");
1901
1902 text_style.decoration_style = txt::TextDecorationStyle::kDouble;
1903 text_style.decoration_color = SK_ColorBLUE;
1904 text_style.decoration_thickness_multiplier = 1.0;
1905 builder.PushStyle(text_style);
1906 builder.AddText(u" decorated even when");
1907
1908 text_style.decoration_style = txt::TextDecorationStyle::kDotted;
1909 text_style.decoration_color = SK_ColorBLACK;
1910 builder.PushStyle(text_style);
1911 builder.AddText(u" wrapped around to");
1912
1913 text_style.decoration_style = txt::TextDecorationStyle::kDashed;
1914 text_style.decoration_color = SK_ColorBLACK;
1915 text_style.decoration_thickness_multiplier = 3.0;
1916 builder.PushStyle(text_style);
1917 builder.AddText(u" the next line.");
1918
1919 text_style.decoration_style = txt::TextDecorationStyle::kWavy;
1920 text_style.decoration_color = SK_ColorRED;
1921 text_style.decoration_thickness_multiplier = 1.0;
1922 builder.PushStyle(text_style);
1923
1924 builder.AddText(u" Otherwise, bad things happen.");
1925
1926 builder.Pop();
1927
1928 auto paragraph = BuildParagraph(builder);
1929 paragraph->Layout(GetTestCanvasWidth() - 100);
1930
1931 paragraph->Paint(GetCanvas(), 0, 0);
1932
1933 ASSERT_TRUE(Snapshot());
1934 ASSERT_EQ(paragraph->runs_.size(), 5ull);
1935 ASSERT_EQ(paragraph->records_.size(), 6ull);
1936
1937 for (size_t i = 0; i < 6; ++i) {
1938 ASSERT_EQ(paragraph->records_[i].style().decoration,
1939 TextDecoration::kUnderline | TextDecoration::kOverline |
1940 TextDecoration::kLineThrough);
1941 }
1942
1943 ASSERT_EQ(paragraph->records_[0].style().decoration_style,
1944 txt::TextDecorationStyle::kSolid);
1945 ASSERT_EQ(paragraph->records_[1].style().decoration_style,
1946 txt::TextDecorationStyle::kDouble);
1947 ASSERT_EQ(paragraph->records_[2].style().decoration_style,
1948 txt::TextDecorationStyle::kDotted);
1949 ASSERT_EQ(paragraph->records_[3].style().decoration_style,
1950 txt::TextDecorationStyle::kDashed);
1951 ASSERT_EQ(paragraph->records_[4].style().decoration_style,
1952 txt::TextDecorationStyle::kDashed);
1953 ASSERT_EQ(paragraph->records_[5].style().decoration_style,
1954 txt::TextDecorationStyle::kWavy);
1955
1956 ASSERT_EQ(paragraph->records_[0].style().decoration_color, SK_ColorBLACK);
1957 ASSERT_EQ(paragraph->records_[1].style().decoration_color, SK_ColorBLUE);
1958 ASSERT_EQ(paragraph->records_[2].style().decoration_color, SK_ColorBLACK);
1959 ASSERT_EQ(paragraph->records_[3].style().decoration_color, SK_ColorBLACK);
1960 ASSERT_EQ(paragraph->records_[4].style().decoration_color, SK_ColorBLACK);
1961 ASSERT_EQ(paragraph->records_[5].style().decoration_color, SK_ColorRED);
1962
1963 ASSERT_EQ(paragraph->records_[0].style().decoration_thickness_multiplier,
1964 2.0);
1965 ASSERT_EQ(paragraph->records_[1].style().decoration_thickness_multiplier,
1966 1.0);
1967 ASSERT_EQ(paragraph->records_[2].style().decoration_thickness_multiplier,
1968 1.0);
1969 ASSERT_EQ(paragraph->records_[3].style().decoration_thickness_multiplier,
1970 3.0);
1971 ASSERT_EQ(paragraph->records_[4].style().decoration_thickness_multiplier,
1972 3.0);
1973 ASSERT_EQ(paragraph->records_[5].style().decoration_thickness_multiplier,
1974 1.0);
1975 }
1976
TEST_F(ParagraphTest,WavyDecorationParagraph)1977 TEST_F(ParagraphTest, WavyDecorationParagraph) {
1978 txt::ParagraphStyle paragraph_style;
1979 paragraph_style.max_lines = 14;
1980 paragraph_style.text_align = TextAlign::left;
1981 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
1982
1983 txt::TextStyle text_style;
1984 text_style.font_families = std::vector<std::string>(1, "Roboto");
1985 text_style.font_size = 26;
1986 text_style.letter_spacing = 0;
1987 text_style.word_spacing = 5;
1988 text_style.color = SK_ColorBLACK;
1989 text_style.height = 2;
1990 text_style.decoration = TextDecoration::kUnderline |
1991 TextDecoration::kOverline |
1992 TextDecoration::kLineThrough;
1993
1994 text_style.decoration_style = txt::TextDecorationStyle::kWavy;
1995 text_style.decoration_color = SK_ColorRED;
1996 text_style.decoration_thickness_multiplier = 1.0;
1997 builder.PushStyle(text_style);
1998
1999 builder.AddText(u" Otherwise, bad things happen.");
2000
2001 builder.Pop();
2002
2003 auto paragraph = BuildParagraph(builder);
2004 paragraph->Layout(GetTestCanvasWidth() - 100);
2005
2006 paragraph->Paint(GetCanvas(), 0, 0);
2007
2008 ASSERT_TRUE(Snapshot());
2009 ASSERT_EQ(paragraph->runs_.size(), 1ull);
2010 ASSERT_EQ(paragraph->records_.size(), 1ull);
2011
2012 for (size_t i = 0; i < 1; ++i) {
2013 ASSERT_EQ(paragraph->records_[i].style().decoration,
2014 TextDecoration::kUnderline | TextDecoration::kOverline |
2015 TextDecoration::kLineThrough);
2016 }
2017
2018 ASSERT_EQ(paragraph->records_[0].style().decoration_style,
2019 txt::TextDecorationStyle::kWavy);
2020
2021 ASSERT_EQ(paragraph->records_[0].style().decoration_color, SK_ColorRED);
2022
2023 ASSERT_EQ(paragraph->records_[0].style().decoration_thickness_multiplier,
2024 1.0);
2025
2026 SkPath path0;
2027 SkPath canonical_path0;
2028 paragraph->ComputeWavyDecoration(path0, 1, 1, 9.56, 1);
2029
2030 canonical_path0.moveTo(1, 1);
2031 canonical_path0.rQuadTo(1, -1, 2, 0);
2032 canonical_path0.rQuadTo(1, 1, 2, 0);
2033 canonical_path0.rQuadTo(1, -1, 2, 0);
2034 canonical_path0.rQuadTo(1, 1, 2, 0);
2035 canonical_path0.rQuadTo(0.78, -0.78, 1.56, -0.3432);
2036
2037 ASSERT_EQ(path0.countPoints(), canonical_path0.countPoints());
2038 for (int i = 0; i < canonical_path0.countPoints(); ++i) {
2039 ASSERT_EQ(path0.getPoint(i).x(), canonical_path0.getPoint(i).x());
2040 ASSERT_EQ(path0.getPoint(i).y(), canonical_path0.getPoint(i).y());
2041 }
2042
2043 SkPath path1;
2044 SkPath canonical_path1;
2045 paragraph->ComputeWavyDecoration(path1, 1, 1, 8.35, 1);
2046
2047 canonical_path1.moveTo(1, 1);
2048 canonical_path1.rQuadTo(1, -1, 2, 0);
2049 canonical_path1.rQuadTo(1, 1, 2, 0);
2050 canonical_path1.rQuadTo(1, -1, 2, 0);
2051 canonical_path1.rQuadTo(1, 1, 2, 0);
2052 canonical_path1.rQuadTo(0.175, -0.175, 0.35, -0.28875);
2053
2054 ASSERT_EQ(path1.countPoints(), canonical_path1.countPoints());
2055 for (int i = 0; i < canonical_path1.countPoints(); ++i) {
2056 ASSERT_EQ(path1.getPoint(i).x(), canonical_path1.getPoint(i).x());
2057 ASSERT_EQ(path1.getPoint(i).y(), canonical_path1.getPoint(i).y());
2058 }
2059
2060 SkPath path2;
2061 SkPath canonical_path2;
2062 paragraph->ComputeWavyDecoration(path2, 1, 1, 10.59, 1);
2063
2064 canonical_path2.moveTo(1, 1);
2065 canonical_path2.rQuadTo(1, -1, 2, 0);
2066 canonical_path2.rQuadTo(1, 1, 2, 0);
2067 canonical_path2.rQuadTo(1, -1, 2, 0);
2068 canonical_path2.rQuadTo(1, 1, 2, 0);
2069 canonical_path2.rQuadTo(1, -1, 2, 0);
2070 canonical_path2.rQuadTo(0.295, 0.295, 0.59, 0.41595);
2071
2072 ASSERT_EQ(path2.countPoints(), canonical_path2.countPoints());
2073 for (int i = 0; i < canonical_path2.countPoints(); ++i) {
2074 ASSERT_EQ(path2.getPoint(i).x(), canonical_path2.getPoint(i).x());
2075 ASSERT_EQ(path2.getPoint(i).y(), canonical_path2.getPoint(i).y());
2076 }
2077
2078 SkPath path3;
2079 SkPath canonical_path3;
2080 paragraph->ComputeWavyDecoration(path3, 1, 1, 11.2, 1);
2081
2082 canonical_path3.moveTo(1, 1);
2083 canonical_path3.rQuadTo(1, -1, 2, 0);
2084 canonical_path3.rQuadTo(1, 1, 2, 0);
2085 canonical_path3.rQuadTo(1, -1, 2, 0);
2086 canonical_path3.rQuadTo(1, 1, 2, 0);
2087 canonical_path3.rQuadTo(1, -1, 2, 0);
2088 canonical_path3.rQuadTo(0.6, 0.6, 1.2, 0.48);
2089
2090 ASSERT_EQ(path3.countPoints(), canonical_path3.countPoints());
2091 for (int i = 0; i < canonical_path3.countPoints(); ++i) {
2092 ASSERT_EQ(path3.getPoint(i).x(), canonical_path3.getPoint(i).x());
2093 ASSERT_EQ(path3.getPoint(i).y(), canonical_path3.getPoint(i).y());
2094 }
2095
2096 SkPath path4;
2097 SkPath canonical_path4;
2098 paragraph->ComputeWavyDecoration(path4, 1, 1, 12, 1);
2099
2100 canonical_path4.moveTo(1, 1);
2101 canonical_path4.rQuadTo(1, -1, 2, 0);
2102 canonical_path4.rQuadTo(1, 1, 2, 0);
2103 canonical_path4.rQuadTo(1, -1, 2, 0);
2104 canonical_path4.rQuadTo(1, 1, 2, 0);
2105 canonical_path4.rQuadTo(1, -1, 2, 0);
2106 canonical_path4.rQuadTo(1, 1, 2, 0);
2107
2108 ASSERT_EQ(path4.countPoints(), canonical_path4.countPoints());
2109 for (int i = 0; i < canonical_path4.countPoints(); ++i) {
2110 ASSERT_EQ(path4.getPoint(i).x(), canonical_path4.getPoint(i).x());
2111 ASSERT_EQ(path4.getPoint(i).y(), canonical_path4.getPoint(i).y());
2112 }
2113 }
2114
TEST_F(ParagraphTest,ItalicsParagraph)2115 TEST_F(ParagraphTest, ItalicsParagraph) {
2116 txt::ParagraphStyle paragraph_style;
2117 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2118
2119 txt::TextStyle text_style;
2120 text_style.font_families = std::vector<std::string>(1, "Roboto");
2121 text_style.color = SK_ColorRED;
2122 text_style.font_size = 10;
2123 builder.PushStyle(text_style);
2124 builder.AddText(u"No italic ");
2125
2126 text_style.font_style = txt::FontStyle::italic;
2127 builder.PushStyle(text_style);
2128 builder.AddText(u"Yes Italic ");
2129
2130 builder.Pop();
2131 builder.AddText(u"No Italic again.");
2132
2133 auto paragraph = BuildParagraph(builder);
2134 paragraph->Layout(GetTestCanvasWidth());
2135
2136 paragraph->Paint(GetCanvas(), 0, 0);
2137
2138 ASSERT_EQ(paragraph->runs_.runs_.size(), 3ull);
2139 ASSERT_EQ(paragraph->runs_.styles_.size(), 3ull);
2140 ASSERT_EQ(paragraph->records_[1].style().color, text_style.color);
2141 ASSERT_EQ(paragraph->records_[1].style().font_style, txt::FontStyle::italic);
2142 ASSERT_EQ(paragraph->records_[2].style().font_style, txt::FontStyle::normal);
2143 ASSERT_EQ(paragraph->records_[0].style().font_style, txt::FontStyle::normal);
2144 ASSERT_TRUE(Snapshot());
2145 }
2146
TEST_F(ParagraphTest,ChineseParagraph)2147 TEST_F(ParagraphTest, ChineseParagraph) {
2148 const char* text =
2149 "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
2150 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭"
2151 "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探"
2152 "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦"
2153 "聞条年所在口。";
2154 auto icu_text = icu::UnicodeString::fromUTF8(text);
2155 std::u16string u16_text(icu_text.getBuffer(),
2156 icu_text.getBuffer() + icu_text.length());
2157
2158 txt::ParagraphStyle paragraph_style;
2159 paragraph_style.max_lines = 14;
2160 paragraph_style.text_align = TextAlign::justify;
2161 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2162
2163 txt::TextStyle text_style;
2164 text_style.color = SK_ColorBLACK;
2165 text_style.font_size = 35;
2166 text_style.letter_spacing = 2;
2167 text_style.font_families = std::vector<std::string>(1, "Source Han Serif CN");
2168 text_style.decoration = TextDecoration::kUnderline |
2169 TextDecoration::kOverline |
2170 TextDecoration::kLineThrough;
2171 text_style.decoration_style = txt::TextDecorationStyle::kSolid;
2172 text_style.decoration_color = SK_ColorBLACK;
2173 builder.PushStyle(text_style);
2174
2175 builder.AddText(u16_text);
2176
2177 builder.Pop();
2178
2179 auto paragraph = BuildParagraph(builder);
2180 paragraph->Layout(GetTestCanvasWidth() - 100);
2181
2182 paragraph->Paint(GetCanvas(), 0, 0);
2183
2184 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
2185 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
2186 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
2187 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
2188 ASSERT_EQ(paragraph->records_.size(), 7ull);
2189
2190 ASSERT_TRUE(Snapshot());
2191 }
2192
2193 // TODO(garyq): Support RTL languages.
TEST_F(ParagraphTest,DISABLED_ArabicParagraph)2194 TEST_F(ParagraphTest, DISABLED_ArabicParagraph) {
2195 const char* text =
2196 "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة "
2197 "بمباركة التقليدية قام عن. تصفح";
2198 auto icu_text = icu::UnicodeString::fromUTF8(text);
2199 std::u16string u16_text(icu_text.getBuffer(),
2200 icu_text.getBuffer() + icu_text.length());
2201
2202 txt::ParagraphStyle paragraph_style;
2203 paragraph_style.max_lines = 14;
2204 paragraph_style.text_align = TextAlign::right;
2205 paragraph_style.text_direction = TextDirection::rtl;
2206 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2207
2208 txt::TextStyle text_style;
2209 text_style.color = SK_ColorBLACK;
2210 text_style.font_size = 35;
2211 text_style.letter_spacing = 2;
2212 text_style.font_families = std::vector<std::string>(1, "Katibeh");
2213 text_style.decoration = TextDecoration::kUnderline |
2214 TextDecoration::kOverline |
2215 TextDecoration::kLineThrough;
2216 text_style.decoration_style = txt::TextDecorationStyle::kSolid;
2217 text_style.decoration_color = SK_ColorBLACK;
2218 builder.PushStyle(text_style);
2219
2220 builder.AddText(u16_text);
2221
2222 builder.Pop();
2223
2224 auto paragraph = BuildParagraph(builder);
2225 paragraph->Layout(GetTestCanvasWidth() - 100);
2226
2227 paragraph->Paint(GetCanvas(), 0, 0);
2228
2229 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
2230
2231 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
2232 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
2233 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
2234 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
2235 ASSERT_EQ(paragraph->records_.size(), 2ull);
2236 ASSERT_EQ(paragraph->paragraph_style_.text_direction, TextDirection::rtl);
2237
2238 for (size_t i = 0; i < u16_text.length(); i++) {
2239 ASSERT_EQ(paragraph->text_[i], u16_text[u16_text.length() - i]);
2240 }
2241
2242 ASSERT_TRUE(Snapshot());
2243 }
2244
2245 // Checks if the rects are in the correct positions after typing spaces in
2246 // Arabic.
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (ArabicRectsParagraph))2247 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(ArabicRectsParagraph)) {
2248 const char* text = "بمباركة التقليدية قام عن. تصفح يد ";
2249 auto icu_text = icu::UnicodeString::fromUTF8(text);
2250 std::u16string u16_text(icu_text.getBuffer(),
2251 icu_text.getBuffer() + icu_text.length());
2252
2253 txt::ParagraphStyle paragraph_style;
2254 paragraph_style.max_lines = 14;
2255 paragraph_style.text_align = TextAlign::right;
2256 paragraph_style.text_direction = TextDirection::rtl;
2257 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2258
2259 txt::TextStyle text_style;
2260 text_style.font_families = std::vector<std::string>(1, "Noto Naskh Arabic");
2261 text_style.font_size = 26;
2262 text_style.letter_spacing = 1;
2263 text_style.word_spacing = 5;
2264 text_style.color = SK_ColorBLACK;
2265 text_style.height = 1;
2266 text_style.decoration = TextDecoration::kUnderline;
2267 text_style.decoration_color = SK_ColorBLACK;
2268 builder.PushStyle(text_style);
2269
2270 builder.AddText(u16_text);
2271
2272 builder.Pop();
2273
2274 auto paragraph = BuildParagraph(builder);
2275 paragraph->Layout(GetTestCanvasWidth() - 100);
2276
2277 paragraph->Paint(GetCanvas(), 0, 0);
2278
2279 SkPaint paint;
2280 paint.setStyle(SkPaint::kStroke_Style);
2281 paint.setAntiAlias(true);
2282 paint.setStrokeWidth(1);
2283
2284 // Tests for GetRectsForRange()
2285 Paragraph::RectHeightStyle rect_height_style =
2286 Paragraph::RectHeightStyle::kMax;
2287 Paragraph::RectWidthStyle rect_width_style =
2288 Paragraph::RectWidthStyle::kTight;
2289 paint.setColor(SK_ColorRED);
2290 std::vector<txt::Paragraph::TextBox> boxes =
2291 paragraph->GetRectsForRange(0, 100, rect_height_style, rect_width_style);
2292 for (size_t i = 0; i < boxes.size(); ++i) {
2293 GetCanvas()->drawRect(boxes[i].rect, paint);
2294 }
2295 EXPECT_EQ(boxes.size(), 2ull);
2296
2297 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 556.54688);
2298 EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.26855469);
2299 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 900);
2300 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 44);
2301
2302 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 510.09375);
2303 EXPECT_FLOAT_EQ(boxes[1].rect.top(), -0.26855469);
2304 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 557.04688);
2305 EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 44);
2306
2307 ASSERT_EQ(paragraph_style.text_align,
2308 paragraph->GetParagraphStyle().text_align);
2309
2310 ASSERT_TRUE(Snapshot());
2311 }
2312
2313 // Trailing space at the end of the arabic rtl run should be at the left end of
2314 // the arabic run.
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (ArabicRectsLTRLeftAlignParagraph))2315 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(ArabicRectsLTRLeftAlignParagraph)) {
2316 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
2317 auto icu_text = icu::UnicodeString::fromUTF8(text);
2318 std::u16string u16_text(icu_text.getBuffer(),
2319 icu_text.getBuffer() + icu_text.length());
2320
2321 txt::ParagraphStyle paragraph_style;
2322 paragraph_style.max_lines = 14;
2323 paragraph_style.text_align = TextAlign::left;
2324 paragraph_style.text_direction = TextDirection::ltr;
2325 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2326
2327 txt::TextStyle text_style;
2328 text_style.font_families = std::vector<std::string>(1, "Noto Naskh Arabic");
2329 text_style.font_size = 26;
2330 text_style.letter_spacing = 1;
2331 text_style.word_spacing = 5;
2332 text_style.color = SK_ColorBLACK;
2333 text_style.height = 1;
2334 text_style.decoration = TextDecoration::kUnderline;
2335 text_style.decoration_color = SK_ColorBLACK;
2336 builder.PushStyle(text_style);
2337
2338 builder.AddText(u16_text);
2339
2340 builder.Pop();
2341
2342 auto paragraph = BuildParagraph(builder);
2343 paragraph->Layout(GetTestCanvasWidth() - 100);
2344
2345 paragraph->Paint(GetCanvas(), 0, 0);
2346
2347 SkPaint paint;
2348 paint.setStyle(SkPaint::kStroke_Style);
2349 paint.setAntiAlias(true);
2350 paint.setStrokeWidth(1);
2351
2352 // Tests for GetRectsForRange()
2353 Paragraph::RectHeightStyle rect_height_style =
2354 Paragraph::RectHeightStyle::kMax;
2355 Paragraph::RectWidthStyle rect_width_style =
2356 Paragraph::RectWidthStyle::kTight;
2357 paint.setColor(SK_ColorRED);
2358 std::vector<txt::Paragraph::TextBox> boxes =
2359 paragraph->GetRectsForRange(36, 40, rect_height_style, rect_width_style);
2360 for (size_t i = 0; i < boxes.size(); ++i) {
2361 GetCanvas()->drawRect(boxes[i].rect, paint);
2362 }
2363 EXPECT_EQ(boxes.size(), 1ull);
2364
2365 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 89.40625);
2366 EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.26855469);
2367 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 121.87891);
2368 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 44);
2369
2370 ASSERT_EQ(paragraph_style.text_align,
2371 paragraph->GetParagraphStyle().text_align);
2372
2373 ASSERT_TRUE(Snapshot());
2374 }
2375
2376 // Trailing space at the end of the arabic rtl run should be at the left end of
2377 // the arabic run and be a ghost space.
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (ArabicRectsLTRRightAlignParagraph))2378 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(ArabicRectsLTRRightAlignParagraph)) {
2379 const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد ";
2380 auto icu_text = icu::UnicodeString::fromUTF8(text);
2381 std::u16string u16_text(icu_text.getBuffer(),
2382 icu_text.getBuffer() + icu_text.length());
2383
2384 txt::ParagraphStyle paragraph_style;
2385 paragraph_style.max_lines = 14;
2386 paragraph_style.text_align = TextAlign::right;
2387 paragraph_style.text_direction = TextDirection::ltr;
2388 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2389
2390 txt::TextStyle text_style;
2391 text_style.font_families = std::vector<std::string>(1, "Noto Naskh Arabic");
2392 text_style.font_size = 26;
2393 text_style.letter_spacing = 1;
2394 text_style.word_spacing = 5;
2395 text_style.color = SK_ColorBLACK;
2396 text_style.height = 1;
2397 text_style.decoration = TextDecoration::kUnderline;
2398 text_style.decoration_color = SK_ColorBLACK;
2399 builder.PushStyle(text_style);
2400
2401 builder.AddText(u16_text);
2402
2403 builder.Pop();
2404
2405 auto paragraph = BuildParagraph(builder);
2406 paragraph->Layout(GetTestCanvasWidth() - 100);
2407
2408 paragraph->Paint(GetCanvas(), 0, 0);
2409
2410 SkPaint paint;
2411 paint.setStyle(SkPaint::kStroke_Style);
2412 paint.setAntiAlias(true);
2413 paint.setStrokeWidth(1);
2414
2415 // Tests for GetRectsForRange()
2416 Paragraph::RectHeightStyle rect_height_style =
2417 Paragraph::RectHeightStyle::kMax;
2418 Paragraph::RectWidthStyle rect_width_style =
2419 Paragraph::RectWidthStyle::kTight;
2420 paint.setColor(SK_ColorRED);
2421 std::vector<txt::Paragraph::TextBox> boxes =
2422 paragraph->GetRectsForRange(36, 40, rect_height_style, rect_width_style);
2423 for (size_t i = 0; i < boxes.size(); ++i) {
2424 GetCanvas()->drawRect(boxes[i].rect, paint);
2425 }
2426 EXPECT_EQ(boxes.size(), 2ull);
2427
2428 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 556.54688);
2429 EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.26855469);
2430 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 577.78125);
2431 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 44);
2432
2433 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 545.30859);
2434 EXPECT_FLOAT_EQ(boxes[1].rect.top(), -0.26855469);
2435 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 557.04688);
2436 EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 44);
2437
2438 ASSERT_EQ(paragraph_style.text_align,
2439 paragraph->GetParagraphStyle().text_align);
2440
2441 ASSERT_TRUE(Snapshot());
2442 }
2443
TEST_F(ParagraphTest,GetGlyphPositionAtCoordinateParagraph)2444 TEST_F(ParagraphTest, GetGlyphPositionAtCoordinateParagraph) {
2445 const char* text =
2446 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2447 "67890 12345";
2448 auto icu_text = icu::UnicodeString::fromUTF8(text);
2449 std::u16string u16_text(icu_text.getBuffer(),
2450 icu_text.getBuffer() + icu_text.length());
2451
2452 txt::ParagraphStyle paragraph_style;
2453 paragraph_style.max_lines = 10;
2454 paragraph_style.text_align = TextAlign::left;
2455 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2456
2457 txt::TextStyle text_style;
2458 text_style.font_families = std::vector<std::string>(1, "Roboto");
2459 text_style.font_size = 50;
2460 text_style.letter_spacing = 1;
2461 text_style.word_spacing = 5;
2462 text_style.color = SK_ColorBLACK;
2463 text_style.height = 1;
2464 builder.PushStyle(text_style);
2465
2466 builder.AddText(u16_text);
2467
2468 builder.Pop();
2469
2470 auto paragraph = BuildParagraph(builder);
2471 paragraph->Layout(550);
2472
2473 paragraph->Paint(GetCanvas(), 0, 0);
2474
2475 ASSERT_TRUE(Snapshot());
2476
2477 // Tests for GetGlyphPositionAtCoordinate()
2478 // NOTE: resulting values can be a few off from their respective positions in
2479 // the original text because the final trailing whitespaces are sometimes not
2480 // drawn (namely, when using "justify" alignment) and therefore are not active
2481 // glyphs.
2482 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(-10000, -10000).position,
2483 0ull);
2484 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(-1, -1).position, 0ull);
2485 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0, 0).position, 0ull);
2486 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(3, 3).position, 0ull);
2487 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(35, 1).position, 1ull);
2488 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(300, 2).position, 11ull);
2489 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(301, 2.2).position, 11ull);
2490 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(302, 2.6).position, 11ull);
2491 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(301, 2.1).position, 11ull);
2492 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(100000, 20).position,
2493 18ull);
2494 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(450, 20).position, 16ull);
2495 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(100000, 90).position,
2496 36ull);
2497 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(-100000, 90).position,
2498 18ull);
2499 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(20, -80).position, 1ull);
2500 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 90).position, 18ull);
2501 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 170).position, 36ull);
2502 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(10000, 180).position,
2503 72ull);
2504 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(70, 180).position, 56ull);
2505 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 270).position, 72ull);
2506 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(35, 90).position, 19ull);
2507 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(10000, 10000).position,
2508 77ull);
2509 ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(85, 10000).position, 75ull);
2510 }
2511
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeParagraph))2512 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeParagraph)) {
2513 const char* text =
2514 "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
2515 "67890 12345";
2516 auto icu_text = icu::UnicodeString::fromUTF8(text);
2517 std::u16string u16_text(icu_text.getBuffer(),
2518 icu_text.getBuffer() + icu_text.length());
2519
2520 txt::ParagraphStyle paragraph_style;
2521 paragraph_style.max_lines = 10;
2522 paragraph_style.text_align = TextAlign::left;
2523 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2524
2525 txt::TextStyle text_style;
2526 text_style.font_families = std::vector<std::string>(1, "Roboto");
2527 text_style.font_size = 50;
2528 text_style.letter_spacing = 0;
2529 text_style.font_weight = FontWeight::w500;
2530 text_style.word_spacing = 0;
2531 text_style.color = SK_ColorBLACK;
2532 text_style.height = 1;
2533 builder.PushStyle(text_style);
2534
2535 builder.AddText(u16_text);
2536
2537 builder.Pop();
2538
2539 auto paragraph = BuildParagraph(builder);
2540 paragraph->Layout(550);
2541
2542 paragraph->Paint(GetCanvas(), 0, 0);
2543
2544 SkPaint paint;
2545 paint.setStyle(SkPaint::kStroke_Style);
2546 paint.setAntiAlias(true);
2547 paint.setStrokeWidth(1);
2548
2549 // Tests for GetRectsForRange()
2550 // NOTE: The base truth values may still need adjustment as the specifics
2551 // are adjusted.
2552 Paragraph::RectHeightStyle rect_height_style =
2553 Paragraph::RectHeightStyle::kMax;
2554 Paragraph::RectWidthStyle rect_width_style =
2555 Paragraph::RectWidthStyle::kTight;
2556 paint.setColor(SK_ColorRED);
2557 std::vector<txt::Paragraph::TextBox> boxes =
2558 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
2559 for (size_t i = 0; i < boxes.size(); ++i) {
2560 GetCanvas()->drawRect(boxes[i].rect, paint);
2561 }
2562 EXPECT_EQ(boxes.size(), 0ull);
2563
2564 boxes =
2565 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
2566 for (size_t i = 0; i < boxes.size(); ++i) {
2567 GetCanvas()->drawRect(boxes[i].rect, paint);
2568 }
2569 EXPECT_EQ(boxes.size(), 1ull);
2570 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
2571 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
2572 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 28.417969);
2573 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
2574
2575 paint.setColor(SK_ColorBLUE);
2576 boxes =
2577 paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style);
2578 for (size_t i = 0; i < boxes.size(); ++i) {
2579 GetCanvas()->drawRect(boxes[i].rect, paint);
2580 }
2581 EXPECT_EQ(boxes.size(), 1ull);
2582 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 56.835938);
2583 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
2584 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 177.97266);
2585 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
2586
2587 paint.setColor(SK_ColorGREEN);
2588 boxes =
2589 paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style);
2590 for (size_t i = 0; i < boxes.size(); ++i) {
2591 GetCanvas()->drawRect(boxes[i].rect, paint);
2592 }
2593 EXPECT_EQ(boxes.size(), 1ull);
2594 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 177.97266);
2595 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
2596 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 507.02344);
2597 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
2598
2599 paint.setColor(SK_ColorRED);
2600 boxes =
2601 paragraph->GetRectsForRange(30, 100, rect_height_style, rect_width_style);
2602 for (size_t i = 0; i < boxes.size(); ++i) {
2603 GetCanvas()->drawRect(boxes[i].rect, paint);
2604 }
2605 EXPECT_EQ(boxes.size(), 4ull);
2606 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 211.375);
2607 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 59.40625);
2608 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 463.61719);
2609 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 118);
2610
2611 // TODO(garyq): The following set of vals are definitely wrong and
2612 // end of paragraph handling needs to be fixed in a later patch.
2613 EXPECT_FLOAT_EQ(boxes[3].rect.left(), 0);
2614 EXPECT_FLOAT_EQ(boxes[3].rect.top(), 236.40625);
2615 EXPECT_FLOAT_EQ(boxes[3].rect.right(), 142.08984);
2616 EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 295);
2617
2618 paint.setColor(SK_ColorBLUE);
2619 boxes =
2620 paragraph->GetRectsForRange(19, 22, rect_height_style, rect_width_style);
2621 for (size_t i = 0; i < boxes.size(); ++i) {
2622 GetCanvas()->drawRect(boxes[i].rect, paint);
2623 }
2624 EXPECT_EQ(boxes.size(), 1ull);
2625 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 450.1875);
2626 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
2627 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 519.47266);
2628 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
2629
2630 paint.setColor(SK_ColorRED);
2631 boxes =
2632 paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style);
2633 for (size_t i = 0; i < boxes.size(); ++i) {
2634 GetCanvas()->drawRect(boxes[i].rect, paint);
2635 }
2636 EXPECT_EQ(boxes.size(), 0ull);
2637
2638 ASSERT_TRUE(Snapshot());
2639 }
2640
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeTight))2641 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeTight)) {
2642 const char* text =
2643 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2644 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2645 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
2646 auto icu_text = icu::UnicodeString::fromUTF8(text);
2647 std::u16string u16_text(icu_text.getBuffer(),
2648 icu_text.getBuffer() + icu_text.length());
2649
2650 txt::ParagraphStyle paragraph_style;
2651 paragraph_style.max_lines = 10;
2652 paragraph_style.text_align = TextAlign::left;
2653 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2654
2655 txt::TextStyle text_style;
2656 text_style.font_families = std::vector<std::string>(1, "Noto Sans CJK JP");
2657 text_style.font_size = 50;
2658 text_style.letter_spacing = 0;
2659 text_style.font_weight = FontWeight::w500;
2660 text_style.word_spacing = 0;
2661 text_style.color = SK_ColorBLACK;
2662 text_style.height = 1;
2663 builder.PushStyle(text_style);
2664
2665 builder.AddText(u16_text);
2666
2667 builder.Pop();
2668
2669 auto paragraph = BuildParagraph(builder);
2670 paragraph->Layout(550);
2671
2672 paragraph->Paint(GetCanvas(), 0, 0);
2673
2674 SkPaint paint;
2675 paint.setStyle(SkPaint::kStroke_Style);
2676 paint.setAntiAlias(true);
2677 paint.setStrokeWidth(1);
2678
2679 // Tests for GetRectsForRange()
2680 // NOTE: The base truth values may still need adjustment as the specifics
2681 // are adjusted.
2682 Paragraph::RectHeightStyle rect_height_style =
2683 Paragraph::RectHeightStyle::kTight;
2684 Paragraph::RectWidthStyle rect_width_style =
2685 Paragraph::RectWidthStyle::kTight;
2686 paint.setColor(SK_ColorRED);
2687 std::vector<txt::Paragraph::TextBox> boxes =
2688 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
2689 for (size_t i = 0; i < boxes.size(); ++i) {
2690 GetCanvas()->drawRect(boxes[i].rect, paint);
2691 }
2692 EXPECT_EQ(boxes.size(), 0ull);
2693
2694 boxes =
2695 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
2696 for (size_t i = 0; i < boxes.size(); ++i) {
2697 GetCanvas()->drawRect(boxes[i].rect, paint);
2698 }
2699 EXPECT_EQ(boxes.size(), 1ull);
2700 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
2701 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
2702 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 16.898438);
2703 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 74);
2704
2705 paint.setColor(SK_ColorBLUE);
2706 boxes =
2707 paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style);
2708 for (size_t i = 0; i < boxes.size(); ++i) {
2709 GetCanvas()->drawRect(boxes[i].rect, paint);
2710 }
2711 EXPECT_EQ(boxes.size(), 1ull);
2712 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
2713 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 264.09375);
2714 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 74);
2715
2716 paint.setColor(SK_ColorGREEN);
2717 boxes =
2718 paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style);
2719 for (size_t i = 0; i < boxes.size(); ++i) {
2720 GetCanvas()->drawRect(boxes[i].rect, paint);
2721 }
2722 EXPECT_EQ(boxes.size(), 2ull);
2723 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 264.09375);
2724 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0);
2725 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 595.08594);
2726 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 74);
2727
2728 ASSERT_TRUE(Snapshot());
2729 }
2730
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeIncludeLineSpacingMiddle))2731 TEST_F(ParagraphTest,
2732 DISABLE_ON_WINDOWS(GetRectsForRangeIncludeLineSpacingMiddle)) {
2733 const char* text =
2734 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2735 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2736 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
2737 auto icu_text = icu::UnicodeString::fromUTF8(text);
2738 std::u16string u16_text(icu_text.getBuffer(),
2739 icu_text.getBuffer() + icu_text.length());
2740
2741 txt::ParagraphStyle paragraph_style;
2742 paragraph_style.max_lines = 10;
2743 paragraph_style.text_align = TextAlign::left;
2744 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2745
2746 txt::TextStyle text_style;
2747 text_style.font_families = std::vector<std::string>(1, "Roboto");
2748 text_style.font_size = 50;
2749 text_style.letter_spacing = 0;
2750 text_style.font_weight = FontWeight::w500;
2751 text_style.word_spacing = 0;
2752 text_style.color = SK_ColorBLACK;
2753 text_style.height = 1.6;
2754 text_style.has_height_override = true;
2755 builder.PushStyle(text_style);
2756
2757 builder.AddText(u16_text);
2758
2759 builder.Pop();
2760
2761 auto paragraph = BuildParagraph(builder);
2762 paragraph->Layout(550);
2763
2764 paragraph->Paint(GetCanvas(), 0, 0);
2765
2766 SkPaint paint;
2767 paint.setStyle(SkPaint::kStroke_Style);
2768 paint.setAntiAlias(true);
2769 paint.setStrokeWidth(1);
2770
2771 // Tests for GetRectsForRange()
2772 // NOTE: The base truth values may still need adjustment as the specifics
2773 // are adjusted.
2774 Paragraph::RectHeightStyle rect_height_style =
2775 Paragraph::RectHeightStyle::kIncludeLineSpacingMiddle;
2776 Paragraph::RectWidthStyle rect_width_style = Paragraph::RectWidthStyle::kMax;
2777 paint.setColor(SK_ColorRED);
2778 std::vector<txt::Paragraph::TextBox> boxes =
2779 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
2780 for (size_t i = 0; i < boxes.size(); ++i) {
2781 GetCanvas()->drawRect(boxes[i].rect, paint);
2782 }
2783 EXPECT_EQ(boxes.size(), 0ull);
2784
2785 boxes =
2786 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
2787 for (size_t i = 0; i < boxes.size(); ++i) {
2788 GetCanvas()->drawRect(boxes[i].rect, paint);
2789 }
2790 EXPECT_EQ(boxes.size(), 1ull);
2791 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
2792 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
2793 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 17.429688);
2794 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 88.473305);
2795
2796 paint.setColor(SK_ColorBLUE);
2797 boxes =
2798 paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style);
2799 for (size_t i = 0; i < boxes.size(); ++i) {
2800 GetCanvas()->drawRect(boxes[i].rect, paint);
2801 }
2802 EXPECT_EQ(boxes.size(), 1ull);
2803 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 67.429688);
2804 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
2805 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 190.00781);
2806 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 88.473305);
2807
2808 paint.setColor(SK_ColorGREEN);
2809 boxes =
2810 paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style);
2811 for (size_t i = 0; i < boxes.size(); ++i) {
2812 GetCanvas()->drawRect(boxes[i].rect, paint);
2813 }
2814 EXPECT_EQ(boxes.size(), 1ull);
2815 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.00781);
2816 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
2817 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 508.0625);
2818 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 88.473312);
2819
2820 paint.setColor(SK_ColorRED);
2821 boxes =
2822 paragraph->GetRectsForRange(30, 150, rect_height_style, rect_width_style);
2823 for (size_t i = 0; i < boxes.size(); ++i) {
2824 GetCanvas()->drawRect(boxes[i].rect, paint);
2825 }
2826 EXPECT_EQ(boxes.size(), 8ull);
2827 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.00781);
2828 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 88.473312);
2829 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 525.6875);
2830 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 168.47331);
2831
2832 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 525.6875);
2833 EXPECT_FLOAT_EQ(boxes[1].rect.top(), 88.473312);
2834 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 570.02344);
2835 EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 168.4733);
2836
2837 EXPECT_FLOAT_EQ(boxes[2].rect.left(), 0);
2838 EXPECT_FLOAT_EQ(boxes[2].rect.top(), 168.4733);
2839 EXPECT_FLOAT_EQ(boxes[2].rect.right(), 531.57422);
2840 EXPECT_FLOAT_EQ(boxes[2].rect.bottom(), 248.47331);
2841
2842 EXPECT_FLOAT_EQ(boxes[3].rect.left(), 531.57422);
2843 EXPECT_FLOAT_EQ(boxes[3].rect.top(), 168.4733);
2844 EXPECT_FLOAT_EQ(boxes[3].rect.right(), 570.02344);
2845 EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 248.47331);
2846
2847 EXPECT_FLOAT_EQ(boxes[4].rect.left(), 0);
2848 EXPECT_FLOAT_EQ(boxes[4].rect.top(), 248.47331);
2849 EXPECT_FLOAT_EQ(boxes[4].rect.right(), 570.02344);
2850 EXPECT_FLOAT_EQ(boxes[4].rect.bottom(), 328.4733);
2851
2852 EXPECT_FLOAT_EQ(boxes[5].rect.left(), 0);
2853 EXPECT_FLOAT_EQ(boxes[5].rect.top(), 328.47333);
2854 EXPECT_FLOAT_EQ(boxes[5].rect.right(), 570.02344);
2855 EXPECT_FLOAT_EQ(boxes[5].rect.bottom(), 408.4733);
2856
2857 paint.setColor(SK_ColorBLUE);
2858 boxes =
2859 paragraph->GetRectsForRange(19, 22, rect_height_style, rect_width_style);
2860 for (size_t i = 0; i < boxes.size(); ++i) {
2861 GetCanvas()->drawRect(boxes[i].rect, paint);
2862 }
2863 EXPECT_EQ(boxes.size(), 1ull);
2864 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 463.72656);
2865 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
2866 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 530.23047);
2867 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 88.473305);
2868
2869 paint.setColor(SK_ColorRED);
2870 boxes =
2871 paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style);
2872 for (size_t i = 0; i < boxes.size(); ++i) {
2873 GetCanvas()->drawRect(boxes[i].rect, paint);
2874 }
2875 EXPECT_EQ(boxes.size(), 0ull);
2876
2877 ASSERT_TRUE(Snapshot());
2878 }
2879
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeIncludeLineSpacingTop))2880 TEST_F(ParagraphTest,
2881 DISABLE_ON_WINDOWS(GetRectsForRangeIncludeLineSpacingTop)) {
2882 const char* text =
2883 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2884 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
2885 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
2886 auto icu_text = icu::UnicodeString::fromUTF8(text);
2887 std::u16string u16_text(icu_text.getBuffer(),
2888 icu_text.getBuffer() + icu_text.length());
2889
2890 txt::ParagraphStyle paragraph_style;
2891 paragraph_style.max_lines = 10;
2892 paragraph_style.text_align = TextAlign::left;
2893 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
2894
2895 txt::TextStyle text_style;
2896 text_style.font_families = std::vector<std::string>(1, "Roboto");
2897 text_style.font_size = 50;
2898 text_style.letter_spacing = 0;
2899 text_style.font_weight = FontWeight::w500;
2900 text_style.word_spacing = 0;
2901 text_style.color = SK_ColorBLACK;
2902 text_style.height = 1.6;
2903 text_style.has_height_override = true;
2904 builder.PushStyle(text_style);
2905
2906 builder.AddText(u16_text);
2907
2908 builder.Pop();
2909
2910 auto paragraph = BuildParagraph(builder);
2911 paragraph->Layout(550);
2912
2913 paragraph->Paint(GetCanvas(), 0, 0);
2914
2915 SkPaint paint;
2916 paint.setStyle(SkPaint::kStroke_Style);
2917 paint.setAntiAlias(true);
2918 paint.setStrokeWidth(1);
2919
2920 // Tests for GetRectsForRange()
2921 // NOTE: The base truth values may still need adjustment as the specifics
2922 // are adjusted.
2923 Paragraph::RectHeightStyle rect_height_style =
2924 Paragraph::RectHeightStyle::kIncludeLineSpacingTop;
2925 Paragraph::RectWidthStyle rect_width_style = Paragraph::RectWidthStyle::kMax;
2926 paint.setColor(SK_ColorRED);
2927 std::vector<txt::Paragraph::TextBox> boxes =
2928 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
2929 for (size_t i = 0; i < boxes.size(); ++i) {
2930 GetCanvas()->drawRect(boxes[i].rect, paint);
2931 }
2932 EXPECT_EQ(boxes.size(), 0ull);
2933
2934 boxes =
2935 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
2936 for (size_t i = 0; i < boxes.size(); ++i) {
2937 GetCanvas()->drawRect(boxes[i].rect, paint);
2938 }
2939 EXPECT_EQ(boxes.size(), 1ull);
2940 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
2941 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
2942 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 17.429688);
2943 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80);
2944
2945 paint.setColor(SK_ColorBLUE);
2946 boxes =
2947 paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style);
2948 for (size_t i = 0; i < boxes.size(); ++i) {
2949 GetCanvas()->drawRect(boxes[i].rect, paint);
2950 }
2951 EXPECT_EQ(boxes.size(), 1ull);
2952 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 67.429688);
2953 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
2954 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 190.00781);
2955 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80);
2956
2957 paint.setColor(SK_ColorGREEN);
2958 boxes =
2959 paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style);
2960 for (size_t i = 0; i < boxes.size(); ++i) {
2961 GetCanvas()->drawRect(boxes[i].rect, paint);
2962 }
2963 EXPECT_EQ(boxes.size(), 1ull);
2964 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.00781);
2965 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
2966 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 508.0625);
2967 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80);
2968
2969 paint.setColor(SK_ColorRED);
2970 boxes =
2971 paragraph->GetRectsForRange(30, 150, rect_height_style, rect_width_style);
2972 for (size_t i = 0; i < boxes.size(); ++i) {
2973 GetCanvas()->drawRect(boxes[i].rect, paint);
2974 }
2975 EXPECT_EQ(boxes.size(), 8ull);
2976 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.00781);
2977 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 80);
2978 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 525.6875);
2979 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 160);
2980
2981 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 525.6875);
2982 EXPECT_FLOAT_EQ(boxes[1].rect.top(), 80);
2983 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 570.02344);
2984 EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 160);
2985
2986 EXPECT_FLOAT_EQ(boxes[2].rect.left(), 0);
2987 EXPECT_FLOAT_EQ(boxes[2].rect.top(), 160);
2988 EXPECT_FLOAT_EQ(boxes[2].rect.right(), 531.57422);
2989 EXPECT_FLOAT_EQ(boxes[2].rect.bottom(), 240);
2990
2991 EXPECT_FLOAT_EQ(boxes[3].rect.left(), 531.57422);
2992 EXPECT_FLOAT_EQ(boxes[3].rect.top(), 160);
2993 EXPECT_FLOAT_EQ(boxes[3].rect.right(), 570.02344);
2994 EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 240);
2995
2996 EXPECT_FLOAT_EQ(boxes[4].rect.left(), 0);
2997 EXPECT_FLOAT_EQ(boxes[4].rect.top(), 240);
2998 EXPECT_FLOAT_EQ(boxes[4].rect.right(), 570.02344);
2999 EXPECT_FLOAT_EQ(boxes[4].rect.bottom(), 320);
3000
3001 EXPECT_FLOAT_EQ(boxes[5].rect.left(), 0);
3002 EXPECT_FLOAT_EQ(boxes[5].rect.top(), 320);
3003 EXPECT_FLOAT_EQ(boxes[5].rect.right(), 570.02344);
3004 EXPECT_FLOAT_EQ(boxes[5].rect.bottom(), 400);
3005
3006 paint.setColor(SK_ColorBLUE);
3007 boxes =
3008 paragraph->GetRectsForRange(19, 22, rect_height_style, rect_width_style);
3009 for (size_t i = 0; i < boxes.size(); ++i) {
3010 GetCanvas()->drawRect(boxes[i].rect, paint);
3011 }
3012 EXPECT_EQ(boxes.size(), 1ull);
3013 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 463.72656);
3014 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
3015 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 530.23047);
3016 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80);
3017
3018 paint.setColor(SK_ColorRED);
3019 boxes =
3020 paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style);
3021 for (size_t i = 0; i < boxes.size(); ++i) {
3022 GetCanvas()->drawRect(boxes[i].rect, paint);
3023 }
3024 EXPECT_EQ(boxes.size(), 0ull);
3025
3026 ASSERT_TRUE(Snapshot());
3027 }
3028
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeIncludeLineSpacingBottom))3029 TEST_F(ParagraphTest,
3030 DISABLE_ON_WINDOWS(GetRectsForRangeIncludeLineSpacingBottom)) {
3031 const char* text =
3032 "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
3033 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)("
3034 " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)";
3035 auto icu_text = icu::UnicodeString::fromUTF8(text);
3036 std::u16string u16_text(icu_text.getBuffer(),
3037 icu_text.getBuffer() + icu_text.length());
3038
3039 txt::ParagraphStyle paragraph_style;
3040 paragraph_style.max_lines = 10;
3041 paragraph_style.text_align = TextAlign::left;
3042 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3043
3044 txt::TextStyle text_style;
3045 text_style.font_families = std::vector<std::string>(1, "Roboto");
3046 text_style.font_size = 50;
3047 text_style.letter_spacing = 0;
3048 text_style.font_weight = FontWeight::w500;
3049 text_style.word_spacing = 0;
3050 text_style.color = SK_ColorBLACK;
3051 text_style.height = 1.6;
3052 text_style.has_height_override = true;
3053 builder.PushStyle(text_style);
3054
3055 builder.AddText(u16_text);
3056
3057 builder.Pop();
3058
3059 auto paragraph = BuildParagraph(builder);
3060 paragraph->Layout(550);
3061
3062 paragraph->Paint(GetCanvas(), 0, 0);
3063
3064 SkPaint paint;
3065 paint.setStyle(SkPaint::kStroke_Style);
3066 paint.setAntiAlias(true);
3067 paint.setStrokeWidth(1);
3068
3069 // Tests for GetRectsForRange()
3070 // NOTE: The base truth values may still need adjustment as the specifics
3071 // are adjusted.
3072 Paragraph::RectHeightStyle rect_height_style =
3073 Paragraph::RectHeightStyle::kIncludeLineSpacingBottom;
3074 Paragraph::RectWidthStyle rect_width_style = Paragraph::RectWidthStyle::kMax;
3075 paint.setColor(SK_ColorRED);
3076 std::vector<txt::Paragraph::TextBox> boxes =
3077 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
3078 for (size_t i = 0; i < boxes.size(); ++i) {
3079 GetCanvas()->drawRect(boxes[i].rect, paint);
3080 }
3081 EXPECT_EQ(boxes.size(), 0ull);
3082
3083 boxes =
3084 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
3085 for (size_t i = 0; i < boxes.size(); ++i) {
3086 GetCanvas()->drawRect(boxes[i].rect, paint);
3087 }
3088 EXPECT_EQ(boxes.size(), 1ull);
3089 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
3090 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
3091 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 17.429688);
3092 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 96.946609);
3093
3094 paint.setColor(SK_ColorBLUE);
3095 boxes =
3096 paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style);
3097 for (size_t i = 0; i < boxes.size(); ++i) {
3098 GetCanvas()->drawRect(boxes[i].rect, paint);
3099 }
3100 EXPECT_EQ(boxes.size(), 1ull);
3101 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 67.429688);
3102 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
3103 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 190.00781);
3104 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 96.946609);
3105
3106 paint.setColor(SK_ColorGREEN);
3107 boxes =
3108 paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style);
3109 for (size_t i = 0; i < boxes.size(); ++i) {
3110 GetCanvas()->drawRect(boxes[i].rect, paint);
3111 }
3112 EXPECT_EQ(boxes.size(), 1ull);
3113 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.00781);
3114 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
3115 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 508.0625);
3116 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 96.946609);
3117
3118 paint.setColor(SK_ColorRED);
3119 boxes =
3120 paragraph->GetRectsForRange(30, 150, rect_height_style, rect_width_style);
3121 for (size_t i = 0; i < boxes.size(); ++i) {
3122 GetCanvas()->drawRect(boxes[i].rect, paint);
3123 }
3124 EXPECT_EQ(boxes.size(), 8ull);
3125 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.00781);
3126 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 96.946617);
3127 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 525.6875);
3128 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 176.94661);
3129
3130 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 525.6875);
3131 EXPECT_FLOAT_EQ(boxes[1].rect.top(), 96.946617);
3132 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 570.02344);
3133 EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 176.94661);
3134
3135 EXPECT_FLOAT_EQ(boxes[2].rect.left(), 0);
3136 EXPECT_FLOAT_EQ(boxes[2].rect.top(), 176.94661);
3137 EXPECT_FLOAT_EQ(boxes[2].rect.right(), 531.57422);
3138 EXPECT_FLOAT_EQ(boxes[2].rect.bottom(), 256.94662);
3139
3140 EXPECT_FLOAT_EQ(boxes[3].rect.left(), 531.57422);
3141 EXPECT_FLOAT_EQ(boxes[3].rect.top(), 176.94661);
3142 EXPECT_FLOAT_EQ(boxes[3].rect.right(), 570.02344);
3143 EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 256.94662);
3144
3145 EXPECT_FLOAT_EQ(boxes[4].rect.left(), 0);
3146 EXPECT_FLOAT_EQ(boxes[4].rect.top(), 256.94662);
3147 EXPECT_FLOAT_EQ(boxes[4].rect.right(), 570.02344);
3148 EXPECT_FLOAT_EQ(boxes[4].rect.bottom(), 336.94662);
3149
3150 EXPECT_FLOAT_EQ(boxes[5].rect.left(), 0);
3151 EXPECT_FLOAT_EQ(boxes[5].rect.top(), 336.94662);
3152 EXPECT_FLOAT_EQ(boxes[5].rect.right(), 570.02344);
3153 EXPECT_FLOAT_EQ(boxes[5].rect.bottom(), 416.94662);
3154
3155 paint.setColor(SK_ColorBLUE);
3156 boxes =
3157 paragraph->GetRectsForRange(19, 22, rect_height_style, rect_width_style);
3158 for (size_t i = 0; i < boxes.size(); ++i) {
3159 GetCanvas()->drawRect(boxes[i].rect, paint);
3160 }
3161 EXPECT_EQ(boxes.size(), 1ull);
3162 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 463.72656);
3163 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615);
3164 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 530.23047);
3165 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 96.946609);
3166
3167 paint.setColor(SK_ColorRED);
3168 boxes =
3169 paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style);
3170 for (size_t i = 0; i < boxes.size(); ++i) {
3171 GetCanvas()->drawRect(boxes[i].rect, paint);
3172 }
3173 EXPECT_EQ(boxes.size(), 0ull);
3174
3175 ASSERT_TRUE(Snapshot());
3176 }
3177
TEST_F(ParagraphTest,GetRectsForRangeIncludeCombiningCharacter)3178 TEST_F(ParagraphTest, GetRectsForRangeIncludeCombiningCharacter) {
3179 const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
3180 auto icu_text = icu::UnicodeString::fromUTF8(text);
3181 std::u16string u16_text(icu_text.getBuffer(),
3182 icu_text.getBuffer() + icu_text.length());
3183
3184 txt::ParagraphStyle paragraph_style;
3185 paragraph_style.max_lines = 10;
3186 paragraph_style.text_align = TextAlign::left;
3187 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3188
3189 txt::TextStyle text_style;
3190 text_style.font_families = std::vector<std::string>(1, "Roboto");
3191 text_style.font_size = 50;
3192 text_style.letter_spacing = 1;
3193 text_style.word_spacing = 5;
3194 text_style.color = SK_ColorBLACK;
3195 text_style.height = 1;
3196 builder.PushStyle(text_style);
3197
3198 builder.AddText(u16_text);
3199
3200 builder.Pop();
3201
3202 auto paragraph = BuildParagraph(builder);
3203 paragraph->Layout(GetTestCanvasWidth() - 100);
3204
3205 paragraph->Paint(GetCanvas(), 0, 0);
3206
3207 Paragraph::RectHeightStyle rect_height_style =
3208 Paragraph::RectHeightStyle::kTight;
3209 Paragraph::RectWidthStyle rect_width_style =
3210 Paragraph::RectWidthStyle::kTight;
3211
3212 std::vector<txt::Paragraph::TextBox> boxes =
3213 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
3214 EXPECT_EQ(boxes.size(), 0ull);
3215
3216 // Case when the sentence starts with a combining character
3217 // We should get 0 box for ด because it's already been combined to ดี
3218 boxes =
3219 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
3220 EXPECT_EQ(boxes.size(), 0ull);
3221
3222 boxes =
3223 paragraph->GetRectsForRange(1, 2, rect_height_style, rect_width_style);
3224 EXPECT_EQ(boxes.size(), 1ull);
3225
3226 boxes =
3227 paragraph->GetRectsForRange(0, 2, rect_height_style, rect_width_style);
3228 EXPECT_EQ(boxes.size(), 1ull);
3229
3230 // Case when the sentence contains a combining character
3231 // We should get 0 box for ว because it's already been combined to วั
3232 boxes =
3233 paragraph->GetRectsForRange(3, 4, rect_height_style, rect_width_style);
3234 EXPECT_EQ(boxes.size(), 0ull);
3235
3236 boxes =
3237 paragraph->GetRectsForRange(4, 5, rect_height_style, rect_width_style);
3238 EXPECT_EQ(boxes.size(), 1ull);
3239
3240 boxes =
3241 paragraph->GetRectsForRange(3, 5, rect_height_style, rect_width_style);
3242 EXPECT_EQ(boxes.size(), 1ull);
3243
3244 // Case when the sentence contains a combining character that contain 3
3245 // characters We should get 0 box for ท and ที because it's already been
3246 // combined to ที่
3247 boxes =
3248 paragraph->GetRectsForRange(14, 15, rect_height_style, rect_width_style);
3249 EXPECT_EQ(boxes.size(), 0ull);
3250
3251 boxes =
3252 paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style);
3253 EXPECT_EQ(boxes.size(), 0ull);
3254
3255 boxes =
3256 paragraph->GetRectsForRange(16, 17, rect_height_style, rect_width_style);
3257 EXPECT_EQ(boxes.size(), 1ull);
3258
3259 boxes =
3260 paragraph->GetRectsForRange(14, 17, rect_height_style, rect_width_style);
3261 EXPECT_EQ(boxes.size(), 1ull);
3262 }
3263
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeCenterParagraph))3264 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeCenterParagraph)) {
3265 const char* text = "01234 "; // includes ideographic space
3266 // and english space.
3267 auto icu_text = icu::UnicodeString::fromUTF8(text);
3268 std::u16string u16_text(icu_text.getBuffer(),
3269 icu_text.getBuffer() + icu_text.length());
3270
3271 txt::ParagraphStyle paragraph_style;
3272 paragraph_style.max_lines = 10;
3273 paragraph_style.text_align = TextAlign::center;
3274 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3275
3276 txt::TextStyle text_style;
3277 text_style.font_families = std::vector<std::string>(1, "Roboto");
3278 text_style.font_size = 50;
3279 text_style.letter_spacing = 0;
3280 text_style.font_weight = FontWeight::w500;
3281 text_style.word_spacing = 0;
3282 text_style.color = SK_ColorBLACK;
3283 text_style.height = 1;
3284 builder.PushStyle(text_style);
3285
3286 builder.AddText(u16_text);
3287
3288 builder.Pop();
3289
3290 auto paragraph = BuildParagraph(builder);
3291 paragraph->Layout(550);
3292
3293 paragraph->Paint(GetCanvas(), 0, 0);
3294
3295 SkPaint paint;
3296 paint.setStyle(SkPaint::kStroke_Style);
3297 paint.setAntiAlias(true);
3298 paint.setStrokeWidth(1);
3299
3300 // Tests for GetRectsForRange()
3301 Paragraph::RectHeightStyle rect_height_style =
3302 Paragraph::RectHeightStyle::kMax;
3303 Paragraph::RectWidthStyle rect_width_style =
3304 Paragraph::RectWidthStyle::kTight;
3305 paint.setColor(SK_ColorRED);
3306 std::vector<txt::Paragraph::TextBox> boxes =
3307 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
3308 for (size_t i = 0; i < boxes.size(); ++i) {
3309 GetCanvas()->drawRect(boxes[i].rect, paint);
3310 }
3311 EXPECT_EQ(boxes.size(), 0ull);
3312
3313 boxes =
3314 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
3315 for (size_t i = 0; i < boxes.size(); ++i) {
3316 GetCanvas()->drawRect(boxes[i].rect, paint);
3317 }
3318 EXPECT_EQ(boxes.size(), 1ull);
3319 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 203.95508);
3320 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3321 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 232.37305);
3322 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3323
3324 paint.setColor(SK_ColorBLUE);
3325 boxes =
3326 paragraph->GetRectsForRange(2, 4, rect_height_style, rect_width_style);
3327 for (size_t i = 0; i < boxes.size(); ++i) {
3328 GetCanvas()->drawRect(boxes[i].rect, paint);
3329 }
3330 EXPECT_EQ(boxes.size(), 1ull);
3331 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 260.79102);
3332 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3333 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 317.62695);
3334 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3335
3336 paint.setColor(SK_ColorGREEN);
3337 boxes =
3338 paragraph->GetRectsForRange(4, 6, rect_height_style, rect_width_style);
3339 for (size_t i = 0; i < boxes.size(); ++i) {
3340 GetCanvas()->drawRect(boxes[i].rect, paint);
3341 }
3342 EXPECT_EQ(boxes.size(), 2ull);
3343 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 317.62695);
3344 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3345 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 346.04492);
3346 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3347
3348 paint.setColor(SK_ColorBLACK);
3349 boxes =
3350 paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style);
3351 for (size_t i = 0; i < boxes.size(); ++i) {
3352 GetCanvas()->drawRect(boxes[i].rect, paint);
3353 }
3354 EXPECT_EQ(boxes.size(), 1ull);
3355 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 346.04492);
3356 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3357 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 358.49414);
3358 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3359
3360 paint.setColor(SK_ColorRED);
3361 boxes =
3362 paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style);
3363 for (size_t i = 0; i < boxes.size(); ++i) {
3364 GetCanvas()->drawRect(boxes[i].rect, paint);
3365 }
3366 EXPECT_EQ(boxes.size(), 0ull);
3367
3368 ASSERT_TRUE(Snapshot());
3369 }
3370
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeCenterParagraphNewlineCentered))3371 TEST_F(ParagraphTest,
3372 DISABLE_ON_WINDOWS(GetRectsForRangeCenterParagraphNewlineCentered)) {
3373 const char* text = "01234\n";
3374 auto icu_text = icu::UnicodeString::fromUTF8(text);
3375 std::u16string u16_text(icu_text.getBuffer(),
3376 icu_text.getBuffer() + icu_text.length());
3377
3378 txt::ParagraphStyle paragraph_style;
3379 paragraph_style.max_lines = 10;
3380 paragraph_style.text_align = TextAlign::center;
3381 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3382
3383 txt::TextStyle text_style;
3384 text_style.font_families = std::vector<std::string>(1, "Roboto");
3385 text_style.font_size = 50;
3386 text_style.letter_spacing = 0;
3387 text_style.font_weight = FontWeight::w500;
3388 text_style.word_spacing = 0;
3389 text_style.color = SK_ColorBLACK;
3390 text_style.height = 1;
3391 builder.PushStyle(text_style);
3392
3393 builder.AddText(u16_text);
3394
3395 builder.Pop();
3396
3397 auto paragraph = BuildParagraph(builder);
3398 paragraph->Layout(550);
3399
3400 paragraph->Paint(GetCanvas(), 0, 0);
3401
3402 SkPaint paint;
3403 paint.setStyle(SkPaint::kStroke_Style);
3404 paint.setAntiAlias(true);
3405 paint.setStrokeWidth(1);
3406
3407 // Tests for GetRectsForRange()
3408 Paragraph::RectHeightStyle rect_height_style =
3409 Paragraph::RectHeightStyle::kMax;
3410 Paragraph::RectWidthStyle rect_width_style =
3411 Paragraph::RectWidthStyle::kTight;
3412 paint.setColor(SK_ColorRED);
3413 std::vector<txt::Paragraph::TextBox> boxes =
3414 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
3415 for (size_t i = 0; i < boxes.size(); ++i) {
3416 GetCanvas()->drawRect(boxes[i].rect, paint);
3417 }
3418 EXPECT_EQ(boxes.size(), 0ull);
3419
3420 boxes =
3421 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
3422 for (size_t i = 0; i < boxes.size(); ++i) {
3423 GetCanvas()->drawRect(boxes[i].rect, paint);
3424 }
3425 EXPECT_EQ(boxes.size(), 1ull);
3426 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 203.95508);
3427 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3428 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 232.37305);
3429 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3430
3431 paint.setColor(SK_ColorGREEN);
3432 boxes =
3433 paragraph->GetRectsForRange(6, 7, rect_height_style, rect_width_style);
3434 for (size_t i = 0; i < boxes.size(); ++i) {
3435 GetCanvas()->drawRect(boxes[i].rect, paint);
3436 }
3437 EXPECT_EQ(boxes.size(), 1ull);
3438 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 275);
3439 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 275);
3440 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(),
3441 75); // TODO(garyq): This value can be improved... Should be
3442 // taller, but we need a good way to obtain a height
3443 // without any glyphs on the line.
3444
3445 ASSERT_TRUE(Snapshot());
3446 }
3447
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeCenterMultiLineParagraph))3448 TEST_F(ParagraphTest,
3449 DISABLE_ON_WINDOWS(GetRectsForRangeCenterMultiLineParagraph)) {
3450 const char* text = "01234 \n0123 "; // includes ideographic
3451 // space and english space.
3452 auto icu_text = icu::UnicodeString::fromUTF8(text);
3453 std::u16string u16_text(icu_text.getBuffer(),
3454 icu_text.getBuffer() + icu_text.length());
3455
3456 txt::ParagraphStyle paragraph_style;
3457 paragraph_style.max_lines = 10;
3458 paragraph_style.text_align = TextAlign::center;
3459 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3460
3461 txt::TextStyle text_style;
3462 text_style.font_families = std::vector<std::string>(1, "Roboto");
3463 text_style.font_size = 50;
3464 text_style.letter_spacing = 0;
3465 text_style.font_weight = FontWeight::w500;
3466 text_style.word_spacing = 0;
3467 text_style.color = SK_ColorBLACK;
3468 text_style.height = 1;
3469 builder.PushStyle(text_style);
3470
3471 builder.AddText(u16_text);
3472
3473 builder.Pop();
3474
3475 auto paragraph = BuildParagraph(builder);
3476 paragraph->Layout(550);
3477
3478 paragraph->Paint(GetCanvas(), 0, 0);
3479
3480 SkPaint paint;
3481 paint.setStyle(SkPaint::kStroke_Style);
3482 paint.setAntiAlias(true);
3483 paint.setStrokeWidth(1);
3484
3485 // Tests for GetRectsForRange()
3486 Paragraph::RectHeightStyle rect_height_style =
3487 Paragraph::RectHeightStyle::kMax;
3488 Paragraph::RectWidthStyle rect_width_style =
3489 Paragraph::RectWidthStyle::kTight;
3490 paint.setColor(SK_ColorRED);
3491 std::vector<txt::Paragraph::TextBox> boxes =
3492 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
3493 for (size_t i = 0; i < boxes.size(); ++i) {
3494 GetCanvas()->drawRect(boxes[i].rect, paint);
3495 }
3496 EXPECT_EQ(boxes.size(), 0ull);
3497
3498 boxes =
3499 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
3500 for (size_t i = 0; i < boxes.size(); ++i) {
3501 GetCanvas()->drawRect(boxes[i].rect, paint);
3502 }
3503 EXPECT_EQ(boxes.size(), 1ull);
3504 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 203.95508);
3505 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3506 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 232.37305);
3507 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3508
3509 paint.setColor(SK_ColorBLUE);
3510 boxes =
3511 paragraph->GetRectsForRange(2, 4, rect_height_style, rect_width_style);
3512 for (size_t i = 0; i < boxes.size(); ++i) {
3513 GetCanvas()->drawRect(boxes[i].rect, paint);
3514 }
3515 EXPECT_EQ(boxes.size(), 1ull);
3516 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 260.79102);
3517 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3518 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 317.62695);
3519 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3520
3521 paint.setColor(SK_ColorGREEN);
3522 boxes =
3523 paragraph->GetRectsForRange(4, 6, rect_height_style, rect_width_style);
3524 for (size_t i = 0; i < boxes.size(); ++i) {
3525 GetCanvas()->drawRect(boxes[i].rect, paint);
3526 }
3527 EXPECT_EQ(boxes.size(), 2ull);
3528 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 317.62695);
3529 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3530 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 346.04492);
3531 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3532
3533 paint.setColor(SK_ColorBLACK);
3534 boxes =
3535 paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style);
3536 for (size_t i = 0; i < boxes.size(); ++i) {
3537 GetCanvas()->drawRect(boxes[i].rect, paint);
3538 }
3539 EXPECT_EQ(boxes.size(), 1ull);
3540 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 346.04492);
3541 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
3542 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 358.49414);
3543 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
3544
3545 paint.setColor(SK_ColorBLACK);
3546 boxes =
3547 paragraph->GetRectsForRange(10, 12, rect_height_style, rect_width_style);
3548 for (size_t i = 0; i < boxes.size(); ++i) {
3549 GetCanvas()->drawRect(boxes[i].rect, paint);
3550 }
3551 EXPECT_EQ(boxes.size(), 1ull);
3552 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 218.16406);
3553 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 59.40625);
3554 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 275);
3555 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 118);
3556
3557 paint.setColor(SK_ColorBLACK);
3558 boxes =
3559 paragraph->GetRectsForRange(14, 18, rect_height_style, rect_width_style);
3560 for (size_t i = 0; i < boxes.size(); ++i) {
3561 GetCanvas()->drawRect(boxes[i].rect, paint);
3562 }
3563 EXPECT_EQ(boxes.size(), 1ull);
3564 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 331.83594);
3565 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 59.40625);
3566 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 419.18359);
3567 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 118);
3568
3569 paint.setColor(SK_ColorRED);
3570 boxes =
3571 paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style);
3572 for (size_t i = 0; i < boxes.size(); ++i) {
3573 GetCanvas()->drawRect(boxes[i].rect, paint);
3574 }
3575 EXPECT_EQ(boxes.size(), 0ull);
3576
3577 ASSERT_TRUE(Snapshot());
3578 }
3579
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeStrut))3580 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeStrut)) {
3581 const char* text = "Chinese 字典";
3582
3583 auto icu_text = icu::UnicodeString::fromUTF8(text);
3584 std::u16string u16_text(icu_text.getBuffer(),
3585 icu_text.getBuffer() + icu_text.length());
3586
3587 txt::ParagraphStyle paragraph_style;
3588 paragraph_style.strut_enabled = true;
3589 paragraph_style.strut_font_families.push_back("Roboto");
3590 paragraph_style.strut_font_size = 14;
3591 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3592
3593 txt::TextStyle text_style;
3594 text_style.font_families.push_back("Noto Sans CJK JP");
3595 text_style.font_size = 20;
3596 text_style.color = SK_ColorBLACK;
3597 builder.PushStyle(text_style);
3598
3599 builder.AddText(u16_text);
3600
3601 builder.Pop();
3602
3603 auto paragraph = BuildParagraph(builder);
3604 paragraph->Layout(550);
3605
3606 paragraph->Paint(GetCanvas(), 0, 0);
3607
3608 SkPaint paint;
3609 paint.setStyle(SkPaint::kStroke_Style);
3610 paint.setAntiAlias(true);
3611 paint.setStrokeWidth(1);
3612
3613 std::vector<txt::Paragraph::TextBox> strut_boxes =
3614 paragraph->GetRectsForRange(0, 10, Paragraph::RectHeightStyle::kStrut,
3615 Paragraph::RectWidthStyle::kMax);
3616 ASSERT_EQ(strut_boxes.size(), 1ull);
3617 const SkRect& strut_rect = strut_boxes.front().rect;
3618 paint.setColor(SK_ColorRED);
3619 GetCanvas()->drawRect(strut_rect, paint);
3620
3621 std::vector<txt::Paragraph::TextBox> tight_boxes =
3622 paragraph->GetRectsForRange(0, 10, Paragraph::RectHeightStyle::kTight,
3623 Paragraph::RectWidthStyle::kMax);
3624 ASSERT_EQ(tight_boxes.size(), 1ull);
3625 const SkRect& tight_rect = tight_boxes.front().rect;
3626 paint.setColor(SK_ColorGREEN);
3627 GetCanvas()->drawRect(tight_rect, paint);
3628
3629 EXPECT_FLOAT_EQ(strut_rect.left(), 0);
3630 EXPECT_FLOAT_EQ(strut_rect.top(), 10.611719);
3631 EXPECT_FLOAT_EQ(strut_rect.right(), 118.60547);
3632 EXPECT_FLOAT_EQ(strut_rect.bottom(), 27.017969);
3633
3634 ASSERT_TRUE(tight_rect.contains(strut_rect));
3635
3636 ASSERT_TRUE(Snapshot());
3637 }
3638
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (GetRectsForRangeStrutFallback))3639 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeStrutFallback)) {
3640 const char* text = "Chinese 字典";
3641
3642 auto icu_text = icu::UnicodeString::fromUTF8(text);
3643 std::u16string u16_text(icu_text.getBuffer(),
3644 icu_text.getBuffer() + icu_text.length());
3645
3646 txt::ParagraphStyle paragraph_style;
3647 paragraph_style.strut_enabled = false;
3648 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3649
3650 txt::TextStyle text_style;
3651 text_style.font_families.push_back("Noto Sans CJK JP");
3652 text_style.font_size = 20;
3653 builder.PushStyle(text_style);
3654
3655 builder.AddText(u16_text);
3656
3657 builder.Pop();
3658
3659 auto paragraph = BuildParagraph(builder);
3660 paragraph->Layout(550);
3661
3662 std::vector<txt::Paragraph::TextBox> strut_boxes =
3663 paragraph->GetRectsForRange(0, 10, Paragraph::RectHeightStyle::kStrut,
3664 Paragraph::RectWidthStyle::kMax);
3665 std::vector<txt::Paragraph::TextBox> tight_boxes =
3666 paragraph->GetRectsForRange(0, 10, Paragraph::RectHeightStyle::kTight,
3667 Paragraph::RectWidthStyle::kMax);
3668
3669 ASSERT_EQ(strut_boxes.size(), 1ull);
3670 ASSERT_EQ(tight_boxes.size(), 1ull);
3671 ASSERT_EQ(strut_boxes.front().rect, tight_boxes.front().rect);
3672 }
3673
GetCoordinatesForGlyphPosition(txt::Paragraph & paragraph,size_t pos)3674 SkRect GetCoordinatesForGlyphPosition(txt::Paragraph& paragraph, size_t pos) {
3675 std::vector<txt::Paragraph::TextBox> boxes =
3676 paragraph.GetRectsForRange(pos, pos + 1, Paragraph::RectHeightStyle::kMax,
3677 Paragraph::RectWidthStyle::kTight);
3678 return !boxes.empty() ? boxes.front().rect : SkRect::MakeEmpty();
3679 }
3680
TEST_F(ParagraphTest,GetWordBoundaryParagraph)3681 TEST_F(ParagraphTest, GetWordBoundaryParagraph) {
3682 const char* text =
3683 "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 "
3684 "67890 12345";
3685 auto icu_text = icu::UnicodeString::fromUTF8(text);
3686 std::u16string u16_text(icu_text.getBuffer(),
3687 icu_text.getBuffer() + icu_text.length());
3688
3689 txt::ParagraphStyle paragraph_style;
3690 paragraph_style.max_lines = 10;
3691 paragraph_style.text_align = TextAlign::left;
3692 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3693
3694 txt::TextStyle text_style;
3695 text_style.font_families = std::vector<std::string>(1, "Roboto");
3696 text_style.font_size = 52;
3697 text_style.letter_spacing = 1.19039;
3698 text_style.word_spacing = 5;
3699 text_style.color = SK_ColorBLACK;
3700 text_style.height = 1.5;
3701 text_style.has_height_override = true;
3702 builder.PushStyle(text_style);
3703
3704 builder.AddText(u16_text);
3705
3706 builder.Pop();
3707
3708 auto paragraph = BuildParagraph(builder);
3709 paragraph->Layout(550);
3710
3711 paragraph->Paint(GetCanvas(), 0, 0);
3712
3713 SkPaint paint;
3714 paint.setStyle(SkPaint::kStroke_Style);
3715 paint.setAntiAlias(true);
3716 paint.setStrokeWidth(1);
3717 paint.setColor(SK_ColorRED);
3718
3719 SkRect rect = GetCoordinatesForGlyphPosition(*paragraph, 0);
3720 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3721
3722 EXPECT_EQ(paragraph->GetWordBoundary(0), txt::Paragraph::Range<size_t>(0, 5));
3723 EXPECT_EQ(paragraph->GetWordBoundary(1), txt::Paragraph::Range<size_t>(0, 5));
3724 EXPECT_EQ(paragraph->GetWordBoundary(2), txt::Paragraph::Range<size_t>(0, 5));
3725 EXPECT_EQ(paragraph->GetWordBoundary(3), txt::Paragraph::Range<size_t>(0, 5));
3726 EXPECT_EQ(paragraph->GetWordBoundary(4), txt::Paragraph::Range<size_t>(0, 5));
3727 rect = GetCoordinatesForGlyphPosition(*paragraph, 5);
3728 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3729
3730 EXPECT_EQ(paragraph->GetWordBoundary(5), txt::Paragraph::Range<size_t>(5, 7));
3731 rect = GetCoordinatesForGlyphPosition(*paragraph, 6);
3732 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3733
3734 EXPECT_EQ(paragraph->GetWordBoundary(6), txt::Paragraph::Range<size_t>(5, 7));
3735 rect = GetCoordinatesForGlyphPosition(*paragraph, 7);
3736 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3737
3738 EXPECT_EQ(paragraph->GetWordBoundary(7),
3739 txt::Paragraph::Range<size_t>(7, 12));
3740 EXPECT_EQ(paragraph->GetWordBoundary(8),
3741 txt::Paragraph::Range<size_t>(7, 12));
3742 EXPECT_EQ(paragraph->GetWordBoundary(9),
3743 txt::Paragraph::Range<size_t>(7, 12));
3744 EXPECT_EQ(paragraph->GetWordBoundary(10),
3745 txt::Paragraph::Range<size_t>(7, 12));
3746 EXPECT_EQ(paragraph->GetWordBoundary(11),
3747 txt::Paragraph::Range<size_t>(7, 12));
3748 rect = GetCoordinatesForGlyphPosition(*paragraph, 12);
3749 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3750
3751 EXPECT_EQ(paragraph->GetWordBoundary(12),
3752 txt::Paragraph::Range<size_t>(12, 13));
3753 rect = GetCoordinatesForGlyphPosition(*paragraph, 13);
3754 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3755
3756 EXPECT_EQ(paragraph->GetWordBoundary(13),
3757 txt::Paragraph::Range<size_t>(13, 18));
3758 rect = GetCoordinatesForGlyphPosition(*paragraph, 18);
3759 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3760
3761 rect = GetCoordinatesForGlyphPosition(*paragraph, 19);
3762 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3763
3764 rect = GetCoordinatesForGlyphPosition(*paragraph, 24);
3765 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3766
3767 rect = GetCoordinatesForGlyphPosition(*paragraph, 25);
3768 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3769
3770 rect = GetCoordinatesForGlyphPosition(*paragraph, 30);
3771 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3772
3773 EXPECT_EQ(paragraph->GetWordBoundary(30),
3774 txt::Paragraph::Range<size_t>(30, 31));
3775 rect = GetCoordinatesForGlyphPosition(*paragraph, 31);
3776 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3777
3778 rect = GetCoordinatesForGlyphPosition(*paragraph, icu_text.length() - 5);
3779 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3780
3781 EXPECT_EQ(
3782 paragraph->GetWordBoundary(icu_text.length() - 1),
3783 txt::Paragraph::Range<size_t>(icu_text.length() - 5, icu_text.length()));
3784 rect = GetCoordinatesForGlyphPosition(*paragraph, icu_text.length());
3785 GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint);
3786
3787 ASSERT_TRUE(Snapshot());
3788 }
3789
TEST_F(ParagraphTest,SpacingParagraph)3790 TEST_F(ParagraphTest, SpacingParagraph) {
3791 const char* text = "H";
3792 auto icu_text = icu::UnicodeString::fromUTF8(text);
3793 std::u16string u16_text(icu_text.getBuffer(),
3794 icu_text.getBuffer() + icu_text.length());
3795
3796 txt::ParagraphStyle paragraph_style;
3797 paragraph_style.max_lines = 10;
3798 paragraph_style.text_align = TextAlign::left;
3799 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3800
3801 txt::TextStyle text_style;
3802 text_style.font_families = std::vector<std::string>(1, "Roboto");
3803 text_style.font_size = 50;
3804 text_style.letter_spacing = 20;
3805 text_style.word_spacing = 0;
3806 text_style.color = SK_ColorBLACK;
3807 text_style.height = 1;
3808 builder.PushStyle(text_style);
3809 builder.AddText(u16_text);
3810 builder.Pop();
3811
3812 text_style.font_size = 50;
3813 text_style.letter_spacing = 10;
3814 text_style.word_spacing = 0;
3815 builder.PushStyle(text_style);
3816 builder.AddText(u16_text);
3817 builder.Pop();
3818
3819 text_style.font_size = 50;
3820 text_style.letter_spacing = 20;
3821 text_style.word_spacing = 0;
3822 builder.PushStyle(text_style);
3823 builder.AddText(u16_text);
3824 builder.Pop();
3825
3826 text_style.font_size = 50;
3827 text_style.letter_spacing = 0;
3828 text_style.word_spacing = 0;
3829 builder.PushStyle(text_style);
3830 builder.AddText(u"|");
3831 builder.Pop();
3832
3833 text_style.font_size = 50;
3834 text_style.letter_spacing = 0;
3835 text_style.word_spacing = 20;
3836 builder.PushStyle(text_style);
3837 builder.AddText(u"H ");
3838 builder.Pop();
3839
3840 text_style.font_size = 50;
3841 text_style.letter_spacing = 0;
3842 text_style.word_spacing = 0;
3843 builder.PushStyle(text_style);
3844 builder.AddText(u"H ");
3845 builder.Pop();
3846
3847 text_style.font_size = 50;
3848 text_style.letter_spacing = 0;
3849 text_style.word_spacing = 20;
3850 builder.PushStyle(text_style);
3851 builder.AddText(u"H ");
3852 builder.Pop();
3853
3854 auto paragraph = BuildParagraph(builder);
3855 paragraph->Layout(550);
3856
3857 paragraph->Paint(GetCanvas(), 0, 0);
3858
3859 SkPaint paint;
3860 paint.setStyle(SkPaint::kStroke_Style);
3861 paint.setAntiAlias(true);
3862 paint.setStrokeWidth(1);
3863 paint.setColor(SK_ColorRED);
3864
3865 ASSERT_TRUE(Snapshot());
3866
3867 ASSERT_EQ(paragraph->records_.size(), 7ull);
3868 ASSERT_EQ(paragraph->records_[0].style().letter_spacing, 20);
3869 ASSERT_EQ(paragraph->records_[1].style().letter_spacing, 10);
3870 ASSERT_EQ(paragraph->records_[2].style().letter_spacing, 20);
3871
3872 ASSERT_EQ(paragraph->records_[4].style().word_spacing, 20);
3873 ASSERT_EQ(paragraph->records_[5].style().word_spacing, 0);
3874 ASSERT_EQ(paragraph->records_[6].style().word_spacing, 20);
3875 }
3876
TEST_F(ParagraphTest,LongWordParagraph)3877 TEST_F(ParagraphTest, LongWordParagraph) {
3878 const char* text =
3879 "A "
3880 "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat"
3881 "wouldbeagoodthingbecausethebreakingisworking.";
3882 auto icu_text = icu::UnicodeString::fromUTF8(text);
3883 std::u16string u16_text(icu_text.getBuffer(),
3884 icu_text.getBuffer() + icu_text.length());
3885
3886 txt::ParagraphStyle paragraph_style;
3887 paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality;
3888 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3889
3890 txt::TextStyle text_style;
3891 text_style.font_families = std::vector<std::string>(1, "Roboto");
3892 text_style.font_size = 31;
3893 text_style.letter_spacing = 0;
3894 text_style.word_spacing = 0;
3895 text_style.color = SK_ColorBLACK;
3896 text_style.height = 1;
3897 builder.PushStyle(text_style);
3898 builder.AddText(u16_text);
3899
3900 builder.Pop();
3901
3902 auto paragraph = BuildParagraph(builder);
3903 paragraph->Layout(GetTestCanvasWidth() / 2);
3904
3905 paragraph->Paint(GetCanvas(), 0, 0);
3906
3907 ASSERT_TRUE(Snapshot());
3908 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
3909 for (size_t i = 0; i < u16_text.length(); i++) {
3910 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
3911 }
3912 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
3913 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
3914 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
3915 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
3916 ASSERT_EQ(paragraph->GetLineCount(), 4ull);
3917 ASSERT_TRUE(Snapshot());
3918 }
3919
TEST_F(ParagraphTest,KernScaleParagraph)3920 TEST_F(ParagraphTest, KernScaleParagraph) {
3921 float scale = 3.0f;
3922
3923 txt::ParagraphStyle paragraph_style;
3924 paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality;
3925 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3926
3927 txt::TextStyle text_style;
3928 text_style.font_families = std::vector<std::string>(1, "Droid Serif");
3929 text_style.font_size = 100 / scale;
3930 text_style.letter_spacing = 0;
3931 text_style.word_spacing = 0;
3932 text_style.color = SK_ColorBLACK;
3933 text_style.height = 1;
3934 builder.PushStyle(text_style);
3935 builder.AddText(u"AVAVAWAH A0 V0 VA To The Lo");
3936 builder.PushStyle(text_style);
3937 builder.AddText(u"A");
3938 builder.PushStyle(text_style);
3939 builder.AddText(u"V");
3940 text_style.font_size = 14 / scale;
3941 builder.PushStyle(text_style);
3942 builder.AddText(
3943 u" Dialog Text List lots of words to see if kerning works on a bigger "
3944 u"set of characters AVAVAW");
3945
3946 builder.Pop();
3947
3948 auto paragraph = BuildParagraph(builder);
3949 paragraph->Layout(GetTestCanvasWidth() / scale);
3950 GetCanvas()->scale(scale, scale);
3951 paragraph->Paint(GetCanvas(), 0, 0);
3952 GetCanvas()->scale(1.0, 1.0);
3953 ASSERT_TRUE(Snapshot());
3954
3955 EXPECT_DOUBLE_EQ(paragraph->records_[0].offset().x(), 0);
3956 EXPECT_DOUBLE_EQ(paragraph->records_[1].offset().x(), 0);
3957 EXPECT_DOUBLE_EQ(paragraph->records_[2].offset().x(), 207.37109375f);
3958 EXPECT_DOUBLE_EQ(paragraph->records_[3].offset().x(), 230.87109375f);
3959 EXPECT_DOUBLE_EQ(paragraph->records_[4].offset().x(), 253.36328125f);
3960 }
3961
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (NewlineParagraph))3962 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(NewlineParagraph)) {
3963 txt::ParagraphStyle paragraph_style;
3964 paragraph_style.font_family = "Roboto";
3965 paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality;
3966
3967 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
3968
3969 txt::TextStyle text_style;
3970 text_style.font_families = std::vector<std::string>(1, "Roboto");
3971 text_style.font_size = 60;
3972 text_style.letter_spacing = 0;
3973 text_style.word_spacing = 0;
3974 text_style.color = SK_ColorBLACK;
3975 text_style.height = 1;
3976 builder.PushStyle(text_style);
3977 builder.AddText(
3978 u"line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 "
3979 "test1 test2 test3 test4");
3980
3981 builder.Pop();
3982
3983 auto paragraph = BuildParagraph(builder);
3984 paragraph->Layout(GetTestCanvasWidth() - 300);
3985
3986 paragraph->Paint(GetCanvas(), 0, 0);
3987
3988 ASSERT_TRUE(Snapshot());
3989
3990 ASSERT_EQ(paragraph->records_.size(), 6ull);
3991 EXPECT_DOUBLE_EQ(paragraph->records_[0].offset().x(), 0);
3992 EXPECT_DOUBLE_EQ(paragraph->records_[1].offset().x(), 0);
3993 EXPECT_DOUBLE_EQ(paragraph->records_[1].offset().y(), 126);
3994 EXPECT_DOUBLE_EQ(paragraph->records_[2].offset().x(), 0);
3995 EXPECT_DOUBLE_EQ(paragraph->records_[3].offset().x(), 0);
3996 EXPECT_DOUBLE_EQ(paragraph->records_[4].offset().x(), 0);
3997 EXPECT_DOUBLE_EQ(paragraph->records_[3].offset().y(), 266);
3998 EXPECT_DOUBLE_EQ(paragraph->records_[5].offset().x(), 0);
3999 }
4000
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (EmojiParagraph))4001 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(EmojiParagraph)) {
4002 const char* text =
4003 "☺♂️\
4004 ☂\
4005 ❄⚽♀️⚓⏰\
4006 ❤♠♣❗️";
4007 auto icu_text = icu::UnicodeString::fromUTF8(text);
4008 std::u16string u16_text(icu_text.getBuffer(),
4009 icu_text.getBuffer() + icu_text.length());
4010
4011 txt::ParagraphStyle paragraph_style;
4012
4013 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4014
4015 txt::TextStyle text_style;
4016 text_style.color = SK_ColorBLACK;
4017 text_style.font_families = std::vector<std::string>(1, "Noto Color Emoji");
4018 text_style.font_size = 50;
4019 text_style.decoration = TextDecoration::kUnderline;
4020 builder.PushStyle(text_style);
4021 builder.AddText(u16_text);
4022
4023 builder.Pop();
4024
4025 auto paragraph = BuildParagraph(builder);
4026 paragraph->Layout(GetTestCanvasWidth());
4027
4028 paragraph->Paint(GetCanvas(), 0, 0);
4029
4030 ASSERT_TRUE(Snapshot());
4031
4032 for (size_t i = 0; i < u16_text.length(); i++) {
4033 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
4034 }
4035
4036 ASSERT_EQ(paragraph->records_.size(), 8ull);
4037
4038 EXPECT_EQ(paragraph->records_[0].line(), 0ull);
4039 EXPECT_EQ(paragraph->records_[1].line(), 1ull);
4040 EXPECT_EQ(paragraph->records_[2].line(), 2ull);
4041 EXPECT_EQ(paragraph->records_[3].line(), 3ull);
4042 EXPECT_EQ(paragraph->records_[7].line(), 7ull);
4043 }
4044
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (EmojiMultiLineRectsParagraph))4045 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(EmojiMultiLineRectsParagraph)) {
4046 // clang-format off
4047 const char* text =
4048 "i"
4049 ""
4050 ""
4051 ""
4052 "❄⚽♀️⚓⏰"
4053 "❤♠♣❗️";
4054 // clang-format on
4055 auto icu_text = icu::UnicodeString::fromUTF8(text);
4056 std::u16string u16_text(icu_text.getBuffer(),
4057 icu_text.getBuffer() + icu_text.length());
4058
4059 txt::ParagraphStyle paragraph_style;
4060
4061 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4062
4063 txt::TextStyle text_style;
4064 text_style.color = SK_ColorBLACK;
4065 text_style.font_families = std::vector<std::string>(1, "Noto Color Emoji");
4066 text_style.font_size = 50;
4067 builder.PushStyle(text_style);
4068 builder.AddText(u16_text);
4069
4070 builder.Pop();
4071
4072 auto paragraph = BuildParagraph(builder);
4073 paragraph->Layout(GetTestCanvasWidth() - 300);
4074
4075 paragraph->Paint(GetCanvas(), 0, 0);
4076
4077 for (size_t i = 0; i < u16_text.length(); i++) {
4078 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
4079 }
4080
4081 ASSERT_EQ(paragraph->records_.size(), 10ull);
4082
4083 SkPaint paint;
4084 paint.setStyle(SkPaint::kStroke_Style);
4085 paint.setAntiAlias(true);
4086 paint.setStrokeWidth(1);
4087
4088 // Tests for GetRectsForRange()
4089 Paragraph::RectHeightStyle rect_height_style =
4090 Paragraph::RectHeightStyle::kTight;
4091 Paragraph::RectWidthStyle rect_width_style =
4092 Paragraph::RectWidthStyle::kTight;
4093 paint.setColor(SK_ColorRED);
4094 std::vector<txt::Paragraph::TextBox> boxes =
4095 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
4096 for (size_t i = 0; i < boxes.size(); ++i) {
4097 GetCanvas()->drawRect(boxes[i].rect, paint);
4098 }
4099 EXPECT_EQ(boxes.size(), 0ull);
4100
4101 // Ligature style indexing.
4102 boxes =
4103 paragraph->GetRectsForRange(0, 119, rect_height_style, rect_width_style);
4104 for (size_t i = 0; i < boxes.size(); ++i) {
4105 GetCanvas()->drawRect(boxes[i].rect, paint);
4106 }
4107 EXPECT_EQ(boxes.size(), 2ull);
4108 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0);
4109 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 334.61475);
4110
4111 boxes = paragraph->GetRectsForRange(122, 132, rect_height_style,
4112 rect_width_style);
4113 paint.setColor(SK_ColorBLUE);
4114 for (size_t i = 0; i < boxes.size(); ++i) {
4115 GetCanvas()->drawRect(boxes[i].rect, paint);
4116 }
4117 EXPECT_EQ(boxes.size(), 1ull);
4118 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 357.95996);
4119 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 418.79901);
4120
4121 // GetPositionForCoordinates should not return inter-emoji positions.
4122 boxes = paragraph->GetRectsForRange(
4123 0, paragraph->GetGlyphPositionAtCoordinate(610, 100).position,
4124 rect_height_style, rect_width_style);
4125 paint.setColor(SK_ColorGREEN);
4126 for (size_t i = 0; i < boxes.size(); ++i) {
4127 GetCanvas()->drawRect(boxes[i].rect, paint);
4128 }
4129 EXPECT_EQ(boxes.size(), 2ull);
4130 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0);
4131 // The following is expected to change to a higher value when
4132 // rounding up is added to getGlyphPositionForCoordinate.
4133 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 560.28516);
4134
4135 boxes = paragraph->GetRectsForRange(
4136 0, paragraph->GetGlyphPositionAtCoordinate(580, 100).position,
4137 rect_height_style, rect_width_style);
4138 paint.setColor(SK_ColorGREEN);
4139 for (size_t i = 0; i < boxes.size(); ++i) {
4140 GetCanvas()->drawRect(boxes[i].rect, paint);
4141 }
4142 EXPECT_EQ(boxes.size(), 2ull);
4143 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0);
4144 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 560.28516);
4145
4146 boxes = paragraph->GetRectsForRange(
4147 0, paragraph->GetGlyphPositionAtCoordinate(560, 100).position,
4148 rect_height_style, rect_width_style);
4149 paint.setColor(SK_ColorGREEN);
4150 for (size_t i = 0; i < boxes.size(); ++i) {
4151 GetCanvas()->drawRect(boxes[i].rect, paint);
4152 }
4153 EXPECT_EQ(boxes.size(), 2ull);
4154 EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0);
4155 // The following is expected to change to the 560.28516 value when
4156 // rounding up is added to getGlyphPositionForCoordinate.
4157 EXPECT_FLOAT_EQ(boxes[1].rect.right(), 498.03125);
4158
4159 ASSERT_TRUE(Snapshot());
4160 }
4161
TEST_F(ParagraphTest,HyphenBreakParagraph)4162 TEST_F(ParagraphTest, HyphenBreakParagraph) {
4163 const char* text =
4164 "A "
4165 "very-very-long-Hyphen-word-to-see-where-this-will-wrap-or-if-it-will-at-"
4166 "all-and-if-it-does-thent-hat-"
4167 "would-be-a-good-thing-because-the-breaking.";
4168 auto icu_text = icu::UnicodeString::fromUTF8(text);
4169 std::u16string u16_text(icu_text.getBuffer(),
4170 icu_text.getBuffer() + icu_text.length());
4171
4172 txt::ParagraphStyle paragraph_style;
4173 paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality;
4174
4175 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4176
4177 txt::TextStyle text_style;
4178 text_style.font_families = std::vector<std::string>(1, "Roboto");
4179 text_style.font_size = 31;
4180 text_style.letter_spacing = 0;
4181 text_style.word_spacing = 0;
4182 text_style.color = SK_ColorBLACK;
4183 text_style.height = 1;
4184 builder.PushStyle(text_style);
4185 builder.AddText(u16_text);
4186
4187 builder.Pop();
4188
4189 auto paragraph = BuildParagraph(builder);
4190 paragraph->Layout(GetTestCanvasWidth() / 2);
4191
4192 paragraph->Paint(GetCanvas(), 0, 0);
4193
4194 ASSERT_TRUE(Snapshot());
4195 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
4196 for (size_t i = 0; i < u16_text.length(); i++) {
4197 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
4198 }
4199 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
4200 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
4201 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
4202 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
4203 ASSERT_EQ(paragraph->GetLineCount(), 5ull);
4204 ASSERT_TRUE(Snapshot());
4205 }
4206
TEST_F(ParagraphTest,RepeatLayoutParagraph)4207 TEST_F(ParagraphTest, RepeatLayoutParagraph) {
4208 const char* text =
4209 "Sentence to layout at diff widths to get diff line counts. short words "
4210 "short words short words short words short words short words short words "
4211 "short words short words short words short words short words short words "
4212 "end";
4213 auto icu_text = icu::UnicodeString::fromUTF8(text);
4214 std::u16string u16_text(icu_text.getBuffer(),
4215 icu_text.getBuffer() + icu_text.length());
4216
4217 txt::ParagraphStyle paragraph_style;
4218 paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality;
4219 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4220
4221 txt::TextStyle text_style;
4222 text_style.font_families = std::vector<std::string>(1, "Roboto");
4223 text_style.font_size = 31;
4224 text_style.letter_spacing = 0;
4225 text_style.word_spacing = 0;
4226 text_style.color = SK_ColorBLACK;
4227 text_style.height = 1;
4228 builder.PushStyle(text_style);
4229 builder.AddText(u16_text);
4230
4231 builder.Pop();
4232
4233 // First Layout.
4234 auto paragraph = BuildParagraph(builder);
4235 paragraph->Layout(300);
4236
4237 paragraph->Paint(GetCanvas(), 0, 0);
4238
4239 ASSERT_TRUE(Snapshot());
4240 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
4241 for (size_t i = 0; i < u16_text.length(); i++) {
4242 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
4243 }
4244 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
4245 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
4246 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
4247 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
4248 ASSERT_EQ(paragraph->GetLineCount(), 12ull);
4249
4250 // Second Layout.
4251 SetUp();
4252 paragraph->Layout(600);
4253 paragraph->Paint(GetCanvas(), 0, 0);
4254
4255 ASSERT_TRUE(Snapshot());
4256 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
4257 for (size_t i = 0; i < u16_text.length(); i++) {
4258 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
4259 }
4260 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
4261 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
4262 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
4263 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
4264 ASSERT_EQ(paragraph->GetLineCount(), 6ull);
4265 ASSERT_TRUE(Snapshot());
4266 }
4267
TEST_F(ParagraphTest,Ellipsize)4268 TEST_F(ParagraphTest, Ellipsize) {
4269 const char* text =
4270 "This is a very long sentence to test if the text will properly wrap "
4271 "around and go to the next line. Sometimes, short sentence. Longer "
4272 "sentences are okay too because they are necessary. Very short. ";
4273 auto icu_text = icu::UnicodeString::fromUTF8(text);
4274 std::u16string u16_text(icu_text.getBuffer(),
4275 icu_text.getBuffer() + icu_text.length());
4276
4277 txt::ParagraphStyle paragraph_style;
4278 paragraph_style.ellipsis = u"\u2026";
4279 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4280
4281 txt::TextStyle text_style;
4282 text_style.font_families = std::vector<std::string>(1, "Roboto");
4283 text_style.color = SK_ColorBLACK;
4284 builder.PushStyle(text_style);
4285 builder.AddText(u16_text);
4286
4287 builder.Pop();
4288
4289 auto paragraph = BuildParagraph(builder);
4290 paragraph->Layout(GetTestCanvasWidth());
4291
4292 paragraph->Paint(GetCanvas(), 0, 0);
4293
4294 ASSERT_TRUE(Snapshot());
4295
4296 // Check that the ellipsizer limited the text to one line and did not wrap
4297 // to a second line.
4298 ASSERT_EQ(paragraph->records_.size(), 1ull);
4299 }
4300
4301 // Test for shifting when identical runs of text are built as multiple runs.
TEST_F(ParagraphTest,UnderlineShiftParagraph)4302 TEST_F(ParagraphTest, UnderlineShiftParagraph) {
4303 const char* text1 = "fluttser ";
4304 auto icu_text1 = icu::UnicodeString::fromUTF8(text1);
4305 std::u16string u16_text1(icu_text1.getBuffer(),
4306 icu_text1.getBuffer() + icu_text1.length());
4307 const char* text2 = "mdje";
4308 auto icu_text2 = icu::UnicodeString::fromUTF8(text2);
4309 std::u16string u16_text2(icu_text2.getBuffer(),
4310 icu_text2.getBuffer() + icu_text2.length());
4311 const char* text3 = "fluttser mdje";
4312 auto icu_text3 = icu::UnicodeString::fromUTF8(text3);
4313 std::u16string u16_text3(icu_text3.getBuffer(),
4314 icu_text3.getBuffer() + icu_text3.length());
4315
4316 // Construct multi-run paragraph.
4317 txt::ParagraphStyle paragraph_style;
4318 paragraph_style.max_lines = 2;
4319 paragraph_style.text_align = TextAlign::left;
4320 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4321
4322 txt::TextStyle text_style1;
4323 text_style1.color = SK_ColorBLACK;
4324 text_style1.font_families = std::vector<std::string>(1, "Roboto");
4325 builder.PushStyle(text_style1);
4326
4327 builder.AddText(u16_text1);
4328
4329 txt::TextStyle text_style2;
4330 text_style2.color = SK_ColorBLACK;
4331 text_style2.font_families = std::vector<std::string>(1, "Roboto");
4332 text_style2.decoration = TextDecoration::kUnderline;
4333 text_style2.decoration_color = SK_ColorBLACK;
4334 builder.PushStyle(text_style2);
4335
4336 builder.AddText(u16_text2);
4337
4338 builder.Pop();
4339
4340 // Construct single run paragraph.
4341 txt::ParagraphBuilderTxt builder2(paragraph_style, GetTestFontCollection());
4342
4343 builder2.PushStyle(text_style1);
4344
4345 builder2.AddText(u16_text3);
4346
4347 builder2.Pop();
4348
4349 // Build multi-run paragraph
4350 auto paragraph = BuildParagraph(builder);
4351 paragraph->Layout(GetTestCanvasWidth());
4352
4353 paragraph->Paint(GetCanvas(), 0, 0);
4354
4355 // Build single-run paragraph
4356 auto paragraph2 = BuildParagraph(builder2);
4357 paragraph2->Layout(GetTestCanvasWidth());
4358
4359 paragraph2->Paint(GetCanvas(), 0, 25);
4360
4361 ASSERT_TRUE(Snapshot());
4362
4363 ASSERT_EQ(paragraph->records_[0].GetRunWidth() +
4364 paragraph->records_[1].GetRunWidth(),
4365 paragraph2->records_[0].GetRunWidth());
4366
4367 auto rects1 =
4368 paragraph->GetRectsForRange(0, 12, Paragraph::RectHeightStyle::kMax,
4369 Paragraph::RectWidthStyle::kTight);
4370 auto rects2 =
4371 paragraph2->GetRectsForRange(0, 12, Paragraph::RectHeightStyle::kMax,
4372 Paragraph::RectWidthStyle::kTight);
4373
4374 for (size_t i = 0; i < 12; ++i) {
4375 auto r1 = GetCoordinatesForGlyphPosition(*paragraph, i);
4376 auto r2 = GetCoordinatesForGlyphPosition(*paragraph2, i);
4377
4378 ASSERT_EQ(r1.fLeft, r2.fLeft);
4379 ASSERT_EQ(r1.fRight, r2.fRight);
4380 }
4381 }
4382
TEST_F(ParagraphTest,SimpleShadow)4383 TEST_F(ParagraphTest, SimpleShadow) {
4384 const char* text = "Hello World Text Dialog";
4385 auto icu_text = icu::UnicodeString::fromUTF8(text);
4386 std::u16string u16_text(icu_text.getBuffer(),
4387 icu_text.getBuffer() + icu_text.length());
4388
4389 txt::ParagraphStyle paragraph_style;
4390 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4391
4392 txt::TextStyle text_style;
4393 text_style.font_families = std::vector<std::string>(1, "Roboto");
4394 text_style.color = SK_ColorBLACK;
4395 text_style.text_shadows.emplace_back(SK_ColorBLACK, SkPoint::Make(2.0, 2.0),
4396 1.0);
4397 builder.PushStyle(text_style);
4398 builder.AddText(u16_text);
4399
4400 builder.Pop();
4401
4402 auto paragraph = BuildParagraph(builder);
4403 paragraph->Layout(GetTestCanvasWidth());
4404 paragraph->Paint(GetCanvas(), 10.0, 15.0);
4405
4406 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
4407 for (size_t i = 0; i < u16_text.length(); i++) {
4408 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
4409 }
4410 ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
4411 ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull);
4412 ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style));
4413 ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
4414
4415 ASSERT_EQ(paragraph->records_[0].style().text_shadows.size(), 1ull);
4416 ASSERT_EQ(paragraph->records_[0].style().text_shadows[0],
4417 text_style.text_shadows[0]);
4418
4419 ASSERT_TRUE(Snapshot());
4420 }
4421
TEST_F(ParagraphTest,ComplexShadow)4422 TEST_F(ParagraphTest, ComplexShadow) {
4423 const char* text = "Text Chunk ";
4424 auto icu_text = icu::UnicodeString::fromUTF8(text);
4425 std::u16string u16_text(icu_text.getBuffer(),
4426 icu_text.getBuffer() + icu_text.length());
4427
4428 txt::ParagraphStyle paragraph_style;
4429 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4430
4431 txt::TextStyle text_style;
4432 text_style.font_families = std::vector<std::string>(1, "Roboto");
4433 text_style.color = SK_ColorBLACK;
4434 text_style.text_shadows.emplace_back(SK_ColorBLACK, SkPoint::Make(2.0, 2.0),
4435 1.0);
4436 builder.PushStyle(text_style);
4437 builder.AddText(u16_text);
4438
4439 text_style.text_shadows.emplace_back(SK_ColorRED, SkPoint::Make(2.0, 2.0),
4440 5.0);
4441 text_style.text_shadows.emplace_back(SK_ColorGREEN, SkPoint::Make(10.0, -5.0),
4442 3.0);
4443 builder.PushStyle(text_style);
4444 builder.AddText(u16_text);
4445
4446 builder.Pop();
4447 builder.AddText(u16_text);
4448
4449 text_style.text_shadows.emplace_back(SK_ColorGREEN, SkPoint::Make(0.0, -1.0),
4450 0.0);
4451 builder.PushStyle(text_style);
4452 builder.AddText(u16_text);
4453
4454 builder.Pop();
4455 builder.AddText(u16_text);
4456
4457 builder.Pop();
4458
4459 auto paragraph = BuildParagraph(builder);
4460 paragraph->Layout(GetTestCanvasWidth());
4461 paragraph->Paint(GetCanvas(), 10.0, 15.0);
4462
4463 ASSERT_EQ(paragraph->text_.size(), std::string{text}.length() * 5);
4464 for (size_t i = 0; i < u16_text.length(); i++) {
4465 ASSERT_EQ(paragraph->text_[i], u16_text[i]);
4466 }
4467
4468 ASSERT_EQ(paragraph->records_[0].style().text_shadows.size(), 1ull);
4469 ASSERT_EQ(paragraph->records_[1].style().text_shadows.size(), 3ull);
4470 ASSERT_EQ(paragraph->records_[2].style().text_shadows.size(), 1ull);
4471 ASSERT_EQ(paragraph->records_[3].style().text_shadows.size(), 4ull);
4472 ASSERT_EQ(paragraph->records_[4].style().text_shadows.size(), 1ull);
4473 for (size_t i = 0; i < 1; ++i)
4474 ASSERT_EQ(paragraph->records_[0].style().text_shadows[i],
4475 text_style.text_shadows[i]);
4476 for (size_t i = 0; i < 3; ++i)
4477 ASSERT_EQ(paragraph->records_[1].style().text_shadows[i],
4478 text_style.text_shadows[i]);
4479 for (size_t i = 0; i < 1; ++i)
4480 ASSERT_EQ(paragraph->records_[2].style().text_shadows[i],
4481 text_style.text_shadows[i]);
4482 for (size_t i = 0; i < 4; ++i)
4483 ASSERT_EQ(paragraph->records_[3].style().text_shadows[i],
4484 text_style.text_shadows[i]);
4485 for (size_t i = 0; i < 1; ++i)
4486 ASSERT_EQ(paragraph->records_[4].style().text_shadows[i],
4487 text_style.text_shadows[i]);
4488
4489 ASSERT_TRUE(Snapshot());
4490 }
4491
TEST_F(ParagraphTest,BaselineParagraph)4492 TEST_F(ParagraphTest, BaselineParagraph) {
4493 const char* text =
4494 "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育"
4495 "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得";
4496 auto icu_text = icu::UnicodeString::fromUTF8(text);
4497 std::u16string u16_text(icu_text.getBuffer(),
4498 icu_text.getBuffer() + icu_text.length());
4499
4500 txt::ParagraphStyle paragraph_style;
4501 paragraph_style.max_lines = 14;
4502 paragraph_style.text_align = TextAlign::justify;
4503 paragraph_style.height = 1.5;
4504 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4505
4506 txt::TextStyle text_style;
4507 text_style.color = SK_ColorBLACK;
4508 text_style.font_size = 55;
4509 text_style.letter_spacing = 2;
4510 text_style.font_families = std::vector<std::string>(1, "Source Han Serif CN");
4511 text_style.decoration_style = txt::TextDecorationStyle::kSolid;
4512 text_style.decoration_color = SK_ColorBLACK;
4513 builder.PushStyle(text_style);
4514
4515 builder.AddText(u16_text);
4516
4517 builder.Pop();
4518
4519 auto paragraph = BuildParagraph(builder);
4520 paragraph->Layout(GetTestCanvasWidth() - 100);
4521
4522 paragraph->Paint(GetCanvas(), 0, 0);
4523
4524 SkPaint paint;
4525 paint.setStyle(SkPaint::kStroke_Style);
4526 paint.setAntiAlias(true);
4527 paint.setStrokeWidth(1);
4528 paint.setColor(SK_ColorRED);
4529 GetCanvas()->drawLine(0, paragraph->GetIdeographicBaseline(),
4530 paragraph->GetMaxWidth(),
4531 paragraph->GetIdeographicBaseline(), paint);
4532
4533 paint.setColor(SK_ColorGREEN);
4534
4535 GetCanvas()->drawLine(0, paragraph->GetAlphabeticBaseline(),
4536 paragraph->GetMaxWidth(),
4537 paragraph->GetAlphabeticBaseline(), paint);
4538 ASSERT_DOUBLE_EQ(paragraph->GetIdeographicBaseline(), 79.035000801086426);
4539 ASSERT_DOUBLE_EQ(paragraph->GetAlphabeticBaseline(), 63.305000305175781);
4540
4541 ASSERT_TRUE(Snapshot());
4542 }
4543
TEST_F(ParagraphTest,FontFallbackParagraph)4544 TEST_F(ParagraphTest, FontFallbackParagraph) {
4545 const char* text = "Roboto 字典 ";
4546 auto icu_text = icu::UnicodeString::fromUTF8(text);
4547 std::u16string u16_text(icu_text.getBuffer(),
4548 icu_text.getBuffer() + icu_text.length());
4549 const char* text2 = "Homemade Apple 字典";
4550 icu_text = icu::UnicodeString::fromUTF8(text2);
4551 std::u16string u16_text2(icu_text.getBuffer(),
4552 icu_text.getBuffer() + icu_text.length());
4553 const char* text3 = "Chinese 字典";
4554 icu_text = icu::UnicodeString::fromUTF8(text3);
4555 std::u16string u16_text3(icu_text.getBuffer(),
4556 icu_text.getBuffer() + icu_text.length());
4557
4558 txt::ParagraphStyle paragraph_style;
4559 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4560
4561 txt::TextStyle text_style;
4562 // No chinese fallback provided, should not be able to render the chinese.
4563 text_style.font_families = std::vector<std::string>(1, "Not a real font");
4564 text_style.font_families.push_back("Also a fake font");
4565 text_style.font_families.push_back("So fake it is obvious");
4566 text_style.font_families.push_back("Next one should be a real font...");
4567 text_style.font_families.push_back("Roboto");
4568 text_style.font_families.push_back("another fake one in between");
4569 text_style.font_families.push_back("Homemade Apple");
4570 text_style.color = SK_ColorBLACK;
4571 builder.PushStyle(text_style);
4572 builder.AddText(u16_text);
4573
4574 // Japanese version of the chinese should be rendered.
4575 text_style.font_families = std::vector<std::string>(1, "Not a real font");
4576 text_style.font_families.push_back("Also a fake font");
4577 text_style.font_families.push_back("So fake it is obvious");
4578 text_style.font_families.push_back("Homemade Apple");
4579 text_style.font_families.push_back("Next one should be a real font...");
4580 text_style.font_families.push_back("Roboto");
4581 text_style.font_families.push_back("another fake one in between");
4582 text_style.font_families.push_back("Noto Sans CJK JP");
4583 text_style.font_families.push_back("Source Han Serif CN");
4584 text_style.color = SK_ColorBLACK;
4585 builder.PushStyle(text_style);
4586 builder.AddText(u16_text2);
4587
4588 // Chinese font defiend first
4589 text_style.font_families = std::vector<std::string>(1, "Not a real font");
4590 text_style.font_families.push_back("Also a fake font");
4591 text_style.font_families.push_back("So fake it is obvious");
4592 text_style.font_families.push_back("Homemade Apple");
4593 text_style.font_families.push_back("Next one should be a real font...");
4594 text_style.font_families.push_back("Roboto");
4595 text_style.font_families.push_back("another fake one in between");
4596 text_style.font_families.push_back("Source Han Serif CN");
4597 text_style.font_families.push_back("Noto Sans CJK JP");
4598 text_style.color = SK_ColorBLACK;
4599 builder.PushStyle(text_style);
4600 builder.AddText(u16_text3);
4601
4602 builder.Pop();
4603
4604 auto paragraph = BuildParagraph(builder);
4605 paragraph->Layout(GetTestCanvasWidth());
4606
4607 paragraph->Paint(GetCanvas(), 10.0, 15.0);
4608
4609 ASSERT_TRUE(Snapshot());
4610
4611 ASSERT_EQ(paragraph->records_.size(), 5ull);
4612 ASSERT_DOUBLE_EQ(paragraph->records_[0].GetRunWidth(), 64.19921875);
4613 ASSERT_DOUBLE_EQ(paragraph->records_[1].GetRunWidth(), 139.1171875);
4614 ASSERT_DOUBLE_EQ(paragraph->records_[2].GetRunWidth(), 28);
4615 ASSERT_DOUBLE_EQ(paragraph->records_[3].GetRunWidth(), 62.24609375);
4616 ASSERT_DOUBLE_EQ(paragraph->records_[4].GetRunWidth(), 28);
4617 // When a different font is resolved, then the metrics are different.
4618 ASSERT_TRUE(paragraph->records_[2].metrics().fTop -
4619 paragraph->records_[4].metrics().fTop !=
4620 0);
4621 ASSERT_TRUE(paragraph->records_[2].metrics().fAscent -
4622 paragraph->records_[4].metrics().fAscent !=
4623 0);
4624 ASSERT_TRUE(paragraph->records_[2].metrics().fDescent -
4625 paragraph->records_[4].metrics().fDescent !=
4626 0);
4627 ASSERT_TRUE(paragraph->records_[2].metrics().fBottom -
4628 paragraph->records_[4].metrics().fBottom !=
4629 0);
4630 ASSERT_TRUE(paragraph->records_[2].metrics().fAvgCharWidth -
4631 paragraph->records_[4].metrics().fAvgCharWidth !=
4632 0);
4633 }
4634
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (StrutParagraph1))4635 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutParagraph1)) {
4636 // The chinese extra height should be absorbed by the strut.
4637 const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可";
4638 auto icu_text = icu::UnicodeString::fromUTF8(text);
4639 std::u16string u16_text(icu_text.getBuffer(),
4640 icu_text.getBuffer() + icu_text.length());
4641
4642 txt::ParagraphStyle paragraph_style;
4643 paragraph_style.max_lines = 10;
4644 paragraph_style.strut_font_families = std::vector<std::string>(1, "BlahFake");
4645 paragraph_style.strut_font_families.push_back("ahem");
4646 paragraph_style.strut_font_size = 50;
4647 paragraph_style.strut_height = 1.8;
4648 paragraph_style.strut_has_height_override = true;
4649 paragraph_style.strut_leading = 0.1;
4650 paragraph_style.strut_enabled = true;
4651
4652 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4653
4654 txt::TextStyle text_style;
4655 text_style.font_families = std::vector<std::string>(1, "ahem");
4656 text_style.font_families.push_back("ahem");
4657 text_style.font_size = 50;
4658 text_style.letter_spacing = 0;
4659 text_style.font_weight = FontWeight::w500;
4660 text_style.word_spacing = 0;
4661 text_style.color = SK_ColorBLACK;
4662 text_style.height = .5;
4663 builder.PushStyle(text_style);
4664
4665 builder.AddText(u16_text);
4666
4667 builder.Pop();
4668
4669 auto paragraph = BuildParagraph(builder);
4670 paragraph->Layout(550);
4671
4672 paragraph->Paint(GetCanvas(), 0, 0);
4673
4674 SkPaint paint;
4675 paint.setStyle(SkPaint::kStroke_Style);
4676 paint.setAntiAlias(true);
4677 paint.setStrokeWidth(1);
4678
4679 // Tests for GetRectsForRange()
4680 Paragraph::RectHeightStyle rect_height_style =
4681 Paragraph::RectHeightStyle::kTight;
4682 Paragraph::RectHeightStyle rect_height_max_style =
4683 Paragraph::RectHeightStyle::kMax;
4684 Paragraph::RectWidthStyle rect_width_style =
4685 Paragraph::RectWidthStyle::kTight;
4686 paint.setColor(SK_ColorRED);
4687 std::vector<txt::Paragraph::TextBox> boxes =
4688 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
4689 for (size_t i = 0; i < boxes.size(); ++i) {
4690 GetCanvas()->drawRect(boxes[i].rect, paint);
4691 }
4692 EXPECT_EQ(boxes.size(), 0ull);
4693
4694 boxes =
4695 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
4696 for (size_t i = 0; i < boxes.size(); ++i) {
4697 GetCanvas()->drawRect(boxes[i].rect, paint);
4698 }
4699 EXPECT_EQ(boxes.size(), 1ull);
4700 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4701 EXPECT_NEAR(boxes[0].rect.top(), 34.5, 0.0001);
4702 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50);
4703 EXPECT_NEAR(boxes[0].rect.bottom(), 84.5, 0.0001);
4704
4705 boxes = paragraph->GetRectsForRange(0, 1, rect_height_max_style,
4706 rect_width_style);
4707 for (size_t i = 0; i < boxes.size(); ++i) {
4708 GetCanvas()->drawRect(boxes[i].rect, paint);
4709 }
4710 EXPECT_EQ(boxes.size(), 1ull);
4711 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4712 EXPECT_NEAR(boxes[0].rect.top(), 34.5, 0.0001);
4713 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50);
4714 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 95);
4715
4716 boxes =
4717 paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style);
4718 for (size_t i = 0; i < boxes.size(); ++i) {
4719 GetCanvas()->drawRect(boxes[i].rect, paint);
4720 }
4721 EXPECT_EQ(boxes.size(), 1ull);
4722 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300);
4723 EXPECT_NEAR(boxes[0].rect.top(), 34.5, 0.0001);
4724 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500);
4725 EXPECT_NEAR(boxes[0].rect.bottom(), 84.5, 0.0001);
4726 ;
4727
4728 boxes = paragraph->GetRectsForRange(6, 10, rect_height_max_style,
4729 rect_width_style);
4730 for (size_t i = 0; i < boxes.size(); ++i) {
4731 GetCanvas()->drawRect(boxes[i].rect, paint);
4732 }
4733 EXPECT_EQ(boxes.size(), 1ull);
4734 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300);
4735 EXPECT_NEAR(boxes[0].rect.top(), 34.5, 0.0001);
4736 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500);
4737 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 95);
4738
4739 boxes = paragraph->GetRectsForRange(14, 16, rect_height_max_style,
4740 rect_width_style);
4741 for (size_t i = 0; i < boxes.size(); ++i) {
4742 GetCanvas()->drawRect(boxes[i].rect, paint);
4743 }
4744 EXPECT_EQ(boxes.size(), 1ull);
4745 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4746 EXPECT_NEAR(boxes[0].rect.top(), 224.5, 0.0001);
4747 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 100);
4748 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 285);
4749
4750 boxes = paragraph->GetRectsForRange(20, 25, rect_height_max_style,
4751 rect_width_style);
4752 for (size_t i = 0; i < boxes.size(); ++i) {
4753 GetCanvas()->drawRect(boxes[i].rect, paint);
4754 }
4755 EXPECT_EQ(boxes.size(), 1ull);
4756 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 50);
4757 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 319.5);
4758 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 300);
4759 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 380);
4760
4761 ASSERT_TRUE(Snapshot());
4762 }
4763
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (StrutParagraph2))4764 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutParagraph2)) {
4765 // This string is all one size and smaller than the strut metrics.
4766 const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH";
4767 auto icu_text = icu::UnicodeString::fromUTF8(text);
4768 std::u16string u16_text(icu_text.getBuffer(),
4769 icu_text.getBuffer() + icu_text.length());
4770
4771 txt::ParagraphStyle paragraph_style;
4772 paragraph_style.max_lines = 10;
4773 paragraph_style.strut_font_families = std::vector<std::string>(1, "ahem");
4774 paragraph_style.strut_font_size = 50;
4775 paragraph_style.strut_height = 1.6;
4776 paragraph_style.strut_has_height_override = true;
4777 paragraph_style.strut_enabled = true;
4778 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4779
4780 txt::TextStyle text_style;
4781 text_style.font_families = std::vector<std::string>(1, "ahem");
4782 text_style.font_families.push_back("ahem");
4783 text_style.font_size = 50;
4784 text_style.letter_spacing = 0;
4785 text_style.font_weight = FontWeight::w500;
4786 text_style.word_spacing = 0;
4787 text_style.color = SK_ColorBLACK;
4788 text_style.height = 1;
4789 builder.PushStyle(text_style);
4790
4791 builder.AddText(u16_text);
4792
4793 builder.Pop();
4794
4795 auto paragraph = BuildParagraph(builder);
4796 paragraph->Layout(550);
4797
4798 paragraph->Paint(GetCanvas(), 0, 0);
4799
4800 SkPaint paint;
4801 paint.setStyle(SkPaint::kStroke_Style);
4802 paint.setAntiAlias(true);
4803 paint.setStrokeWidth(1);
4804
4805 // Tests for GetRectsForRange()
4806 Paragraph::RectHeightStyle rect_height_style =
4807 Paragraph::RectHeightStyle::kTight;
4808 Paragraph::RectHeightStyle rect_height_max_style =
4809 Paragraph::RectHeightStyle::kMax;
4810 Paragraph::RectWidthStyle rect_width_style =
4811 Paragraph::RectWidthStyle::kTight;
4812 paint.setColor(SK_ColorRED);
4813 std::vector<txt::Paragraph::TextBox> boxes =
4814 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
4815 for (size_t i = 0; i < boxes.size(); ++i) {
4816 GetCanvas()->drawRect(boxes[i].rect, paint);
4817 }
4818 EXPECT_EQ(boxes.size(), 0ull);
4819
4820 boxes =
4821 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
4822 for (size_t i = 0; i < boxes.size(); ++i) {
4823 GetCanvas()->drawRect(boxes[i].rect, paint);
4824 }
4825 EXPECT_EQ(boxes.size(), 1ull);
4826 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4827 EXPECT_NEAR(boxes[0].rect.top(), 24, 0.0001);
4828 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50);
4829 EXPECT_NEAR(boxes[0].rect.bottom(), 74, 0.0001);
4830
4831 boxes = paragraph->GetRectsForRange(0, 1, rect_height_max_style,
4832 rect_width_style);
4833 for (size_t i = 0; i < boxes.size(); ++i) {
4834 GetCanvas()->drawRect(boxes[i].rect, paint);
4835 }
4836 EXPECT_EQ(boxes.size(), 1ull);
4837 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4838 EXPECT_NEAR(boxes[0].rect.top(), 24, 0.0001);
4839 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50);
4840 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80);
4841
4842 boxes =
4843 paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style);
4844 for (size_t i = 0; i < boxes.size(); ++i) {
4845 GetCanvas()->drawRect(boxes[i].rect, paint);
4846 }
4847 EXPECT_EQ(boxes.size(), 1ull);
4848 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300);
4849 EXPECT_NEAR(boxes[0].rect.top(), 24, 0.0001);
4850 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500);
4851 EXPECT_NEAR(boxes[0].rect.bottom(), 74, 0.0001);
4852
4853 boxes = paragraph->GetRectsForRange(6, 10, rect_height_max_style,
4854 rect_width_style);
4855 for (size_t i = 0; i < boxes.size(); ++i) {
4856 GetCanvas()->drawRect(boxes[i].rect, paint);
4857 }
4858 EXPECT_EQ(boxes.size(), 1ull);
4859 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300);
4860 EXPECT_NEAR(boxes[0].rect.top(), 24, 0.0001);
4861 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500);
4862 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80);
4863
4864 boxes = paragraph->GetRectsForRange(14, 16, rect_height_max_style,
4865 rect_width_style);
4866 for (size_t i = 0; i < boxes.size(); ++i) {
4867 GetCanvas()->drawRect(boxes[i].rect, paint);
4868 }
4869 EXPECT_EQ(boxes.size(), 1ull);
4870 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4871 EXPECT_NEAR(boxes[0].rect.top(), 184, 0.0001);
4872 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 100);
4873 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 240);
4874
4875 boxes = paragraph->GetRectsForRange(20, 25, rect_height_max_style,
4876 rect_width_style);
4877 for (size_t i = 0; i < boxes.size(); ++i) {
4878 GetCanvas()->drawRect(boxes[i].rect, paint);
4879 }
4880 EXPECT_EQ(boxes.size(), 1ull);
4881 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 50);
4882 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 264);
4883 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 300);
4884 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 320);
4885
4886 ASSERT_TRUE(Snapshot());
4887 }
4888
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (StrutParagraph3))4889 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutParagraph3)) {
4890 // The strut is too small to absorb the extra chinese height, but the english
4891 // second line height is increased due to strut.
4892 const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可";
4893 auto icu_text = icu::UnicodeString::fromUTF8(text);
4894 std::u16string u16_text(icu_text.getBuffer(),
4895 icu_text.getBuffer() + icu_text.length());
4896
4897 txt::ParagraphStyle paragraph_style;
4898 paragraph_style.max_lines = 10;
4899 paragraph_style.strut_font_families = std::vector<std::string>(1, "ahem");
4900 paragraph_style.strut_font_size = 50;
4901 paragraph_style.strut_height = 1.2;
4902 paragraph_style.strut_has_height_override = true;
4903 paragraph_style.strut_enabled = true;
4904 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
4905
4906 txt::TextStyle text_style;
4907 text_style.font_families = std::vector<std::string>(1, "ahem");
4908 text_style.font_families.push_back("ahem");
4909 text_style.font_size = 50;
4910 text_style.letter_spacing = 0;
4911 text_style.font_weight = FontWeight::w500;
4912 text_style.word_spacing = 0;
4913 text_style.color = SK_ColorBLACK;
4914 text_style.height = 1;
4915 builder.PushStyle(text_style);
4916
4917 builder.AddText(u16_text);
4918
4919 builder.Pop();
4920
4921 auto paragraph = BuildParagraph(builder);
4922 paragraph->Layout(550);
4923
4924 paragraph->Paint(GetCanvas(), 0, 0);
4925
4926 SkPaint paint;
4927 paint.setStyle(SkPaint::kStroke_Style);
4928 paint.setAntiAlias(true);
4929 paint.setStrokeWidth(1);
4930
4931 // Tests for GetRectsForRange()
4932 Paragraph::RectHeightStyle rect_height_style =
4933 Paragraph::RectHeightStyle::kTight;
4934 Paragraph::RectHeightStyle rect_height_max_style =
4935 Paragraph::RectHeightStyle::kMax;
4936 Paragraph::RectWidthStyle rect_width_style =
4937 Paragraph::RectWidthStyle::kTight;
4938 paint.setColor(SK_ColorRED);
4939 std::vector<txt::Paragraph::TextBox> boxes =
4940 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
4941 for (size_t i = 0; i < boxes.size(); ++i) {
4942 GetCanvas()->drawRect(boxes[i].rect, paint);
4943 }
4944 EXPECT_EQ(boxes.size(), 0ull);
4945
4946 boxes =
4947 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
4948 for (size_t i = 0; i < boxes.size(); ++i) {
4949 GetCanvas()->drawRect(boxes[i].rect, paint);
4950 }
4951 EXPECT_EQ(boxes.size(), 1ull);
4952 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4953 EXPECT_NEAR(boxes[0].rect.top(), 8, 0.0001);
4954 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50);
4955 EXPECT_NEAR(boxes[0].rect.bottom(), 58, 0.0001);
4956
4957 boxes = paragraph->GetRectsForRange(0, 1, rect_height_max_style,
4958 rect_width_style);
4959 for (size_t i = 0; i < boxes.size(); ++i) {
4960 GetCanvas()->drawRect(boxes[i].rect, paint);
4961 }
4962 EXPECT_EQ(boxes.size(), 1ull);
4963 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4964 EXPECT_NEAR(boxes[0].rect.top(), 8, 0.0001);
4965 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50);
4966 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 60);
4967
4968 boxes =
4969 paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style);
4970 for (size_t i = 0; i < boxes.size(); ++i) {
4971 GetCanvas()->drawRect(boxes[i].rect, paint);
4972 }
4973 EXPECT_EQ(boxes.size(), 1ull);
4974 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300);
4975 EXPECT_NEAR(boxes[0].rect.top(), 8, 0.0001);
4976 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500);
4977 EXPECT_NEAR(boxes[0].rect.bottom(), 58, 0.0001);
4978
4979 boxes = paragraph->GetRectsForRange(6, 10, rect_height_max_style,
4980 rect_width_style);
4981 for (size_t i = 0; i < boxes.size(); ++i) {
4982 GetCanvas()->drawRect(boxes[i].rect, paint);
4983 }
4984 EXPECT_EQ(boxes.size(), 1ull);
4985 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300);
4986 EXPECT_NEAR(boxes[0].rect.top(), 8, 0.0001);
4987 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500);
4988 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 60);
4989
4990 boxes = paragraph->GetRectsForRange(14, 16, rect_height_max_style,
4991 rect_width_style);
4992 for (size_t i = 0; i < boxes.size(); ++i) {
4993 GetCanvas()->drawRect(boxes[i].rect, paint);
4994 }
4995 EXPECT_EQ(boxes.size(), 1ull);
4996 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
4997 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 128);
4998 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 100);
4999 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 180);
5000
5001 boxes = paragraph->GetRectsForRange(20, 25, rect_height_max_style,
5002 rect_width_style);
5003 for (size_t i = 0; i < boxes.size(); ++i) {
5004 GetCanvas()->drawRect(boxes[i].rect, paint);
5005 }
5006 EXPECT_EQ(boxes.size(), 1ull);
5007 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 50);
5008 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 188);
5009 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 300);
5010 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 240);
5011
5012 ASSERT_TRUE(Snapshot());
5013 }
5014
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (StrutForceParagraph))5015 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutForceParagraph)) {
5016 // The strut is too small to absorb the extra chinese height, but the english
5017 // second line height is increased due to strut.
5018 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
5019 auto icu_text = icu::UnicodeString::fromUTF8(text);
5020 std::u16string u16_text(icu_text.getBuffer(),
5021 icu_text.getBuffer() + icu_text.length());
5022
5023 txt::ParagraphStyle paragraph_style;
5024 paragraph_style.max_lines = 10;
5025 paragraph_style.strut_font_families = std::vector<std::string>(1, "ahem");
5026 paragraph_style.strut_font_size = 50;
5027 paragraph_style.strut_height = 1.5;
5028 paragraph_style.strut_has_height_override = true;
5029 paragraph_style.strut_leading = 0.1;
5030 paragraph_style.force_strut_height = true;
5031 paragraph_style.strut_enabled = true;
5032 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
5033
5034 txt::TextStyle text_style;
5035 text_style.font_families = std::vector<std::string>(1, "ahem");
5036 text_style.font_families.push_back("ahem");
5037 text_style.font_size = 50;
5038 text_style.letter_spacing = 0;
5039 text_style.word_spacing = 0;
5040 text_style.color = SK_ColorBLACK;
5041 text_style.height = 1;
5042 builder.PushStyle(text_style);
5043
5044 builder.AddText(u16_text);
5045
5046 builder.Pop();
5047
5048 auto paragraph = BuildParagraph(builder);
5049 paragraph->Layout(550);
5050
5051 paragraph->Paint(GetCanvas(), 0, 0);
5052
5053 SkPaint paint;
5054 paint.setStyle(SkPaint::kStroke_Style);
5055 paint.setAntiAlias(true);
5056 paint.setStrokeWidth(1);
5057
5058 // Tests for GetRectsForRange()
5059 Paragraph::RectHeightStyle rect_height_style =
5060 Paragraph::RectHeightStyle::kTight;
5061 Paragraph::RectHeightStyle rect_height_max_style =
5062 Paragraph::RectHeightStyle::kMax;
5063 Paragraph::RectWidthStyle rect_width_style =
5064 Paragraph::RectWidthStyle::kTight;
5065 paint.setColor(SK_ColorRED);
5066 std::vector<txt::Paragraph::TextBox> boxes =
5067 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
5068 for (size_t i = 0; i < boxes.size(); ++i) {
5069 GetCanvas()->drawRect(boxes[i].rect, paint);
5070 }
5071 EXPECT_EQ(boxes.size(), 0ull);
5072
5073 boxes =
5074 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
5075 for (size_t i = 0; i < boxes.size(); ++i) {
5076 GetCanvas()->drawRect(boxes[i].rect, paint);
5077 }
5078 EXPECT_EQ(boxes.size(), 1ull);
5079 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
5080 EXPECT_NEAR(boxes[0].rect.top(), 22.5, 0.0001);
5081 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50);
5082 EXPECT_NEAR(boxes[0].rect.bottom(), 72.5, 0.0001);
5083
5084 boxes = paragraph->GetRectsForRange(0, 1, rect_height_max_style,
5085 rect_width_style);
5086 for (size_t i = 0; i < boxes.size(); ++i) {
5087 GetCanvas()->drawRect(boxes[i].rect, paint);
5088 }
5089 EXPECT_EQ(boxes.size(), 1ull);
5090 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
5091 EXPECT_NEAR(boxes[0].rect.top(), 22.5, 0.0001);
5092 ;
5093 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50);
5094 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80);
5095
5096 boxes =
5097 paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style);
5098 for (size_t i = 0; i < boxes.size(); ++i) {
5099 GetCanvas()->drawRect(boxes[i].rect, paint);
5100 }
5101 EXPECT_EQ(boxes.size(), 1ull);
5102 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300);
5103 EXPECT_NEAR(boxes[0].rect.top(), 22.5, 0.0001);
5104 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500);
5105 EXPECT_NEAR(boxes[0].rect.bottom(), 72.5, 0.0001);
5106
5107 boxes = paragraph->GetRectsForRange(6, 10, rect_height_max_style,
5108 rect_width_style);
5109 for (size_t i = 0; i < boxes.size(); ++i) {
5110 GetCanvas()->drawRect(boxes[i].rect, paint);
5111 }
5112 EXPECT_EQ(boxes.size(), 1ull);
5113 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300);
5114 EXPECT_NEAR(boxes[0].rect.top(), 22.5, 0.0001);
5115 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500);
5116 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80);
5117
5118 boxes = paragraph->GetRectsForRange(14, 16, rect_height_max_style,
5119 rect_width_style);
5120 for (size_t i = 0; i < boxes.size(); ++i) {
5121 GetCanvas()->drawRect(boxes[i].rect, paint);
5122 }
5123 EXPECT_EQ(boxes.size(), 1ull);
5124 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
5125 EXPECT_NEAR(boxes[0].rect.top(), 182.5, 0.0001);
5126 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 100);
5127 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 240);
5128
5129 boxes = paragraph->GetRectsForRange(20, 25, rect_height_max_style,
5130 rect_width_style);
5131 for (size_t i = 0; i < boxes.size(); ++i) {
5132 GetCanvas()->drawRect(boxes[i].rect, paint);
5133 }
5134 EXPECT_EQ(boxes.size(), 1ull);
5135 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 50);
5136 EXPECT_FLOAT_EQ(boxes[0].rect.top(), 262.5);
5137 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 300);
5138 EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 320);
5139
5140 ASSERT_TRUE(Snapshot());
5141 }
5142
5143 // The height override is disabled for this test. Direct metrics from the font.
TEST_F(ParagraphTest,DISABLE_ON_WINDOWS (StrutDefaultParagraph))5144 TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutDefaultParagraph)) {
5145 const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可";
5146 auto icu_text = icu::UnicodeString::fromUTF8(text);
5147 std::u16string u16_text(icu_text.getBuffer(),
5148 icu_text.getBuffer() + icu_text.length());
5149
5150 txt::ParagraphStyle paragraph_style;
5151 paragraph_style.max_lines = 10;
5152 paragraph_style.strut_font_families = std::vector<std::string>(1, "ahem");
5153 paragraph_style.strut_font_size = 50;
5154 paragraph_style.strut_height = 1.5;
5155 paragraph_style.strut_leading = 0.1;
5156 paragraph_style.force_strut_height = false;
5157 paragraph_style.strut_enabled = true;
5158 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
5159
5160 txt::TextStyle text_style;
5161 text_style.font_families = std::vector<std::string>(1, "ahem");
5162 text_style.font_families.push_back("ahem");
5163 text_style.font_size = 20;
5164 text_style.letter_spacing = 0;
5165 text_style.word_spacing = 0;
5166 text_style.color = SK_ColorBLACK;
5167 text_style.height = 1;
5168 builder.PushStyle(text_style);
5169
5170 builder.AddText(u16_text);
5171
5172 builder.Pop();
5173
5174 auto paragraph = BuildParagraph(builder);
5175 paragraph->Layout(550);
5176
5177 paragraph->Paint(GetCanvas(), 0, 0);
5178
5179 SkPaint paint;
5180 paint.setStyle(SkPaint::kStroke_Style);
5181 paint.setAntiAlias(true);
5182 paint.setStrokeWidth(1);
5183
5184 // Tests for GetRectsForRange()
5185 Paragraph::RectHeightStyle rect_height_style =
5186 Paragraph::RectHeightStyle::kTight;
5187 Paragraph::RectHeightStyle rect_height_strut_style =
5188 Paragraph::RectHeightStyle::kStrut;
5189 Paragraph::RectWidthStyle rect_width_style =
5190 Paragraph::RectWidthStyle::kTight;
5191 paint.setColor(SK_ColorRED);
5192 std::vector<txt::Paragraph::TextBox> boxes =
5193 paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
5194 for (size_t i = 0; i < boxes.size(); ++i) {
5195 GetCanvas()->drawRect(boxes[i].rect, paint);
5196 }
5197 EXPECT_EQ(boxes.size(), 0ull);
5198
5199 boxes =
5200 paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
5201 for (size_t i = 0; i < boxes.size(); ++i) {
5202 GetCanvas()->drawRect(boxes[i].rect, paint);
5203 }
5204 EXPECT_EQ(boxes.size(), 1ull);
5205 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
5206 EXPECT_NEAR(boxes[0].rect.top(), 26.5, 0.0001);
5207 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 20);
5208 EXPECT_NEAR(boxes[0].rect.bottom(), 46.5, 0.0001);
5209
5210 boxes = paragraph->GetRectsForRange(0, 2, rect_height_strut_style,
5211 rect_width_style);
5212 for (size_t i = 0; i < boxes.size(); ++i) {
5213 GetCanvas()->drawRect(boxes[i].rect, paint);
5214 }
5215 EXPECT_EQ(boxes.size(), 1ull);
5216 EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0);
5217 EXPECT_NEAR(boxes[0].rect.top(), 2.5, 0.0001);
5218 EXPECT_FLOAT_EQ(boxes[0].rect.right(), 40);
5219 EXPECT_NEAR(boxes[0].rect.bottom(), 52.5, 0.0001);
5220
5221 ASSERT_TRUE(Snapshot());
5222 }
5223
TEST_F(ParagraphTest,FontFeaturesParagraph)5224 TEST_F(ParagraphTest, FontFeaturesParagraph) {
5225 const char* text = "12ab\n";
5226 auto icu_text = icu::UnicodeString::fromUTF8(text);
5227 std::u16string u16_text(icu_text.getBuffer(),
5228 icu_text.getBuffer() + icu_text.length());
5229
5230 txt::ParagraphStyle paragraph_style;
5231 txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection());
5232
5233 txt::TextStyle text_style;
5234 text_style.font_families = std::vector<std::string>(1, "Roboto");
5235 text_style.color = SK_ColorBLACK;
5236 text_style.font_features.SetFeature("tnum", 1);
5237 builder.PushStyle(text_style);
5238 builder.AddText(u16_text);
5239
5240 text_style.font_features.SetFeature("tnum", 0);
5241 text_style.font_features.SetFeature("pnum", 1);
5242 builder.PushStyle(text_style);
5243 builder.AddText(u16_text);
5244
5245 builder.Pop();
5246 builder.Pop();
5247
5248 auto paragraph = BuildParagraph(builder);
5249 paragraph->Layout(GetTestCanvasWidth());
5250
5251 paragraph->Paint(GetCanvas(), 10.0, 15.0);
5252
5253 ASSERT_EQ(paragraph->glyph_lines_.size(), 3ull);
5254
5255 // Tabular numbers should have equal widths.
5256 const txt::ParagraphTxt::GlyphLine& tnum_line = paragraph->glyph_lines_[0];
5257 ASSERT_EQ(tnum_line.positions.size(), 4ull);
5258 EXPECT_FLOAT_EQ(tnum_line.positions[0].x_pos.width(),
5259 tnum_line.positions[1].x_pos.width());
5260
5261 // Proportional numbers should have variable widths.
5262 const txt::ParagraphTxt::GlyphLine& pnum_line = paragraph->glyph_lines_[1];
5263 ASSERT_EQ(pnum_line.positions.size(), 4ull);
5264 EXPECT_NE(pnum_line.positions[0].x_pos.width(),
5265 pnum_line.positions[1].x_pos.width());
5266
5267 // Alphabetic characters should be unaffected.
5268 EXPECT_FLOAT_EQ(tnum_line.positions[2].x_pos.width(),
5269 pnum_line.positions[2].x_pos.width());
5270
5271 ASSERT_TRUE(Snapshot());
5272 }
5273
5274 } // namespace txt
5275