Fix LibTxt/minikin text shifiting when breaking into multiple runs (originally #6184) (#6242)
This is for a test of the beta release patching process documented at https://github.com/flutter/flutter/wiki/Release-process
This is an hopefully harmless arbitrary commit chosen from those that landed after the last beta's commit.
diff --git a/third_party/txt/src/minikin/Layout.cpp b/third_party/txt/src/minikin/Layout.cpp
index 6475cb2..4339fcb 100644
--- a/third_party/txt/src/minikin/Layout.cpp
+++ b/third_party/txt/src/minikin/Layout.cpp
@@ -1132,7 +1132,9 @@
int font_ix = findFace(src->mFaces[i], NULL);
fontMap[i] = font_ix;
}
- int x0 = mAdvance;
+ // LibTxt: Changed x0 from int to float to prevent rounding that causes text
+ // jitter.
+ float x0 = mAdvance;
for (size_t i = 0; i < src->mGlyphs.size(); i++) {
LayoutGlyph& srcGlyph = src->mGlyphs[i];
int font_ix = fontMap[srcGlyph.font_ix];
diff --git a/third_party/txt/src/txt/paint_record.h b/third_party/txt/src/txt/paint_record.h
index 8fa52fa..2b9248e 100644
--- a/third_party/txt/src/txt/paint_record.h
+++ b/third_party/txt/src/txt/paint_record.h
@@ -63,7 +63,7 @@
size_t line() const { return line_; }
- size_t GetRunWidth() const { return run_width_; }
+ double GetRunWidth() const { return run_width_; }
private:
TextStyle style_;
diff --git a/third_party/txt/src/txt/paragraph.h b/third_party/txt/src/txt/paragraph.h
index e83be66..2cadfbb 100644
--- a/third_party/txt/src/txt/paragraph.h
+++ b/third_party/txt/src/txt/paragraph.h
@@ -184,6 +184,7 @@
FRIEND_TEST(ParagraphTest, HyphenBreakParagraph);
FRIEND_TEST(ParagraphTest, RepeatLayoutParagraph);
FRIEND_TEST(ParagraphTest, Ellipsize);
+ FRIEND_TEST(ParagraphTest, UnderlineShiftParagraph);
// Starting data to layout.
std::vector<uint16_t> text_;
diff --git a/third_party/txt/tests/paragraph_unittests.cc b/third_party/txt/tests/paragraph_unittests.cc
index 2631f35..2a375d9 100644
--- a/third_party/txt/tests/paragraph_unittests.cc
+++ b/third_party/txt/tests/paragraph_unittests.cc
@@ -1007,7 +1007,7 @@
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.44922);
+ EXPECT_FLOAT_EQ(boxes[0].rect.right(), 177.97266);
EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
paint.setColor(SK_ColorGREEN);
@@ -1016,9 +1016,9 @@
GetCanvas()->drawRect(boxes[i].rect, paint);
}
EXPECT_EQ(boxes.size(), 1ull);
- EXPECT_FLOAT_EQ(boxes[0].rect.left(), 177);
+ EXPECT_FLOAT_EQ(boxes[0].rect.left(), 177.97266);
EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
- EXPECT_FLOAT_EQ(boxes[0].rect.right(), 506.08984);
+ EXPECT_FLOAT_EQ(boxes[0].rect.right(), 507.02344);
EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
paint.setColor(SK_ColorRED);
@@ -1027,9 +1027,9 @@
GetCanvas()->drawRect(boxes[i].rect, paint);
}
EXPECT_EQ(boxes.size(), 4ull);
- EXPECT_FLOAT_EQ(boxes[0].rect.left(), 210.83594);
+ EXPECT_FLOAT_EQ(boxes[0].rect.left(), 211.375);
EXPECT_FLOAT_EQ(boxes[0].rect.top(), 59.40625);
- EXPECT_FLOAT_EQ(boxes[0].rect.right(), 463.44922);
+ EXPECT_FLOAT_EQ(boxes[0].rect.right(), 463.61719);
EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 118);
// TODO(garyq): The following set of vals are definetly wrong and
@@ -1045,9 +1045,9 @@
GetCanvas()->drawRect(boxes[i].rect, paint);
}
EXPECT_EQ(boxes.size(), 1ull);
- EXPECT_FLOAT_EQ(boxes[0].rect.left(), 449.25391);
+ EXPECT_FLOAT_EQ(boxes[0].rect.left(), 450.1875);
EXPECT_FLOAT_EQ(boxes[0].rect.top(), 0.40625);
- EXPECT_FLOAT_EQ(boxes[0].rect.right(), 519.44922);
+ EXPECT_FLOAT_EQ(boxes[0].rect.right(), 519.47266);
EXPECT_FLOAT_EQ(boxes[0].rect.bottom(), 59);
paint.setColor(SK_ColorRED);
@@ -1569,4 +1569,82 @@
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::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
+
+ txt::TextStyle text_style1;
+ text_style1.color = SK_ColorBLACK;
+ text_style1.font_family = "Roboto";
+ builder.PushStyle(text_style1);
+
+ builder.AddText(u16_text1);
+
+ txt::TextStyle text_style2;
+ text_style2.color = SK_ColorBLACK;
+ text_style2.font_family = "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::ParagraphBuilder builder2(paragraph_style, GetTestFontCollection());
+
+ builder2.PushStyle(text_style1);
+
+ builder2.AddText(u16_text3);
+
+ builder2.Pop();
+
+ // Build multi-run paragraph
+ auto paragraph = builder.Build();
+ paragraph->Layout(GetTestCanvasWidth());
+
+ paragraph->Paint(GetCanvas(), 0, 0);
+
+ // Build single-run paragraph
+ auto paragraph2 = builder2.Build();
+ 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);
+ auto rects2 = paragraph2->GetRectsForRange(0, 12);
+
+ 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);
+ }
+}
+
} // namespace txt