| 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 } | 237 } |
| 247 | 238 |
| 248 void SkiaTextRenderer::SetTypeface(SkTypeface* typeface) { | 239 void SkiaTextRenderer::SetTypeface(SkTypeface* typeface) { |
| 249 paint_.setTypeface(typeface); | 240 paint_.setTypeface(typeface); |
| 250 } | 241 } |
| 251 | 242 |
| 252 void SkiaTextRenderer::SetTextSize(SkScalar size) { | 243 void SkiaTextRenderer::SetTextSize(SkScalar size) { |
| 253 paint_.setTextSize(size); | 244 paint_.setTextSize(size); |
| 254 } | 245 } |
| 255 | 246 |
| 256 void SkiaTextRenderer::SetFontWithStyle(const Font& font, int style) { | 247 void SkiaTextRenderer::SetFont(const Font& font, |
| 257 skia::RefPtr<SkTypeface> typeface = CreateSkiaTypeface(font, style); | 248 bool italic, |
| 249 gfx::Font::Weight weight) { |
| 250 skia::RefPtr<SkTypeface> typeface = CreateSkiaTypeface(font, italic, weight); |
| 258 if (typeface) { | 251 if (typeface) { |
| 259 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. | 252 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. |
| 260 SetTypeface(typeface.get()); | 253 SetTypeface(typeface.get()); |
| 261 | 254 |
| 262 // Enable fake bold text if bold style is needed but new typeface does not | 255 // Enable fake bold text if bold style is needed but new typeface does not |
| 263 // have it. | 256 // have it. |
| 264 paint_.setFakeBoldText((style & Font::BOLD) && !typeface->isBold()); | 257 paint_.setFakeBoldText(weight >= gfx::Font::Weight::SEMIBOLD && |
| 258 !typeface->isBold()); |
| 265 } | 259 } |
| 266 } | 260 } |
| 267 | 261 |
| 268 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { | 262 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { |
| 269 paint_.setColor(foreground); | 263 paint_.setColor(foreground); |
| 270 } | 264 } |
| 271 | 265 |
| 272 void SkiaTextRenderer::SetShader(SkShader* shader) { | 266 void SkiaTextRenderer::SetShader(SkShader* shader) { |
| 273 paint_.setShader(shader); | 267 paint_.setShader(shader); |
| 274 } | 268 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 | 371 |
| 378 if (clipped) | 372 if (clipped) |
| 379 canvas_->Restore(); | 373 canvas_->Restore(); |
| 380 | 374 |
| 381 x += pieces_[i].first; | 375 x += pieces_[i].first; |
| 382 } | 376 } |
| 383 } | 377 } |
| 384 | 378 |
| 385 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 379 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
| 386 const BreakList<BaselineStyle>& baselines, | 380 const BreakList<BaselineStyle>& baselines, |
| 381 const BreakList<gfx::Font::Weight>& weights, |
| 387 const std::vector<BreakList<bool>>& styles) | 382 const std::vector<BreakList<bool>>& styles) |
| 388 : colors_(colors), baselines_(baselines), styles_(styles) { | 383 : colors_(colors), |
| 384 baselines_(baselines), |
| 385 weights_(weights), |
| 386 styles_(styles) { |
| 389 color_ = colors_.breaks().begin(); | 387 color_ = colors_.breaks().begin(); |
| 390 baseline_ = baselines_.breaks().begin(); | 388 baseline_ = baselines_.breaks().begin(); |
| 389 weight_ = weights_.breaks().begin(); |
| 391 for (size_t i = 0; i < styles_.size(); ++i) | 390 for (size_t i = 0; i < styles_.size(); ++i) |
| 392 style_.push_back(styles_[i].breaks().begin()); | 391 style_.push_back(styles_[i].breaks().begin()); |
| 393 } | 392 } |
| 394 | 393 |
| 395 StyleIterator::~StyleIterator() {} | 394 StyleIterator::~StyleIterator() {} |
| 396 | 395 |
| 397 Range StyleIterator::GetRange() const { | 396 Range StyleIterator::GetRange() const { |
| 398 Range range(colors_.GetRange(color_)); | 397 Range range(colors_.GetRange(color_)); |
| 399 range = range.Intersect(baselines_.GetRange(baseline_)); | 398 range = range.Intersect(baselines_.GetRange(baseline_)); |
| 399 range = range.Intersect(weights_.GetRange(weight_)); |
| 400 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 400 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 401 range = range.Intersect(styles_[i].GetRange(style_[i])); | 401 range = range.Intersect(styles_[i].GetRange(style_[i])); |
| 402 return range; | 402 return range; |
| 403 } | 403 } |
| 404 | 404 |
| 405 void StyleIterator::UpdatePosition(size_t position) { | 405 void StyleIterator::UpdatePosition(size_t position) { |
| 406 color_ = colors_.GetBreak(position); | 406 color_ = colors_.GetBreak(position); |
| 407 baseline_ = baselines_.GetBreak(position); | 407 baseline_ = baselines_.GetBreak(position); |
| 408 weight_ = weights_.GetBreak(position); |
| 408 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 409 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 409 style_[i] = styles_[i].GetBreak(position); | 410 style_[i] = styles_[i].GetBreak(position); |
| 410 } | 411 } |
| 411 | 412 |
| 412 LineSegment::LineSegment() : run(0) {} | 413 LineSegment::LineSegment() : run(0) {} |
| 413 | 414 |
| 414 LineSegment::~LineSegment() {} | 415 LineSegment::~LineSegment() {} |
| 415 | 416 |
| 416 Line::Line() : preceding_heights(0), baseline(0) {} | 417 Line::Line() : preceding_heights(0), baseline(0) {} |
| 417 | 418 |
| 418 Line::Line(const Line& other) = default; | 419 Line::Line(const Line& other) = default; |
| 419 | 420 |
| 420 Line::~Line() {} | 421 Line::~Line() {} |
| 421 | 422 |
| 422 #if !defined(OS_MACOSX) | 423 #if !defined(OS_MACOSX) |
| 423 skia::RefPtr<SkTypeface> CreateSkiaTypeface(const gfx::Font& font, int style) { | 424 skia::RefPtr<SkTypeface> CreateSkiaTypeface(const gfx::Font& font, |
| 424 SkTypeface::Style skia_style = ConvertFontStyleToSkiaTypefaceStyle(style); | 425 bool italic, |
| 426 gfx::Font::Weight weight) { |
| 427 SkFontStyle skia_style( |
| 428 static_cast<int>(weight), SkFontStyle::kNormal_Width, |
| 429 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); |
| 425 return skia::AdoptRef( | 430 return skia::AdoptRef( |
| 426 SkTypeface::CreateFromName(font.GetFontName().c_str(), skia_style)); | 431 SkTypeface::CreateFromName(font.GetFontName().c_str(), skia_style)); |
| 427 } | 432 } |
| 428 #endif | 433 #endif |
| 429 | 434 |
| 430 void ApplyRenderParams(const FontRenderParams& params, | 435 void ApplyRenderParams(const FontRenderParams& params, |
| 431 bool subpixel_rendering_suppressed, | 436 bool subpixel_rendering_suppressed, |
| 432 SkPaint* paint) { | 437 SkPaint* paint) { |
| 433 paint->setAntiAlias(params.antialiasing); | 438 paint->setAntiAlias(params.antialiasing); |
| 434 paint->setLCDRenderText(!subpixel_rendering_suppressed && | 439 paint->setLCDRenderText(!subpixel_rendering_suppressed && |
| (...skipping 29 matching lines...) Expand all Loading... |
| 464 DCHECK(!composition_range_.IsValid()); | 469 DCHECK(!composition_range_.IsValid()); |
| 465 if (text_ == text) | 470 if (text_ == text) |
| 466 return; | 471 return; |
| 467 text_ = text; | 472 text_ = text; |
| 468 UpdateStyleLengths(); | 473 UpdateStyleLengths(); |
| 469 | 474 |
| 470 // Clear style ranges as they might break new text graphemes and apply | 475 // Clear style ranges as they might break new text graphemes and apply |
| 471 // the first style to the whole text instead. | 476 // the first style to the whole text instead. |
| 472 colors_.SetValue(colors_.breaks().begin()->second); | 477 colors_.SetValue(colors_.breaks().begin()->second); |
| 473 baselines_.SetValue(baselines_.breaks().begin()->second); | 478 baselines_.SetValue(baselines_.breaks().begin()->second); |
| 479 weights_.SetValue(weights_.breaks().begin()->second); |
| 474 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 480 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 475 styles_[style].SetValue(styles_[style].breaks().begin()->second); | 481 styles_[style].SetValue(styles_[style].breaks().begin()->second); |
| 476 cached_bounds_and_offset_valid_ = false; | 482 cached_bounds_and_offset_valid_ = false; |
| 477 | 483 |
| 478 // Reset selection model. SetText should always followed by SetSelectionModel | 484 // Reset selection model. SetText should always followed by SetSelectionModel |
| 479 // or SetCursorPosition in upper layer. | 485 // or SetCursorPosition in upper layer. |
| 480 SetSelectionModel(SelectionModel()); | 486 SetSelectionModel(SelectionModel()); |
| 481 | 487 |
| 482 // Invalidate the cached text direction if it depends on the text contents. | 488 // Invalidate the cached text direction if it depends on the text contents. |
| 483 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) | 489 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 499 if (horizontal_alignment_ != alignment) { | 505 if (horizontal_alignment_ != alignment) { |
| 500 horizontal_alignment_ = alignment; | 506 horizontal_alignment_ = alignment; |
| 501 display_offset_ = Vector2d(); | 507 display_offset_ = Vector2d(); |
| 502 cached_bounds_and_offset_valid_ = false; | 508 cached_bounds_and_offset_valid_ = false; |
| 503 } | 509 } |
| 504 } | 510 } |
| 505 | 511 |
| 506 void RenderText::SetFontList(const FontList& font_list) { | 512 void RenderText::SetFontList(const FontList& font_list) { |
| 507 font_list_ = font_list; | 513 font_list_ = font_list; |
| 508 const int font_style = font_list.GetFontStyle(); | 514 const int font_style = font_list.GetFontStyle(); |
| 509 SetStyle(BOLD, (font_style & gfx::Font::BOLD) != 0); | 515 weights_.SetValue(font_list.GetFontWeight()); |
| 510 SetStyle(ITALIC, (font_style & gfx::Font::ITALIC) != 0); | 516 styles_[ITALIC].SetValue((font_style & gfx::Font::ITALIC) != 0); |
| 511 SetStyle(UNDERLINE, (font_style & gfx::Font::UNDERLINE) != 0); | 517 styles_[UNDERLINE].SetValue((font_style & gfx::Font::UNDERLINE) != 0); |
| 512 baseline_ = kInvalidBaseline; | 518 baseline_ = kInvalidBaseline; |
| 513 cached_bounds_and_offset_valid_ = false; | 519 cached_bounds_and_offset_valid_ = false; |
| 514 OnLayoutTextAttributeChanged(false); | 520 OnLayoutTextAttributeChanged(false); |
| 515 } | 521 } |
| 516 | 522 |
| 517 void RenderText::SetCursorEnabled(bool cursor_enabled) { | 523 void RenderText::SetCursorEnabled(bool cursor_enabled) { |
| 518 cursor_enabled_ = cursor_enabled; | 524 cursor_enabled_ = cursor_enabled; |
| 519 cached_bounds_and_offset_valid_ = false; | 525 cached_bounds_and_offset_valid_ = false; |
| 520 } | 526 } |
| 521 | 527 |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 const size_t end = IsValidCursorIndex(range.end()) ? range.end() : | 767 const size_t end = IsValidCursorIndex(range.end()) ? range.end() : |
| 762 IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); | 768 IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); |
| 763 styles_[style].ApplyValue(value, Range(start, end)); | 769 styles_[style].ApplyValue(value, Range(start, end)); |
| 764 | 770 |
| 765 cached_bounds_and_offset_valid_ = false; | 771 cached_bounds_and_offset_valid_ = false; |
| 766 // TODO(oshima|msw): Not all style change requires layout changes. | 772 // TODO(oshima|msw): Not all style change requires layout changes. |
| 767 // Consider optimizing based on the type of change. | 773 // Consider optimizing based on the type of change. |
| 768 OnLayoutTextAttributeChanged(false); | 774 OnLayoutTextAttributeChanged(false); |
| 769 } | 775 } |
| 770 | 776 |
| 777 void RenderText::SetWeight(gfx::Font::Weight weight) { |
| 778 weights_.SetValue(weight); |
| 779 |
| 780 cached_bounds_and_offset_valid_ = false; |
| 781 OnLayoutTextAttributeChanged(false); |
| 782 } |
| 783 |
| 784 void RenderText::ApplyWeight(gfx::Font::Weight weight, const Range& range) { |
| 785 weights_.ApplyValue(weight, range); |
| 786 |
| 787 cached_bounds_and_offset_valid_ = false; |
| 788 OnLayoutTextAttributeChanged(false); |
| 789 } |
| 790 |
| 771 bool RenderText::GetStyle(TextStyle style) const { | 791 bool RenderText::GetStyle(TextStyle style) const { |
| 772 return (styles_[style].breaks().size() == 1) && | 792 return (styles_[style].breaks().size() == 1) && |
| 773 styles_[style].breaks().front().second; | 793 styles_[style].breaks().front().second; |
| 774 } | 794 } |
| 775 | 795 |
| 776 void RenderText::SetDirectionalityMode(DirectionalityMode mode) { | 796 void RenderText::SetDirectionalityMode(DirectionalityMode mode) { |
| 777 if (mode == directionality_mode_) | 797 if (mode == directionality_mode_) |
| 778 return; | 798 return; |
| 779 | 799 |
| 780 directionality_mode_ = mode; | 800 directionality_mode_ = mode; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 cursor_enabled_(true), | 1012 cursor_enabled_(true), |
| 993 cursor_visible_(false), | 1013 cursor_visible_(false), |
| 994 insert_mode_(true), | 1014 insert_mode_(true), |
| 995 cursor_color_(kDefaultColor), | 1015 cursor_color_(kDefaultColor), |
| 996 selection_color_(kDefaultColor), | 1016 selection_color_(kDefaultColor), |
| 997 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 1017 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
| 998 focused_(false), | 1018 focused_(false), |
| 999 composition_range_(Range::InvalidRange()), | 1019 composition_range_(Range::InvalidRange()), |
| 1000 colors_(kDefaultColor), | 1020 colors_(kDefaultColor), |
| 1001 baselines_(NORMAL_BASELINE), | 1021 baselines_(NORMAL_BASELINE), |
| 1022 weights_(gfx::Font::Weight::NORMAL), |
| 1002 styles_(NUM_TEXT_STYLES), | 1023 styles_(NUM_TEXT_STYLES), |
| 1003 composition_and_selection_styles_applied_(false), | 1024 composition_and_selection_styles_applied_(false), |
| 1004 obscured_(false), | 1025 obscured_(false), |
| 1005 obscured_reveal_index_(-1), | 1026 obscured_reveal_index_(-1), |
| 1006 truncate_length_(0), | 1027 truncate_length_(0), |
| 1007 elide_behavior_(NO_ELIDE), | 1028 elide_behavior_(NO_ELIDE), |
| 1008 text_elided_(false), | 1029 text_elided_(false), |
| 1009 min_line_height_(0), | 1030 min_line_height_(0), |
| 1010 multiline_(false), | 1031 multiline_(false), |
| 1011 word_wrap_behavior_(IGNORE_LONG_WORDS), | 1032 word_wrap_behavior_(IGNORE_LONG_WORDS), |
| 1012 replace_newline_chars_with_symbols_(true), | 1033 replace_newline_chars_with_symbols_(true), |
| 1013 subpixel_rendering_suppressed_(false), | 1034 subpixel_rendering_suppressed_(false), |
| 1014 clip_to_display_rect_(true), | 1035 clip_to_display_rect_(true), |
| 1015 baseline_(kInvalidBaseline), | 1036 baseline_(kInvalidBaseline), |
| 1016 cached_bounds_and_offset_valid_(false) { | 1037 cached_bounds_and_offset_valid_(false) {} |
| 1017 } | |
| 1018 | 1038 |
| 1019 SelectionModel RenderText::GetAdjacentSelectionModel( | 1039 SelectionModel RenderText::GetAdjacentSelectionModel( |
| 1020 const SelectionModel& current, | 1040 const SelectionModel& current, |
| 1021 BreakType break_type, | 1041 BreakType break_type, |
| 1022 VisualCursorDirection direction) { | 1042 VisualCursorDirection direction) { |
| 1023 EnsureLayout(); | 1043 EnsureLayout(); |
| 1024 | 1044 |
| 1025 if (break_type == LINE_BREAK || text().empty()) | 1045 if (break_type == LINE_BREAK || text().empty()) |
| 1026 return EdgeSelectionModel(direction); | 1046 return EdgeSelectionModel(direction); |
| 1027 if (break_type == CHARACTER_BREAK) | 1047 if (break_type == CHARACTER_BREAK) |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index; | 1298 ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index; |
| 1279 CHECK_GE(i, 0); | 1299 CHECK_GE(i, 0); |
| 1280 // Clamp indices to the length of the given layout or display text. | 1300 // Clamp indices to the length of the given layout or display text. |
| 1281 return std::min<size_t>(given_text.length(), i); | 1301 return std::min<size_t>(given_text.length(), i); |
| 1282 } | 1302 } |
| 1283 | 1303 |
| 1284 void RenderText::UpdateStyleLengths() { | 1304 void RenderText::UpdateStyleLengths() { |
| 1285 const size_t text_length = text_.length(); | 1305 const size_t text_length = text_.length(); |
| 1286 colors_.SetMax(text_length); | 1306 colors_.SetMax(text_length); |
| 1287 baselines_.SetMax(text_length); | 1307 baselines_.SetMax(text_length); |
| 1308 weights_.SetMax(text_length); |
| 1288 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1309 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 1289 styles_[style].SetMax(text_length); | 1310 styles_[style].SetMax(text_length); |
| 1290 } | 1311 } |
| 1291 | 1312 |
| 1292 // static | 1313 // static |
| 1293 bool RenderText::RangeContainsCaret(const Range& range, | 1314 bool RenderText::RangeContainsCaret(const Range& range, |
| 1294 size_t caret_pos, | 1315 size_t caret_pos, |
| 1295 LogicalCursorDirection caret_affinity) { | 1316 LogicalCursorDirection caret_affinity) { |
| 1296 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). | 1317 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). |
| 1297 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? | 1318 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 | 1402 |
| 1382 // Create a RenderText copy with attributes that affect the rendering width. | 1403 // Create a RenderText copy with attributes that affect the rendering width. |
| 1383 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); | 1404 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); |
| 1384 render_text->SetFontList(font_list_); | 1405 render_text->SetFontList(font_list_); |
| 1385 render_text->SetDirectionalityMode(directionality_mode_); | 1406 render_text->SetDirectionalityMode(directionality_mode_); |
| 1386 render_text->SetCursorEnabled(cursor_enabled_); | 1407 render_text->SetCursorEnabled(cursor_enabled_); |
| 1387 render_text->set_truncate_length(truncate_length_); | 1408 render_text->set_truncate_length(truncate_length_); |
| 1388 render_text->styles_ = styles_; | 1409 render_text->styles_ = styles_; |
| 1389 render_text->baselines_ = baselines_; | 1410 render_text->baselines_ = baselines_; |
| 1390 render_text->colors_ = colors_; | 1411 render_text->colors_ = colors_; |
| 1412 render_text->weights_ = weights_; |
| 1391 if (text_width == 0) { | 1413 if (text_width == 0) { |
| 1392 render_text->SetText(text); | 1414 render_text->SetText(text); |
| 1393 text_width = render_text->GetContentWidthF(); | 1415 text_width = render_text->GetContentWidthF(); |
| 1394 } | 1416 } |
| 1395 if (text_width <= available_width) | 1417 if (text_width <= available_width) |
| 1396 return text; | 1418 return text; |
| 1397 | 1419 |
| 1398 const base::string16 ellipsis = base::string16(kEllipsisUTF16); | 1420 const base::string16 ellipsis = base::string16(kEllipsisUTF16); |
| 1399 const bool insert_ellipsis = (behavior != TRUNCATE); | 1421 const bool insert_ellipsis = (behavior != TRUNCATE); |
| 1400 const bool elide_in_middle = (behavior == ELIDE_MIDDLE); | 1422 const bool elide_in_middle = (behavior == ELIDE_MIDDLE); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 new_text += base::i18n::kRightToLeftMark; | 1460 new_text += base::i18n::kRightToLeftMark; |
| 1439 } | 1461 } |
| 1440 render_text->SetText(new_text); | 1462 render_text->SetText(new_text); |
| 1441 } | 1463 } |
| 1442 | 1464 |
| 1443 // Restore styles and baselines without breaking multi-character graphemes. | 1465 // Restore styles and baselines without breaking multi-character graphemes. |
| 1444 render_text->styles_ = styles_; | 1466 render_text->styles_ = styles_; |
| 1445 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1467 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 1446 RestoreBreakList(render_text.get(), &render_text->styles_[style]); | 1468 RestoreBreakList(render_text.get(), &render_text->styles_[style]); |
| 1447 RestoreBreakList(render_text.get(), &render_text->baselines_); | 1469 RestoreBreakList(render_text.get(), &render_text->baselines_); |
| 1470 RestoreBreakList(render_text.get(), &render_text->weights_); |
| 1448 | 1471 |
| 1449 // We check the width of the whole desired string at once to ensure we | 1472 // We check the width of the whole desired string at once to ensure we |
| 1450 // handle kerning/ligatures/etc. correctly. | 1473 // handle kerning/ligatures/etc. correctly. |
| 1451 const float guess_width = render_text->GetContentWidthF(); | 1474 const float guess_width = render_text->GetContentWidthF(); |
| 1452 if (guess_width == available_width) | 1475 if (guess_width == available_width) |
| 1453 break; | 1476 break; |
| 1454 if (guess_width > available_width) { | 1477 if (guess_width > available_width) { |
| 1455 hi = guess - 1; | 1478 hi = guess - 1; |
| 1456 // Move back on the loop terminating condition when the guess is too wide. | 1479 // Move back on the loop terminating condition when the guess is too wide. |
| 1457 if (hi < lo) | 1480 if (hi < lo) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1544 | 1567 |
| 1545 SetDisplayOffset(display_offset_.x() + delta_x); | 1568 SetDisplayOffset(display_offset_.x() + delta_x); |
| 1546 } | 1569 } |
| 1547 | 1570 |
| 1548 void RenderText::DrawSelection(Canvas* canvas) { | 1571 void RenderText::DrawSelection(Canvas* canvas) { |
| 1549 for (const Rect& s : GetSubstringBounds(selection())) | 1572 for (const Rect& s : GetSubstringBounds(selection())) |
| 1550 canvas->FillRect(s, selection_background_focused_color_); | 1573 canvas->FillRect(s, selection_background_focused_color_); |
| 1551 } | 1574 } |
| 1552 | 1575 |
| 1553 } // namespace gfx | 1576 } // namespace gfx |
| OLD | NEW |