Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(797)

Unified Diff: third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp

Issue 2875933006: [LayoutNG] Misc fixes in ShapingLineBreaker (Closed)
Patch Set: eae review + RTL snapping fixes Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp
index 5206620abd964b923089b5c2b7b48b99b87f3495..dafe8f19e9a07cc0bdc11a84600fe359ea0e06c8 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp
@@ -12,16 +12,15 @@
namespace blink {
-ShapingLineBreaker::ShapingLineBreaker(const HarfBuzzShaper* shaper,
- const Font* font,
- const ShapeResult* result,
- const AtomicString locale,
- LineBreakType break_type)
+ShapingLineBreaker::ShapingLineBreaker(
+ const HarfBuzzShaper* shaper,
+ const Font* font,
+ const ShapeResult* result,
+ const LazyLineBreakIterator* break_iterator)
: shaper_(shaper),
font_(font),
result_(result),
- locale_(locale),
- break_type_(break_type) {
+ break_iterator_(break_iterator) {
text_ = String(shaper->GetText(), shaper->TextLength());
}
@@ -51,6 +50,24 @@ unsigned NextSafeToBreakBefore(const UChar* text,
return offset;
}
+// ShapingLineBreaker computes using visual positions. This function flips
+// logical advance to visual, or vice versa.
+LayoutUnit FlipRtl(LayoutUnit value, TextDirection direction) {
+ return direction != TextDirection::kRtl ? value : -value;
+}
+
+// Snaps a visual position to the line start direction.
+LayoutUnit SnapStart(float value, TextDirection direction) {
+ return direction != TextDirection::kRtl ? LayoutUnit::FromFloatFloor(value)
+ : LayoutUnit::FromFloatCeil(value);
+}
+
+// Snaps a visual position to the line end direction.
+LayoutUnit SnapEnd(float value, TextDirection direction) {
+ return direction != TextDirection::kRtl ? LayoutUnit::FromFloatCeil(value)
+ : LayoutUnit::FromFloatFloor(value);
+}
+
} // namespace
// Shapes a line of text by finding a valid and appropriate break opportunity
@@ -86,9 +103,35 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine(
unsigned start,
LayoutUnit available_space,
unsigned* break_offset) {
+ DCHECK_GE(available_space, LayoutUnit(0));
+ unsigned range_start = result_->StartIndexForResult();
+ unsigned range_end = result_->EndIndexForResult();
+ DCHECK_GE(start, range_start);
+ DCHECK_LT(start, range_end);
+
// The start position in the original shape results.
- LayoutUnit start_position = result_->SnappedStartPositionForOffset(start);
+ float start_position_float = result_->PositionForOffset(start - range_start);
TextDirection direction = result_->Direction();
+ LayoutUnit start_position = SnapStart(start_position_float, direction);
+
+ // Find a candidate break opportunity by identifying the last offset before
+ // exceeding the available space and the determine the closest valid break
+ // preceding the candidate.
+ LayoutUnit end_position = SnapEnd(start_position_float, direction) +
+ FlipRtl(available_space, direction);
+ DCHECK_GE(FlipRtl(end_position - start_position, direction), LayoutUnit(0));
+ unsigned candidate_break =
+ result_->OffsetForPosition(end_position, false) + range_start;
+ // candidate_break should be >= start, but rounding errors can chime in when
+ // comparing floats. See ShapeLineZeroAvailableWidth on Linux/Mac.
+ candidate_break = std::max(candidate_break, start);
+ unsigned break_opportunity =
+ break_iterator_->PreviousBreakOpportunity(candidate_break, start);
+ if (break_opportunity <= start) {
+ break_opportunity = break_iterator_->NextBreakOpportunity(
+ std::max(candidate_break, start + 1));
+ }
+ DCHECK_GT(break_opportunity, start);
// If the start offset is not at a safe-to-break boundary the content between
// the start and the next safe-to-break boundary needs to be reshaped and the
@@ -96,25 +139,19 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine(
RefPtr<ShapeResult> line_start_result;
unsigned first_safe =
NextSafeToBreakBefore(shaper_->GetText(), shaper_->TextLength(), start);
- if (first_safe != start) {
+ DCHECK_GE(first_safe, start);
+ // Reshape takes place only when first_safe is before the break opportunity.
+ // Otherwise reshape will be part of line_end_result.
+ if (first_safe != start && first_safe < break_opportunity) {
LayoutUnit original_width =
- result_->SnappedEndPositionForOffset(first_safe) - start_position;
+ FlipRtl(SnapEnd(result_->PositionForOffset(first_safe - range_start),
+ direction) -
+ start_position,
+ direction);
line_start_result = shaper_->Shape(font_, direction, start, first_safe);
available_space += line_start_result->SnappedWidth() - original_width;
}
- // Find a candidate break opportunity by identifying the last offset before
- // exceeding the available space and the determine the closest valid break
- // preceding the candidate.
- LazyLineBreakIterator break_iterator(text_, locale_, break_type_);
- LayoutUnit end_position = start_position + available_space;
- unsigned candidate_break = result_->OffsetForPosition(end_position, false);
- unsigned break_opportunity =
- break_iterator.PreviousBreakOpportunity(candidate_break, start);
- if (break_opportunity <= start) {
- break_opportunity = break_iterator.NextBreakOpportunity(candidate_break);
- }
-
RefPtr<ShapeResult> line_end_result;
unsigned last_safe = break_opportunity;
while (break_opportunity > start) {
@@ -125,17 +162,26 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine(
unsigned previous_safe = std::max(
PreviousSafeToBreakAfter(shaper_->GetText(), start, break_opportunity),
start);
+ DCHECK_LE(previous_safe, break_opportunity);
if (previous_safe != break_opportunity) {
- LayoutUnit safe_position =
- result_->SnappedStartPositionForOffset(previous_safe);
- while (break_opportunity > previous_safe && previous_safe > start) {
+ LayoutUnit safe_position = SnapStart(
+ result_->PositionForOffset(previous_safe - range_start), direction);
+ while (break_opportunity > previous_safe && previous_safe >= start) {
line_end_result =
- shaper_->Shape(font_, direction, previous_safe, break_opportunity);
- if (safe_position + line_end_result->SnappedWidth() <= end_position)
+ shaper_->Shape(font_, direction, previous_safe,
+ std::min(break_opportunity, range_end));
+ if (line_end_result->SnappedWidth() <=
+ FlipRtl(end_position - safe_position, direction))
break;
+ // Doesn't fit after the reshape. Try previous break opportunity, or
+ // overflow if there were none.
+ unsigned previous_break_opportunity =
+ break_iterator_->PreviousBreakOpportunity(break_opportunity - 1,
+ start);
+ if (previous_break_opportunity <= start)
+ break;
+ break_opportunity = previous_break_opportunity;
line_end_result = nullptr;
- break_opportunity = break_iterator.PreviousBreakOpportunity(
- break_opportunity - 1, start);
}
}
@@ -146,7 +192,7 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine(
// No suitable break opportunity, not exceeding the available space,
// found. Choose the next valid one even though it will overflow.
- break_opportunity = break_iterator.NextBreakOpportunity(candidate_break);
+ break_opportunity = break_iterator_->NextBreakOpportunity(candidate_break);
}
// Create shape results for the line by copying from the re-shaped result (if
@@ -160,6 +206,10 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine(
if (line_end_result)
line_end_result->CopyRange(last_safe, max_length, line_result.Get());
+ DCHECK_GT(break_opportunity, start);
+ DCHECK_EQ(std::min(break_opportunity, range_end) - start,
+ line_result->NumCharacters());
+
*break_offset = break_opportunity;
return line_result.Release();
}

Powered by Google App Engine
This is Rietveld 408576698