Chromium Code Reviews| 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 dafe8f19e9a07cc0bdc11a84600fe359ea0e06c8..d306d49a9173dce81b968d9d818ae9ce47e75bd4 100644 |
| --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp |
| +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp |
| @@ -122,6 +122,15 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine( |
| DCHECK_GE(FlipRtl(end_position - start_position, direction), LayoutUnit(0)); |
| unsigned candidate_break = |
| result_->OffsetForPosition(end_position, false) + range_start; |
| + |
| + if (candidate_break >= range_end) { |
|
eae
2017/06/12 16:51:37
When would this happen?
kojii
2017/06/12 16:54:34
"==" happens when end_position >= result->Width().
|
| + // The |result_| does not have glyphs to fill the available space, |
| + // and thus unable to compute. Return the result up to range_end. |
| + DCHECK_EQ(candidate_break, range_end); |
| + *break_offset = range_end; |
| + return ShapeToEnd(start, start_position, range_end); |
| + } |
| + |
| // 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); |
| @@ -130,6 +139,9 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine( |
| if (break_opportunity <= start) { |
| break_opportunity = break_iterator_->NextBreakOpportunity( |
| std::max(candidate_break, start + 1)); |
| + // |range_end| may not be a break opportunity, but this function cannot |
| + // measure beyond it. |
| + break_opportunity = std::min(break_opportunity, range_end); |
| } |
| DCHECK_GT(break_opportunity, start); |
| @@ -167,9 +179,9 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine( |
| LayoutUnit safe_position = SnapStart( |
| result_->PositionForOffset(previous_safe - range_start), direction); |
| while (break_opportunity > previous_safe && previous_safe >= start) { |
| + DCHECK_LE(break_opportunity, range_end); |
| line_end_result = |
| - shaper_->Shape(font_, direction, previous_safe, |
| - std::min(break_opportunity, range_end)); |
| + shaper_->Shape(font_, direction, previous_safe, break_opportunity); |
| if (line_end_result->SnappedWidth() <= |
| FlipRtl(end_position - safe_position, direction)) |
| break; |
| @@ -193,6 +205,9 @@ 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); |
| + // |range_end| may not be a break opportunity, but this function cannot |
| + // measure beyond it. |
| + break_opportunity = std::min(break_opportunity, range_end); |
| } |
| // Create shape results for the line by copying from the re-shaped result (if |
| @@ -214,4 +229,31 @@ PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeLine( |
| return line_result.Release(); |
| } |
| +// Shape from the specified offset to the end of the ShapeResult. |
| +// If |start| is safe-to-break, this copies the subset of the result. |
| +PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeToEnd( |
| + unsigned start, |
| + LayoutUnit start_position, |
| + unsigned range_end) { |
| + unsigned first_safe = |
| + NextSafeToBreakBefore(shaper_->GetText(), shaper_->TextLength(), start); |
| + DCHECK_GE(first_safe, start); |
| + |
| + RefPtr<ShapeResult> line_result; |
| + TextDirection direction = result_->Direction(); |
| + if (first_safe == start) { |
| + // If |start| is safe-to-break, reshape is not needed. |
| + line_result = ShapeResult::Create(font_, 0, direction); |
| + result_->CopyRange(start, range_end, line_result.Get()); |
| + } else if (first_safe < range_end) { |
| + // Otherwise reshape to the first safe, then copy the rest. |
| + line_result = shaper_->Shape(font_, direction, start, first_safe); |
| + result_->CopyRange(first_safe, range_end, line_result.Get()); |
| + } else { |
| + // If no safe-to-break in the ragne, reshape the whole range. |
| + line_result = shaper_->Shape(font_, direction, start, range_end); |
| + } |
| + return line_result.Release(); |
| +} |
| + |
| } // namespace blink |