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

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

Issue 2879093002: [LayoutNG] Fix ShapingLineBreaker when the end of range is needed (Closed)
Patch Set: Rebase Created 3 years, 6 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 unified diff | Download patch
OLDNEW
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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 LayoutUnit start_position = SnapStart(start_position_float, direction); 115 LayoutUnit start_position = SnapStart(start_position_float, direction);
116 116
117 // Find a candidate break opportunity by identifying the last offset before 117 // Find a candidate break opportunity by identifying the last offset before
118 // exceeding the available space and the determine the closest valid break 118 // exceeding the available space and the determine the closest valid break
119 // preceding the candidate. 119 // preceding the candidate.
120 LayoutUnit end_position = SnapEnd(start_position_float, direction) + 120 LayoutUnit end_position = SnapEnd(start_position_float, direction) +
121 FlipRtl(available_space, direction); 121 FlipRtl(available_space, direction);
122 DCHECK_GE(FlipRtl(end_position - start_position, direction), LayoutUnit(0)); 122 DCHECK_GE(FlipRtl(end_position - start_position, direction), LayoutUnit(0));
123 unsigned candidate_break = 123 unsigned candidate_break =
124 result_->OffsetForPosition(end_position, false) + range_start; 124 result_->OffsetForPosition(end_position, false) + range_start;
125
126 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().
127 // The |result_| does not have glyphs to fill the available space,
128 // and thus unable to compute. Return the result up to range_end.
129 DCHECK_EQ(candidate_break, range_end);
130 *break_offset = range_end;
131 return ShapeToEnd(start, start_position, range_end);
132 }
133
125 // candidate_break should be >= start, but rounding errors can chime in when 134 // candidate_break should be >= start, but rounding errors can chime in when
126 // comparing floats. See ShapeLineZeroAvailableWidth on Linux/Mac. 135 // comparing floats. See ShapeLineZeroAvailableWidth on Linux/Mac.
127 candidate_break = std::max(candidate_break, start); 136 candidate_break = std::max(candidate_break, start);
128 unsigned break_opportunity = 137 unsigned break_opportunity =
129 break_iterator_->PreviousBreakOpportunity(candidate_break, start); 138 break_iterator_->PreviousBreakOpportunity(candidate_break, start);
130 if (break_opportunity <= start) { 139 if (break_opportunity <= start) {
131 break_opportunity = break_iterator_->NextBreakOpportunity( 140 break_opportunity = break_iterator_->NextBreakOpportunity(
132 std::max(candidate_break, start + 1)); 141 std::max(candidate_break, start + 1));
142 // |range_end| may not be a break opportunity, but this function cannot
143 // measure beyond it.
144 break_opportunity = std::min(break_opportunity, range_end);
133 } 145 }
134 DCHECK_GT(break_opportunity, start); 146 DCHECK_GT(break_opportunity, start);
135 147
136 // If the start offset is not at a safe-to-break boundary the content between 148 // If the start offset is not at a safe-to-break boundary the content between
137 // the start and the next safe-to-break boundary needs to be reshaped and the 149 // the start and the next safe-to-break boundary needs to be reshaped and the
138 // available space adjusted to take the reshaping into account. 150 // available space adjusted to take the reshaping into account.
139 RefPtr<ShapeResult> line_start_result; 151 RefPtr<ShapeResult> line_start_result;
140 unsigned first_safe = 152 unsigned first_safe =
141 NextSafeToBreakBefore(shaper_->GetText(), shaper_->TextLength(), start); 153 NextSafeToBreakBefore(shaper_->GetText(), shaper_->TextLength(), start);
142 DCHECK_GE(first_safe, start); 154 DCHECK_GE(first_safe, start);
(...skipping 17 matching lines...) Expand all
160 // offset. If the resulting width exceeds the available space the 172 // offset. If the resulting width exceeds the available space the
161 // preceding boundary is tried until the available space is sufficient. 173 // preceding boundary is tried until the available space is sufficient.
162 unsigned previous_safe = std::max( 174 unsigned previous_safe = std::max(
163 PreviousSafeToBreakAfter(shaper_->GetText(), start, break_opportunity), 175 PreviousSafeToBreakAfter(shaper_->GetText(), start, break_opportunity),
164 start); 176 start);
165 DCHECK_LE(previous_safe, break_opportunity); 177 DCHECK_LE(previous_safe, break_opportunity);
166 if (previous_safe != break_opportunity) { 178 if (previous_safe != break_opportunity) {
167 LayoutUnit safe_position = SnapStart( 179 LayoutUnit safe_position = SnapStart(
168 result_->PositionForOffset(previous_safe - range_start), direction); 180 result_->PositionForOffset(previous_safe - range_start), direction);
169 while (break_opportunity > previous_safe && previous_safe >= start) { 181 while (break_opportunity > previous_safe && previous_safe >= start) {
182 DCHECK_LE(break_opportunity, range_end);
170 line_end_result = 183 line_end_result =
171 shaper_->Shape(font_, direction, previous_safe, 184 shaper_->Shape(font_, direction, previous_safe, break_opportunity);
172 std::min(break_opportunity, range_end));
173 if (line_end_result->SnappedWidth() <= 185 if (line_end_result->SnappedWidth() <=
174 FlipRtl(end_position - safe_position, direction)) 186 FlipRtl(end_position - safe_position, direction))
175 break; 187 break;
176 // Doesn't fit after the reshape. Try previous break opportunity, or 188 // Doesn't fit after the reshape. Try previous break opportunity, or
177 // overflow if there were none. 189 // overflow if there were none.
178 unsigned previous_break_opportunity = 190 unsigned previous_break_opportunity =
179 break_iterator_->PreviousBreakOpportunity(break_opportunity - 1, 191 break_iterator_->PreviousBreakOpportunity(break_opportunity - 1,
180 start); 192 start);
181 if (previous_break_opportunity <= start) 193 if (previous_break_opportunity <= start)
182 break; 194 break;
183 break_opportunity = previous_break_opportunity; 195 break_opportunity = previous_break_opportunity;
184 line_end_result = nullptr; 196 line_end_result = nullptr;
185 } 197 }
186 } 198 }
187 199
188 if (break_opportunity > start) { 200 if (break_opportunity > start) {
189 last_safe = previous_safe; 201 last_safe = previous_safe;
190 break; 202 break;
191 } 203 }
192 204
193 // No suitable break opportunity, not exceeding the available space, 205 // No suitable break opportunity, not exceeding the available space,
194 // found. Choose the next valid one even though it will overflow. 206 // found. Choose the next valid one even though it will overflow.
195 break_opportunity = break_iterator_->NextBreakOpportunity(candidate_break); 207 break_opportunity = break_iterator_->NextBreakOpportunity(candidate_break);
208 // |range_end| may not be a break opportunity, but this function cannot
209 // measure beyond it.
210 break_opportunity = std::min(break_opportunity, range_end);
196 } 211 }
197 212
198 // Create shape results for the line by copying from the re-shaped result (if 213 // Create shape results for the line by copying from the re-shaped result (if
199 // reshaping was needed) and the original shape results. 214 // reshaping was needed) and the original shape results.
200 RefPtr<ShapeResult> line_result = ShapeResult::Create(font_, 0, direction); 215 RefPtr<ShapeResult> line_result = ShapeResult::Create(font_, 0, direction);
201 unsigned max_length = std::numeric_limits<unsigned>::max(); 216 unsigned max_length = std::numeric_limits<unsigned>::max();
202 if (line_start_result) 217 if (line_start_result)
203 line_start_result->CopyRange(0, max_length, line_result.Get()); 218 line_start_result->CopyRange(0, max_length, line_result.Get());
204 if (last_safe > first_safe) 219 if (last_safe > first_safe)
205 result_->CopyRange(first_safe, last_safe, line_result.Get()); 220 result_->CopyRange(first_safe, last_safe, line_result.Get());
206 if (line_end_result) 221 if (line_end_result)
207 line_end_result->CopyRange(last_safe, max_length, line_result.Get()); 222 line_end_result->CopyRange(last_safe, max_length, line_result.Get());
208 223
209 DCHECK_GT(break_opportunity, start); 224 DCHECK_GT(break_opportunity, start);
210 DCHECK_EQ(std::min(break_opportunity, range_end) - start, 225 DCHECK_EQ(std::min(break_opportunity, range_end) - start,
211 line_result->NumCharacters()); 226 line_result->NumCharacters());
212 227
213 *break_offset = break_opportunity; 228 *break_offset = break_opportunity;
214 return line_result.Release(); 229 return line_result.Release();
215 } 230 }
216 231
232 // Shape from the specified offset to the end of the ShapeResult.
233 // If |start| is safe-to-break, this copies the subset of the result.
234 PassRefPtr<ShapeResult> ShapingLineBreaker::ShapeToEnd(
235 unsigned start,
236 LayoutUnit start_position,
237 unsigned range_end) {
238 unsigned first_safe =
239 NextSafeToBreakBefore(shaper_->GetText(), shaper_->TextLength(), start);
240 DCHECK_GE(first_safe, start);
241
242 RefPtr<ShapeResult> line_result;
243 TextDirection direction = result_->Direction();
244 if (first_safe == start) {
245 // If |start| is safe-to-break, reshape is not needed.
246 line_result = ShapeResult::Create(font_, 0, direction);
247 result_->CopyRange(start, range_end, line_result.Get());
248 } else if (first_safe < range_end) {
249 // Otherwise reshape to the first safe, then copy the rest.
250 line_result = shaper_->Shape(font_, direction, start, first_safe);
251 result_->CopyRange(first_safe, range_end, line_result.Get());
252 } else {
253 // If no safe-to-break in the ragne, reshape the whole range.
254 line_result = shaper_->Shape(font_, direction, start, range_end);
255 }
256 return line_result.Release();
257 }
258
217 } // namespace blink 259 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698