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 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 const internal::TextRunList& run_list) | 226 const internal::TextRunList& run_list) |
227 : max_width_((max_width == 0) ? SK_ScalarMax : SkIntToScalar(max_width)), | 227 : max_width_((max_width == 0) ? SK_ScalarMax : SkIntToScalar(max_width)), |
228 min_baseline_(min_baseline), | 228 min_baseline_(min_baseline), |
229 min_height_(min_height), | 229 min_height_(min_height), |
230 multiline_(multiline), | 230 multiline_(multiline), |
231 text_(text), | 231 text_(text), |
232 words_(words), | 232 words_(words), |
233 run_list_(run_list), | 233 run_list_(run_list), |
234 text_x_(0), | 234 text_x_(0), |
235 line_x_(0), | 235 line_x_(0), |
236 max_top_(0), | |
237 max_bottom_(0), | |
236 max_descent_(0), | 238 max_descent_(0), |
237 max_ascent_(0) { | 239 max_ascent_(0) { |
238 DCHECK_EQ(multiline_, (words_ != nullptr)); | 240 DCHECK_EQ(multiline_, (words_ != nullptr)); |
239 AdvanceLine(); | 241 AdvanceLine(); |
240 } | 242 } |
241 | 243 |
242 // Breaks the run at given |run_index| into Line structs. | 244 // Breaks the run at given |run_index| into Line structs. |
243 void AddRun(int run_index) { | 245 void AddRun(int run_index) { |
244 const internal::TextRunHarfBuzz* run = run_list_.runs()[run_index]; | 246 const internal::TextRunHarfBuzz* run = run_list_.runs()[run_index]; |
245 base::char16 first_char = text_[run->range.start()]; | 247 base::char16 first_char = text_[run->range.start()]; |
246 if (multiline_ && first_char == '\n') { | 248 if (multiline_ && first_char == '\n') { |
247 AdvanceLine(); | 249 AdvanceLine(); |
248 } else if (multiline_ && (line_x_ + SkFloatToScalar(run->width)) > | 250 } else if (multiline_ && (line_x_ + SkFloatToScalar(run->width)) > |
249 max_width_) { | 251 max_width_) { |
250 BreakRun(run_index); | 252 BreakRun(run_index); |
251 } else { | 253 } else { |
252 AddSegment(run_index, run->range, run->width); | 254 AddSegment(run_index, run->range, run->width); |
253 } | 255 } |
254 } | 256 } |
255 | 257 |
256 // Finishes line breaking and outputs the results. Can be called at most once. | 258 // Finishes line breaking and outputs the results. Can be called at most once. |
257 void Finalize(std::vector<internal::Line>* lines, SizeF* size) { | 259 void Finalize(std::vector<internal::Line>* lines, SizeF* size) { |
258 DCHECK(!lines_.empty()); | 260 DCHECK(!lines_.empty()); |
261 float trailing_height = std::max(0.f, max_bottom_ - max_descent_); | |
259 // Add an empty line to finish the line size calculation and remove it. | 262 // Add an empty line to finish the line size calculation and remove it. |
260 AdvanceLine(); | 263 AdvanceLine(); |
261 lines_.pop_back(); | 264 lines_.pop_back(); |
262 *size = total_size_; | 265 *size = total_size_; |
266 size->Enlarge(0, trailing_height); | |
263 lines->swap(lines_); | 267 lines->swap(lines_); |
264 } | 268 } |
265 | 269 |
266 private: | 270 private: |
267 // A (line index, segment index) pair that specifies a segment in |lines_|. | 271 // A (line index, segment index) pair that specifies a segment in |lines_|. |
268 typedef std::pair<size_t, size_t> SegmentHandle; | 272 typedef std::pair<size_t, size_t> SegmentHandle; |
269 | 273 |
270 internal::LineSegment* SegmentFromHandle(const SegmentHandle& handle) { | 274 internal::LineSegment* SegmentFromHandle(const SegmentHandle& handle) { |
271 return &lines_[handle.first].segments[handle.second]; | 275 return &lines_[handle.first].segments[handle.second]; |
272 } | 276 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 internal::Line* line = &lines_.back(); | 381 internal::Line* line = &lines_.back(); |
378 std::sort(line->segments.begin(), line->segments.end(), | 382 std::sort(line->segments.begin(), line->segments.end(), |
379 [this](const internal::LineSegment& s1, | 383 [this](const internal::LineSegment& s1, |
380 const internal::LineSegment& s2) -> bool { | 384 const internal::LineSegment& s2) -> bool { |
381 return run_list_.logical_to_visual(s1.run) < | 385 return run_list_.logical_to_visual(s1.run) < |
382 run_list_.logical_to_visual(s2.run); | 386 run_list_.logical_to_visual(s2.run); |
383 }); | 387 }); |
384 line->size.set_height(std::max(min_height_, max_descent_ + max_ascent_)); | 388 line->size.set_height(std::max(min_height_, max_descent_ + max_ascent_)); |
385 line->baseline = | 389 line->baseline = |
386 std::max(min_baseline_, SkScalarRoundToInt(max_ascent_)); | 390 std::max(min_baseline_, SkScalarRoundToInt(max_ascent_)); |
387 line->preceding_heights = std::ceil(total_size_.height()); | 391 if (line == &lines_.front()) { |
msw
2015/02/24 23:31:35
Why does only the first line add the extra height
Jun Mukai
2015/02/25 23:49:19
Comments added. Our code base seems to assume lin
| |
388 total_size_.set_height(total_size_.height() + line->size.height()); | 392 line->preceding_heights = |
393 std::ceil(std::max(0.f, max_top_ - max_ascent_)); | |
394 total_size_.set_height(line->preceding_heights + line->size.height()); | |
395 } else { | |
396 line->preceding_heights = std::ceil(total_size_.height()); | |
397 total_size_.set_height(total_size_.height() + line->size.height()); | |
398 } | |
389 total_size_.set_width(std::max(total_size_.width(), line->size.width())); | 399 total_size_.set_width(std::max(total_size_.width(), line->size.width())); |
390 } | 400 } |
401 max_top_ = 0; | |
402 max_bottom_ = 0; | |
391 max_descent_ = 0; | 403 max_descent_ = 0; |
392 max_ascent_ = 0; | 404 max_ascent_ = 0; |
393 line_x_ = 0; | 405 line_x_ = 0; |
394 lines_.push_back(internal::Line()); | 406 lines_.push_back(internal::Line()); |
395 } | 407 } |
396 | 408 |
397 // Adds a new segment with the given properties to |lines_.back()|. | 409 // Adds a new segment with the given properties to |lines_.back()|. |
398 void AddSegment(int run_index, Range char_range, float width) { | 410 void AddSegment(int run_index, Range char_range, float width) { |
399 if (char_range.is_empty()) { | 411 if (char_range.is_empty()) { |
400 DCHECK_EQ(0, width); | 412 DCHECK_EQ(0, width); |
(...skipping 14 matching lines...) Expand all Loading... | |
415 | 427 |
416 SkPaint paint; | 428 SkPaint paint; |
417 paint.setTypeface(run.skia_face.get()); | 429 paint.setTypeface(run.skia_face.get()); |
418 paint.setTextSize(SkIntToScalar(run.font_size)); | 430 paint.setTextSize(SkIntToScalar(run.font_size)); |
419 paint.setAntiAlias(run.render_params.antialiasing); | 431 paint.setAntiAlias(run.render_params.antialiasing); |
420 SkPaint::FontMetrics metrics; | 432 SkPaint::FontMetrics metrics; |
421 paint.getFontMetrics(&metrics); | 433 paint.getFontMetrics(&metrics); |
422 | 434 |
423 line->size.set_width(line->size.width() + width); | 435 line->size.set_width(line->size.width() + width); |
424 max_descent_ = std::max(max_descent_, metrics.fDescent); | 436 max_descent_ = std::max(max_descent_, metrics.fDescent); |
425 // fAscent is always negative. | 437 max_bottom_ = std::max(max_bottom_, metrics.fBottom); |
438 // fAscent and fTop are always negative. | |
426 max_ascent_ = std::max(max_ascent_, -metrics.fAscent); | 439 max_ascent_ = std::max(max_ascent_, -metrics.fAscent); |
440 max_top_ = std::max(max_top_, -metrics.fTop); | |
427 | 441 |
428 if (run.is_rtl) { | 442 if (run.is_rtl) { |
429 rtl_segments_.push_back( | 443 rtl_segments_.push_back( |
430 SegmentHandle(lines_.size() - 1, line->segments.size() - 1)); | 444 SegmentHandle(lines_.size() - 1, line->segments.size() - 1)); |
431 // If this is the last segment of an RTL run, reprocess the text-space x | 445 // If this is the last segment of an RTL run, reprocess the text-space x |
432 // ranges of all segments from the run. | 446 // ranges of all segments from the run. |
433 if (char_range.end() == run.range.end()) | 447 if (char_range.end() == run.range.end()) |
434 UpdateRTLSegmentRanges(); | 448 UpdateRTLSegmentRanges(); |
435 } | 449 } |
436 text_x_ += SkFloatToScalar(width); | 450 text_x_ += SkFloatToScalar(width); |
437 line_x_ += SkFloatToScalar(width); | 451 line_x_ += SkFloatToScalar(width); |
438 } | 452 } |
439 | 453 |
440 const SkScalar max_width_; | 454 const SkScalar max_width_; |
441 const int min_baseline_; | 455 const int min_baseline_; |
442 const float min_height_; | 456 const float min_height_; |
443 const bool multiline_; | 457 const bool multiline_; |
444 const base::string16& text_; | 458 const base::string16& text_; |
445 const BreakList<size_t>* const words_; | 459 const BreakList<size_t>* const words_; |
446 const internal::TextRunList& run_list_; | 460 const internal::TextRunList& run_list_; |
447 | 461 |
448 // Stores the resulting lines. | 462 // Stores the resulting lines. |
449 std::vector<internal::Line> lines_; | 463 std::vector<internal::Line> lines_; |
450 | 464 |
451 // Text space and line space x coordinates of the next segment to be added. | 465 // Text space and line space x coordinates of the next segment to be added. |
452 SkScalar text_x_; | 466 SkScalar text_x_; |
453 SkScalar line_x_; | 467 SkScalar line_x_; |
454 | 468 |
469 float max_top_; | |
470 float max_bottom_; | |
455 float max_descent_; | 471 float max_descent_; |
456 float max_ascent_; | 472 float max_ascent_; |
457 | 473 |
458 // Size of the multiline text, not including the currently processed line. | 474 // Size of the multiline text, not including the currently processed line. |
459 SizeF total_size_; | 475 SizeF total_size_; |
460 | 476 |
461 // The current RTL run segments, to be applied by |UpdateRTLSegmentRanges()|. | 477 // The current RTL run segments, to be applied by |UpdateRTLSegmentRanges()|. |
462 std::vector<SegmentHandle> rtl_segments_; | 478 std::vector<SegmentHandle> rtl_segments_; |
463 | 479 |
464 DISALLOW_COPY_AND_ASSIGN(HarfBuzzLineBreaker); | 480 DISALLOW_COPY_AND_ASSIGN(HarfBuzzLineBreaker); |
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1468 DCHECK(!update_layout_run_list_); | 1484 DCHECK(!update_layout_run_list_); |
1469 DCHECK(!update_display_run_list_); | 1485 DCHECK(!update_display_run_list_); |
1470 return text_elided() ? display_run_list_.get() : &layout_run_list_; | 1486 return text_elided() ? display_run_list_.get() : &layout_run_list_; |
1471 } | 1487 } |
1472 | 1488 |
1473 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { | 1489 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { |
1474 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); | 1490 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); |
1475 } | 1491 } |
1476 | 1492 |
1477 } // namespace gfx | 1493 } // namespace gfx |
OLD | NEW |