Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions third_party/txt/src/txt/paragraph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -479,10 +479,6 @@ void Paragraph::Layout(double width, bool force) {
}
}

// TODO(garyq): Make GetRectsForRange return a zero-width box for the
// excluded whitespace such that the caret placement is correct regardless
// of the index being whitespace or not.

// Exclude trailing whitespace from right and center-justified lines so the
// last visible character in the line will be flush with the right margin.
size_t line_end_index =
Expand Down Expand Up @@ -740,6 +736,23 @@ void Paragraph::Layout(double width, bool force) {
code_unit_runs_.insert(code_unit_runs_.end(), line_code_unit_runs.begin(),
line_code_unit_runs.end());

// Add extra empty metrics for skipped whitespace at line end. This allows
// GetRectsForRange to properly draw empty rects at the ends of lines with
// truncated whitespace.
if (line_end_index < line_range.end) {
std::vector<GlyphPosition> empty_glyph_positions;
double end_x = line_code_unit_runs.back().positions.back().x_pos.end;
for (size_t index = line_end_index; index < line_range.end; ++index) {
empty_glyph_positions.emplace_back(end_x, 0, index, 1);
}
code_unit_runs_.emplace_back(
std::move(empty_glyph_positions),
Range<size_t>(line_end_index, line_range.end),
Range<double>(end_x, end_x), line_code_unit_runs.back().line_number,
line_code_unit_runs.back().font_metrics,
line_code_unit_runs.back().direction);
}

double max_line_spacing = 0;
double max_descent = 0;
SkScalar max_unscaled_ascent = 0;
Expand Down
239 changes: 239 additions & 0 deletions third_party/txt/tests/paragraph_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,245 @@ TEST_F(ParagraphTest,
ASSERT_TRUE(Snapshot());
}

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::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());

txt::TextStyle text_style;
text_style.font_family = "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 = builder.Build();
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(), 346.04492);
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,
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::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());

txt::TextStyle text_style;
text_style.font_family = "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 = builder.Build();
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(), 346.04492);
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(), 331.83594);
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());
}

SkRect GetCoordinatesForGlyphPosition(const txt::Paragraph& paragraph,
size_t pos) {
std::vector<txt::Paragraph::TextBox> boxes =
Expand Down