Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 302e2e9

Browse files
HelloCoreGaryQian
authored andcommitted
Fix cursor jumping when typing some special characters. (#7964)
1 parent fe15149 commit 302e2e9

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

third_party/txt/src/txt/paragraph.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,7 @@ std::vector<Paragraph::TextBox> Paragraph::GetRectsForRange(
12481248
// Lines that are actually in the requested range.
12491249
size_t max_line = 0;
12501250
size_t min_line = INT_MAX;
1251+
size_t glyph_length = 0;
12511252

12521253
// Generate initial boxes and calculate metrics.
12531254
for (const CodeUnitRun& run : code_unit_runs_) {
@@ -1276,6 +1277,15 @@ std::vector<Paragraph::TextBox> Paragraph::GetRectsForRange(
12761277
if (gp.code_units.start >= start && gp.code_units.end <= end) {
12771278
left = std::min(left, static_cast<SkScalar>(gp.x_pos.start));
12781279
right = std::max(right, static_cast<SkScalar>(gp.x_pos.end));
1280+
} else if (gp.code_units.end == end) {
1281+
// Calculate left and right when we are at
1282+
// the last position of a combining character.
1283+
glyph_length = (gp.code_units.end - gp.code_units.start) - 1;
1284+
if (gp.code_units.start ==
1285+
std::max<size_t>(0, (start - glyph_length))) {
1286+
left = std::min(left, static_cast<SkScalar>(gp.x_pos.start));
1287+
right = std::max(right, static_cast<SkScalar>(gp.x_pos.end));
1288+
}
12791289
}
12801290
}
12811291
if (left == SK_ScalarMax || right == SK_ScalarMin)

third_party/txt/tests/paragraph_unittests.cc

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,92 @@ TEST_F(ParagraphTest,
16731673
ASSERT_TRUE(Snapshot());
16741674
}
16751675

1676+
TEST_F(ParagraphTest, GetRectsForRangeIncludeCombiningCharacter) {
1677+
const char* text = "ดีสวัสดีชาวโลกที่น่ารัก";
1678+
auto icu_text = icu::UnicodeString::fromUTF8(text);
1679+
std::u16string u16_text(icu_text.getBuffer(),
1680+
icu_text.getBuffer() + icu_text.length());
1681+
1682+
txt::ParagraphStyle paragraph_style;
1683+
paragraph_style.max_lines = 10;
1684+
paragraph_style.text_align = TextAlign::left;
1685+
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
1686+
1687+
txt::TextStyle text_style;
1688+
text_style.font_families = std::vector<std::string>(1, "Roboto");
1689+
text_style.font_size = 50;
1690+
text_style.letter_spacing = 1;
1691+
text_style.word_spacing = 5;
1692+
text_style.color = SK_ColorBLACK;
1693+
text_style.height = 1;
1694+
builder.PushStyle(text_style);
1695+
1696+
builder.AddText(u16_text);
1697+
1698+
builder.Pop();
1699+
1700+
auto paragraph = builder.Build();
1701+
paragraph->Layout(GetTestCanvasWidth() - 100);
1702+
1703+
paragraph->Paint(GetCanvas(), 0, 0);
1704+
1705+
Paragraph::RectHeightStyle rect_height_style =
1706+
Paragraph::RectHeightStyle::kTight;
1707+
Paragraph::RectWidthStyle rect_width_style =
1708+
Paragraph::RectWidthStyle::kTight;
1709+
1710+
std::vector<txt::Paragraph::TextBox> boxes =
1711+
paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style);
1712+
EXPECT_EQ(boxes.size(), 0ull);
1713+
1714+
// Case when the sentence starts with a combining character
1715+
// We should get 0 box for ด because it's already been combined to ดี
1716+
boxes =
1717+
paragraph->GetRectsForRange(0, 1, rect_height_style, rect_width_style);
1718+
EXPECT_EQ(boxes.size(), 0ull);
1719+
1720+
boxes =
1721+
paragraph->GetRectsForRange(1, 2, rect_height_style, rect_width_style);
1722+
EXPECT_EQ(boxes.size(), 1ull);
1723+
1724+
boxes =
1725+
paragraph->GetRectsForRange(0, 2, rect_height_style, rect_width_style);
1726+
EXPECT_EQ(boxes.size(), 1ull);
1727+
1728+
// Case when the sentence contains a combining character
1729+
// We should get 0 box for ว because it's already been combined to วั
1730+
boxes =
1731+
paragraph->GetRectsForRange(3, 4, rect_height_style, rect_width_style);
1732+
EXPECT_EQ(boxes.size(), 0ull);
1733+
1734+
boxes =
1735+
paragraph->GetRectsForRange(4, 5, rect_height_style, rect_width_style);
1736+
EXPECT_EQ(boxes.size(), 1ull);
1737+
1738+
boxes =
1739+
paragraph->GetRectsForRange(3, 5, rect_height_style, rect_width_style);
1740+
EXPECT_EQ(boxes.size(), 1ull);
1741+
1742+
// Case when the sentence contains a combining character that contain 3
1743+
// characters We should get 0 box for ท and ที because it's already been
1744+
// combined to ที่
1745+
boxes =
1746+
paragraph->GetRectsForRange(14, 15, rect_height_style, rect_width_style);
1747+
EXPECT_EQ(boxes.size(), 0ull);
1748+
1749+
boxes =
1750+
paragraph->GetRectsForRange(15, 16, rect_height_style, rect_width_style);
1751+
EXPECT_EQ(boxes.size(), 0ull);
1752+
1753+
boxes =
1754+
paragraph->GetRectsForRange(16, 17, rect_height_style, rect_width_style);
1755+
EXPECT_EQ(boxes.size(), 1ull);
1756+
1757+
boxes =
1758+
paragraph->GetRectsForRange(14, 17, rect_height_style, rect_width_style);
1759+
EXPECT_EQ(boxes.size(), 1ull);
1760+
}
1761+
16761762
TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeCenterParagraph)) {
16771763
const char* text = "01234   "; // includes ideographic space
16781764
// and english space.

0 commit comments

Comments
 (0)