Skip to content

Commit

Permalink
Add empty metrics to account for truncated whitespace for GetRectsFor…
Browse files Browse the repository at this point in the history
…Range. (flutter#7164)
  • Loading branch information
GaryQian authored Dec 10, 2018
1 parent 9611d74 commit 25c6c1b
Show file tree
Hide file tree
Showing 2 changed files with 256 additions and 4 deletions.
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

0 comments on commit 25c6c1b

Please sign in to comment.