Commit cdc72a13 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[LayoutNG] Implement glyph bounding box to ShapeResult::CopyRange()

For LayoutNG inline to compute visual overflow, ShapingLineBreaker needs
to compute glyph bounding box. This is currently set to empty.

To implement:
1. ShapeResult::CopyRange() should copy adjusted glyph bounding box
   when copying start/end edge of the source.
2. When start/end is safe-to-break, ShapingLineBreaker subsets
   ShapeResult, but unable to compute glyph bounding box.

This patch implements #1. How to solve #2 is to be discussed.

BUG=636993
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_layout_tests_layout_ng

Change-Id: Ic239c8531bb2e5f09e2e80d7ea7e0e25c6aaa847
Reviewed-on: https://chromium-review.googlesource.com/574508
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#487410}
parent ed12c7da
...@@ -407,6 +407,7 @@ TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoLatin) { ...@@ -407,6 +407,7 @@ TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoLatin) {
EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters()); EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters());
EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth()); EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth());
EXPECT_EQ(result->Bounds(), composite_result->Bounds());
EXPECT_EQ(result->SnappedStartPositionForOffset(0), EXPECT_EQ(result->SnappedStartPositionForOffset(0),
composite_result->SnappedStartPositionForOffset(0)); composite_result->SnappedStartPositionForOffset(0));
EXPECT_EQ(result->SnappedStartPositionForOffset(15), EXPECT_EQ(result->SnappedStartPositionForOffset(15),
...@@ -432,6 +433,7 @@ TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoArabicThaiHanLatin) { ...@@ -432,6 +433,7 @@ TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoArabicThaiHanLatin) {
EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters()); EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters());
EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth()); EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth());
EXPECT_EQ(result->Bounds(), composite_result->Bounds());
EXPECT_EQ(result->SnappedStartPositionForOffset(0), EXPECT_EQ(result->SnappedStartPositionForOffset(0),
composite_result->SnappedStartPositionForOffset(0)); composite_result->SnappedStartPositionForOffset(0));
EXPECT_EQ(result->SnappedStartPositionForOffset(1), EXPECT_EQ(result->SnappedStartPositionForOffset(1),
...@@ -468,4 +470,22 @@ TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeAcrossRuns) { ...@@ -468,4 +470,22 @@ TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeAcrossRuns) {
EXPECT_EQ(2u, target->NumCharacters()); EXPECT_EQ(2u, target->NumCharacters());
} }
TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeSegmentGlyphBoundingBox) {
String string(u"THello worldL");
TextDirection direction = TextDirection::kLtr;
HarfBuzzShaper shaper(string.Characters16(), string.length());
RefPtr<ShapeResult> result1 = shaper.Shape(&font, direction, 0, 6);
RefPtr<ShapeResult> result2 =
shaper.Shape(&font, direction, 6, string.length());
RefPtr<ShapeResult> composite_result =
ShapeResult::Create(&font, 0, direction);
result1->CopyRange(0, 6, composite_result.Get());
result2->CopyRange(6, string.length(), composite_result.Get());
RefPtr<ShapeResult> result = shaper.Shape(&font, direction);
EXPECT_EQ(result->Bounds(), composite_result->Bounds());
}
} // namespace blink } // namespace blink
...@@ -456,6 +456,7 @@ void ShapeResult::CopyRange(unsigned start_offset, ...@@ -456,6 +456,7 @@ void ShapeResult::CopyRange(unsigned start_offset,
unsigned end_offset, unsigned end_offset,
ShapeResult* target) const { ShapeResult* target) const {
unsigned index = target->num_characters_; unsigned index = target->num_characters_;
float total_width = 0;
for (const auto& run : runs_) { for (const auto& run : runs_) {
unsigned run_start = (*run).start_index_; unsigned run_start = (*run).start_index_;
unsigned run_end = run_start + (*run).num_characters_; unsigned run_end = run_start + (*run).num_characters_;
...@@ -467,12 +468,37 @@ void ShapeResult::CopyRange(unsigned start_offset, ...@@ -467,12 +468,37 @@ void ShapeResult::CopyRange(unsigned start_offset,
auto sub_run = (*run).CreateSubRun(start, end); auto sub_run = (*run).CreateSubRun(start, end);
sub_run->start_index_ = index; sub_run->start_index_ = index;
target->width_ += sub_run->width_; total_width += sub_run->width_;
index += sub_run->num_characters_; index += sub_run->num_characters_;
target->runs_.push_back(std::move(sub_run)); target->runs_.push_back(std::move(sub_run));
} }
} }
// Compute new glyph bounding box.
// If |start_offset| or |end_offset| are the start/end of |this|, use
// |glyph_bounding_box_| from |this| for the side. Otherwise, we cannot
// compute accurate glyph bounding box; approximate by assuming there are no
// glyph overflow nor underflow.
// TODO(kojii): This is not correct for vertical flow since glyphs are in
// physical coordinates.
float left = target->width_;
target->width_ += total_width;
float right = target->width_;
if (start_offset <= StartIndexForResult())
left += glyph_bounding_box_.X();
if (end_offset >= EndIndexForResult())
right += glyph_bounding_box_.MaxX() - width_;
if (right >= left) {
FloatRect adjusted_box(left, glyph_bounding_box_.Y(), right - left,
glyph_bounding_box_.Height());
target->glyph_bounding_box_.UniteIfNonZero(adjusted_box);
} else {
FloatRect adjusted_box(left, glyph_bounding_box_.Y(), 0,
glyph_bounding_box_.Height());
target->glyph_bounding_box_.UniteIfNonZero(adjusted_box);
target->glyph_bounding_box_.ShiftMaxXEdgeTo(right);
}
DCHECK_EQ(index - target->num_characters_, DCHECK_EQ(index - target->num_characters_,
std::min(end_offset, EndIndexForResult()) - std::min(end_offset, EndIndexForResult()) -
std::max(start_offset, StartIndexForResult())); std::max(start_offset, StartIndexForResult()));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment