OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/gfx/render_text_harfbuzz.h" | 5 #include "ui/gfx/render_text_harfbuzz.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/i18n/bidi_line_iterator.h" | 9 #include "base/i18n/bidi_line_iterator.h" |
10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 AdvanceLine(); | 292 AdvanceLine(); |
293 } | 293 } |
294 } | 294 } |
295 | 295 |
296 // Starting from |start_char|, finds a suitable line break position at or | 296 // Starting from |start_char|, finds a suitable line break position at or |
297 // before available width using word break. If the current position is at the | 297 // before available width using word break. If the current position is at the |
298 // beginning of a line, this function will not roll back to |start_char| and | 298 // beginning of a line, this function will not roll back to |start_char| and |
299 // |*next_char| will be greater than |start_char| (to avoid constructing empty | 299 // |*next_char| will be greater than |start_char| (to avoid constructing empty |
300 // lines). | 300 // lines). |
301 // Returns whether to skip the line before |*next_char|. | 301 // Returns whether to skip the line before |*next_char|. |
302 // TODO(ckocagil): Check clusters to avoid breaking ligatures and diacritics. | |
303 // TODO(ckocagil): We might have to reshape after breaking at ligatures. | 302 // TODO(ckocagil): We might have to reshape after breaking at ligatures. |
304 // See whether resolving the TODO above resolves this too. | 303 // See whether resolving the TODO above resolves this too. |
305 // TODO(ckocagil): Do not reserve width for whitespace at the end of lines. | 304 // TODO(ckocagil): Do not reserve width for whitespace at the end of lines. |
306 bool BreakRunAtWidth(const internal::TextRunHarfBuzz& run, | 305 bool BreakRunAtWidth(const internal::TextRunHarfBuzz& run, |
307 size_t start_char, | 306 size_t start_char, |
308 SkScalar* width, | 307 SkScalar* width, |
309 size_t* next_char) { | 308 size_t* next_char) { |
310 DCHECK(words_); | 309 DCHECK(words_); |
311 DCHECK(run.range.Contains(Range(start_char, start_char + 1))); | 310 DCHECK(run.range.Contains(Range(start_char, start_char + 1))); |
312 SkScalar available_width = max_width_ - line_x_; | 311 SkScalar available_width = max_width_ - line_x_; |
313 BreakList<size_t>::const_iterator word = words_->GetBreak(start_char); | 312 BreakList<size_t>::const_iterator word = words_->GetBreak(start_char); |
314 BreakList<size_t>::const_iterator next_word = word + 1; | 313 BreakList<size_t>::const_iterator next_word = word + 1; |
315 // Width from |std::max(word->first, start_char)| to the current character. | 314 // Width from |std::max(word->first, start_char)| to the current character. |
316 SkScalar word_width = 0; | 315 SkScalar word_width = 0; |
317 *width = 0; | 316 *width = 0; |
318 | 317 |
319 for (size_t i = start_char; i < run.range.end(); ++i) { | 318 Range char_range; |
| 319 for (size_t i = start_char; i < run.range.end(); i += char_range.length()) { |
320 // |word| holds the word boundary at or before |i|, and |next_word| holds | 320 // |word| holds the word boundary at or before |i|, and |next_word| holds |
321 // the word boundary right after |i|. Advance both |word| and |next_word| | 321 // the word boundary right after |i|. Advance both |word| and |next_word| |
322 // when |i| reaches |next_word|. | 322 // when |i| reaches |next_word|. |
323 if (next_word != words_->breaks().end() && i >= next_word->first) { | 323 if (next_word != words_->breaks().end() && i >= next_word->first) { |
324 word = next_word++; | 324 word = next_word++; |
325 word_width = 0; | 325 word_width = 0; |
326 } | 326 } |
327 | 327 |
328 Range glyph_range = run.CharRangeToGlyphRange(Range(i, i + 1)); | 328 Range glyph_range; |
| 329 run.GetClusterAt(i, &char_range, &glyph_range); |
| 330 DCHECK_LT(0U, char_range.length()); |
| 331 |
329 SkScalar char_width = ((glyph_range.end() >= run.glyph_count) | 332 SkScalar char_width = ((glyph_range.end() >= run.glyph_count) |
330 ? SkFloatToScalar(run.width) | 333 ? SkFloatToScalar(run.width) |
331 : run.positions[glyph_range.end()].x()) - | 334 : run.positions[glyph_range.end()].x()) - |
332 run.positions[glyph_range.start()].x(); | 335 run.positions[glyph_range.start()].x(); |
333 | 336 |
334 *width += char_width; | 337 *width += char_width; |
335 word_width += char_width; | 338 word_width += char_width; |
336 | 339 |
337 if (*width > available_width) { | 340 if (*width > available_width) { |
338 if (line_x_ != 0 || word_width < *width) { | 341 if (line_x_ != 0 || word_width < *width) { |
339 // Roll back one word. | 342 // Roll back one word. |
340 *width -= word_width; | 343 *width -= word_width; |
341 *next_char = std::max(word->first, start_char); | 344 *next_char = std::max(word->first, start_char); |
342 } else if (char_width < *width) { | 345 } else if (char_width < *width) { |
343 // Roll back one character. | 346 // Roll back one character. |
344 *width -= char_width; | 347 *width -= char_width; |
345 *next_char = i; | 348 *next_char = i; |
346 } else { | 349 } else { |
347 // Continue from the next character. | 350 // Continue from the next character. |
348 *next_char = i + 1; | 351 *next_char = i + char_range.length(); |
349 } | 352 } |
350 return true; | 353 return true; |
351 } | 354 } |
352 } | 355 } |
353 | 356 |
354 *next_char = run.range.end(); | 357 *next_char = run.range.end(); |
355 return false; | 358 return false; |
356 } | 359 } |
357 | 360 |
358 // RTL runs are broken in logical order but displayed in visual order. To find | 361 // RTL runs are broken in logical order but displayed in visual order. To find |
(...skipping 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1519 DCHECK(!update_layout_run_list_); | 1522 DCHECK(!update_layout_run_list_); |
1520 DCHECK(!update_display_run_list_); | 1523 DCHECK(!update_display_run_list_); |
1521 return text_elided() ? display_run_list_.get() : &layout_run_list_; | 1524 return text_elided() ? display_run_list_.get() : &layout_run_list_; |
1522 } | 1525 } |
1523 | 1526 |
1524 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { | 1527 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { |
1525 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); | 1528 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); |
1526 } | 1529 } |
1527 | 1530 |
1528 } // namespace gfx | 1531 } // namespace gfx |
OLD | NEW |