Chromium Code Reviews| 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 |