| /* |
| * Copyright 2017 Google, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <cstring> |
| #include <iostream> |
| |
| #include "flutter/fml/logging.h" |
| #include "render_test.h" |
| #include "third_party/icu/source/common/unicode/unistr.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| #include "third_party/skia/include/core/SkPath.h" |
| #include "txt/font_style.h" |
| #include "txt/font_weight.h" |
| #include "txt/paragraph_builder_txt.h" |
| #include "txt/paragraph_txt.h" |
| #include "txt/placeholder_run.h" |
| #include "txt_test_utils.h" |
| |
| #define DISABLE_ON_WINDOWS(TEST) DISABLE_TEST_WINDOWS(TEST) |
| #define DISABLE_ON_MAC(TEST) DISABLE_TEST_MAC(TEST) |
| |
| namespace txt { |
| |
| using ParagraphTest = RenderTest; |
| |
| TEST_F(ParagraphTest, SimpleParagraph) { |
| const char* text = "Hello World Text Dialog"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| // We must supply a font here, as the default is Arial, and we do not |
| // include Arial in our test fonts as it is proprietary. We want it to |
| // be Arial default though as it is one of the most common fonts on host |
| // platforms. On real devices/apps, Arial should be able to be resolved. |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, SimpleParagraphSmall) { |
| const char* text = |
| "Hello World Text Dialog. This is a very small text in order to check " |
| "for constant advance additions that are only visible when the advance " |
| "of the glyphs are small."; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_size = 6; |
| // We must supply a font here, as the default is Arial, and we do not |
| // include Arial in our test fonts as it is proprietary. We want it to |
| // be Arial default though as it is one of the most common fonts on host |
| // platforms. On real devices/apps, Arial should be able to be resolved. |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| // It is possible for the line_metrics_ vector in paragraph to have an empty |
| // line at the end as a result of the line breaking algorithm. This causes |
| // the final_line_count_ to be one less than line metrics. This tests that we |
| // properly handle this case and do not segfault. |
| TEST_F(ParagraphTest, GetGlyphPositionAtCoordinateSegfault) { |
| const char* text = "Hello World\nText Dialog"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| // We must supply a font here, as the default is Arial, and we do not |
| // include Arial in our test fonts as it is proprietary. We want it to |
| // be Arial default though as it is one of the most common fonts on host |
| // platforms. On real devices/apps, Arial should be able to be resolved. |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->final_line_count_, paragraph->line_metrics_.size()); |
| ASSERT_EQ(paragraph->final_line_count_, 2ull); |
| ASSERT_EQ(paragraph->GetLineCount(), 2ull); |
| |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0.2, 0.2).position, 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(20.2, 0.2).position, 3ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0.2, 20.2).position, 12ull); |
| |
| // We artificially reproduce the conditions that cause segfaults in very |
| // specific circumstances in the wild. By adding this empty un-laid-out |
| // LineMetrics at the end, we force the case where final_line_count_ |
| // represents the true number of lines whereas line_metrics_ has one |
| // extra empty one. |
| paragraph->line_metrics_.emplace_back(23, 24, 24, 24, true); |
| |
| ASSERT_EQ(paragraph->final_line_count_, paragraph->line_metrics_.size() - 1); |
| ASSERT_EQ(paragraph->final_line_count_, 2ull); |
| ASSERT_EQ(paragraph->GetLineCount(), 2ull); |
| |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0.2, 20.2).position, 12ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0.2, 0.2).position, 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(20.2, 0.2).position, 3ull); |
| |
| paragraph->line_metrics_.emplace_back(24, 25, 25, 25, true); |
| |
| ASSERT_EQ(paragraph->final_line_count_, paragraph->line_metrics_.size() - 2); |
| ASSERT_EQ(paragraph->final_line_count_, 2ull); |
| ASSERT_EQ(paragraph->GetLineCount(), 2ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| // Check that GetGlyphPositionAtCoordinate computes correct text positions for |
| // a paragraph containing multiple styled runs. |
| TEST_F(ParagraphTest, GetGlyphPositionAtCoordinateMultiRun) { |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Ahem"); |
| text_style.color = SK_ColorBLACK; |
| text_style.font_size = 10; |
| builder.PushStyle(text_style); |
| builder.AddText(u"A"); |
| text_style.font_size = 20; |
| builder.PushStyle(text_style); |
| builder.AddText(u"B"); |
| text_style.font_size = 30; |
| builder.PushStyle(text_style); |
| builder.AddText(u"C"); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(2.0, 5.0).position, 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(12.0, 5.0).position, 1ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(32.0, 5.0).position, 2ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, LineMetricsParagraph1) { |
| const char* text = "Hello! What is going on?\nSecond line \nthirdline"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| // We must supply a font here, as the default is Arial, and we do not |
| // include Arial in our test fonts as it is proprietary. We want it to |
| // be Arial default though as it is one of the most common fonts on host |
| // platforms. On real devices/apps, Arial should be able to be resolved. |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| ASSERT_EQ(paragraph->GetLineMetrics().size(), 3ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].start_index, 0ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].end_index, 24ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].end_including_newline, 25ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].end_excluding_whitespace, 24ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].hard_break, true); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].ascent, 12.988281); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].descent, 3.4179688); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].width, 149.72266); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].left, 0.0); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].baseline, 12.582031); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].line_number, 0ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].run_metrics.size(), 1ull); |
| ASSERT_EQ( |
| paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) |
| ->second.text_style->color, |
| SK_ColorBLACK); |
| ASSERT_EQ( |
| paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) |
| ->second.text_style->font_families, |
| std::vector<std::string>(1, "Roboto")); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) |
| ->second.font_metrics.fAscent, |
| -12.988281); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) |
| ->second.font_metrics.fDescent, |
| 3.4179688); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) |
| ->second.font_metrics.fXHeight, |
| 7.3964844); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) |
| ->second.font_metrics.fLeading, |
| 0); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) |
| ->second.font_metrics.fTop, |
| -14.786133); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) |
| ->second.font_metrics.fUnderlinePosition, |
| 1.0253906); |
| |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].start_index, 25ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].end_index, 37ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].end_including_newline, 38ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].end_excluding_whitespace, 36ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].hard_break, true); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].ascent, 12.988281); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].descent, 3.4179688); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].width, 72.0625); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].left, 0.0); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].baseline, 28.582031); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].line_number, 1ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].run_metrics.size(), 1ull); |
| ASSERT_EQ( |
| paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) |
| ->second.text_style->color, |
| SK_ColorBLACK); |
| ASSERT_EQ( |
| paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) |
| ->second.text_style->font_families, |
| std::vector<std::string>(1, "Roboto")); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) |
| ->second.font_metrics.fAscent, |
| -12.988281); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) |
| ->second.font_metrics.fDescent, |
| 3.4179688); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) |
| ->second.font_metrics.fXHeight, |
| 7.3964844); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) |
| ->second.font_metrics.fLeading, |
| 0); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) |
| ->second.font_metrics.fTop, |
| -14.786133); |
| ASSERT_FLOAT_EQ( |
| paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) |
| ->second.font_metrics.fUnderlinePosition, |
| 1.0253906); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_MAC(LineMetricsParagraph2)) { |
| const char* text = "test string alphabetic"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string alphabetic(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| const char* text2 = "测试中文日本語한국어"; |
| auto icu_text2 = icu::UnicodeString::fromUTF8(text2); |
| std::u16string cjk(icu_text2.getBuffer(), |
| icu_text2.getBuffer() + icu_text2.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_families.push_back("Noto Sans CJK JP"); |
| text_style.font_size = 27; |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(alphabetic); |
| |
| text_style.font_size = 24; |
| builder.PushStyle(text_style); |
| builder.AddText(cjk); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(350); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| ASSERT_EQ(paragraph->GetLineMetrics().size(), 2ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].start_index, 0ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].end_index, 26ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].end_including_newline, 26ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].end_excluding_whitespace, 26ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].hard_break, false); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].ascent, 27.84); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].descent, 7.6799998); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].width, 348.61328); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].left, 0.0); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].baseline, 28.32); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].line_number, 0ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0].run_metrics.size(), 2ull); |
| // First run |
| ASSERT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(2) |
| ->second.text_style->font_size, |
| 27); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(2) |
| ->second.text_style->font_families, |
| text_style.font_families); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(2) |
| ->second.font_metrics.fAscent, |
| -25.048828); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(2) |
| ->second.font_metrics.fDescent, |
| 6.5917969); |
| |
| ASSERT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(21) |
| ->second.text_style->font_size, |
| 27); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(21) |
| ->second.text_style->font_families, |
| text_style.font_families); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(21) |
| ->second.font_metrics.fAscent, |
| -25.048828); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(21) |
| ->second.font_metrics.fDescent, |
| 6.5917969); |
| |
| // Second run |
| ASSERT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(22) |
| ->second.text_style->font_size, |
| 24); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(22) |
| ->second.text_style->font_families, |
| text_style.font_families); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(22) |
| ->second.font_metrics.fAscent, |
| -27.84); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(22) |
| ->second.font_metrics.fDescent, |
| 7.6799998); |
| |
| ASSERT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(24) |
| ->second.text_style->font_size, |
| 24); |
| ASSERT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(24) |
| ->second.text_style->font_families, |
| text_style.font_families); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(24) |
| ->second.font_metrics.fAscent, |
| -27.84); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] |
| .run_metrics.lower_bound(24) |
| ->second.font_metrics.fDescent, |
| 7.6799998); |
| |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].start_index, 26ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].end_index, 32ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].end_including_newline, 32ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].end_excluding_whitespace, 32ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].hard_break, true); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].ascent, 27.84); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].descent, 7.6799998); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].width, 138.23438); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].left, 0.0); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].baseline, 64.32); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].line_number, 1ull); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1].run_metrics.size(), 1ull); |
| // Indexing below the line will just resolve to the first run in the line. |
| ASSERT_EQ(paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(3) |
| ->second.text_style->font_size, |
| 24); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(3) |
| ->second.text_style->font_families, |
| text_style.font_families); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(3) |
| ->second.font_metrics.fAscent, |
| -27.84); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(3) |
| ->second.font_metrics.fDescent, |
| 7.6799998); |
| |
| // Indexing within the line |
| ASSERT_EQ(paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(31) |
| ->second.text_style->font_size, |
| 24); |
| ASSERT_EQ(paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(31) |
| ->second.text_style->font_families, |
| text_style.font_families); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(31) |
| ->second.font_metrics.fAscent, |
| -27.84); |
| ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1] |
| .run_metrics.lower_bound(31) |
| ->second.font_metrics.fDescent, |
| 7.6799998); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 0); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.AddPlaceholder(placeholder_run); |
| txt::PlaceholderRun placeholder_run2(5, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 50); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddText(u16_text); |
| builder.AddPlaceholder(placeholder_run2); |
| |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 3, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| // ASSERT_TRUE(Snapshot()); |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(4, 17, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 7ull); |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[1].rect.top(), 50); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 140.94531); |
| EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 100); |
| |
| EXPECT_FLOAT_EQ(boxes[3].rect.left(), 231.39062); |
| EXPECT_FLOAT_EQ(boxes[3].rect.top(), 50); |
| EXPECT_FLOAT_EQ(boxes[3].rect.right(), 231.39062 + 50); |
| EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 100); |
| |
| EXPECT_FLOAT_EQ(boxes[4].rect.left(), 281.39062); |
| EXPECT_FLOAT_EQ(boxes[4].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[4].rect.right(), 281.39062 + 5); |
| EXPECT_FLOAT_EQ(boxes[4].rect.bottom(), 50); |
| |
| EXPECT_FLOAT_EQ(boxes[6].rect.left(), 336.39062); |
| EXPECT_FLOAT_EQ(boxes[6].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[6].rect.right(), 336.39062 + 5); |
| EXPECT_FLOAT_EQ(boxes[6].rect.bottom(), 50); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderBaselineParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 38.34734); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the box is in the right place |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.94531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the other text didn't just shift to accommodate it. |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 75.34375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 14.226246); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 44.694996); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_WINDOWS(InlinePlaceholderAboveBaselineParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(55, 50, |
| PlaceholderAlignment::kAboveBaseline, |
| TextBaseline::kAlphabetic, 903129.129308); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the box is in the right place |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.34765625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.94531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 49.652344); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the other text didn't just shift to accommodate it. |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 75.34375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 25.53125); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 56); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_WINDOWS(InlinePlaceholderBelowBaselineParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(55, 50, |
| PlaceholderAlignment::kBelowBaseline, |
| TextBaseline::kAlphabetic, 903129.129308); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the box is in the right place |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 24); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.94531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 74); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the other text didn't just shift to accommodate it. |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 75.34375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.12109375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 30.347656); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderBottomParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kBottom, |
| TextBaseline::kAlphabetic, 0); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the box is in the right place |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.94531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the other text didn't just shift to accommodate it. |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0.5); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 19.53125); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 16.101562); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderTopParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kTop, |
| TextBaseline::kAlphabetic, 0); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the box is in the right place |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.94531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the other text didn't just shift to accommodate it. |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0.5); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 16.101562); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 30.46875); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderMiddleParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kMiddle, |
| TextBaseline::kAlphabetic, 0); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the box is in the right place |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 145.94531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the other text didn't just shift to accommodate it. |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 75.34375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 9.765625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 40.234375); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_MAC( |
| DISABLE_ON_WINDOWS(InlinePlaceholderIdeographicBaselineParagraph))) { |
| const char* text = "給能上目秘使"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Source Han Serif CN"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(55, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kIdeographic, 38.34734); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the box is in the right place |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 162.5); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 217.5); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| // Verify the other text didn't just shift to accommodate it. |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 135.5); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 4.7033391); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 162.5); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 42.065342); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderBreakParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 50); |
| txt::PlaceholderRun placeholder_run2(25, 25, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 12.5); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddText(u16_text); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddText(u16_text); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 3, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = paragraph->GetRectsForRange(175, 176, rect_height_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 31.703125); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 218.53125); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 47.304688); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 249); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(4, 45, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 30ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 59.742188); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 26.378906); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 56.847656); |
| |
| EXPECT_FLOAT_EQ(boxes[11].rect.left(), 606.39062); |
| EXPECT_FLOAT_EQ(boxes[11].rect.top(), 38); |
| EXPECT_FLOAT_EQ(boxes[11].rect.right(), 631.39062); |
| EXPECT_FLOAT_EQ(boxes[11].rect.bottom(), 63); |
| |
| EXPECT_FLOAT_EQ(boxes[17].rect.left(), 0.5); |
| EXPECT_FLOAT_EQ(boxes[17].rect.top(), 63.5); |
| EXPECT_FLOAT_EQ(boxes[17].rect.right(), 50.5); |
| EXPECT_FLOAT_EQ(boxes[17].rect.bottom(), 113.5); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderGetRectsParagraph)) { |
| const char* text = "012 34"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 50); |
| txt::PlaceholderRun placeholder_run2(5, 20, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 10); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.AddText(u16_text); |
| |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run2); |
| |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddText(u16_text); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddPlaceholder(placeholder_run2); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 34ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 90.945312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 140.94531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50); |
| |
| EXPECT_FLOAT_EQ(boxes[16].rect.left(), 800.94531); |
| EXPECT_FLOAT_EQ(boxes[16].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[16].rect.right(), 850.94531); |
| EXPECT_FLOAT_EQ(boxes[16].rect.bottom(), 50); |
| |
| EXPECT_FLOAT_EQ(boxes[33].rect.left(), 503.48438); |
| EXPECT_FLOAT_EQ(boxes[33].rect.top(), 160); |
| EXPECT_FLOAT_EQ(boxes[33].rect.right(), 508.48438); |
| EXPECT_FLOAT_EQ(boxes[33].rect.bottom(), 180); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(30, 50, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 8ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 216.10156); |
| // Top should be taller than "tight" |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 60); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 290.94531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 120); |
| |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 290.94531); |
| EXPECT_FLOAT_EQ(boxes[1].rect.top(), 60); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 340.94531); |
| EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 120); |
| |
| EXPECT_FLOAT_EQ(boxes[2].rect.left(), 340.94531); |
| EXPECT_FLOAT_EQ(boxes[2].rect.top(), 60); |
| EXPECT_FLOAT_EQ(boxes[2].rect.right(), 345.94531); |
| EXPECT_FLOAT_EQ(boxes[2].rect.bottom(), 120); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderLongestLine)) { |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 1; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 0); |
| builder.AddPlaceholder(placeholder_run); |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| ASSERT_DOUBLE_EQ(paragraph->width_, GetTestCanvasWidth()); |
| ASSERT_TRUE(paragraph->longest_line_ < GetTestCanvasWidth()); |
| ASSERT_TRUE(paragraph->longest_line_ >= 50); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholderIntrinsicWidth)) { |
| const char* text = "A "; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 0); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 20; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| builder.AddPlaceholder(placeholder_run); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| ASSERT_DOUBLE_EQ(paragraph->GetMinIntrinsicWidth(), 50); |
| ASSERT_DOUBLE_EQ(paragraph->GetMaxIntrinsicWidth(), 68); |
| } |
| |
| #if OS_LINUX |
| // Tests if manually inserted 0xFFFC characters are replaced to 0xFFFD in order |
| // to not interfere with the placeholder box layout. |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(InlinePlaceholder0xFFFCParagraph)) { |
| const char* text = "ab\uFFFCcd"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| // Used to generate the replaced version. |
| const char* text2 = "ab\uFFFDcd"; |
| auto icu_text2 = icu::UnicodeString::fromUTF8(text2); |
| std::u16string u16_text2(icu_text2.getBuffer(), |
| icu_text2.getBuffer() + icu_text2.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| std::vector<uint16_t> truth_text; |
| |
| builder.AddText(u16_text); |
| truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end()); |
| builder.AddText(u16_text); |
| truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end()); |
| |
| txt::PlaceholderRun placeholder_run(50, 50, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 25); |
| builder.AddPlaceholder(placeholder_run); |
| truth_text.push_back(0xFFFC); |
| |
| builder.AddText(u16_text); |
| truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end()); |
| builder.AddText(u16_text); |
| truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end()); |
| |
| builder.AddPlaceholder(placeholder_run); |
| truth_text.push_back(0xFFFC); |
| builder.AddPlaceholder(placeholder_run); |
| truth_text.push_back(0xFFFC); |
| builder.AddText(u16_text); |
| truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end()); |
| builder.AddText(u16_text); |
| truth_text.insert(truth_text.end(), u16_text2.begin(), u16_text2.end()); |
| builder.AddPlaceholder(placeholder_run); |
| truth_text.push_back(0xFFFC); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| for (size_t i = 0; i < truth_text.size(); ++i) { |
| EXPECT_EQ(paragraph->text_[i], truth_text[i]); |
| } |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| paint.setColor(SK_ColorRED); |
| |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForPlaceholders(); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 4ull); |
| |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 177.83594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 227.83594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 50); |
| |
| EXPECT_FLOAT_EQ(boxes[3].rect.left(), 682.50781); |
| EXPECT_FLOAT_EQ(boxes[3].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[3].rect.right(), 732.50781); |
| EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 50); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| #endif |
| |
| TEST_F(ParagraphTest, SimpleRedParagraph) { |
| const char* text = "I am RED"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorRED; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, RainbowParagraph) { |
| const char* text1 = "Red Roboto"; |
| auto icu_text1 = icu::UnicodeString::fromUTF8(text1); |
| std::u16string u16_text1(icu_text1.getBuffer(), |
| icu_text1.getBuffer() + icu_text1.length()); |
| const char* text2 = "big Greeen Default"; |
| auto icu_text2 = icu::UnicodeString::fromUTF8(text2); |
| std::u16string u16_text2(icu_text2.getBuffer(), |
| icu_text2.getBuffer() + icu_text2.length()); |
| const char* text3 = "Defcolor Homemade Apple"; |
| auto icu_text3 = icu::UnicodeString::fromUTF8(text3); |
| std::u16string u16_text3(icu_text3.getBuffer(), |
| icu_text3.getBuffer() + icu_text3.length()); |
| const char* text4 = "Small Blue Roboto"; |
| auto icu_text4 = icu::UnicodeString::fromUTF8(text4); |
| std::u16string u16_text4(icu_text4.getBuffer(), |
| icu_text4.getBuffer() + icu_text4.length()); |
| const char* text5 = |
| "Continue Last Style With lots of words to check if it overlaps " |
| "properly or not"; |
| auto icu_text5 = icu::UnicodeString::fromUTF8(text5); |
| std::u16string u16_text5(icu_text5.getBuffer(), |
| icu_text5.getBuffer() + icu_text5.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 2; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style1; |
| text_style1.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style1.color = SK_ColorRED; |
| |
| builder.PushStyle(text_style1); |
| |
| builder.AddText(u16_text1); |
| |
| txt::TextStyle text_style2; |
| text_style2.font_size = 50; |
| text_style2.letter_spacing = 10; |
| text_style2.word_spacing = 30; |
| text_style2.font_weight = txt::FontWeight::w600; |
| text_style2.color = SK_ColorGREEN; |
| text_style2.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style2.decoration = TextDecoration::kUnderline | |
| TextDecoration::kOverline | |
| TextDecoration::kLineThrough; |
| text_style2.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style2); |
| |
| builder.AddText(u16_text2); |
| |
| txt::TextStyle text_style3; |
| text_style3.font_families = std::vector<std::string>(1, "Homemade Apple"); |
| builder.PushStyle(text_style3); |
| |
| builder.AddText(u16_text3); |
| |
| txt::TextStyle text_style4; |
| text_style4.font_size = 14; |
| text_style4.color = SK_ColorBLUE; |
| text_style4.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style4.decoration = TextDecoration::kUnderline | |
| TextDecoration::kOverline | |
| TextDecoration::kLineThrough; |
| text_style4.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style4); |
| |
| builder.AddText(u16_text4); |
| |
| // Extra text to see if it goes to default when there is more text chunks than |
| // styles. |
| builder.AddText(u16_text5); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| u16_text1 += u16_text2 + u16_text3 + u16_text4; |
| for (size_t i = 0; i < u16_text1.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text1[i]); |
| } |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 4ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 5ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style1)); |
| ASSERT_TRUE(paragraph->runs_.styles_[2].equals(text_style2)); |
| ASSERT_TRUE(paragraph->runs_.styles_[3].equals(text_style3)); |
| ASSERT_TRUE(paragraph->runs_.styles_[4].equals(text_style4)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style1.color); |
| ASSERT_EQ(paragraph->records_[1].style().color, text_style2.color); |
| ASSERT_EQ(paragraph->records_[2].style().color, text_style3.color); |
| ASSERT_EQ(paragraph->records_[3].style().color, text_style4.color); |
| } |
| |
| // Currently, this should render nothing without a supplied TextStyle. |
| TEST_F(ParagraphTest, DefaultStyleParagraph) { |
| const char* text = "No TextStyle! Uh Oh!"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.font_family = "Roboto"; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 1ull); |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, BoldParagraph) { |
| const char* text = "This is Red max bold text!"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 60; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = txt::FontWeight::w900; |
| text_style.color = SK_ColorRED; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 60.0); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_TRUE(Snapshot()); |
| |
| // width_ takes the full available space, but longest_line_ is only the width |
| // of the text, which is less than one line. |
| ASSERT_DOUBLE_EQ(paragraph->width_, GetTestCanvasWidth()); |
| ASSERT_TRUE(paragraph->longest_line_ < paragraph->width_); |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| std::vector<txt::Paragraph::TextBox> boxes = paragraph->GetRectsForRange( |
| 0, strlen(text), rect_height_style, rect_width_style); |
| ASSERT_DOUBLE_EQ(paragraph->longest_line_, |
| boxes[boxes.size() - 1].rect.right() - boxes[0].rect.left()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideParagraph)) { |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 20; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 3.6345; |
| text_style.has_height_override = true; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kIncludeLineSpacingMiddle; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 40, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 3ull); |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0); |
| EXPECT_NEAR(boxes[1].rect.top(), 92.805778503417969, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 43.851562); |
| EXPECT_NEAR(boxes[1].rect.bottom(), 165.49578857421875, 0.0001); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideHalfLeadingTextStyle)) { |
| // All 3 lines will have the same typeface. |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_height_behavior = TextHeightBehavior::kAll; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 20; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 3.6345; |
| text_style.has_height_override = true; |
| // Override paragraph_style.text_height_behavior: |
| text_style.half_leading = true; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_style_max = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 40, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| |
| std::vector<txt::Paragraph::TextBox> line_boxes = paragraph->GetRectsForRange( |
| 0, 40, rect_height_style_max, rect_width_style); |
| EXPECT_EQ(boxes.size(), 3ull); |
| EXPECT_EQ(line_boxes.size(), 3ull); |
| |
| const double line_spacing1 = boxes[1].rect.top() - boxes[0].rect.bottom(); |
| const double line_spacing2 = boxes[2].rect.top() - boxes[1].rect.bottom(); |
| |
| EXPECT_EQ(line_spacing1, line_spacing2); |
| |
| // half leading. |
| EXPECT_EQ(line_boxes[0].rect.top() - boxes[0].rect.top(), |
| boxes[0].rect.bottom() - line_boxes[0].rect.bottom()); |
| EXPECT_EQ(line_boxes[1].rect.top() - boxes[1].rect.top(), |
| boxes[1].rect.bottom() - line_boxes[1].rect.bottom()); |
| EXPECT_EQ(line_boxes[2].rect.top() - boxes[2].rect.top(), |
| boxes[2].rect.bottom() - line_boxes[2].rect.bottom()); |
| // With half-leadding, the x coordinates should remain the same. |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 43.851562); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(MixedTextHeightBehaviorSameLine)) { |
| // Both runs will still have the same typeface, but with different text height |
| // behaviors. |
| const char* text = "01234満毎冠行来昼本可abcd"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| std::u16string u16_text2(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_height_behavior = TextHeightBehavior::kAll; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 20; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 3.6345; |
| text_style.has_height_override = true; |
| // First run, with half-leading. |
| text_style.half_leading = true; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| // Second run with AD-scaling. |
| text_style.half_leading = false; |
| |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text2); |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_style_max = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| |
| std::vector<txt::Paragraph::TextBox> boxes = paragraph->GetRectsForRange( |
| 0, icu_text.length(), rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| |
| std::vector<txt::Paragraph::TextBox> line_boxes = paragraph->GetRectsForRange( |
| 0, icu_text.length(), rect_height_style_max, rect_width_style); |
| // The runs has the same typeface so they should be grouped together. |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_EQ(line_boxes.size(), 1ull); |
| |
| const double glyphHeight = boxes[0].rect.height(); |
| const double metricsAscent = 18.5546875; |
| const double metricsDescent = 4.8828125; |
| EXPECT_DOUBLE_EQ(glyphHeight, metricsAscent + metricsDescent); |
| |
| const double line_height = 3.6345 * 20; |
| const double leading = line_height - glyphHeight; |
| |
| // Overall descent is from half-leading and overall ascent is from AD-scaling. |
| EXPECT_NEAR(boxes[0].rect.top() - line_boxes[0].rect.top(), |
| leading * metricsAscent / (metricsAscent + metricsDescent), |
| 0.001); |
| |
| EXPECT_NEAR(line_boxes[0].rect.bottom() - boxes[0].rect.bottom(), |
| leading * 0.5, 0.001); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_WINDOWS(MixedTextHeightBehaviorSameLineWithZeroHeight)) { |
| // Both runs will still have the same typeface, but with different text height |
| // behaviors. |
| const char* text = "01234満毎冠行来昼本可abcd"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_height_behavior = TextHeightBehavior::kAll; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 20; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| // Set height to 0 |
| text_style.height = 0; |
| text_style.has_height_override = true; |
| // First run, with half-leading. |
| text_style.half_leading = true; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| // Second run with AD-scaling. |
| text_style.half_leading = false; |
| |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_style_max = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| |
| std::vector<txt::Paragraph::TextBox> boxes = paragraph->GetRectsForRange( |
| 0, icu_text.length(), rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| |
| std::vector<txt::Paragraph::TextBox> line_boxes = paragraph->GetRectsForRange( |
| 0, icu_text.length(), rect_height_style_max, rect_width_style); |
| // The runs has the same typeface so they should be grouped together. |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_EQ(line_boxes.size(), 1ull); |
| |
| const double glyphHeight = boxes[0].rect.height(); |
| const double metricsAscent = 18.5546875; |
| const double metricsDescent = 4.8828125; |
| EXPECT_DOUBLE_EQ(glyphHeight, metricsAscent + metricsDescent); |
| |
| // line_height for both styled runs is 0, but the overall line height is not |
| // 0. |
| EXPECT_DOUBLE_EQ(line_boxes[0].rect.height(), |
| metricsAscent - (metricsAscent + metricsDescent) / 2); |
| EXPECT_LT(boxes[0].rect.top(), 0.0); |
| EXPECT_GT(boxes[0].rect.bottom(), 0.0); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideHalfLeadingStrut)) { |
| // All 3 lines will have the same typeface. |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.strut_enabled = true; |
| paragraph_style.strut_has_height_override = true; |
| paragraph_style.strut_height = 3.6345; |
| paragraph_style.strut_font_size = 20; |
| paragraph_style.strut_font_families.push_back("Roboto"); |
| paragraph_style.strut_half_leading = true; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 20; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 3.6345; |
| text_style.has_height_override = true; |
| text_style.half_leading = true; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_style_max = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 40, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| |
| std::vector<txt::Paragraph::TextBox> line_boxes = paragraph->GetRectsForRange( |
| 0, 40, rect_height_style_max, rect_width_style); |
| EXPECT_EQ(boxes.size(), 3ull); |
| EXPECT_EQ(line_boxes.size(), 3ull); |
| |
| const double line_spacing1 = boxes[1].rect.top() - boxes[0].rect.bottom(); |
| const double line_spacing2 = boxes[2].rect.top() - boxes[1].rect.bottom(); |
| |
| EXPECT_EQ(line_spacing1, line_spacing2); |
| |
| // Strut half leading. |
| EXPECT_EQ(line_boxes[0].rect.top() - boxes[0].rect.top(), |
| boxes[0].rect.bottom() - line_boxes[0].rect.bottom()); |
| EXPECT_EQ(line_boxes[1].rect.top() - boxes[1].rect.top(), |
| boxes[1].rect.bottom() - line_boxes[1].rect.bottom()); |
| EXPECT_EQ(line_boxes[2].rect.top() - boxes[2].rect.top(), |
| boxes[2].rect.bottom() - line_boxes[2].rect.bottom()); |
| |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 43.851562); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_WINDOWS(ZeroHeightHalfLeadingStrutForceHeight)) { |
| // All 3 lines will have the same typeface. |
| const char* text = "01234満毎冠行来昼本可abcdn満毎冠行来昼本可"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.strut_enabled = true; |
| paragraph_style.strut_has_height_override = true; |
| paragraph_style.strut_height = 0; |
| // Force strut height. |
| paragraph_style.force_strut_height = true; |
| paragraph_style.strut_font_size = 20; |
| paragraph_style.strut_font_families.push_back("Roboto"); |
| paragraph_style.strut_half_leading = true; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 20; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 0; |
| text_style.has_height_override = true; |
| |
| // First run, with half-leading. |
| text_style.half_leading = true; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| // Second run with AD-scaling. |
| text_style.half_leading = false; |
| |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_style_max = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| |
| std::vector<txt::Paragraph::TextBox> boxes = paragraph->GetRectsForRange( |
| 0, icu_text.length(), rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| |
| std::vector<txt::Paragraph::TextBox> line_boxes = paragraph->GetRectsForRange( |
| 0, icu_text.length(), rect_height_style_max, rect_width_style); |
| // The runs has the same typeface so they should be grouped together. |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_EQ(line_boxes.size(), 1ull); |
| |
| const double glyphHeight = boxes[0].rect.height(); |
| const double metricsAscent = 18.5546875; |
| const double metricsDescent = 4.8828125; |
| EXPECT_DOUBLE_EQ(glyphHeight, metricsAscent + metricsDescent); |
| |
| EXPECT_DOUBLE_EQ(line_boxes[0].rect.height(), 0.0); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(LeftAlignParagraph)) { |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are necessary. Very short. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum."; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_.size(), paragraph_style.max_lines); |
| double expected_y = 24; |
| |
| ASSERT_TRUE(paragraph->records_[0].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().x(), 0); |
| |
| ASSERT_TRUE(paragraph->records_[1].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[1].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_DOUBLE_EQ(paragraph->records_[1].offset().x(), 0); |
| |
| ASSERT_TRUE(paragraph->records_[2].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().x(), 0); |
| |
| ASSERT_TRUE(paragraph->records_[3].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[3].offset().y(), expected_y); |
| expected_y += 30 * 10; |
| ASSERT_DOUBLE_EQ(paragraph->records_[3].offset().x(), 0); |
| |
| ASSERT_TRUE(paragraph->records_[13].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[13].offset().y(), expected_y); |
| ASSERT_DOUBLE_EQ(paragraph->records_[13].offset().x(), 0); |
| |
| ASSERT_EQ(paragraph_style.text_align, |
| paragraph->GetParagraphStyle().text_align); |
| |
| // Tests for GetGlyphPositionAtCoordinate() |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0, 0).position, 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 1).position, 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 35).position, 68ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 70).position, 134ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(2000, 35).position, 134ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(LeftAlignRTLParagraphHitTest)) { |
| // Regression test for https://github.com/flutter/flutter/issues/54969. |
| const char* text = "بمباركة التقليدية قام عن. تصفح"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 1; |
| paragraph_style.text_align = TextAlign::left; |
| paragraph_style.text_direction = TextDirection::rtl; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| // Tests for GetGlyphPositionAtCoordinate() |
| ASSERT_EQ( |
| paragraph->GetGlyphPositionAtCoordinate(GetTestCanvasWidth() - 0.5, 0.5) |
| .position, |
| 0ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(RightAlignParagraph)) { |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are necessary. Very short. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum."; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::right; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| int available_width = GetTestCanvasWidth() - 100; |
| paragraph->Layout(available_width); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| // Two records for each due to 'ghost' trailing whitespace run. |
| ASSERT_EQ(paragraph->records_.size(), paragraph_style.max_lines * 2); |
| double expected_y = 24; |
| |
| ASSERT_TRUE(paragraph->records_[0].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_NEAR( |
| paragraph->records_[0].offset().x(), |
| paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[0].line()], |
| 2.0); |
| |
| // width_ takes the full available space, while longest_line_ wraps the glyphs |
| // as tightly as possible. Even though this text is more than one line long, |
| // no line perfectly spans the width of the full line, so longest_line_ is |
| // less than width_. |
| ASSERT_DOUBLE_EQ(paragraph->width_, available_width); |
| ASSERT_TRUE(paragraph->longest_line_ < available_width); |
| ASSERT_DOUBLE_EQ(paragraph->longest_line_, 880.87109375); |
| |
| ASSERT_TRUE(paragraph->records_[2].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_NEAR( |
| paragraph->records_[2].offset().x(), |
| paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[2].line()], |
| 2.0); |
| |
| ASSERT_TRUE(paragraph->records_[4].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[4].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_NEAR( |
| paragraph->records_[4].offset().x(), |
| paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[4].line()], |
| 2.0); |
| |
| ASSERT_TRUE(paragraph->records_[6].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[6].offset().y(), expected_y); |
| expected_y += 30 * 10; |
| ASSERT_NEAR( |
| paragraph->records_[6].offset().x(), |
| paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[6].line()], |
| 2.0); |
| |
| ASSERT_TRUE(paragraph->records_[26].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[26].offset().y(), expected_y); |
| ASSERT_NEAR( |
| paragraph->records_[26].offset().x(), |
| paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[26].line()], |
| 2.0); |
| |
| ASSERT_EQ(paragraph_style.text_align, |
| paragraph->GetParagraphStyle().text_align); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(CenterAlignParagraph)) { |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are necessary. Very short. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum."; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::center; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| // Two records for each due to 'ghost' trailing whitespace run. |
| ASSERT_EQ(paragraph->records_.size(), paragraph_style.max_lines * 2); |
| double expected_y = 24; |
| |
| ASSERT_TRUE(paragraph->records_[0].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_NEAR(paragraph->records_[0].offset().x(), |
| (paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[0].line()]) / |
| 2, |
| 2.0); |
| |
| ASSERT_TRUE(paragraph->records_[2].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_NEAR(paragraph->records_[2].offset().x(), |
| (paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[2].line()]) / |
| 2, |
| 2.0); |
| |
| ASSERT_TRUE(paragraph->records_[4].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[4].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_NEAR(paragraph->records_[4].offset().x(), |
| (paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[4].line()]) / |
| 2, |
| 2.0); |
| |
| ASSERT_TRUE(paragraph->records_[6].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[6].offset().y(), expected_y); |
| expected_y += 30 * 10; |
| ASSERT_NEAR(paragraph->records_[6].offset().x(), |
| (paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[6].line()]) / |
| 2, |
| 2.0); |
| |
| ASSERT_TRUE(paragraph->records_[26].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[26].offset().y(), expected_y); |
| ASSERT_NEAR( |
| paragraph->records_[26].offset().x(), |
| (paragraph->width_ - |
| paragraph->breaker_.getWidths()[paragraph->records_[26].line()]) / |
| 2, |
| 2.0); |
| |
| ASSERT_EQ(paragraph_style.text_align, |
| paragraph->GetParagraphStyle().text_align); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyAlignParagraph)) { |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are necessary. Very short. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " |
| "occaecat cupidatat non proident, sunt in culpa qui officia deserunt " |
| "mollit anim id est laborum. " |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " |
| "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim " |
| "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " |
| "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate " |
| "velit esse cillum dolore eu fugiat."; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::justify; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_.size(), 27ull); |
| double expected_y = 24; |
| |
| ASSERT_TRUE(paragraph->records_[0].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_DOUBLE_EQ(paragraph->records_[0].offset().x(), 0); |
| |
| ASSERT_TRUE(paragraph->records_[2].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_DOUBLE_EQ(paragraph->records_[2].offset().x(), 0); |
| |
| ASSERT_TRUE(paragraph->records_[4].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[4].offset().y(), expected_y); |
| expected_y += 30; |
| ASSERT_DOUBLE_EQ(paragraph->records_[4].offset().x(), 0); |
| |
| ASSERT_TRUE(paragraph->records_[6].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[6].offset().y(), expected_y); |
| expected_y += 30 * 10; |
| ASSERT_DOUBLE_EQ(paragraph->records_[6].offset().x(), 0); |
| |
| ASSERT_TRUE(paragraph->records_[26].style().equals(text_style)); |
| ASSERT_DOUBLE_EQ(paragraph->records_[26].offset().y(), expected_y); |
| ASSERT_DOUBLE_EQ(paragraph->records_[26].offset().x(), 0); |
| |
| ASSERT_EQ(paragraph_style.text_align, |
| paragraph->GetParagraphStyle().text_align); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyRTL)) { |
| const char* text = |
| "אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ"; |
| |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::justify; |
| paragraph_style.text_direction = TextDirection::rtl; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Ahem"); |
| text_style.font_size = 26; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| size_t paragraph_width = GetTestCanvasWidth() - 100; |
| paragraph->Layout(paragraph_width); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| auto glyph_line_width = [¶graph](int index) { |
| size_t second_to_last_position_index = |
| paragraph->glyph_lines_[index].positions.size() - 1; |
| return paragraph->glyph_lines_[index] |
| .positions[second_to_last_position_index] |
| .x_pos.end; |
| }; |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 100, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| ASSERT_EQ(boxes.size(), 5ull); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = paragraph->GetRectsForRange(240, 250, rect_height_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| ASSERT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 588); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 130); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 640); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 156); |
| ASSERT_TRUE(Snapshot()); |
| |
| // All lines should be justified to the width of the |
| // paragraph. |
| for (size_t i = 0; i < paragraph->glyph_lines_.size(); ++i) { |
| ASSERT_EQ(glyph_line_width(i), paragraph_width); |
| } |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(JustifyRTLNewLine)) { |
| const char* text = |
| "אאא בּבּבּבּ אאאא\nבּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ " |
| "אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ"; |
| |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::justify; |
| paragraph_style.text_direction = TextDirection::rtl; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Ahem"); |
| text_style.font_size = 26; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| size_t paragraph_width = GetTestCanvasWidth() - 100; |
| paragraph->Layout(paragraph_width); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| auto glyph_line_width = [¶graph](int index) { |
| size_t second_to_last_position_index = |
| paragraph->glyph_lines_[index].positions.size() - 1; |
| return paragraph->glyph_lines_[index] |
| .positions[second_to_last_position_index] |
| .x_pos.end; |
| }; |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 30, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| ASSERT_EQ(boxes.size(), 2ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 562); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), -1.4305115e-06); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 900); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 26); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = paragraph->GetRectsForRange(240, 250, rect_height_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| ASSERT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 68); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 130); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 120); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 156); |
| ASSERT_TRUE(Snapshot()); |
| |
| // All lines should be justified to the width of the |
| // paragraph. |
| for (size_t i = 0; i < paragraph->glyph_lines_.size(); ++i) { |
| ASSERT_EQ(glyph_line_width(i), paragraph_width); |
| } |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyPlaceholder)) { |
| const char* text1 = "A "; |
| auto icu_text1 = icu::UnicodeString::fromUTF8(text1); |
| std::u16string u16_text1(icu_text1.getBuffer(), |
| icu_text1.getBuffer() + icu_text1.length()); |
| |
| txt::PlaceholderRun placeholder_run(60, 60, PlaceholderAlignment::kBaseline, |
| TextBaseline::kAlphabetic, 0); |
| |
| const char* text2 = " B CCCCC"; |
| auto icu_text2 = icu::UnicodeString::fromUTF8(text2); |
| std::u16string u16_text2(icu_text2.getBuffer(), |
| icu_text2.getBuffer() + icu_text2.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.text_align = TextAlign::justify; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Ahem"); |
| text_style.font_size = 20; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text1); |
| builder.AddPlaceholder(placeholder_run); |
| builder.AddText(u16_text2); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(200); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| |
| // Check location of placeholder at the center of the line. |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(2, 3, rect_height_style, rect_width_style); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 70); |
| |
| // Check location of character B at the end of the line. |
| boxes = |
| paragraph->GetRectsForRange(4, 5, rect_height_style, rect_width_style); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 180); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(LeadingSpaceRTL)) { |
| const char* text = " leading space"; |
| |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::justify; |
| paragraph_style.text_direction = TextDirection::rtl; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Ahem"); |
| text_style.font_size = 26; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| size_t paragraph_width = GetTestCanvasWidth() - 100; |
| paragraph->Layout(paragraph_width); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 100, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| ASSERT_EQ(boxes.size(), 2ull); |
| |
| // This test should crash if behavior regresses. |
| } |
| |
| TEST_F(ParagraphTest, DecorationsParagraph) { |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 2; |
| text_style.decoration = TextDecoration::kUnderline | |
| TextDecoration::kOverline | |
| TextDecoration::kLineThrough; |
| text_style.decoration_style = txt::TextDecorationStyle::kSolid; |
| text_style.decoration_color = SK_ColorBLACK; |
| text_style.decoration_thickness_multiplier = 2.0; |
| builder.PushStyle(text_style); |
| builder.AddText(u"This text should be"); |
| |
| text_style.decoration_style = txt::TextDecorationStyle::kDouble; |
| text_style.decoration_color = SK_ColorBLUE; |
| text_style.decoration_thickness_multiplier = 1.0; |
| builder.PushStyle(text_style); |
| builder.AddText(u" decorated even when"); |
| |
| text_style.decoration_style = txt::TextDecorationStyle::kDotted; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u" wrapped around to"); |
| |
| text_style.decoration_style = txt::TextDecorationStyle::kDashed; |
| text_style.decoration_color = SK_ColorBLACK; |
| text_style.decoration_thickness_multiplier = 3.0; |
| builder.PushStyle(text_style); |
| builder.AddText(u" the next line."); |
| |
| text_style.decoration_style = txt::TextDecorationStyle::kWavy; |
| text_style.decoration_color = SK_ColorRED; |
| text_style.decoration_thickness_multiplier = 1.0; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u" Otherwise, bad things happen."); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->runs_.size(), 5ull); |
| ASSERT_EQ(paragraph->records_.size(), 6ull); |
| |
| for (size_t i = 0; i < 6; ++i) { |
| ASSERT_EQ(paragraph->records_[i].style().decoration, |
| TextDecoration::kUnderline | TextDecoration::kOverline | |
| TextDecoration::kLineThrough); |
| } |
| |
| ASSERT_EQ(paragraph->records_[0].style().decoration_style, |
| txt::TextDecorationStyle::kSolid); |
| ASSERT_EQ(paragraph->records_[1].style().decoration_style, |
| txt::TextDecorationStyle::kDouble); |
| ASSERT_EQ(paragraph->records_[2].style().decoration_style, |
| txt::TextDecorationStyle::kDotted); |
| ASSERT_EQ(paragraph->records_[3].style().decoration_style, |
| txt::TextDecorationStyle::kDashed); |
| ASSERT_EQ(paragraph->records_[4].style().decoration_style, |
| txt::TextDecorationStyle::kDashed); |
| ASSERT_EQ(paragraph->records_[5].style().decoration_style, |
| txt::TextDecorationStyle::kWavy); |
| |
| ASSERT_EQ(paragraph->records_[0].style().decoration_color, SK_ColorBLACK); |
| ASSERT_EQ(paragraph->records_[1].style().decoration_color, SK_ColorBLUE); |
| ASSERT_EQ(paragraph->records_[2].style().decoration_color, SK_ColorBLACK); |
| ASSERT_EQ(paragraph->records_[3].style().decoration_color, SK_ColorBLACK); |
| ASSERT_EQ(paragraph->records_[4].style().decoration_color, SK_ColorBLACK); |
| ASSERT_EQ(paragraph->records_[5].style().decoration_color, SK_ColorRED); |
| |
| ASSERT_EQ(paragraph->records_[0].style().decoration_thickness_multiplier, |
| 2.0); |
| ASSERT_EQ(paragraph->records_[1].style().decoration_thickness_multiplier, |
| 1.0); |
| ASSERT_EQ(paragraph->records_[2].style().decoration_thickness_multiplier, |
| 1.0); |
| ASSERT_EQ(paragraph->records_[3].style().decoration_thickness_multiplier, |
| 3.0); |
| ASSERT_EQ(paragraph->records_[4].style().decoration_thickness_multiplier, |
| 3.0); |
| ASSERT_EQ(paragraph->records_[5].style().decoration_thickness_multiplier, |
| 1.0); |
| } |
| |
| TEST_F(ParagraphTest, WavyDecorationParagraph) { |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 2; |
| text_style.decoration = TextDecoration::kUnderline | |
| TextDecoration::kOverline | |
| TextDecoration::kLineThrough; |
| |
| text_style.decoration_style = txt::TextDecorationStyle::kWavy; |
| text_style.decoration_color = SK_ColorRED; |
| text_style.decoration_thickness_multiplier = 1.0; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u" Otherwise, bad things happen."); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->records_.size(), 1ull); |
| |
| for (size_t i = 0; i < 1; ++i) { |
| ASSERT_EQ(paragraph->records_[i].style().decoration, |
| TextDecoration::kUnderline | TextDecoration::kOverline | |
| TextDecoration::kLineThrough); |
| } |
| |
| ASSERT_EQ(paragraph->records_[0].style().decoration_style, |
| txt::TextDecorationStyle::kWavy); |
| |
| ASSERT_EQ(paragraph->records_[0].style().decoration_color, SK_ColorRED); |
| |
| ASSERT_EQ(paragraph->records_[0].style().decoration_thickness_multiplier, |
| 1.0); |
| |
| SkPath path0; |
| SkPath canonical_path0; |
| paragraph->ComputeWavyDecoration(path0, 1, 1, 9.56, 1); |
| |
| canonical_path0.moveTo(1, 1); |
| canonical_path0.rQuadTo(1, -1, 2, 0); |
| canonical_path0.rQuadTo(1, 1, 2, 0); |
| canonical_path0.rQuadTo(1, -1, 2, 0); |
| canonical_path0.rQuadTo(1, 1, 2, 0); |
| canonical_path0.rQuadTo(0.78, -0.78, 1.56, -0.3432); |
| |
| ASSERT_EQ(path0.countPoints(), canonical_path0.countPoints()); |
| for (int i = 0; i < canonical_path0.countPoints(); ++i) { |
| ASSERT_EQ(path0.getPoint(i).x(), canonical_path0.getPoint(i).x()); |
| ASSERT_EQ(path0.getPoint(i).y(), canonical_path0.getPoint(i).y()); |
| } |
| |
| SkPath path1; |
| SkPath canonical_path1; |
| paragraph->ComputeWavyDecoration(path1, 1, 1, 8.35, 1); |
| |
| canonical_path1.moveTo(1, 1); |
| canonical_path1.rQuadTo(1, -1, 2, 0); |
| canonical_path1.rQuadTo(1, 1, 2, 0); |
| canonical_path1.rQuadTo(1, -1, 2, 0); |
| canonical_path1.rQuadTo(1, 1, 2, 0); |
| canonical_path1.rQuadTo(0.175, -0.175, 0.35, -0.28875); |
| |
| ASSERT_EQ(path1.countPoints(), canonical_path1.countPoints()); |
| for (int i = 0; i < canonical_path1.countPoints(); ++i) { |
| ASSERT_EQ(path1.getPoint(i).x(), canonical_path1.getPoint(i).x()); |
| ASSERT_EQ(path1.getPoint(i).y(), canonical_path1.getPoint(i).y()); |
| } |
| |
| SkPath path2; |
| SkPath canonical_path2; |
| paragraph->ComputeWavyDecoration(path2, 1, 1, 10.59, 1); |
| |
| canonical_path2.moveTo(1, 1); |
| canonical_path2.rQuadTo(1, -1, 2, 0); |
| canonical_path2.rQuadTo(1, 1, 2, 0); |
| canonical_path2.rQuadTo(1, -1, 2, 0); |
| canonical_path2.rQuadTo(1, 1, 2, 0); |
| canonical_path2.rQuadTo(1, -1, 2, 0); |
| canonical_path2.rQuadTo(0.295, 0.295, 0.59, 0.41595); |
| |
| ASSERT_EQ(path2.countPoints(), canonical_path2.countPoints()); |
| for (int i = 0; i < canonical_path2.countPoints(); ++i) { |
| ASSERT_EQ(path2.getPoint(i).x(), canonical_path2.getPoint(i).x()); |
| ASSERT_EQ(path2.getPoint(i).y(), canonical_path2.getPoint(i).y()); |
| } |
| |
| SkPath path3; |
| SkPath canonical_path3; |
| paragraph->ComputeWavyDecoration(path3, 1, 1, 11.2, 1); |
| |
| canonical_path3.moveTo(1, 1); |
| canonical_path3.rQuadTo(1, -1, 2, 0); |
| canonical_path3.rQuadTo(1, 1, 2, 0); |
| canonical_path3.rQuadTo(1, -1, 2, 0); |
| canonical_path3.rQuadTo(1, 1, 2, 0); |
| canonical_path3.rQuadTo(1, -1, 2, 0); |
| canonical_path3.rQuadTo(0.6, 0.6, 1.2, 0.48); |
| |
| ASSERT_EQ(path3.countPoints(), canonical_path3.countPoints()); |
| for (int i = 0; i < canonical_path3.countPoints(); ++i) { |
| ASSERT_EQ(path3.getPoint(i).x(), canonical_path3.getPoint(i).x()); |
| ASSERT_EQ(path3.getPoint(i).y(), canonical_path3.getPoint(i).y()); |
| } |
| |
| SkPath path4; |
| SkPath canonical_path4; |
| paragraph->ComputeWavyDecoration(path4, 1, 1, 12, 1); |
| |
| canonical_path4.moveTo(1, 1); |
| canonical_path4.rQuadTo(1, -1, 2, 0); |
| canonical_path4.rQuadTo(1, 1, 2, 0); |
| canonical_path4.rQuadTo(1, -1, 2, 0); |
| canonical_path4.rQuadTo(1, 1, 2, 0); |
| canonical_path4.rQuadTo(1, -1, 2, 0); |
| canonical_path4.rQuadTo(1, 1, 2, 0); |
| |
| ASSERT_EQ(path4.countPoints(), canonical_path4.countPoints()); |
| for (int i = 0; i < canonical_path4.countPoints(); ++i) { |
| ASSERT_EQ(path4.getPoint(i).x(), canonical_path4.getPoint(i).x()); |
| ASSERT_EQ(path4.getPoint(i).y(), canonical_path4.getPoint(i).y()); |
| } |
| } |
| |
| TEST_F(ParagraphTest, ItalicsParagraph) { |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorRED; |
| text_style.font_size = 10; |
| builder.PushStyle(text_style); |
| builder.AddText(u"No italic "); |
| |
| text_style.font_style = txt::FontStyle::italic; |
| builder.PushStyle(text_style); |
| builder.AddText(u"Yes Italic "); |
| |
| builder.Pop(); |
| builder.AddText(u"No Italic again."); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 3ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 3ull); |
| ASSERT_EQ(paragraph->records_[1].style().color, text_style.color); |
| ASSERT_EQ(paragraph->records_[1].style().font_style, txt::FontStyle::italic); |
| ASSERT_EQ(paragraph->records_[2].style().font_style, txt::FontStyle::normal); |
| ASSERT_EQ(paragraph->records_[0].style().font_style, txt::FontStyle::normal); |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, ChineseParagraph) { |
| const char* text = |
| "左線読設重説切後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育" |
| "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得庭" |
| "際輝求佐抗蒼提夜合逃表。注統天言件自謙雅載報紙喪。作画稿愛器灯女書利変探" |
| "訃第金線朝開化建。子戦年帝励害表月幕株漠新期刊人秘。図的海力生禁挙保天戦" |
| "聞条年所在口。"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::justify; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.color = SK_ColorBLACK; |
| text_style.font_size = 35; |
| text_style.letter_spacing = 2; |
| text_style.font_families = std::vector<std::string>(1, "Source Han Serif CN"); |
| text_style.decoration = TextDecoration::kUnderline | |
| TextDecoration::kOverline | |
| TextDecoration::kLineThrough; |
| text_style.decoration_style = txt::TextDecorationStyle::kSolid; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_EQ(paragraph->records_.size(), 7ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| // TODO(garyq): Support RTL languages. |
| TEST_F(ParagraphTest, DISABLED_ArabicParagraph) { |
| const char* text = |
| "من أسر وإعلان الخاصّة وهولندا،, عل قائمة الضغوط بالمطالبة تلك. الصفحة " |
| "بمباركة التقليدية قام عن. تصفح"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::right; |
| paragraph_style.text_direction = TextDirection::rtl; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.color = SK_ColorBLACK; |
| text_style.font_size = 35; |
| text_style.letter_spacing = 2; |
| text_style.font_families = std::vector<std::string>(1, "Katibeh"); |
| text_style.decoration = TextDecoration::kUnderline | |
| TextDecoration::kOverline | |
| TextDecoration::kLineThrough; |
| text_style.decoration_style = txt::TextDecorationStyle::kSolid; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_EQ(paragraph->records_.size(), 2ull); |
| ASSERT_EQ(paragraph->paragraph_style_.text_direction, TextDirection::rtl); |
| |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[u16_text.length() - i]); |
| } |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| // Checks if the rects are in the correct positions after typing spaces in |
| // Arabic. |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(ArabicRectsParagraph)) { |
| const char* text = "بمباركة التقليدية قام عن. تصفح يد "; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::right; |
| paragraph_style.text_direction = TextDirection::rtl; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Noto Naskh Arabic"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 100, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 2ull); |
| |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 556.48438); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.26855469); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 900); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 44); |
| |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 510.03125); |
| EXPECT_FLOAT_EQ(boxes[1].rect.top(), -0.26855469); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 556.98438); |
| EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 44); |
| |
| ASSERT_EQ(paragraph_style.text_align, |
| paragraph->GetParagraphStyle().text_align); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| // Trailing space at the end of the arabic rtl run should be at the left end of |
| // the arabic run. |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(ArabicRectsLTRLeftAlignParagraph)) { |
| const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد "; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::left; |
| paragraph_style.text_direction = TextDirection::ltr; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Noto Naskh Arabic"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(36, 40, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 89.425781); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.26855469); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 121.90625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 44); |
| |
| ASSERT_EQ(paragraph_style.text_align, |
| paragraph->GetParagraphStyle().text_align); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| // Trailing space at the end of the arabic rtl run should be at the left end of |
| // the arabic run and be a ghost space. |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(ArabicRectsLTRRightAlignParagraph)) { |
| const char* text = "Helloبمباركة التقليدية قام عن. تصفح يد "; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::right; |
| paragraph_style.text_direction = TextDirection::ltr; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Noto Naskh Arabic"); |
| text_style.font_size = 26; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| text_style.decoration = TextDecoration::kUnderline; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(36, 40, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 2ull); |
| |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 556.48438); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.26855469); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 577.72656); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 44); |
| |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 545.24609); |
| EXPECT_FLOAT_EQ(boxes[1].rect.top(), -0.26855469); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 556.98438); |
| EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 44); |
| |
| ASSERT_EQ(paragraph_style.text_align, |
| paragraph->GetParagraphStyle().text_align); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, GetGlyphPositionAtCoordinateParagraph) { |
| const char* text = |
| "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 " |
| "67890 12345"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| // Tests for GetGlyphPositionAtCoordinate() |
| // NOTE: resulting values can be a few off from their respective positions in |
| // the original text because the final trailing whitespaces are sometimes not |
| // drawn (namely, when using "justify" alignment) and therefore are not active |
| // glyphs. |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(-10000, -10000).position, |
| 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(-1, -1).position, 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(0, 0).position, 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(3, 3).position, 0ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(35, 1).position, 1ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(300, 2).position, 11ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(301, 2.2).position, 11ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(302, 2.6).position, 11ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(301, 2.1).position, 11ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(100000, 20).position, |
| 18ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(450, 20).position, 16ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(100000, 90).position, |
| 36ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(-100000, 90).position, |
| 18ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(20, -80).position, 1ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 90).position, 18ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 170).position, 36ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(10000, 180).position, |
| 72ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(70, 180).position, 56ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(1, 270).position, 72ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(35, 90).position, 19ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(10000, 10000).position, |
| 77ull); |
| ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(85, 10000).position, 75ull); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeParagraph)) { |
| const char* text = |
| "12345, \"67890\" 12345 67890 12345 67890 12345 67890 12345 67890 12345 " |
| "67890 12345"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| // NOTE: The base truth values may still need adjustment as the specifics |
| // are adjusted. |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 28.417969); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 56.835938); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 177.98438); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 177.98438); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 507.03906); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(30, 100, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 4ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 211.37891); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 59.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 463.62891); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 118); |
| |
| // TODO(garyq): The following set of vals are definitely wrong and |
| // end of paragraph handling needs to be fixed in a later patch. |
| EXPECT_FLOAT_EQ(boxes[3].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[3].rect.top(), 236.40625); |
| EXPECT_FLOAT_EQ(boxes[3].rect.right(), 142.08984); |
| EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 295); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(19, 22, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 450.20312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 519.49219); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(GetRectsForRangeTight)) { |
| const char* text = |
| "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Noto Sans CJK JP"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| // NOTE: The base truth values may still need adjustment as the specifics |
| // are adjusted. |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 16.898438); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 74); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 264.09766); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 74); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 2ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 264.09766); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 595.09375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 74); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_WINDOWS(GetRectsForRangeIncludeLineSpacingMiddle)) { |
| const char* text = |
| "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1.6; |
| text_style.has_height_override = true; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| // NOTE: The base truth values may still need adjustment as the specifics |
| // are adjusted. |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kIncludeLineSpacingMiddle; |
| Paragraph::RectWidthStyle rect_width_style = Paragraph::RectWidthStyle::kMax; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 17.433594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 88.473305); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 67.433594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 88.473305); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 508.09375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 88.473312); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(30, 150, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 8ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 88.473312); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 525.72266); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 168.47331); |
| |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 525.72266); |
| EXPECT_FLOAT_EQ(boxes[1].rect.top(), 88.473312); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 168.4733); |
| |
| EXPECT_FLOAT_EQ(boxes[2].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[2].rect.top(), 168.4733); |
| EXPECT_FLOAT_EQ(boxes[2].rect.right(), 531.60547); |
| EXPECT_FLOAT_EQ(boxes[2].rect.bottom(), 248.47331); |
| |
| EXPECT_FLOAT_EQ(boxes[3].rect.left(), 531.60547); |
| EXPECT_FLOAT_EQ(boxes[3].rect.top(), 168.4733); |
| EXPECT_FLOAT_EQ(boxes[3].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 248.47331); |
| |
| EXPECT_FLOAT_EQ(boxes[4].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[4].rect.top(), 248.47331); |
| EXPECT_FLOAT_EQ(boxes[4].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[4].rect.bottom(), 328.4733); |
| |
| EXPECT_FLOAT_EQ(boxes[5].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[5].rect.top(), 328.47333); |
| EXPECT_FLOAT_EQ(boxes[5].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[5].rect.bottom(), 408.4733); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(19, 22, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 463.75781); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 530.26172); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 88.473305); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_WINDOWS(GetRectsForRangeIncludeLineSpacingTop)) { |
| const char* text = |
| "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1.6; |
| text_style.has_height_override = true; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| // NOTE: The base truth values may still need adjustment as the specifics |
| // are adjusted. |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kIncludeLineSpacingTop; |
| Paragraph::RectWidthStyle rect_width_style = Paragraph::RectWidthStyle::kMax; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 17.433594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 67.433594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 508.09375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(30, 150, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 8ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 80); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 525.72266); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 160); |
| |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 525.72266); |
| EXPECT_FLOAT_EQ(boxes[1].rect.top(), 80); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 160); |
| |
| EXPECT_FLOAT_EQ(boxes[2].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[2].rect.top(), 160); |
| EXPECT_FLOAT_EQ(boxes[2].rect.right(), 531.60547); |
| EXPECT_FLOAT_EQ(boxes[2].rect.bottom(), 240); |
| |
| EXPECT_FLOAT_EQ(boxes[3].rect.left(), 531.60547); |
| EXPECT_FLOAT_EQ(boxes[3].rect.top(), 160); |
| EXPECT_FLOAT_EQ(boxes[3].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 240); |
| |
| EXPECT_FLOAT_EQ(boxes[4].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[4].rect.top(), 240); |
| EXPECT_FLOAT_EQ(boxes[4].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[4].rect.bottom(), 320); |
| |
| EXPECT_FLOAT_EQ(boxes[5].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[5].rect.top(), 320); |
| EXPECT_FLOAT_EQ(boxes[5].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[5].rect.bottom(), 400); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(19, 22, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 463.75781); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 530.26172); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_WINDOWS(GetRectsForRangeIncludeLineSpacingBottom)) { |
| const char* text = |
| "( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)(" |
| " ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)( ´・‿・`)"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1.6; |
| text_style.has_height_override = true; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| // NOTE: The base truth values may still need adjustment as the specifics |
| // are adjusted. |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kIncludeLineSpacingBottom; |
| Paragraph::RectWidthStyle rect_width_style = Paragraph::RectWidthStyle::kMax; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 17.433594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 96.946609); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(2, 8, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 67.433594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 96.946609); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(8, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 508.09375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 96.946609); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(30, 150, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 8ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 190.01953); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 96.946617); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 525.72266); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 176.94661); |
| |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 525.72266); |
| EXPECT_FLOAT_EQ(boxes[1].rect.top(), 96.946617); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[1].rect.bottom(), 176.94661); |
| |
| EXPECT_FLOAT_EQ(boxes[2].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[2].rect.top(), 176.94661); |
| EXPECT_FLOAT_EQ(boxes[2].rect.right(), 531.60547); |
| EXPECT_FLOAT_EQ(boxes[2].rect.bottom(), 256.94662); |
| |
| EXPECT_FLOAT_EQ(boxes[3].rect.left(), 531.60547); |
| EXPECT_FLOAT_EQ(boxes[3].rect.top(), 176.94661); |
| EXPECT_FLOAT_EQ(boxes[3].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[3].rect.bottom(), 256.94662); |
| |
| EXPECT_FLOAT_EQ(boxes[4].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[4].rect.top(), 256.94662); |
| EXPECT_FLOAT_EQ(boxes[4].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[4].rect.bottom(), 336.94662); |
| |
| EXPECT_FLOAT_EQ(boxes[5].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[5].rect.top(), 336.94662); |
| EXPECT_FLOAT_EQ(boxes[5].rect.right(), 570.05859); |
| EXPECT_FLOAT_EQ(boxes[5].rect.bottom(), 416.94662); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(19, 22, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 463.75781); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 16.946615); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 530.26172); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 96.946609); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, GetRectsForRangeIncludeCombiningCharacter) { |
| const char* text = "ดีสวัสดีชาวโลกที่น่ารัก"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 1; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| // Case when the sentence starts with a combining character |
| // We should get 0 box for ด because it's already been combined to ดี |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(1, 2, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 2, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| // Case when the sentence contains a combining character |
| // We should get 0 box for ว because it's already been combined to วั |
| boxes = |
| paragraph->GetRectsForRange(3, 4, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(4, 5, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(3, 5, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| // Case when the sentence contains a combining character that contain 3 |
| // characters We should get 0 box for ท and ที because it's already been |
| // combined to ที่ |
| boxes = |
| paragraph->GetRectsForRange(14, 15, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(16, 17, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 1ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(14, 17, rect_height_style, rect_width_style); |
| EXPECT_EQ(boxes.size(), 1ull); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeCenterParagraph)) { |
| const char* text = "01234 "; // includes ideographic space |
| // and english space. |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::center; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 203.95508); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 232.37305); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(2, 4, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 260.79102); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 317.62695); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(4, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 2ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 317.62695); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 346.04492); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorBLACK); |
| boxes = |
| paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 346.04492); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 358.49805); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(GetRectsForRangeParagraphNewlineLeftAlign)) { |
| const char* text = "01234\n\nعab\naعلی\n"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.font_family = "Roboto"; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_direction = TextDirection::ltr; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = {"Roboto", "Noto Naskh Arabic"}; |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 28.417969); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(6, 7, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), |
| 75); // TODO(garyq): This value can be improved... Should be |
| // taller, but we need a good way to obtain a height |
| // without any glyphs on the line. |
| |
| boxes = |
| paragraph->GetRectsForRange(10, 11, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 85); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 85); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 160); |
| |
| boxes = |
| paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 27); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 27); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 245); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(GetRectsForRangeParagraphNewlineRightAlign)) { |
| const char* text = "01234\n\nعab\naعلی\n"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.font_family = "Roboto"; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_direction = TextDirection::ltr; |
| paragraph_style.text_align = TextAlign::right; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = {"Roboto", "Noto Naskh Arabic"}; |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 407.91016); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 436.32812); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(6, 7, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 550); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 550); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), |
| 75); // TODO(garyq): This value can be improved... Should be |
| // taller, but we need a good way to obtain a height |
| // without any glyphs on the line. |
| |
| boxes = |
| paragraph->GetRectsForRange(10, 11, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 550); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 550); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 160); |
| |
| boxes = |
| paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 478); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 478); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 245); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| LINUX_ONLY(GetRectsForRangeCenterParagraphNewlineCentered)) { |
| const char* text = "01234\n\nعab\naعلی\n"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.font_family = "Roboto"; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_direction = TextDirection::ltr; |
| paragraph_style.text_align = TextAlign::center; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = {"Roboto", "Noto Naskh Arabic"}; |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 203.95508); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 232.37305); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(6, 7, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 275); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 275); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), |
| 75); // TODO(garyq): This value can be improved... Should be |
| // taller, but we need a good way to obtain a height |
| // without any glyphs on the line. |
| |
| boxes = |
| paragraph->GetRectsForRange(10, 11, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 317); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 317); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 160); |
| |
| boxes = |
| paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 252); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 252); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 245); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| LINUX_ONLY(GetRectsForRangeParagraphNewlineRTLLeftAlign)) { |
| const char* text = "01234\n\nعab\naعلی\n"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.font_family = "Roboto"; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_direction = TextDirection::rtl; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = {"Roboto", "Noto Naskh Arabic"}; |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 28.417969); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(6, 7, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), |
| 75); // TODO(garyq): This value can be improved... Should be |
| // taller, but we need a good way to obtain a height |
| // without any glyphs on the line. |
| |
| boxes = |
| paragraph->GetRectsForRange(10, 11, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 55); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 55); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 160); |
| |
| boxes = |
| paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 245); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| LINUX_ONLY(GetRectsForRangeParagraphNewlineRTLRightAlign)) { |
| const char* text = "01234\n\nعab\naعلی\n"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.font_family = "Roboto"; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_direction = TextDirection::rtl; |
| paragraph_style.text_align = TextAlign::right; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = {"Roboto", "Noto Naskh Arabic"}; |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 407.91016); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 436.32812); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(6, 7, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 550); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 550); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), |
| 75); // TODO(garyq): This value can be improved... Should be |
| // taller, but we need a good way to obtain a height |
| // without any glyphs on the line. |
| |
| boxes = |
| paragraph->GetRectsForRange(10, 11, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 519); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 519); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 160); |
| |
| boxes = |
| paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 451); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 451); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 245); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| LINUX_ONLY(GetRectsForRangeCenterParagraphNewlineRTLCentered)) { |
| const char* text = "01234\n\nعab\naعلی\n"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.font_family = "Roboto"; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_direction = TextDirection::rtl; |
| paragraph_style.text_align = TextAlign::center; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = {"Roboto", "Noto Naskh Arabic"}; |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 203.95508); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 232.37305); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(6, 7, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 275); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 275); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), |
| 75); // TODO(garyq): This value can be improved... Should be |
| // taller, but we need a good way to obtain a height |
| // without any glyphs on the line. |
| |
| boxes = |
| paragraph->GetRectsForRange(10, 11, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 287); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 287); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 160); |
| |
| boxes = |
| paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 225); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 225); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 245); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, |
| DISABLE_ON_WINDOWS(GetRectsForRangeCenterMultiLineParagraph)) { |
| const char* text = "01234 \n0123 "; // includes ideographic |
| // space and english space. |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::center; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 203.95508); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 232.37305); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorBLUE); |
| boxes = |
| paragraph->GetRectsForRange(2, 4, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 260.79102); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 317.62695); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorGREEN); |
| boxes = |
| paragraph->GetRectsForRange(4, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 2ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 317.62695); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 346.04492); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorBLACK); |
| boxes = |
| paragraph->GetRectsForRange(5, 6, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 346.04492); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 358.49805); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| |
| paint.setColor(SK_ColorBLACK); |
| boxes = |
| paragraph->GetRectsForRange(10, 12, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 218.16406); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 59.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 275); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 118); |
| |
| paint.setColor(SK_ColorBLACK); |
| boxes = |
| paragraph->GetRectsForRange(14, 18, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 331.83594); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 59.40625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 419.19531); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 118); |
| |
| paint.setColor(SK_ColorRED); |
| boxes = |
| paragraph->GetRectsForRange(21, 21, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(GetRectsForRangeStrut)) { |
| const char* text = "Chinese 字典"; |
| |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.strut_enabled = true; |
| paragraph_style.strut_font_families.push_back("Roboto"); |
| paragraph_style.strut_font_size = 14; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families.push_back("Noto Sans CJK JP"); |
| text_style.font_size = 20; |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| std::vector<txt::Paragraph::TextBox> strut_boxes = |
| paragraph->GetRectsForRange(0, 10, Paragraph::RectHeightStyle::kStrut, |
| Paragraph::RectWidthStyle::kMax); |
| ASSERT_EQ(strut_boxes.size(), 1ull); |
| const SkRect& strut_rect = strut_boxes.front().rect; |
| paint.setColor(SK_ColorRED); |
| GetCanvas()->drawRect(strut_rect, paint); |
| |
| std::vector<txt::Paragraph::TextBox> tight_boxes = |
| paragraph->GetRectsForRange(0, 10, Paragraph::RectHeightStyle::kTight, |
| Paragraph::RectWidthStyle::kMax); |
| ASSERT_EQ(tight_boxes.size(), 1ull); |
| const SkRect& tight_rect = tight_boxes.front().rect; |
| paint.setColor(SK_ColorGREEN); |
| GetCanvas()->drawRect(tight_rect, paint); |
| |
| EXPECT_FLOAT_EQ(strut_rect.left(), 0); |
| EXPECT_FLOAT_EQ(strut_rect.top(), 10.611719); |
| EXPECT_FLOAT_EQ(strut_rect.right(), 118.61719); |
| EXPECT_FLOAT_EQ(strut_rect.bottom(), 27.017969); |
| |
| ASSERT_TRUE(tight_rect.contains(strut_rect)); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeStrutFallback)) { |
| const char* text = "Chinese 字典"; |
| |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.strut_enabled = false; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families.push_back("Noto Sans CJK JP"); |
| text_style.font_size = 20; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| std::vector<txt::Paragraph::TextBox> strut_boxes = |
| paragraph->GetRectsForRange(0, 10, Paragraph::RectHeightStyle::kStrut, |
| Paragraph::RectWidthStyle::kMax); |
| std::vector<txt::Paragraph::TextBox> tight_boxes = |
| paragraph->GetRectsForRange(0, 10, Paragraph::RectHeightStyle::kTight, |
| Paragraph::RectWidthStyle::kMax); |
| |
| ASSERT_EQ(strut_boxes.size(), 1ull); |
| ASSERT_EQ(tight_boxes.size(), 1ull); |
| ASSERT_EQ(strut_boxes.front().rect, tight_boxes.front().rect); |
| } |
| |
| SkRect GetCoordinatesForGlyphPosition(txt::Paragraph& paragraph, size_t pos) { |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph.GetRectsForRange(pos, pos + 1, Paragraph::RectHeightStyle::kMax, |
| Paragraph::RectWidthStyle::kTight); |
| return !boxes.empty() ? boxes.front().rect : SkRect::MakeEmpty(); |
| } |
| |
| TEST_F(ParagraphTest, GetWordBoundaryParagraph) { |
| const char* text = |
| "12345 67890 12345 67890 12345 67890 12345 67890 12345 67890 12345 " |
| "67890 12345"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 52; |
| text_style.letter_spacing = 1.19039; |
| text_style.word_spacing = 5; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1.5; |
| text_style.has_height_override = true; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| paint.setColor(SK_ColorRED); |
| |
| SkRect rect = GetCoordinatesForGlyphPosition(*paragraph, 0); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| EXPECT_EQ(paragraph->GetWordBoundary(0), txt::Paragraph::Range<size_t>(0, 5)); |
| EXPECT_EQ(paragraph->GetWordBoundary(1), txt::Paragraph::Range<size_t>(0, 5)); |
| EXPECT_EQ(paragraph->GetWordBoundary(2), txt::Paragraph::Range<size_t>(0, 5)); |
| EXPECT_EQ(paragraph->GetWordBoundary(3), txt::Paragraph::Range<size_t>(0, 5)); |
| EXPECT_EQ(paragraph->GetWordBoundary(4), txt::Paragraph::Range<size_t>(0, 5)); |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 5); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| EXPECT_EQ(paragraph->GetWordBoundary(5), txt::Paragraph::Range<size_t>(5, 7)); |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 6); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| EXPECT_EQ(paragraph->GetWordBoundary(6), txt::Paragraph::Range<size_t>(5, 7)); |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 7); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| EXPECT_EQ(paragraph->GetWordBoundary(7), |
| txt::Paragraph::Range<size_t>(7, 12)); |
| EXPECT_EQ(paragraph->GetWordBoundary(8), |
| txt::Paragraph::Range<size_t>(7, 12)); |
| EXPECT_EQ(paragraph->GetWordBoundary(9), |
| txt::Paragraph::Range<size_t>(7, 12)); |
| EXPECT_EQ(paragraph->GetWordBoundary(10), |
| txt::Paragraph::Range<size_t>(7, 12)); |
| EXPECT_EQ(paragraph->GetWordBoundary(11), |
| txt::Paragraph::Range<size_t>(7, 12)); |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 12); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| EXPECT_EQ(paragraph->GetWordBoundary(12), |
| txt::Paragraph::Range<size_t>(12, 13)); |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 13); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| EXPECT_EQ(paragraph->GetWordBoundary(13), |
| txt::Paragraph::Range<size_t>(13, 18)); |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 18); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 19); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 24); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 25); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 30); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| EXPECT_EQ(paragraph->GetWordBoundary(30), |
| txt::Paragraph::Range<size_t>(30, 31)); |
| rect = GetCoordinatesForGlyphPosition(*paragraph, 31); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| rect = GetCoordinatesForGlyphPosition(*paragraph, icu_text.length() - 5); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| EXPECT_EQ( |
| paragraph->GetWordBoundary(icu_text.length() - 1), |
| txt::Paragraph::Range<size_t>(icu_text.length() - 5, icu_text.length())); |
| rect = GetCoordinatesForGlyphPosition(*paragraph, icu_text.length()); |
| GetCanvas()->drawLine(rect.fLeft, rect.fTop, rect.fLeft, rect.fBottom, paint); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, SpacingParagraph) { |
| const char* text = "H"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 20; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| builder.Pop(); |
| |
| text_style.font_size = 50; |
| text_style.letter_spacing = 10; |
| text_style.word_spacing = 0; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| builder.Pop(); |
| |
| text_style.font_size = 50; |
| text_style.letter_spacing = 20; |
| text_style.word_spacing = 0; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| builder.Pop(); |
| |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| builder.PushStyle(text_style); |
| builder.AddText(u"|"); |
| builder.Pop(); |
| |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 20; |
| builder.PushStyle(text_style); |
| builder.AddText(u"H "); |
| builder.Pop(); |
| |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| builder.PushStyle(text_style); |
| builder.AddText(u"H "); |
| builder.Pop(); |
| |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 20; |
| builder.PushStyle(text_style); |
| builder.AddText(u"H "); |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| paint.setColor(SK_ColorRED); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| ASSERT_EQ(paragraph->records_.size(), 7ull); |
| ASSERT_EQ(paragraph->records_[0].style().letter_spacing, 20); |
| ASSERT_EQ(paragraph->records_[1].style().letter_spacing, 10); |
| ASSERT_EQ(paragraph->records_[2].style().letter_spacing, 20); |
| |
| ASSERT_EQ(paragraph->records_[4].style().word_spacing, 20); |
| ASSERT_EQ(paragraph->records_[5].style().word_spacing, 0); |
| ASSERT_EQ(paragraph->records_[6].style().word_spacing, 20); |
| } |
| |
| TEST_F(ParagraphTest, LongWordParagraph) { |
| const char* text = |
| "A " |
| "veryverylongwordtoseewherethiswillwraporifitwillatallandifitdoesthenthat" |
| "wouldbeagoodthingbecausethebreakingisworking."; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 31; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() / 2); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_EQ(paragraph->GetLineCount(), 4ull); |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(KernScaleParagraph)) { |
| float scale = 3.0f; |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Droid Serif"); |
| text_style.font_size = 100 / scale; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| builder.AddText(u"AVAVAWAH A0 V0 VA To The Lo"); |
| builder.PushStyle(text_style); |
| builder.AddText(u"A"); |
| builder.PushStyle(text_style); |
| builder.AddText(u"V"); |
| text_style.font_size = 14 / scale; |
| builder.PushStyle(text_style); |
| builder.AddText( |
| u" Dialog Text List lots of words to see if kerning works on a bigger " |
| u"set of characters AVAVAW"); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() / scale); |
| GetCanvas()->scale(scale, scale); |
| paragraph->Paint(GetCanvas(), 0, 0); |
| GetCanvas()->scale(1.0, 1.0); |
| ASSERT_TRUE(Snapshot()); |
| |
| EXPECT_DOUBLE_EQ(paragraph->records_[0].offset().x(), 0); |
| EXPECT_DOUBLE_EQ(paragraph->records_[1].offset().x(), 0); |
| EXPECT_DOUBLE_EQ(paragraph->records_[2].offset().x(), 207.359375f); |
| EXPECT_DOUBLE_EQ(paragraph->records_[3].offset().x(), 230.859375f); |
| EXPECT_DOUBLE_EQ(paragraph->records_[4].offset().x(), 253.34765625f); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(NewlineParagraph)) { |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.font_family = "Roboto"; |
| paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality; |
| |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 60; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| builder.AddText( |
| u"line1\nline2 test1 test2 test3 test4 test5 test6 test7\nline3\n\nline4 " |
| "test1 test2 test3 test4"); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 300); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| ASSERT_EQ(paragraph->records_.size(), 6ull); |
| EXPECT_DOUBLE_EQ(paragraph->records_[0].offset().x(), 0); |
| EXPECT_DOUBLE_EQ(paragraph->records_[1].offset().x(), 0); |
| EXPECT_DOUBLE_EQ(paragraph->records_[1].offset().y(), 126); |
| EXPECT_DOUBLE_EQ(paragraph->records_[2].offset().x(), 0); |
| EXPECT_DOUBLE_EQ(paragraph->records_[3].offset().x(), 0); |
| EXPECT_DOUBLE_EQ(paragraph->records_[4].offset().x(), 0); |
| EXPECT_DOUBLE_EQ(paragraph->records_[3].offset().y(), 266); |
| EXPECT_DOUBLE_EQ(paragraph->records_[5].offset().x(), 0); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(EmojiParagraph)) { |
| const char* text = |
| "😀😃😄😁😆😅😂🤣☺😇🙂😍😡😟😢😻👽💩👍👎🙏👌👋👄👁👦👼👨🚀👨🚒🙋♂️👳👨👨👧👧\ |
| 💼👡👠☂🐶🐰🐻🐼🐷🐒🐵🐔🐧🐦🐋🐟🐡🕸🐌🐴🐊🐄🐪🐘🌸🌏🔥🌟🌚🌝💦💧\ |
| ❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓\ |
| 📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.color = SK_ColorBLACK; |
| text_style.font_families = std::vector<std::string>(1, "Noto Color Emoji"); |
| text_style.font_size = 50; |
| text_style.decoration = TextDecoration::kUnderline; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| |
| ASSERT_EQ(paragraph->records_.size(), 8ull); |
| |
| EXPECT_EQ(paragraph->records_[0].line(), 0ull); |
| EXPECT_EQ(paragraph->records_[1].line(), 1ull); |
| EXPECT_EQ(paragraph->records_[2].line(), 2ull); |
| EXPECT_EQ(paragraph->records_[3].line(), 3ull); |
| EXPECT_EQ(paragraph->records_[7].line(), 7ull); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(EmojiMultiLineRectsParagraph)) { |
| // clang-format off |
| const char* text = |
| "👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧i🇺🇸👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸" |
| "👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸" |
| "👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸" |
| "👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸👩👩👦👩👩👧👧🇺🇸" |
| "❄🍕🍔🍟🥝🍱🕶🎩🏈⚽🚴♀️🎻🎼🎹🚨🚎🚐⚓🛳🚀🚁🏪🏢🖱⏰📱💾💉📉🛏🔑🔓" |
| "📁🗓📊❤💯🚫🔻♠♣🕓❗🏳🏁🏳️🌈🇮🇹🇱🇷🇺🇸🇬🇧🇨🇳🇧🇴"; |
| // clang-format on |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.color = SK_ColorBLACK; |
| text_style.font_families = std::vector<std::string>(1, "Noto Color Emoji"); |
| text_style.font_size = 50; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 300); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| |
| ASSERT_EQ(paragraph->records_.size(), 10ull); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| // GetPositionForCoordinates should not return inter-emoji positions. |
| boxes = paragraph->GetRectsForRange( |
| 0, paragraph->GetGlyphPositionAtCoordinate(610, 100).position, |
| rect_height_style, rect_width_style); |
| paint.setColor(SK_ColorGREEN); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 2ull); |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 622.53906); |
| |
| boxes = paragraph->GetRectsForRange( |
| 0, paragraph->GetGlyphPositionAtCoordinate(580, 100).position, |
| rect_height_style, rect_width_style); |
| paint.setColor(SK_ColorGREEN); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 2ull); |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 560.28516); |
| |
| boxes = paragraph->GetRectsForRange( |
| 0, paragraph->GetGlyphPositionAtCoordinate(560, 100).position, |
| rect_height_style, rect_width_style); |
| paint.setColor(SK_ColorGREEN); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 2ull); |
| EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[1].rect.right(), 560.28516); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(LigatureCharacters)) { |
| const char* text = "Office"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| // The "ffi" characters will be combined into one glyph in the Roboto font. |
| // Verify that the graphemes within the glyph have distinct boxes. |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(1, 2, Paragraph::RectHeightStyle::kTight, |
| Paragraph::RectWidthStyle::kTight); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 9.625); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 13.608073); |
| |
| boxes = paragraph->GetRectsForRange(2, 4, Paragraph::RectHeightStyle::kTight, |
| Paragraph::RectWidthStyle::kTight); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 13.608073); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 21.574219); |
| } |
| |
| TEST_F(ParagraphTest, HyphenBreakParagraph) { |
| const char* text = |
| "A " |
| "very-very-long-Hyphen-word-to-see-where-this-will-wrap-or-if-it-will-at-" |
| "all-and-if-it-does-thent-hat-" |
| "would-be-a-good-thing-because-the-breaking."; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality; |
| |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 31; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() / 2); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_EQ(paragraph->GetLineCount(), 5ull); |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, RepeatLayoutParagraph) { |
| const char* text = |
| "Sentence to layout at diff widths to get diff line counts. short words " |
| "short words short words short words short words short words short words " |
| "short words short words short words short words short words short words " |
| "end"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.break_strategy = minikin::kBreakStrategy_HighQuality; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 31; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| // First Layout. |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(300); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_EQ(paragraph->GetLineCount(), 12ull); |
| |
| // Second Layout. |
| SetUp(); |
| paragraph->Layout(600); |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| ASSERT_EQ(paragraph->GetLineCount(), 6ull); |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, Ellipsize) { |
| const char* text = |
| "This is a very long sentence to test if the text will properly wrap " |
| "around and go to the next line. Sometimes, short sentence. Longer " |
| "sentences are okay too because they are necessary. Very short. "; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.ellipsis = u"\u2026"; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| // Check that the ellipsizer limited the text to one line and did not wrap |
| // to a second line. |
| ASSERT_EQ(paragraph->records_.size(), 1ull); |
| } |
| |
| // Test for shifting when identical runs of text are built as multiple runs. |
| TEST_F(ParagraphTest, UnderlineShiftParagraph) { |
| const char* text1 = "fluttser "; |
| auto icu_text1 = icu::UnicodeString::fromUTF8(text1); |
| std::u16string u16_text1(icu_text1.getBuffer(), |
| icu_text1.getBuffer() + icu_text1.length()); |
| const char* text2 = "mdje"; |
| auto icu_text2 = icu::UnicodeString::fromUTF8(text2); |
| std::u16string u16_text2(icu_text2.getBuffer(), |
| icu_text2.getBuffer() + icu_text2.length()); |
| const char* text3 = "fluttser mdje"; |
| auto icu_text3 = icu::UnicodeString::fromUTF8(text3); |
| std::u16string u16_text3(icu_text3.getBuffer(), |
| icu_text3.getBuffer() + icu_text3.length()); |
| |
| // Construct multi-run paragraph. |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 2; |
| paragraph_style.text_align = TextAlign::left; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style1; |
| text_style1.color = SK_ColorBLACK; |
| text_style1.font_families = std::vector<std::string>(1, "Roboto"); |
| builder.PushStyle(text_style1); |
| |
| builder.AddText(u16_text1); |
| |
| txt::TextStyle text_style2; |
| text_style2.color = SK_ColorBLACK; |
| text_style2.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style2.decoration = TextDecoration::kUnderline; |
| text_style2.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style2); |
| |
| builder.AddText(u16_text2); |
| |
| builder.Pop(); |
| |
| // Construct single run paragraph. |
| txt::ParagraphBuilderTxt builder2(paragraph_style, GetTestFontCollection()); |
| |
| builder2.PushStyle(text_style1); |
| |
| builder2.AddText(u16_text3); |
| |
| builder2.Pop(); |
| |
| // Build multi-run paragraph |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| // Build single-run paragraph |
| auto paragraph2 = BuildParagraph(builder2); |
| paragraph2->Layout(GetTestCanvasWidth()); |
| |
| paragraph2->Paint(GetCanvas(), 0, 25); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| ASSERT_EQ(paragraph->records_[0].GetRunWidth() + |
| paragraph->records_[1].GetRunWidth(), |
| paragraph2->records_[0].GetRunWidth()); |
| |
| auto rects1 = |
| paragraph->GetRectsForRange(0, 12, Paragraph::RectHeightStyle::kMax, |
| Paragraph::RectWidthStyle::kTight); |
| auto rects2 = |
| paragraph2->GetRectsForRange(0, 12, Paragraph::RectHeightStyle::kMax, |
| Paragraph::RectWidthStyle::kTight); |
| |
| for (size_t i = 0; i < 12; ++i) { |
| auto r1 = GetCoordinatesForGlyphPosition(*paragraph, i); |
| auto r2 = GetCoordinatesForGlyphPosition(*paragraph2, i); |
| |
| ASSERT_EQ(r1.fLeft, r2.fLeft); |
| ASSERT_EQ(r1.fRight, r2.fRight); |
| } |
| } |
| |
| TEST_F(ParagraphTest, SimpleShadow) { |
| const char* text = "Hello World Text Dialog"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| text_style.text_shadows.emplace_back(SK_ColorBLACK, SkPoint::Make(2.0, 2.0), |
| 1.0); |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length()); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull); |
| ASSERT_EQ(paragraph->runs_.styles_.size(), 2ull); |
| ASSERT_TRUE(paragraph->runs_.styles_[1].equals(text_style)); |
| ASSERT_EQ(paragraph->records_[0].style().color, text_style.color); |
| |
| ASSERT_EQ(paragraph->records_[0].style().text_shadows.size(), 1ull); |
| ASSERT_EQ(paragraph->records_[0].style().text_shadows[0], |
| text_style.text_shadows[0]); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, ComplexShadow) { |
| const char* text = "Text Chunk "; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| text_style.text_shadows.emplace_back(SK_ColorBLACK, SkPoint::Make(2.0, 2.0), |
| 1.0); |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| text_style.text_shadows.emplace_back(SK_ColorRED, SkPoint::Make(2.0, 2.0), |
| 5.0); |
| text_style.text_shadows.emplace_back(SK_ColorGREEN, SkPoint::Make(10.0, -5.0), |
| 3.0); |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| builder.AddText(u16_text); |
| |
| text_style.text_shadows.emplace_back(SK_ColorGREEN, SkPoint::Make(0.0, -1.0), |
| 0.0); |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->text_.size(), std::string{text}.length() * 5); |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| |
| ASSERT_EQ(paragraph->records_[0].style().text_shadows.size(), 1ull); |
| ASSERT_EQ(paragraph->records_[1].style().text_shadows.size(), 3ull); |
| ASSERT_EQ(paragraph->records_[2].style().text_shadows.size(), 1ull); |
| ASSERT_EQ(paragraph->records_[3].style().text_shadows.size(), 4ull); |
| ASSERT_EQ(paragraph->records_[4].style().text_shadows.size(), 1ull); |
| for (size_t i = 0; i < 1; ++i) |
| ASSERT_EQ(paragraph->records_[0].style().text_shadows[i], |
| text_style.text_shadows[i]); |
| for (size_t i = 0; i < 3; ++i) |
| ASSERT_EQ(paragraph->records_[1].style().text_shadows[i], |
| text_style.text_shadows[i]); |
| for (size_t i = 0; i < 1; ++i) |
| ASSERT_EQ(paragraph->records_[2].style().text_shadows[i], |
| text_style.text_shadows[i]); |
| for (size_t i = 0; i < 4; ++i) |
| ASSERT_EQ(paragraph->records_[3].style().text_shadows[i], |
| text_style.text_shadows[i]); |
| for (size_t i = 0; i < 1; ++i) |
| ASSERT_EQ(paragraph->records_[4].style().text_shadows[i], |
| text_style.text_shadows[i]); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_MAC(BaselineParagraph)) { |
| const char* text = |
| "左線読設Byg後碁給能上目秘使約。満毎冠行来昼本可必図将発確年。今属場育" |
| "図情闘陰野高備込制詩西校客。審対江置講今固残必託地集済決維駆年策。立得"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 14; |
| paragraph_style.text_align = TextAlign::justify; |
| paragraph_style.height = 1.5; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.color = SK_ColorBLACK; |
| text_style.font_size = 55; |
| text_style.letter_spacing = 2; |
| text_style.font_families = std::vector<std::string>(1, "Source Han Serif CN"); |
| text_style.decoration_style = txt::TextDecorationStyle::kSolid; |
| text_style.decoration_color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 100); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| paint.setColor(SK_ColorRED); |
| GetCanvas()->drawLine(0, paragraph->GetIdeographicBaseline(), |
| paragraph->GetMaxWidth(), |
| paragraph->GetIdeographicBaseline(), paint); |
| |
| paint.setColor(SK_ColorGREEN); |
| |
| GetCanvas()->drawLine(0, paragraph->GetAlphabeticBaseline(), |
| paragraph->GetMaxWidth(), |
| paragraph->GetAlphabeticBaseline(), paint); |
| ASSERT_DOUBLE_EQ(paragraph->GetIdeographicBaseline(), 79.035000801086426); |
| ASSERT_DOUBLE_EQ(paragraph->GetAlphabeticBaseline(), 63.305000305175781); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, FontFallbackParagraph) { |
| const char* text = "Roboto 字典 "; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| const char* text2 = "Homemade Apple 字典"; |
| icu_text = icu::UnicodeString::fromUTF8(text2); |
| std::u16string u16_text2(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| const char* text3 = "Chinese 字典"; |
| icu_text = icu::UnicodeString::fromUTF8(text3); |
| std::u16string u16_text3(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| // No chinese fallback provided, should not be able to render the chinese. |
| text_style.font_families = std::vector<std::string>(1, "Not a real font"); |
| text_style.font_families.push_back("Also a fake font"); |
| text_style.font_families.push_back("So fake it is obvious"); |
| text_style.font_families.push_back("Next one should be a real font..."); |
| text_style.font_families.push_back("Roboto"); |
| text_style.font_families.push_back("another fake one in between"); |
| text_style.font_families.push_back("Homemade Apple"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| // Japanese version of the chinese should be rendered. |
| text_style.font_families = std::vector<std::string>(1, "Not a real font"); |
| text_style.font_families.push_back("Also a fake font"); |
| text_style.font_families.push_back("So fake it is obvious"); |
| text_style.font_families.push_back("Homemade Apple"); |
| text_style.font_families.push_back("Next one should be a real font..."); |
| text_style.font_families.push_back("Roboto"); |
| text_style.font_families.push_back("another fake one in between"); |
| text_style.font_families.push_back("Noto Sans CJK JP"); |
| text_style.font_families.push_back("Source Han Serif CN"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text2); |
| |
| // Chinese font defiend first |
| text_style.font_families = std::vector<std::string>(1, "Not a real font"); |
| text_style.font_families.push_back("Also a fake font"); |
| text_style.font_families.push_back("So fake it is obvious"); |
| text_style.font_families.push_back("Homemade Apple"); |
| text_style.font_families.push_back("Next one should be a real font..."); |
| text_style.font_families.push_back("Roboto"); |
| text_style.font_families.push_back("another fake one in between"); |
| text_style.font_families.push_back("Source Han Serif CN"); |
| text_style.font_families.push_back("Noto Sans CJK JP"); |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text3); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_TRUE(Snapshot()); |
| |
| ASSERT_EQ(paragraph->records_.size(), 5ull); |
| ASSERT_DOUBLE_EQ(paragraph->records_[0].GetRunWidth(), 64.2109375); |
| ASSERT_DOUBLE_EQ(paragraph->records_[1].GetRunWidth(), 139.1328125); |
| ASSERT_DOUBLE_EQ(paragraph->records_[2].GetRunWidth(), 28); |
| ASSERT_DOUBLE_EQ(paragraph->records_[3].GetRunWidth(), 62.25); |
| ASSERT_DOUBLE_EQ(paragraph->records_[4].GetRunWidth(), 28); |
| // When a different font is resolved, then the metrics are different. |
| ASSERT_TRUE(paragraph->records_[2].metrics().fTop - |
| paragraph->records_[4].metrics().fTop != |
| 0); |
| ASSERT_TRUE(paragraph->records_[2].metrics().fAscent - |
| paragraph->records_[4].metrics().fAscent != |
| 0); |
| ASSERT_TRUE(paragraph->records_[2].metrics().fDescent - |
| paragraph->records_[4].metrics().fDescent != |
| 0); |
| ASSERT_TRUE(paragraph->records_[2].metrics().fBottom - |
| paragraph->records_[4].metrics().fBottom != |
| 0); |
| ASSERT_TRUE(paragraph->records_[2].metrics().fAvgCharWidth - |
| paragraph->records_[4].metrics().fAvgCharWidth != |
| 0); |
| } |
| |
| TEST_F(ParagraphTest, LINUX_ONLY(StrutParagraph1)) { |
| // The chinese extra height should be absorbed by the strut. |
| const char* text = "01234満毎冠p来É本可\nabcd\n満毎É行p昼本可"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.strut_font_families = std::vector<std::string>(1, "BlahFake"); |
| paragraph_style.strut_font_families.push_back("ahem"); |
| paragraph_style.strut_font_size = 50; |
| paragraph_style.strut_height = 1.8; |
| paragraph_style.strut_has_height_override = true; |
| paragraph_style.strut_leading = 0.1; |
| paragraph_style.strut_enabled = true; |
| |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "ahem"); |
| text_style.font_families.push_back("ahem"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = .5; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_max_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 34.5, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 84.5, 0.0001); |
| |
| boxes = paragraph->GetRectsForRange(0, 1, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 0, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 95); |
| |
| boxes = |
| paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300); |
| EXPECT_NEAR(boxes[0].rect.top(), 34.5, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 84.5, 0.0001); |
| ; |
| |
| boxes = paragraph->GetRectsForRange(6, 10, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300); |
| EXPECT_NEAR(boxes[0].rect.top(), 0, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 95); |
| |
| boxes = paragraph->GetRectsForRange(14, 16, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 190, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 100); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 285); |
| |
| boxes = paragraph->GetRectsForRange(20, 25, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 50); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 285); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 300); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 380); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutParagraph2)) { |
| // This string is all one size and smaller than the strut metrics. |
| const char* text = "01234ABCDEFGH\nabcd\nABCDEFGH"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.strut_font_families = std::vector<std::string>(1, "ahem"); |
| paragraph_style.strut_font_size = 50; |
| paragraph_style.strut_height = 1.6; |
| paragraph_style.strut_has_height_override = true; |
| paragraph_style.strut_enabled = true; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "ahem"); |
| text_style.font_families.push_back("ahem"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_max_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 24, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 74, 0.0001); |
| |
| boxes = paragraph->GetRectsForRange(0, 1, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 0, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80); |
| |
| boxes = |
| paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300); |
| EXPECT_NEAR(boxes[0].rect.top(), 24, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 74, 0.0001); |
| |
| boxes = paragraph->GetRectsForRange(6, 10, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300); |
| EXPECT_NEAR(boxes[0].rect.top(), 0, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80); |
| |
| boxes = paragraph->GetRectsForRange(14, 16, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 160, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 100); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 240); |
| |
| boxes = paragraph->GetRectsForRange(20, 25, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 50); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 240); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 300); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 320); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutParagraph3)) { |
| // The strut is too small to absorb the extra chinese height, but the english |
| // second line height is increased due to strut. |
| const char* text = "01234満毎p行来昼本可\nabcd\n満毎冠行来昼本可"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.strut_font_families = std::vector<std::string>(1, "ahem"); |
| paragraph_style.strut_font_size = 50; |
| paragraph_style.strut_height = 1.2; |
| paragraph_style.strut_has_height_override = true; |
| paragraph_style.strut_enabled = true; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "ahem"); |
| text_style.font_families.push_back("ahem"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.font_weight = FontWeight::w500; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_max_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 8, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 58, 0.0001); |
| |
| boxes = paragraph->GetRectsForRange(0, 1, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 0, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 60); |
| |
| boxes = |
| paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300); |
| EXPECT_NEAR(boxes[0].rect.top(), 8, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 58, 0.0001); |
| |
| boxes = paragraph->GetRectsForRange(6, 10, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300); |
| EXPECT_NEAR(boxes[0].rect.top(), 0, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 60); |
| |
| boxes = paragraph->GetRectsForRange(14, 16, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 120); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 100); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 180); |
| |
| boxes = paragraph->GetRectsForRange(20, 25, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 50); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 180); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 300); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 240); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutForceParagraph)) { |
| // The strut is too small to absorb the extra chinese height, but the english |
| // second line height is increased due to strut. |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.strut_font_families = std::vector<std::string>(1, "ahem"); |
| paragraph_style.strut_font_size = 50; |
| paragraph_style.strut_height = 1.5; |
| paragraph_style.strut_has_height_override = true; |
| paragraph_style.strut_leading = 0.1; |
| paragraph_style.force_strut_height = true; |
| paragraph_style.strut_enabled = true; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "ahem"); |
| text_style.font_families.push_back("ahem"); |
| text_style.font_size = 50; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_max_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 22.5, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 72.5, 0.0001); |
| |
| boxes = paragraph->GetRectsForRange(0, 1, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 0, 0.0001); |
| ; |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 50); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80); |
| |
| boxes = |
| paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300); |
| EXPECT_NEAR(boxes[0].rect.top(), 22.5, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 72.5, 0.0001); |
| |
| boxes = paragraph->GetRectsForRange(6, 10, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 300); |
| EXPECT_NEAR(boxes[0].rect.top(), 0, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 500); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 80); |
| |
| boxes = paragraph->GetRectsForRange(14, 16, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 160, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 100); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 240); |
| |
| boxes = paragraph->GetRectsForRange(20, 25, rect_height_max_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 50); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 240); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 300); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 320); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| // The height override is disabled for this test. Direct metrics from the font. |
| TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(StrutDefaultParagraph)) { |
| const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.max_lines = 10; |
| paragraph_style.strut_font_families = std::vector<std::string>(1, "ahem"); |
| paragraph_style.strut_font_size = 50; |
| paragraph_style.strut_height = 1.5; |
| paragraph_style.strut_leading = 0.1; |
| paragraph_style.force_strut_height = false; |
| paragraph_style.strut_enabled = true; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "ahem"); |
| text_style.font_families.push_back("ahem"); |
| text_style.font_size = 20; |
| text_style.letter_spacing = 0; |
| text_style.word_spacing = 0; |
| text_style.color = SK_ColorBLACK; |
| text_style.height = 1; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(550); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kTight; |
| Paragraph::RectHeightStyle rect_height_strut_style = |
| Paragraph::RectHeightStyle::kStrut; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| boxes = |
| paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 26.5, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 20); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 46.5, 0.0001); |
| |
| boxes = paragraph->GetRectsForRange(0, 2, rect_height_strut_style, |
| rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_NEAR(boxes[0].rect.top(), 2.5, 0.0001); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 40); |
| EXPECT_NEAR(boxes[0].rect.bottom(), 52.5, 0.0001); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, FontFeaturesParagraph) { |
| const char* text = "12ab\n"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.color = SK_ColorBLACK; |
| text_style.font_features.SetFeature("tnum", 1); |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| text_style.font_features.SetFeature("tnum", 0); |
| text_style.font_features.SetFeature("pnum", 1); |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth()); |
| |
| paragraph->Paint(GetCanvas(), 10.0, 15.0); |
| |
| ASSERT_EQ(paragraph->glyph_lines_.size(), 3ull); |
| |
| // Tabular numbers should have equal widths. |
| const txt::ParagraphTxt::GlyphLine& tnum_line = paragraph->glyph_lines_[0]; |
| ASSERT_EQ(tnum_line.positions.size(), 4ull); |
| EXPECT_FLOAT_EQ(tnum_line.positions[0].x_pos.width(), |
| tnum_line.positions[1].x_pos.width()); |
| |
| // Proportional numbers should have variable widths. |
| const txt::ParagraphTxt::GlyphLine& pnum_line = paragraph->glyph_lines_[1]; |
| ASSERT_EQ(pnum_line.positions.size(), 4ull); |
| EXPECT_NE(pnum_line.positions[0].x_pos.width(), |
| pnum_line.positions[1].x_pos.width()); |
| |
| // Alphabetic characters should be unaffected. |
| EXPECT_FLOAT_EQ(tnum_line.positions[2].x_pos.width(), |
| pnum_line.positions[2].x_pos.width()); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, KhmerLineBreaker) { |
| const char* text = "និងក្មេងចង់ផ្ទៃសមុទ្រសែនខៀវស្រងាត់"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.font_families = std::vector<std::string>(1, "Noto Sans Khmer"); |
| text_style.font_size = 24; |
| text_style.color = SK_ColorBLACK; |
| builder.PushStyle(text_style); |
| |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(200); |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| ASSERT_EQ(paragraph->glyph_lines_.size(), 3ull); |
| EXPECT_EQ(paragraph->glyph_lines_[0].positions.size(), 7ul); |
| EXPECT_EQ(paragraph->glyph_lines_[1].positions.size(), 7ul); |
| EXPECT_EQ(paragraph->glyph_lines_[2].positions.size(), 3ul); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, TextHeightBehaviorRectsParagraph) { |
| // clang-format off |
| const char* text = |
| "line1\nline2\nline3"; |
| // clang-format on |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| paragraph_style.text_height_behavior = |
| txt::TextHeightBehavior::kDisableFirstAscent | |
| txt::TextHeightBehavior::kDisableLastDescent; |
| |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.color = SK_ColorBLACK; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 30; |
| text_style.height = 5; |
| text_style.has_height_override = true; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 300); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| for (size_t i = 0; i < u16_text.length(); i++) { |
| ASSERT_EQ(paragraph->text_[i], u16_text[i]); |
| } |
| |
| ASSERT_EQ(paragraph->records_.size(), 3ull); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 0ull); |
| |
| // First line. Shorter due to disabled height modifications on first ascent. |
| boxes = |
| paragraph->GetRectsForRange(0, 3, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 31.117188); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), -0.08203125); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom() - boxes[0].rect.top(), 59.082031); |
| |
| // Second line. Normal. |
| boxes = |
| paragraph->GetRectsForRange(6, 10, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 47.011719); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 59); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 209); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom() - boxes[0].rect.top(), 150); |
| |
| // Third line. Shorter due to disabled height modifications on last descent |
| boxes = |
| paragraph->GetRectsForRange(12, 17, rect_height_style, rect_width_style); |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| EXPECT_EQ(boxes.size(), 1ull); |
| EXPECT_FLOAT_EQ(boxes[0].rect.left(), 0); |
| EXPECT_FLOAT_EQ(boxes[0].rect.right(), 63.859375); |
| EXPECT_FLOAT_EQ(boxes[0].rect.top(), 208.92578); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 335); |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom() - boxes[0].rect.top(), 126.07422); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| |
| TEST_F(ParagraphTest, MixedTextHeightBehaviorRectsParagraph) { |
| const char* text = "0123456789"; |
| auto icu_text = icu::UnicodeString::fromUTF8(text); |
| std::u16string u16_text(icu_text.getBuffer(), |
| icu_text.getBuffer() + icu_text.length()); |
| |
| txt::ParagraphStyle paragraph_style; |
| // The paragraph's first line and the last line use the font's ascent/descent. |
| paragraph_style.text_height_behavior = |
| txt::TextHeightBehavior::kDisableFirstAscent | |
| txt::TextHeightBehavior::kDisableLastDescent; |
| |
| txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); |
| |
| txt::TextStyle text_style; |
| text_style.color = SK_ColorBLACK; |
| text_style.font_families = std::vector<std::string>(1, "Roboto"); |
| text_style.font_size = 30; |
| text_style.height = 5; |
| text_style.has_height_override = true; |
| text_style.half_leading = true; |
| |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| text_style.half_leading = false; |
| builder.PushStyle(text_style); |
| builder.AddText(u16_text); |
| |
| // 2 identical runs except the first run has half-leading enabled. |
| builder.Pop(); |
| |
| auto paragraph = BuildParagraph(builder); |
| paragraph->Layout(GetTestCanvasWidth() - 300); |
| |
| paragraph->Paint(GetCanvas(), 0, 0); |
| |
| SkPaint paint; |
| paint.setStyle(SkPaint::kStroke_Style); |
| paint.setAntiAlias(true); |
| paint.setStrokeWidth(1); |
| |
| // Tests for GetRectsForRange() |
| Paragraph::RectHeightStyle rect_height_style = |
| Paragraph::RectHeightStyle::kMax; |
| Paragraph::RectWidthStyle rect_width_style = |
| Paragraph::RectWidthStyle::kTight; |
| paint.setColor(SK_ColorRED); |
| std::vector<txt::Paragraph::TextBox> boxes = |
| paragraph->GetRectsForRange(0, 20, rect_height_style, rect_width_style); |
| |
| for (size_t i = 0; i < boxes.size(); ++i) { |
| GetCanvas()->drawRect(boxes[i].rect, paint); |
| } |
| // The kDisableAll flag is applied. |
| EXPECT_GT(boxes.size(), 1ull); |
| // The height of the line equals to the metrics height of the font |
| // (ascent + descent). |
| EXPECT_FLOAT_EQ(boxes[0].rect.bottom() - boxes[0].rect.top(), |
| 27.8320312 + 7.32421875); |
| |
| ASSERT_TRUE(Snapshot()); |
| } |
| } // namespace txt |