Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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.h" | 5 #include "ui/gfx/render_text.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <climits> | 10 #include <climits> |
| 11 | 11 |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/i18n/break_iterator.h" | 13 #include "base/i18n/break_iterator.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 18 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
| 19 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 20 #include "third_party/icu/source/common/unicode/rbbi.h" | 20 #include "third_party/icu/source/common/unicode/rbbi.h" |
| 21 #include "third_party/icu/source/common/unicode/utf16.h" | 21 #include "third_party/icu/source/common/unicode/utf16.h" |
| 22 #include "third_party/skia/include/core/SkDrawLooper.h" | 22 #include "third_party/skia/include/core/SkDrawLooper.h" |
| 23 #include "third_party/skia/include/core/SkFontStyle.h" | |
| 23 #include "third_party/skia/include/core/SkTypeface.h" | 24 #include "third_party/skia/include/core/SkTypeface.h" |
| 24 #include "third_party/skia/include/effects/SkGradientShader.h" | 25 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 25 #include "ui/gfx/canvas.h" | 26 #include "ui/gfx/canvas.h" |
| 26 #include "ui/gfx/geometry/insets.h" | 27 #include "ui/gfx/geometry/insets.h" |
| 27 #include "ui/gfx/geometry/safe_integer_conversions.h" | 28 #include "ui/gfx/geometry/safe_integer_conversions.h" |
| 28 #include "ui/gfx/platform_font.h" | 29 #include "ui/gfx/platform_font.h" |
| 29 #include "ui/gfx/render_text_harfbuzz.h" | 30 #include "ui/gfx/render_text_harfbuzz.h" |
| 30 #include "ui/gfx/scoped_canvas.h" | 31 #include "ui/gfx/scoped_canvas.h" |
| 31 #include "ui/gfx/skia_util.h" | 32 #include "ui/gfx/skia_util.h" |
| 32 #include "ui/gfx/switches.h" | 33 #include "ui/gfx/switches.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 // Some platforms don't support getting the cap height, and simply return | 84 // Some platforms don't support getting the cap height, and simply return |
| 84 // the entire font ascent from GetCapHeight(). Centering the ascent makes | 85 // the entire font ascent from GetCapHeight(). Centering the ascent makes |
| 85 // the font look too low, so if GetCapHeight() returns the ascent, center | 86 // the font look too low, so if GetCapHeight() returns the ascent, center |
| 86 // the entire font height instead. | 87 // the entire font height instead. |
| 87 const int space = | 88 const int space = |
| 88 display_height - ((internal_leading != 0) ? cap_height : font_height); | 89 display_height - ((internal_leading != 0) ? cap_height : font_height); |
| 89 const int baseline_shift = space / 2 - internal_leading; | 90 const int baseline_shift = space / 2 - internal_leading; |
| 90 return baseline + std::max(min_shift, std::min(max_shift, baseline_shift)); | 91 return baseline + std::max(min_shift, std::min(max_shift, baseline_shift)); |
| 91 } | 92 } |
| 92 | 93 |
| 93 #if !defined(OS_MACOSX) | |
| 94 // Converts |Font::FontStyle| flags to |SkTypeface::Style| flags. | |
| 95 SkTypeface::Style ConvertFontStyleToSkiaTypefaceStyle(int font_style) { | |
| 96 int skia_style = SkTypeface::kNormal; | |
| 97 skia_style |= (font_style & Font::BOLD) ? SkTypeface::kBold : 0; | |
| 98 skia_style |= (font_style & Font::ITALIC) ? SkTypeface::kItalic : 0; | |
| 99 return static_cast<SkTypeface::Style>(skia_style); | |
| 100 } | |
| 101 #endif | |
| 102 | |
| 103 int round(float value) { | 94 int round(float value) { |
| 104 return static_cast<int>(floor(value + 0.5f)); | 95 return static_cast<int>(floor(value + 0.5f)); |
| 105 } | 96 } |
| 106 | 97 |
| 107 // Given |font| and |display_width|, returns the width of the fade gradient. | 98 // Given |font| and |display_width|, returns the width of the fade gradient. |
| 108 int CalculateFadeGradientWidth(const FontList& font_list, int display_width) { | 99 int CalculateFadeGradientWidth(const FontList& font_list, int display_width) { |
| 109 // Fade in/out about 3 characters of the beginning/end of the string. | 100 // Fade in/out about 3 characters of the beginning/end of the string. |
| 110 // Use a 1/3 of the display width if the display width is very short. | 101 // Use a 1/3 of the display width if the display width is very short. |
| 111 const int narrow_width = font_list.GetExpectedTextWidth(3); | 102 const int narrow_width = font_list.GetExpectedTextWidth(3); |
| 112 const int gradient_width = std::min(narrow_width, round(display_width / 3.f)); | 103 const int gradient_width = std::min(narrow_width, round(display_width / 3.f)); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 } | 241 } |
| 251 | 242 |
| 252 void SkiaTextRenderer::SetTypeface(SkTypeface* typeface) { | 243 void SkiaTextRenderer::SetTypeface(SkTypeface* typeface) { |
| 253 paint_.setTypeface(typeface); | 244 paint_.setTypeface(typeface); |
| 254 } | 245 } |
| 255 | 246 |
| 256 void SkiaTextRenderer::SetTextSize(SkScalar size) { | 247 void SkiaTextRenderer::SetTextSize(SkScalar size) { |
| 257 paint_.setTextSize(size); | 248 paint_.setTextSize(size); |
| 258 } | 249 } |
| 259 | 250 |
| 260 void SkiaTextRenderer::SetFontWithStyle(const Font& font, int style) { | 251 void SkiaTextRenderer::SetFont(const Font& font, |
| 261 skia::RefPtr<SkTypeface> typeface = CreateSkiaTypeface(font, style); | 252 bool italic, |
| 253 gfx::Font::Weight weight) { | |
|
Alexei Svitkine (slow)
2016/04/05 16:38:53
Remove gfx::
| |
| 254 skia::RefPtr<SkTypeface> typeface = CreateSkiaTypeface(font, italic, weight); | |
| 262 if (typeface) { | 255 if (typeface) { |
| 263 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. | 256 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. |
| 264 SetTypeface(typeface.get()); | 257 SetTypeface(typeface.get()); |
| 265 | 258 |
| 266 // Enable fake bold text if bold style is needed but new typeface does not | 259 // Enable fake bold text if bold style is needed but new typeface does not |
| 267 // have it. | 260 // have it. |
| 268 paint_.setFakeBoldText((style & Font::BOLD) && !typeface->isBold()); | 261 paint_.setFakeBoldText(weight >= gfx::Font::Weight::SEMIBOLD && |
|
Alexei Svitkine (slow)
2016/04/05 16:38:52
Remove gfx::
| |
| 262 !typeface->isBold()); | |
| 269 } | 263 } |
| 270 } | 264 } |
| 271 | 265 |
| 272 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { | 266 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { |
| 273 paint_.setColor(foreground); | 267 paint_.setColor(foreground); |
| 274 } | 268 } |
| 275 | 269 |
| 276 void SkiaTextRenderer::SetShader(sk_sp<SkShader> shader) { | 270 void SkiaTextRenderer::SetShader(sk_sp<SkShader> shader) { |
| 277 paint_.setShader(std::move(shader)); | 271 paint_.setShader(std::move(shader)); |
| 278 } | 272 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 | 375 |
| 382 if (clipped) | 376 if (clipped) |
| 383 canvas_->Restore(); | 377 canvas_->Restore(); |
| 384 | 378 |
| 385 x += pieces_[i].first; | 379 x += pieces_[i].first; |
| 386 } | 380 } |
| 387 } | 381 } |
| 388 | 382 |
| 389 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 383 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
| 390 const BreakList<BaselineStyle>& baselines, | 384 const BreakList<BaselineStyle>& baselines, |
| 385 const BreakList<gfx::Font::Weight>& weights, | |
|
Alexei Svitkine (slow)
2016/04/05 16:38:53
Remove gfx::
| |
| 391 const std::vector<BreakList<bool>>& styles) | 386 const std::vector<BreakList<bool>>& styles) |
| 392 : colors_(colors), baselines_(baselines), styles_(styles) { | 387 : colors_(colors), |
| 388 baselines_(baselines), | |
| 389 weights_(weights), | |
| 390 styles_(styles) { | |
| 393 color_ = colors_.breaks().begin(); | 391 color_ = colors_.breaks().begin(); |
| 394 baseline_ = baselines_.breaks().begin(); | 392 baseline_ = baselines_.breaks().begin(); |
| 393 weight_ = weights_.breaks().begin(); | |
| 395 for (size_t i = 0; i < styles_.size(); ++i) | 394 for (size_t i = 0; i < styles_.size(); ++i) |
| 396 style_.push_back(styles_[i].breaks().begin()); | 395 style_.push_back(styles_[i].breaks().begin()); |
| 397 } | 396 } |
| 398 | 397 |
| 399 StyleIterator::~StyleIterator() {} | 398 StyleIterator::~StyleIterator() {} |
| 400 | 399 |
| 401 Range StyleIterator::GetRange() const { | 400 Range StyleIterator::GetRange() const { |
| 402 Range range(colors_.GetRange(color_)); | 401 Range range(colors_.GetRange(color_)); |
| 403 range = range.Intersect(baselines_.GetRange(baseline_)); | 402 range = range.Intersect(baselines_.GetRange(baseline_)); |
| 403 range = range.Intersect(weights_.GetRange(weight_)); | |
| 404 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 404 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 405 range = range.Intersect(styles_[i].GetRange(style_[i])); | 405 range = range.Intersect(styles_[i].GetRange(style_[i])); |
| 406 return range; | 406 return range; |
| 407 } | 407 } |
| 408 | 408 |
| 409 void StyleIterator::UpdatePosition(size_t position) { | 409 void StyleIterator::UpdatePosition(size_t position) { |
| 410 color_ = colors_.GetBreak(position); | 410 color_ = colors_.GetBreak(position); |
| 411 baseline_ = baselines_.GetBreak(position); | 411 baseline_ = baselines_.GetBreak(position); |
| 412 weight_ = weights_.GetBreak(position); | |
| 412 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 413 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 413 style_[i] = styles_[i].GetBreak(position); | 414 style_[i] = styles_[i].GetBreak(position); |
| 414 } | 415 } |
| 415 | 416 |
| 416 LineSegment::LineSegment() : run(0) {} | 417 LineSegment::LineSegment() : run(0) {} |
| 417 | 418 |
| 418 LineSegment::~LineSegment() {} | 419 LineSegment::~LineSegment() {} |
| 419 | 420 |
| 420 Line::Line() : preceding_heights(0), baseline(0) {} | 421 Line::Line() : preceding_heights(0), baseline(0) {} |
| 421 | 422 |
| 422 Line::Line(const Line& other) = default; | 423 Line::Line(const Line& other) = default; |
| 423 | 424 |
| 424 Line::~Line() {} | 425 Line::~Line() {} |
| 425 | 426 |
| 426 #if !defined(OS_MACOSX) | 427 #if !defined(OS_MACOSX) |
| 427 skia::RefPtr<SkTypeface> CreateSkiaTypeface(const gfx::Font& font, int style) { | 428 skia::RefPtr<SkTypeface> CreateSkiaTypeface(const gfx::Font& font, |
|
Alexei Svitkine (slow)
2016/04/05 16:38:53
Remove gfx::
| |
| 428 SkTypeface::Style skia_style = ConvertFontStyleToSkiaTypefaceStyle(style); | 429 bool italic, |
| 430 gfx::Font::Weight weight) { | |
|
Alexei Svitkine (slow)
2016/04/05 16:38:53
Remove gfx::
| |
| 431 SkFontStyle skia_style( | |
| 432 static_cast<int>(weight), SkFontStyle::kNormal_Width, | |
| 433 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); | |
| 429 return skia::AdoptRef( | 434 return skia::AdoptRef( |
| 430 SkTypeface::CreateFromName(font.GetFontName().c_str(), skia_style)); | 435 SkTypeface::CreateFromName(font.GetFontName().c_str(), skia_style)); |
| 431 } | 436 } |
| 432 #endif | 437 #endif |
| 433 | 438 |
| 434 void ApplyRenderParams(const FontRenderParams& params, | 439 void ApplyRenderParams(const FontRenderParams& params, |
| 435 bool subpixel_rendering_suppressed, | 440 bool subpixel_rendering_suppressed, |
| 436 SkPaint* paint) { | 441 SkPaint* paint) { |
| 437 paint->setAntiAlias(params.antialiasing); | 442 paint->setAntiAlias(params.antialiasing); |
| 438 paint->setLCDRenderText(!subpixel_rendering_suppressed && | 443 paint->setLCDRenderText(!subpixel_rendering_suppressed && |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 468 DCHECK(!composition_range_.IsValid()); | 473 DCHECK(!composition_range_.IsValid()); |
| 469 if (text_ == text) | 474 if (text_ == text) |
| 470 return; | 475 return; |
| 471 text_ = text; | 476 text_ = text; |
| 472 UpdateStyleLengths(); | 477 UpdateStyleLengths(); |
| 473 | 478 |
| 474 // Clear style ranges as they might break new text graphemes and apply | 479 // Clear style ranges as they might break new text graphemes and apply |
| 475 // the first style to the whole text instead. | 480 // the first style to the whole text instead. |
| 476 colors_.SetValue(colors_.breaks().begin()->second); | 481 colors_.SetValue(colors_.breaks().begin()->second); |
| 477 baselines_.SetValue(baselines_.breaks().begin()->second); | 482 baselines_.SetValue(baselines_.breaks().begin()->second); |
| 483 weights_.SetValue(weights_.breaks().begin()->second); | |
| 478 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 484 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 479 styles_[style].SetValue(styles_[style].breaks().begin()->second); | 485 styles_[style].SetValue(styles_[style].breaks().begin()->second); |
| 480 cached_bounds_and_offset_valid_ = false; | 486 cached_bounds_and_offset_valid_ = false; |
| 481 | 487 |
| 482 // Reset selection model. SetText should always followed by SetSelectionModel | 488 // Reset selection model. SetText should always followed by SetSelectionModel |
| 483 // or SetCursorPosition in upper layer. | 489 // or SetCursorPosition in upper layer. |
| 484 SetSelectionModel(SelectionModel()); | 490 SetSelectionModel(SelectionModel()); |
| 485 | 491 |
| 486 // Invalidate the cached text direction if it depends on the text contents. | 492 // Invalidate the cached text direction if it depends on the text contents. |
| 487 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) | 493 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 503 if (horizontal_alignment_ != alignment) { | 509 if (horizontal_alignment_ != alignment) { |
| 504 horizontal_alignment_ = alignment; | 510 horizontal_alignment_ = alignment; |
| 505 display_offset_ = Vector2d(); | 511 display_offset_ = Vector2d(); |
| 506 cached_bounds_and_offset_valid_ = false; | 512 cached_bounds_and_offset_valid_ = false; |
| 507 } | 513 } |
| 508 } | 514 } |
| 509 | 515 |
| 510 void RenderText::SetFontList(const FontList& font_list) { | 516 void RenderText::SetFontList(const FontList& font_list) { |
| 511 font_list_ = font_list; | 517 font_list_ = font_list; |
| 512 const int font_style = font_list.GetFontStyle(); | 518 const int font_style = font_list.GetFontStyle(); |
| 513 SetStyle(BOLD, (font_style & gfx::Font::BOLD) != 0); | 519 weights_.SetValue(font_list.GetFontWeight()); |
| 514 SetStyle(ITALIC, (font_style & gfx::Font::ITALIC) != 0); | 520 styles_[ITALIC].SetValue((font_style & gfx::Font::ITALIC) != 0); |
| 515 SetStyle(UNDERLINE, (font_style & gfx::Font::UNDERLINE) != 0); | 521 styles_[UNDERLINE].SetValue((font_style & gfx::Font::UNDERLINE) != 0); |
| 516 baseline_ = kInvalidBaseline; | 522 baseline_ = kInvalidBaseline; |
| 517 cached_bounds_and_offset_valid_ = false; | 523 cached_bounds_and_offset_valid_ = false; |
| 518 OnLayoutTextAttributeChanged(false); | 524 OnLayoutTextAttributeChanged(false); |
| 519 } | 525 } |
| 520 | 526 |
| 521 void RenderText::SetCursorEnabled(bool cursor_enabled) { | 527 void RenderText::SetCursorEnabled(bool cursor_enabled) { |
| 522 cursor_enabled_ = cursor_enabled; | 528 cursor_enabled_ = cursor_enabled; |
| 523 cached_bounds_and_offset_valid_ = false; | 529 cached_bounds_and_offset_valid_ = false; |
| 524 } | 530 } |
| 525 | 531 |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 765 const size_t end = IsValidCursorIndex(range.end()) ? range.end() : | 771 const size_t end = IsValidCursorIndex(range.end()) ? range.end() : |
| 766 IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); | 772 IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); |
| 767 styles_[style].ApplyValue(value, Range(start, end)); | 773 styles_[style].ApplyValue(value, Range(start, end)); |
| 768 | 774 |
| 769 cached_bounds_and_offset_valid_ = false; | 775 cached_bounds_and_offset_valid_ = false; |
| 770 // TODO(oshima|msw): Not all style change requires layout changes. | 776 // TODO(oshima|msw): Not all style change requires layout changes. |
| 771 // Consider optimizing based on the type of change. | 777 // Consider optimizing based on the type of change. |
| 772 OnLayoutTextAttributeChanged(false); | 778 OnLayoutTextAttributeChanged(false); |
| 773 } | 779 } |
| 774 | 780 |
| 781 void RenderText::SetWeight(gfx::Font::Weight weight) { | |
|
Alexei Svitkine (slow)
2016/04/05 16:38:53
Remove gfx::
| |
| 782 weights_.SetValue(weight); | |
| 783 | |
| 784 cached_bounds_and_offset_valid_ = false; | |
| 785 OnLayoutTextAttributeChanged(false); | |
| 786 } | |
| 787 | |
| 788 void RenderText::ApplyWeight(gfx::Font::Weight weight, const Range& range) { | |
|
Alexei Svitkine (slow)
2016/04/05 16:38:52
Remove gfx::
| |
| 789 weights_.ApplyValue(weight, range); | |
| 790 | |
| 791 cached_bounds_and_offset_valid_ = false; | |
| 792 OnLayoutTextAttributeChanged(false); | |
| 793 } | |
| 794 | |
| 775 bool RenderText::GetStyle(TextStyle style) const { | 795 bool RenderText::GetStyle(TextStyle style) const { |
| 776 return (styles_[style].breaks().size() == 1) && | 796 return (styles_[style].breaks().size() == 1) && |
| 777 styles_[style].breaks().front().second; | 797 styles_[style].breaks().front().second; |
| 778 } | 798 } |
| 779 | 799 |
| 780 void RenderText::SetDirectionalityMode(DirectionalityMode mode) { | 800 void RenderText::SetDirectionalityMode(DirectionalityMode mode) { |
| 781 if (mode == directionality_mode_) | 801 if (mode == directionality_mode_) |
| 782 return; | 802 return; |
| 783 | 803 |
| 784 directionality_mode_ = mode; | 804 directionality_mode_ = mode; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 996 cursor_enabled_(true), | 1016 cursor_enabled_(true), |
| 997 cursor_visible_(false), | 1017 cursor_visible_(false), |
| 998 insert_mode_(true), | 1018 insert_mode_(true), |
| 999 cursor_color_(kDefaultColor), | 1019 cursor_color_(kDefaultColor), |
| 1000 selection_color_(kDefaultColor), | 1020 selection_color_(kDefaultColor), |
| 1001 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 1021 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
| 1002 focused_(false), | 1022 focused_(false), |
| 1003 composition_range_(Range::InvalidRange()), | 1023 composition_range_(Range::InvalidRange()), |
| 1004 colors_(kDefaultColor), | 1024 colors_(kDefaultColor), |
| 1005 baselines_(NORMAL_BASELINE), | 1025 baselines_(NORMAL_BASELINE), |
| 1026 weights_(gfx::Font::Weight::NORMAL), | |
|
Alexei Svitkine (slow)
2016/04/05 16:38:53
Remove gfx::
| |
| 1006 styles_(NUM_TEXT_STYLES), | 1027 styles_(NUM_TEXT_STYLES), |
| 1007 composition_and_selection_styles_applied_(false), | 1028 composition_and_selection_styles_applied_(false), |
| 1008 obscured_(false), | 1029 obscured_(false), |
| 1009 obscured_reveal_index_(-1), | 1030 obscured_reveal_index_(-1), |
| 1010 truncate_length_(0), | 1031 truncate_length_(0), |
| 1011 elide_behavior_(NO_ELIDE), | 1032 elide_behavior_(NO_ELIDE), |
| 1012 text_elided_(false), | 1033 text_elided_(false), |
| 1013 min_line_height_(0), | 1034 min_line_height_(0), |
| 1014 multiline_(false), | 1035 multiline_(false), |
| 1015 word_wrap_behavior_(IGNORE_LONG_WORDS), | 1036 word_wrap_behavior_(IGNORE_LONG_WORDS), |
| 1016 replace_newline_chars_with_symbols_(true), | 1037 replace_newline_chars_with_symbols_(true), |
| 1017 subpixel_rendering_suppressed_(false), | 1038 subpixel_rendering_suppressed_(false), |
| 1018 clip_to_display_rect_(true), | 1039 clip_to_display_rect_(true), |
| 1019 baseline_(kInvalidBaseline), | 1040 baseline_(kInvalidBaseline), |
| 1020 cached_bounds_and_offset_valid_(false) { | 1041 cached_bounds_and_offset_valid_(false) {} |
| 1021 } | |
| 1022 | 1042 |
| 1023 SelectionModel RenderText::GetAdjacentSelectionModel( | 1043 SelectionModel RenderText::GetAdjacentSelectionModel( |
| 1024 const SelectionModel& current, | 1044 const SelectionModel& current, |
| 1025 BreakType break_type, | 1045 BreakType break_type, |
| 1026 VisualCursorDirection direction) { | 1046 VisualCursorDirection direction) { |
| 1027 EnsureLayout(); | 1047 EnsureLayout(); |
| 1028 | 1048 |
| 1029 if (break_type == LINE_BREAK || text().empty()) | 1049 if (break_type == LINE_BREAK || text().empty()) |
| 1030 return EdgeSelectionModel(direction); | 1050 return EdgeSelectionModel(direction); |
| 1031 if (break_type == CHARACTER_BREAK) | 1051 if (break_type == CHARACTER_BREAK) |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1279 ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index; | 1299 ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index; |
| 1280 CHECK_GE(i, 0); | 1300 CHECK_GE(i, 0); |
| 1281 // Clamp indices to the length of the given layout or display text. | 1301 // Clamp indices to the length of the given layout or display text. |
| 1282 return std::min<size_t>(given_text.length(), i); | 1302 return std::min<size_t>(given_text.length(), i); |
| 1283 } | 1303 } |
| 1284 | 1304 |
| 1285 void RenderText::UpdateStyleLengths() { | 1305 void RenderText::UpdateStyleLengths() { |
| 1286 const size_t text_length = text_.length(); | 1306 const size_t text_length = text_.length(); |
| 1287 colors_.SetMax(text_length); | 1307 colors_.SetMax(text_length); |
| 1288 baselines_.SetMax(text_length); | 1308 baselines_.SetMax(text_length); |
| 1309 weights_.SetMax(text_length); | |
| 1289 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1310 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 1290 styles_[style].SetMax(text_length); | 1311 styles_[style].SetMax(text_length); |
| 1291 } | 1312 } |
| 1292 | 1313 |
| 1293 // static | 1314 // static |
| 1294 bool RenderText::RangeContainsCaret(const Range& range, | 1315 bool RenderText::RangeContainsCaret(const Range& range, |
| 1295 size_t caret_pos, | 1316 size_t caret_pos, |
| 1296 LogicalCursorDirection caret_affinity) { | 1317 LogicalCursorDirection caret_affinity) { |
| 1297 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). | 1318 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). |
| 1298 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? | 1319 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1382 | 1403 |
| 1383 // Create a RenderText copy with attributes that affect the rendering width. | 1404 // Create a RenderText copy with attributes that affect the rendering width. |
| 1384 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); | 1405 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); |
| 1385 render_text->SetFontList(font_list_); | 1406 render_text->SetFontList(font_list_); |
| 1386 render_text->SetDirectionalityMode(directionality_mode_); | 1407 render_text->SetDirectionalityMode(directionality_mode_); |
| 1387 render_text->SetCursorEnabled(cursor_enabled_); | 1408 render_text->SetCursorEnabled(cursor_enabled_); |
| 1388 render_text->set_truncate_length(truncate_length_); | 1409 render_text->set_truncate_length(truncate_length_); |
| 1389 render_text->styles_ = styles_; | 1410 render_text->styles_ = styles_; |
| 1390 render_text->baselines_ = baselines_; | 1411 render_text->baselines_ = baselines_; |
| 1391 render_text->colors_ = colors_; | 1412 render_text->colors_ = colors_; |
| 1413 render_text->weights_ = weights_; | |
| 1392 if (text_width == 0) { | 1414 if (text_width == 0) { |
| 1393 render_text->SetText(text); | 1415 render_text->SetText(text); |
| 1394 text_width = render_text->GetContentWidthF(); | 1416 text_width = render_text->GetContentWidthF(); |
| 1395 } | 1417 } |
| 1396 if (text_width <= available_width) | 1418 if (text_width <= available_width) |
| 1397 return text; | 1419 return text; |
| 1398 | 1420 |
| 1399 const base::string16 ellipsis = base::string16(kEllipsisUTF16); | 1421 const base::string16 ellipsis = base::string16(kEllipsisUTF16); |
| 1400 const bool insert_ellipsis = (behavior != TRUNCATE); | 1422 const bool insert_ellipsis = (behavior != TRUNCATE); |
| 1401 const bool elide_in_middle = (behavior == ELIDE_MIDDLE); | 1423 const bool elide_in_middle = (behavior == ELIDE_MIDDLE); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1439 new_text += base::i18n::kRightToLeftMark; | 1461 new_text += base::i18n::kRightToLeftMark; |
| 1440 } | 1462 } |
| 1441 render_text->SetText(new_text); | 1463 render_text->SetText(new_text); |
| 1442 } | 1464 } |
| 1443 | 1465 |
| 1444 // Restore styles and baselines without breaking multi-character graphemes. | 1466 // Restore styles and baselines without breaking multi-character graphemes. |
| 1445 render_text->styles_ = styles_; | 1467 render_text->styles_ = styles_; |
| 1446 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1468 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 1447 RestoreBreakList(render_text.get(), &render_text->styles_[style]); | 1469 RestoreBreakList(render_text.get(), &render_text->styles_[style]); |
| 1448 RestoreBreakList(render_text.get(), &render_text->baselines_); | 1470 RestoreBreakList(render_text.get(), &render_text->baselines_); |
| 1471 RestoreBreakList(render_text.get(), &render_text->weights_); | |
| 1449 | 1472 |
| 1450 // We check the width of the whole desired string at once to ensure we | 1473 // We check the width of the whole desired string at once to ensure we |
| 1451 // handle kerning/ligatures/etc. correctly. | 1474 // handle kerning/ligatures/etc. correctly. |
| 1452 const float guess_width = render_text->GetContentWidthF(); | 1475 const float guess_width = render_text->GetContentWidthF(); |
| 1453 if (guess_width == available_width) | 1476 if (guess_width == available_width) |
| 1454 break; | 1477 break; |
| 1455 if (guess_width > available_width) { | 1478 if (guess_width > available_width) { |
| 1456 hi = guess - 1; | 1479 hi = guess - 1; |
| 1457 // Move back on the loop terminating condition when the guess is too wide. | 1480 // Move back on the loop terminating condition when the guess is too wide. |
| 1458 if (hi < lo) | 1481 if (hi < lo) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1545 | 1568 |
| 1546 SetDisplayOffset(display_offset_.x() + delta_x); | 1569 SetDisplayOffset(display_offset_.x() + delta_x); |
| 1547 } | 1570 } |
| 1548 | 1571 |
| 1549 void RenderText::DrawSelection(Canvas* canvas) { | 1572 void RenderText::DrawSelection(Canvas* canvas) { |
| 1550 for (const Rect& s : GetSubstringBounds(selection())) | 1573 for (const Rect& s : GetSubstringBounds(selection())) |
| 1551 canvas->FillRect(s, selection_background_focused_color_); | 1574 canvas->FillRect(s, selection_background_focused_color_); |
| 1552 } | 1575 } |
| 1553 | 1576 |
| 1554 } // namespace gfx | 1577 } // namespace gfx |
| OLD | NEW |