diff --git a/third_party/txt/src/txt/paragraph.cc b/third_party/txt/src/txt/paragraph.cc index 4084ccd1de620..d583615f53cde 100644 --- a/third_party/txt/src/txt/paragraph.cc +++ b/third_party/txt/src/txt/paragraph.cc @@ -729,14 +729,15 @@ void Paragraph::Layout(double width, bool force) { auto update_line_metrics = [&](const SkPaint::FontMetrics& metrics, const TextStyle& style) { double line_spacing = - (line_number == 0) - ? -metrics.fAscent * style.height - : (-metrics.fAscent + metrics.fLeading) * style.height; + (line_number == 0) ? -metrics.fAscent * style.height + : (-metrics.fAscent + metrics.fLeading) * + style.height * paragraph_style_.line_height; if (line_spacing > max_line_spacing) { max_line_spacing = line_spacing; if (line_number == 0) { alphabetic_baseline_ = line_spacing; - // TODO(garyq): Properly implement ideographic_baseline_. + // TODO(garyq): Properly implement ideographic_baseline_ and update + // tests. ideographic_baseline_ = (metrics.fUnderlinePosition - metrics.fAscent) * style.height; } diff --git a/third_party/txt/src/txt/paragraph.h b/third_party/txt/src/txt/paragraph.h index 152d6c42c1935..0c31243e79e77 100644 --- a/third_party/txt/src/txt/paragraph.h +++ b/third_party/txt/src/txt/paragraph.h @@ -206,6 +206,7 @@ class Paragraph { FRIEND_TEST(ParagraphTest, RepeatLayoutParagraph); FRIEND_TEST(ParagraphTest, Ellipsize); FRIEND_TEST(ParagraphTest, UnderlineShiftParagraph); + FRIEND_TEST(ParagraphTest, LineHeightsParagraph); // Starting data to layout. std::vector text_; diff --git a/third_party/txt/src/txt/styled_runs.h b/third_party/txt/src/txt/styled_runs.h index 24669e098c2f9..f1ef7dc73e45a 100644 --- a/third_party/txt/src/txt/styled_runs.h +++ b/third_party/txt/src/txt/styled_runs.h @@ -79,6 +79,7 @@ class StyledRuns { FRIEND_TEST(ParagraphTest, HyphenBreakParagraph); FRIEND_TEST(ParagraphTest, RepeatLayoutParagraph); FRIEND_TEST(ParagraphTest, Ellipsize); + FRIEND_TEST(ParagraphTest, LineHeightsParagraph); struct IndexedRun { size_t style_index = 0; diff --git a/third_party/txt/tests/paragraph_unittests.cc b/third_party/txt/tests/paragraph_unittests.cc index 88613b2ec1429..7a821d3d00b6b 100644 --- a/third_party/txt/tests/paragraph_unittests.cc +++ b/third_party/txt/tests/paragraph_unittests.cc @@ -1731,4 +1731,155 @@ TEST_F(ParagraphTest, UnderlineShiftParagraph) { } } +TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(LineHeightsParagraph)) { + 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 nessecary. 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; + double line_height = 2.0; + paragraph_style.line_height = line_height; + txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection()); + + txt::TextStyle text_style; + text_style.font_family = "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 = builder.Build(); + 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 += 27.5 * line_height; + 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 += 27.5 * line_height; + 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 += 27.5 * line_height; + 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 += 27.5 * 10 * line_height; + 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, 68ull); + ASSERT_EQ(paragraph->GetGlyphPositionAtCoordinate(2000, 35).position, 134ull); + + ASSERT_TRUE(Snapshot()); +} + +TEST_F(ParagraphTest, 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.line_height = 1.5; + txt::ParagraphBuilder 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_family = "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 = builder.Build(); + 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(), 70.180000305175781); + ASSERT_DOUBLE_EQ(paragraph->GetAlphabeticBaseline(), 63.305000305175781); + + ASSERT_TRUE(Snapshot()); +} + } // namespace txt