| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/fonts/shaping/ShapingLineBreaker.h" | 5 #include "platform/fonts/shaping/ShapingLineBreaker.h" |
| 6 | 6 |
| 7 #include "platform/fonts/Font.h" | 7 #include "platform/fonts/Font.h" |
| 8 #include "platform/fonts/shaping/HarfBuzzShaper.h" | 8 #include "platform/fonts/shaping/HarfBuzzShaper.h" |
| 9 #include "platform/fonts/shaping/ShapeResult.h" | 9 #include "platform/fonts/shaping/ShapeResult.h" |
| 10 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" | 10 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 // HarfBuzzHarfBuzz safe to break info when available. | 46 // HarfBuzzHarfBuzz safe to break info when available. |
| 47 for (; offset < end; offset++) { | 47 for (; offset < end; offset++) { |
| 48 if (text[offset] == kSpaceCharacter) | 48 if (text[offset] == kSpaceCharacter) |
| 49 break; | 49 break; |
| 50 } | 50 } |
| 51 return offset; | 51 return offset; |
| 52 } | 52 } |
| 53 | 53 |
| 54 } // namespace | 54 } // namespace |
| 55 | 55 |
| 56 // TODO(eae); Should take a const LazyLineBreakIterator& but that requires the | |
| 57 // LazyLineBreakIterator::isBreakable method to be updated to be const. | |
| 58 unsigned ShapingLineBreaker::PreviousBreakOpportunity( | |
| 59 LazyLineBreakIterator* break_iterator, | |
| 60 unsigned start, | |
| 61 unsigned offset) { | |
| 62 DCHECK(break_iterator); | |
| 63 unsigned pos = std::min(start + offset, shaper_->TextLength()); | |
| 64 for (; pos > start; pos--) { | |
| 65 int next_break = 0; | |
| 66 if (break_iterator->IsBreakable(pos, next_break, break_type_)) | |
| 67 return pos; | |
| 68 } | |
| 69 return start; | |
| 70 } | |
| 71 | |
| 72 unsigned ShapingLineBreaker::NextBreakOpportunity( | |
| 73 LazyLineBreakIterator* break_iterator, | |
| 74 unsigned offset) { | |
| 75 DCHECK(break_iterator); | |
| 76 int next_break = 0; | |
| 77 break_iterator->IsBreakable(offset, next_break, break_type_); | |
| 78 return next_break; | |
| 79 } | |
| 80 | |
| 81 // Shapes a line of text by finding a valid and appropriate break opportunity | 56 // Shapes a line of text by finding a valid and appropriate break opportunity |
| 82 // based on the shaping results for the entire paragraph. Re-shapes the start | 57 // based on the shaping results for the entire paragraph. Re-shapes the start |
| 83 // and end of the line as needed. | 58 // and end of the line as needed. |
| 84 // | 59 // |
| 85 // Definitions: | 60 // Definitions: |
| 86 // Candidate break opportunity: Ideal point to break, disregarding line | 61 // Candidate break opportunity: Ideal point to break, disregarding line |
| 87 // breaking rules. May be in the middle of a word | 62 // breaking rules. May be in the middle of a word |
| 88 // or inside a ligature. | 63 // or inside a ligature. |
| 89 // Valid break opportunity: A point where a break is allowed according to | 64 // Valid break opportunity: A point where a break is allowed according to |
| 90 // the relevant breaking rules. | 65 // the relevant breaking rules. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 if (first_safe != start) { | 99 if (first_safe != start) { |
| 125 LayoutUnit original_width = | 100 LayoutUnit original_width = |
| 126 result_->SnappedEndPositionForOffset(first_safe) - start_position; | 101 result_->SnappedEndPositionForOffset(first_safe) - start_position; |
| 127 line_start_result = shaper_->Shape(font_, direction, start, first_safe); | 102 line_start_result = shaper_->Shape(font_, direction, start, first_safe); |
| 128 available_space += line_start_result->SnappedWidth() - original_width; | 103 available_space += line_start_result->SnappedWidth() - original_width; |
| 129 } | 104 } |
| 130 | 105 |
| 131 // Find a candidate break opportunity by identifying the last offset before | 106 // Find a candidate break opportunity by identifying the last offset before |
| 132 // exceeding the available space and the determine the closest valid break | 107 // exceeding the available space and the determine the closest valid break |
| 133 // preceding the candidate. | 108 // preceding the candidate. |
| 134 LazyLineBreakIterator break_iterator(text_, locale_); | 109 LazyLineBreakIterator break_iterator(text_, locale_, break_type_); |
| 135 LayoutUnit end_position = start_position + available_space; | 110 LayoutUnit end_position = start_position + available_space; |
| 136 unsigned candidate_break = result_->OffsetForPosition(end_position, false); | 111 unsigned candidate_break = result_->OffsetForPosition(end_position, false); |
| 137 unsigned break_opportunity = | 112 unsigned break_opportunity = |
| 138 PreviousBreakOpportunity(&break_iterator, start, candidate_break); | 113 break_iterator.PreviousBreakOpportunity(candidate_break, start); |
| 139 if (break_opportunity <= start) { | 114 if (break_opportunity <= start) { |
| 140 break_opportunity = NextBreakOpportunity(&break_iterator, candidate_break); | 115 break_opportunity = break_iterator.NextBreakOpportunity(candidate_break); |
| 141 } | 116 } |
| 142 | 117 |
| 143 RefPtr<ShapeResult> line_end_result; | 118 RefPtr<ShapeResult> line_end_result; |
| 144 unsigned last_safe = break_opportunity; | 119 unsigned last_safe = break_opportunity; |
| 145 while (break_opportunity > start) { | 120 while (break_opportunity > start) { |
| 146 // If the previous valid break opportunity is not at a safe-to-break | 121 // If the previous valid break opportunity is not at a safe-to-break |
| 147 // boundary reshape between the safe-to-break offset and the valid break | 122 // boundary reshape between the safe-to-break offset and the valid break |
| 148 // offset. If the resulting width exceeds the available space the | 123 // offset. If the resulting width exceeds the available space the |
| 149 // preceding boundary is tried until the available space is sufficient. | 124 // preceding boundary is tried until the available space is sufficient. |
| 150 unsigned previous_safe = std::max( | 125 unsigned previous_safe = std::max( |
| 151 PreviousSafeToBreakAfter(shaper_->GetText(), start, break_opportunity), | 126 PreviousSafeToBreakAfter(shaper_->GetText(), start, break_opportunity), |
| 152 start); | 127 start); |
| 153 if (previous_safe != break_opportunity) { | 128 if (previous_safe != break_opportunity) { |
| 154 LayoutUnit safe_position = | 129 LayoutUnit safe_position = |
| 155 result_->SnappedStartPositionForOffset(previous_safe); | 130 result_->SnappedStartPositionForOffset(previous_safe); |
| 156 while (break_opportunity > previous_safe && previous_safe > start) { | 131 while (break_opportunity > previous_safe && previous_safe > start) { |
| 157 line_end_result = | 132 line_end_result = |
| 158 shaper_->Shape(font_, direction, previous_safe, break_opportunity); | 133 shaper_->Shape(font_, direction, previous_safe, break_opportunity); |
| 159 if (safe_position + line_end_result->SnappedWidth() <= end_position) | 134 if (safe_position + line_end_result->SnappedWidth() <= end_position) |
| 160 break; | 135 break; |
| 161 line_end_result = nullptr; | 136 line_end_result = nullptr; |
| 162 break_opportunity = PreviousBreakOpportunity(&break_iterator, start, | 137 break_opportunity = break_iterator.PreviousBreakOpportunity( |
| 163 break_opportunity - 1); | 138 break_opportunity - 1, start); |
| 164 } | 139 } |
| 165 } | 140 } |
| 166 | 141 |
| 167 if (break_opportunity > start) { | 142 if (break_opportunity > start) { |
| 168 last_safe = previous_safe; | 143 last_safe = previous_safe; |
| 169 break; | 144 break; |
| 170 } | 145 } |
| 171 | 146 |
| 172 // No suitable break opportunity, not exceeding the available space, | 147 // No suitable break opportunity, not exceeding the available space, |
| 173 // found. Choose the next valid one even though it will overflow. | 148 // found. Choose the next valid one even though it will overflow. |
| 174 break_opportunity = NextBreakOpportunity(&break_iterator, candidate_break); | 149 break_opportunity = break_iterator.NextBreakOpportunity(candidate_break); |
| 175 } | 150 } |
| 176 | 151 |
| 177 // Create shape results for the line by copying from the re-shaped result (if | 152 // Create shape results for the line by copying from the re-shaped result (if |
| 178 // reshaping was needed) and the original shape results. | 153 // reshaping was needed) and the original shape results. |
| 179 RefPtr<ShapeResult> line_result = ShapeResult::Create(font_, 0, direction); | 154 RefPtr<ShapeResult> line_result = ShapeResult::Create(font_, 0, direction); |
| 180 unsigned max_length = std::numeric_limits<unsigned>::max(); | 155 unsigned max_length = std::numeric_limits<unsigned>::max(); |
| 181 if (line_start_result) | 156 if (line_start_result) |
| 182 line_start_result->CopyRange(0, max_length, line_result.Get()); | 157 line_start_result->CopyRange(0, max_length, line_result.Get()); |
| 183 if (last_safe > first_safe) | 158 if (last_safe > first_safe) |
| 184 result_->CopyRange(first_safe, last_safe, line_result.Get()); | 159 result_->CopyRange(first_safe, last_safe, line_result.Get()); |
| 185 if (line_end_result) | 160 if (line_end_result) |
| 186 line_end_result->CopyRange(last_safe, max_length, line_result.Get()); | 161 line_end_result->CopyRange(last_safe, max_length, line_result.Get()); |
| 187 | 162 |
| 188 *break_offset = break_opportunity; | 163 *break_offset = break_opportunity; |
| 189 return line_result.Release(); | 164 return line_result.Release(); |
| 190 } | 165 } |
| 191 | 166 |
| 192 } // namespace blink | 167 } // namespace blink |
| OLD | NEW |