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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 #if !defined(OS_MACOSX) |
| 94 // Converts |Font::FontStyle| flags to |SkTypeface::Style| flags. | 95 // Converts |Font::FontStyle| flags to |SkTypeface::Style| flags. |
| 95 SkTypeface::Style ConvertFontStyleToSkiaTypefaceStyle(int font_style) { | 96 SkTypeface::Style ConvertFontStyleToSkiaTypefaceStyle(int font_style) { |
|
msw
2016/03/22 01:53:44
Remove this function if it's no longer used.
Mikus
2016/03/22 14:19:51
Done.
| |
| 96 int skia_style = SkTypeface::kNormal; | 97 int skia_style = SkTypeface::kNormal; |
| 97 skia_style |= (font_style & Font::BOLD) ? SkTypeface::kBold : 0; | 98 // skia_style |= (font_style & Font::BOLD) ? SkTypeface::kBold : 0; |
|
msw
2016/03/22 01:53:44
Remove this
Mikus
2016/03/22 14:19:51
Done.
| |
| 98 skia_style |= (font_style & Font::ITALIC) ? SkTypeface::kItalic : 0; | 99 skia_style |= (font_style & Font::ITALIC) ? SkTypeface::kItalic : 0; |
| 99 return static_cast<SkTypeface::Style>(skia_style); | 100 return static_cast<SkTypeface::Style>(skia_style); |
| 100 } | 101 } |
| 101 #endif | 102 #endif |
| 102 | 103 |
| 103 int round(float value) { | 104 int round(float value) { |
| 104 return static_cast<int>(floor(value + 0.5f)); | 105 return static_cast<int>(floor(value + 0.5f)); |
| 105 } | 106 } |
| 106 | 107 |
| 107 // Given |font| and |display_width|, returns the width of the fade gradient. | 108 // Given |font| and |display_width|, returns the width of the fade gradient. |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 } | 247 } |
| 247 | 248 |
| 248 void SkiaTextRenderer::SetTypeface(SkTypeface* typeface) { | 249 void SkiaTextRenderer::SetTypeface(SkTypeface* typeface) { |
| 249 paint_.setTypeface(typeface); | 250 paint_.setTypeface(typeface); |
| 250 } | 251 } |
| 251 | 252 |
| 252 void SkiaTextRenderer::SetTextSize(SkScalar size) { | 253 void SkiaTextRenderer::SetTextSize(SkScalar size) { |
| 253 paint_.setTextSize(size); | 254 paint_.setTextSize(size); |
| 254 } | 255 } |
| 255 | 256 |
| 256 void SkiaTextRenderer::SetFontWithStyle(const Font& font, int style) { | 257 void SkiaTextRenderer::SetFontWithStyle(const Font& font, |
| 257 skia::RefPtr<SkTypeface> typeface = CreateSkiaTypeface(font, style); | 258 int style, |
| 259 gfx::Font::FontWeight weight) { | |
| 260 skia::RefPtr<SkTypeface> typeface = CreateSkiaTypeface(font, style, weight); | |
| 258 if (typeface) { | 261 if (typeface) { |
| 259 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. | 262 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. |
| 260 SetTypeface(typeface.get()); | 263 SetTypeface(typeface.get()); |
| 261 | 264 |
| 262 // Enable fake bold text if bold style is needed but new typeface does not | 265 // Enable fake bold text if bold style is needed but new typeface does not |
| 263 // have it. | 266 // have it. |
| 264 paint_.setFakeBoldText((style & Font::BOLD) && !typeface->isBold()); | 267 paint_.setFakeBoldText(weight >= gfx::Font::WEIGHT_SEMIBOLD && |
| 268 !typeface->isBold()); | |
| 265 } | 269 } |
| 266 } | 270 } |
| 267 | 271 |
| 268 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { | 272 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { |
| 269 paint_.setColor(foreground); | 273 paint_.setColor(foreground); |
| 270 } | 274 } |
| 271 | 275 |
| 272 void SkiaTextRenderer::SetShader(SkShader* shader) { | 276 void SkiaTextRenderer::SetShader(SkShader* shader) { |
| 273 paint_.setShader(shader); | 277 paint_.setShader(shader); |
| 274 } | 278 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 | 381 |
| 378 if (clipped) | 382 if (clipped) |
| 379 canvas_->Restore(); | 383 canvas_->Restore(); |
| 380 | 384 |
| 381 x += pieces_[i].first; | 385 x += pieces_[i].first; |
| 382 } | 386 } |
| 383 } | 387 } |
| 384 | 388 |
| 385 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 389 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
| 386 const BreakList<BaselineStyle>& baselines, | 390 const BreakList<BaselineStyle>& baselines, |
| 391 const BreakList<gfx::Font::FontWeight>& weights, | |
| 387 const std::vector<BreakList<bool>>& styles) | 392 const std::vector<BreakList<bool>>& styles) |
| 388 : colors_(colors), baselines_(baselines), styles_(styles) { | 393 : colors_(colors), |
| 394 baselines_(baselines), | |
| 395 weights_(weights), | |
| 396 styles_(styles) { | |
| 389 color_ = colors_.breaks().begin(); | 397 color_ = colors_.breaks().begin(); |
| 390 baseline_ = baselines_.breaks().begin(); | 398 baseline_ = baselines_.breaks().begin(); |
| 399 weight_ = weights_.breaks().begin(); | |
| 391 for (size_t i = 0; i < styles_.size(); ++i) | 400 for (size_t i = 0; i < styles_.size(); ++i) |
| 392 style_.push_back(styles_[i].breaks().begin()); | 401 style_.push_back(styles_[i].breaks().begin()); |
| 393 } | 402 } |
| 394 | 403 |
| 395 StyleIterator::~StyleIterator() {} | 404 StyleIterator::~StyleIterator() {} |
| 396 | 405 |
| 397 Range StyleIterator::GetRange() const { | 406 Range StyleIterator::GetRange() const { |
| 398 Range range(colors_.GetRange(color_)); | 407 Range range(colors_.GetRange(color_)); |
| 399 range = range.Intersect(baselines_.GetRange(baseline_)); | 408 range = range.Intersect(baselines_.GetRange(baseline_)); |
| 409 range = range.Intersect(weights_.GetRange(weight_)); | |
| 400 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 410 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 401 range = range.Intersect(styles_[i].GetRange(style_[i])); | 411 range = range.Intersect(styles_[i].GetRange(style_[i])); |
| 402 return range; | 412 return range; |
| 403 } | 413 } |
| 404 | 414 |
| 405 void StyleIterator::UpdatePosition(size_t position) { | 415 void StyleIterator::UpdatePosition(size_t position) { |
| 406 color_ = colors_.GetBreak(position); | 416 color_ = colors_.GetBreak(position); |
| 407 baseline_ = baselines_.GetBreak(position); | 417 baseline_ = baselines_.GetBreak(position); |
| 418 weight_ = weights_.GetBreak(position); | |
| 408 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 419 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 409 style_[i] = styles_[i].GetBreak(position); | 420 style_[i] = styles_[i].GetBreak(position); |
| 410 } | 421 } |
| 411 | 422 |
| 412 LineSegment::LineSegment() : run(0) {} | 423 LineSegment::LineSegment() : run(0) {} |
| 413 | 424 |
| 414 LineSegment::~LineSegment() {} | 425 LineSegment::~LineSegment() {} |
| 415 | 426 |
| 416 Line::Line() : preceding_heights(0), baseline(0) {} | 427 Line::Line() : preceding_heights(0), baseline(0) {} |
| 417 | 428 |
| 418 Line::Line(const Line& other) = default; | 429 Line::Line(const Line& other) = default; |
| 419 | 430 |
| 420 Line::~Line() {} | 431 Line::~Line() {} |
| 421 | 432 |
| 422 #if !defined(OS_MACOSX) | 433 #if !defined(OS_MACOSX) |
| 423 skia::RefPtr<SkTypeface> CreateSkiaTypeface(const gfx::Font& font, int style) { | 434 skia::RefPtr<SkTypeface> CreateSkiaTypeface(const gfx::Font& font, |
| 424 SkTypeface::Style skia_style = ConvertFontStyleToSkiaTypefaceStyle(style); | 435 int style, |
| 425 return skia::AdoptRef( | 436 gfx::Font::FontWeight weight) { |
| 426 SkTypeface::CreateFromName(font.GetFontName().c_str(), skia_style)); | 437 SkFontStyle skia_style(weight, SkFontStyle::kNormal_Width, |
| 438 style & gfx::Font::ITALIC | |
|
msw
2016/03/22 01:53:44
nit: if |style| only handles italic, make it a boo
Mikus
2016/03/22 14:19:51
Done.
| |
| 439 ? SkFontStyle::kItalic_Slant | |
| 440 : SkFontStyle::kUpright_Slant); | |
| 441 return skia::AdoptRef(SkTypeface::CreateFromNameAndStyle( | |
| 442 font.GetFontName().c_str(), skia_style)); | |
| 427 } | 443 } |
| 444 | |
| 428 #endif | 445 #endif |
| 429 | 446 |
| 430 void ApplyRenderParams(const FontRenderParams& params, | 447 void ApplyRenderParams(const FontRenderParams& params, |
| 431 bool subpixel_rendering_suppressed, | 448 bool subpixel_rendering_suppressed, |
| 432 SkPaint* paint) { | 449 SkPaint* paint) { |
| 433 paint->setAntiAlias(params.antialiasing); | 450 paint->setAntiAlias(params.antialiasing); |
| 434 paint->setLCDRenderText(!subpixel_rendering_suppressed && | 451 paint->setLCDRenderText(!subpixel_rendering_suppressed && |
| 435 params.subpixel_rendering != FontRenderParams::SUBPIXEL_RENDERING_NONE); | 452 params.subpixel_rendering != FontRenderParams::SUBPIXEL_RENDERING_NONE); |
| 436 paint->setSubpixelText(params.subpixel_positioning); | 453 paint->setSubpixelText(params.subpixel_positioning); |
| 437 paint->setAutohinted(params.autohinter); | 454 paint->setAutohinted(params.autohinter); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 464 DCHECK(!composition_range_.IsValid()); | 481 DCHECK(!composition_range_.IsValid()); |
| 465 if (text_ == text) | 482 if (text_ == text) |
| 466 return; | 483 return; |
| 467 text_ = text; | 484 text_ = text; |
| 468 UpdateStyleLengths(); | 485 UpdateStyleLengths(); |
| 469 | 486 |
| 470 // Clear style ranges as they might break new text graphemes and apply | 487 // Clear style ranges as they might break new text graphemes and apply |
| 471 // the first style to the whole text instead. | 488 // the first style to the whole text instead. |
| 472 colors_.SetValue(colors_.breaks().begin()->second); | 489 colors_.SetValue(colors_.breaks().begin()->second); |
| 473 baselines_.SetValue(baselines_.breaks().begin()->second); | 490 baselines_.SetValue(baselines_.breaks().begin()->second); |
| 491 weights_.SetValue(weights_.breaks().begin()->second); | |
| 474 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 492 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 475 styles_[style].SetValue(styles_[style].breaks().begin()->second); | 493 styles_[style].SetValue(styles_[style].breaks().begin()->second); |
| 476 cached_bounds_and_offset_valid_ = false; | 494 cached_bounds_and_offset_valid_ = false; |
| 477 | 495 |
| 478 // Reset selection model. SetText should always followed by SetSelectionModel | 496 // Reset selection model. SetText should always followed by SetSelectionModel |
| 479 // or SetCursorPosition in upper layer. | 497 // or SetCursorPosition in upper layer. |
| 480 SetSelectionModel(SelectionModel()); | 498 SetSelectionModel(SelectionModel()); |
| 481 | 499 |
| 482 // Invalidate the cached text direction if it depends on the text contents. | 500 // Invalidate the cached text direction if it depends on the text contents. |
| 483 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) | 501 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 499 if (horizontal_alignment_ != alignment) { | 517 if (horizontal_alignment_ != alignment) { |
| 500 horizontal_alignment_ = alignment; | 518 horizontal_alignment_ = alignment; |
| 501 display_offset_ = Vector2d(); | 519 display_offset_ = Vector2d(); |
| 502 cached_bounds_and_offset_valid_ = false; | 520 cached_bounds_and_offset_valid_ = false; |
| 503 } | 521 } |
| 504 } | 522 } |
| 505 | 523 |
| 506 void RenderText::SetFontList(const FontList& font_list) { | 524 void RenderText::SetFontList(const FontList& font_list) { |
| 507 font_list_ = font_list; | 525 font_list_ = font_list; |
| 508 const int font_style = font_list.GetFontStyle(); | 526 const int font_style = font_list.GetFontStyle(); |
| 509 SetStyle(BOLD, (font_style & gfx::Font::BOLD) != 0); | 527 weights_.SetValue(font_list.GetFontWeight()); |
| 510 SetStyle(ITALIC, (font_style & gfx::Font::ITALIC) != 0); | 528 SetStyle(ITALIC, (font_style & gfx::Font::ITALIC) != 0); |
| 511 SetStyle(UNDERLINE, (font_style & gfx::Font::UNDERLINE) != 0); | 529 SetStyle(UNDERLINE, (font_style & gfx::Font::UNDERLINE) != 0); |
| 512 baseline_ = kInvalidBaseline; | 530 baseline_ = kInvalidBaseline; |
| 513 cached_bounds_and_offset_valid_ = false; | 531 cached_bounds_and_offset_valid_ = false; |
| 514 OnLayoutTextAttributeChanged(false); | 532 OnLayoutTextAttributeChanged(false); |
| 515 } | 533 } |
| 516 | 534 |
| 517 void RenderText::SetCursorEnabled(bool cursor_enabled) { | 535 void RenderText::SetCursorEnabled(bool cursor_enabled) { |
| 518 cursor_enabled_ = cursor_enabled; | 536 cursor_enabled_ = cursor_enabled; |
| 519 cached_bounds_and_offset_valid_ = false; | 537 cached_bounds_and_offset_valid_ = false; |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 761 const size_t end = IsValidCursorIndex(range.end()) ? range.end() : | 779 const size_t end = IsValidCursorIndex(range.end()) ? range.end() : |
| 762 IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); | 780 IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); |
| 763 styles_[style].ApplyValue(value, Range(start, end)); | 781 styles_[style].ApplyValue(value, Range(start, end)); |
| 764 | 782 |
| 765 cached_bounds_and_offset_valid_ = false; | 783 cached_bounds_and_offset_valid_ = false; |
| 766 // TODO(oshima|msw): Not all style change requires layout changes. | 784 // TODO(oshima|msw): Not all style change requires layout changes. |
| 767 // Consider optimizing based on the type of change. | 785 // Consider optimizing based on the type of change. |
| 768 OnLayoutTextAttributeChanged(false); | 786 OnLayoutTextAttributeChanged(false); |
| 769 } | 787 } |
| 770 | 788 |
| 789 void RenderText::SetWeight(gfx::Font::FontWeight weight) { | |
| 790 weights_.SetValue(weight); | |
| 791 | |
| 792 cached_bounds_and_offset_valid_ = false; | |
| 793 OnLayoutTextAttributeChanged(false); | |
| 794 } | |
| 795 | |
| 796 void RenderText::ApplyWeight(gfx::Font::FontWeight weight, const Range& range) { | |
| 797 weights_.ApplyValue(weight, range); | |
| 798 | |
| 799 cached_bounds_and_offset_valid_ = false; | |
| 800 OnLayoutTextAttributeChanged(false); | |
| 801 } | |
| 802 | |
| 771 bool RenderText::GetStyle(TextStyle style) const { | 803 bool RenderText::GetStyle(TextStyle style) const { |
| 772 return (styles_[style].breaks().size() == 1) && | 804 return (styles_[style].breaks().size() == 1) && |
| 773 styles_[style].breaks().front().second; | 805 styles_[style].breaks().front().second; |
| 774 } | 806 } |
| 775 | 807 |
| 776 void RenderText::SetDirectionalityMode(DirectionalityMode mode) { | 808 void RenderText::SetDirectionalityMode(DirectionalityMode mode) { |
| 777 if (mode == directionality_mode_) | 809 if (mode == directionality_mode_) |
| 778 return; | 810 return; |
| 779 | 811 |
| 780 directionality_mode_ = mode; | 812 directionality_mode_ = mode; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 992 cursor_enabled_(true), | 1024 cursor_enabled_(true), |
| 993 cursor_visible_(false), | 1025 cursor_visible_(false), |
| 994 insert_mode_(true), | 1026 insert_mode_(true), |
| 995 cursor_color_(kDefaultColor), | 1027 cursor_color_(kDefaultColor), |
| 996 selection_color_(kDefaultColor), | 1028 selection_color_(kDefaultColor), |
| 997 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 1029 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
| 998 focused_(false), | 1030 focused_(false), |
| 999 composition_range_(Range::InvalidRange()), | 1031 composition_range_(Range::InvalidRange()), |
| 1000 colors_(kDefaultColor), | 1032 colors_(kDefaultColor), |
| 1001 baselines_(NORMAL_BASELINE), | 1033 baselines_(NORMAL_BASELINE), |
| 1034 weights_(gfx::Font::WEIGHT_NORMAL), | |
| 1002 styles_(NUM_TEXT_STYLES), | 1035 styles_(NUM_TEXT_STYLES), |
| 1003 composition_and_selection_styles_applied_(false), | 1036 composition_and_selection_styles_applied_(false), |
| 1004 obscured_(false), | 1037 obscured_(false), |
| 1005 obscured_reveal_index_(-1), | 1038 obscured_reveal_index_(-1), |
| 1006 truncate_length_(0), | 1039 truncate_length_(0), |
| 1007 elide_behavior_(NO_ELIDE), | 1040 elide_behavior_(NO_ELIDE), |
| 1008 text_elided_(false), | 1041 text_elided_(false), |
| 1009 min_line_height_(0), | 1042 min_line_height_(0), |
| 1010 multiline_(false), | 1043 multiline_(false), |
| 1011 word_wrap_behavior_(IGNORE_LONG_WORDS), | 1044 word_wrap_behavior_(IGNORE_LONG_WORDS), |
| 1012 replace_newline_chars_with_symbols_(true), | 1045 replace_newline_chars_with_symbols_(true), |
| 1013 subpixel_rendering_suppressed_(false), | 1046 subpixel_rendering_suppressed_(false), |
| 1014 clip_to_display_rect_(true), | 1047 clip_to_display_rect_(true), |
| 1015 baseline_(kInvalidBaseline), | 1048 baseline_(kInvalidBaseline), |
| 1016 cached_bounds_and_offset_valid_(false) { | 1049 cached_bounds_and_offset_valid_(false) {} |
| 1017 } | |
| 1018 | 1050 |
| 1019 SelectionModel RenderText::GetAdjacentSelectionModel( | 1051 SelectionModel RenderText::GetAdjacentSelectionModel( |
| 1020 const SelectionModel& current, | 1052 const SelectionModel& current, |
| 1021 BreakType break_type, | 1053 BreakType break_type, |
| 1022 VisualCursorDirection direction) { | 1054 VisualCursorDirection direction) { |
| 1023 EnsureLayout(); | 1055 EnsureLayout(); |
| 1024 | 1056 |
| 1025 if (break_type == LINE_BREAK || text().empty()) | 1057 if (break_type == LINE_BREAK || text().empty()) |
| 1026 return EdgeSelectionModel(direction); | 1058 return EdgeSelectionModel(direction); |
| 1027 if (break_type == CHARACTER_BREAK) | 1059 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; | 1310 ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index; |
| 1279 CHECK_GE(i, 0); | 1311 CHECK_GE(i, 0); |
| 1280 // Clamp indices to the length of the given layout or display text. | 1312 // Clamp indices to the length of the given layout or display text. |
| 1281 return std::min<size_t>(given_text.length(), i); | 1313 return std::min<size_t>(given_text.length(), i); |
| 1282 } | 1314 } |
| 1283 | 1315 |
| 1284 void RenderText::UpdateStyleLengths() { | 1316 void RenderText::UpdateStyleLengths() { |
| 1285 const size_t text_length = text_.length(); | 1317 const size_t text_length = text_.length(); |
| 1286 colors_.SetMax(text_length); | 1318 colors_.SetMax(text_length); |
| 1287 baselines_.SetMax(text_length); | 1319 baselines_.SetMax(text_length); |
| 1320 weights_.SetMax(text_length); | |
| 1288 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1321 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 1289 styles_[style].SetMax(text_length); | 1322 styles_[style].SetMax(text_length); |
| 1290 } | 1323 } |
| 1291 | 1324 |
| 1292 // static | 1325 // static |
| 1293 bool RenderText::RangeContainsCaret(const Range& range, | 1326 bool RenderText::RangeContainsCaret(const Range& range, |
| 1294 size_t caret_pos, | 1327 size_t caret_pos, |
| 1295 LogicalCursorDirection caret_affinity) { | 1328 LogicalCursorDirection caret_affinity) { |
| 1296 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). | 1329 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). |
| 1297 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? | 1330 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1381 | 1414 |
| 1382 // Create a RenderText copy with attributes that affect the rendering width. | 1415 // Create a RenderText copy with attributes that affect the rendering width. |
| 1383 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); | 1416 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); |
| 1384 render_text->SetFontList(font_list_); | 1417 render_text->SetFontList(font_list_); |
| 1385 render_text->SetDirectionalityMode(directionality_mode_); | 1418 render_text->SetDirectionalityMode(directionality_mode_); |
| 1386 render_text->SetCursorEnabled(cursor_enabled_); | 1419 render_text->SetCursorEnabled(cursor_enabled_); |
| 1387 render_text->set_truncate_length(truncate_length_); | 1420 render_text->set_truncate_length(truncate_length_); |
| 1388 render_text->styles_ = styles_; | 1421 render_text->styles_ = styles_; |
| 1389 render_text->baselines_ = baselines_; | 1422 render_text->baselines_ = baselines_; |
| 1390 render_text->colors_ = colors_; | 1423 render_text->colors_ = colors_; |
| 1424 render_text->weights_ = weights_; | |
| 1391 if (text_width == 0) { | 1425 if (text_width == 0) { |
| 1392 render_text->SetText(text); | 1426 render_text->SetText(text); |
| 1393 text_width = render_text->GetContentWidthF(); | 1427 text_width = render_text->GetContentWidthF(); |
| 1394 } | 1428 } |
| 1395 if (text_width <= available_width) | 1429 if (text_width <= available_width) |
| 1396 return text; | 1430 return text; |
| 1397 | 1431 |
| 1398 const base::string16 ellipsis = base::string16(kEllipsisUTF16); | 1432 const base::string16 ellipsis = base::string16(kEllipsisUTF16); |
| 1399 const bool insert_ellipsis = (behavior != TRUNCATE); | 1433 const bool insert_ellipsis = (behavior != TRUNCATE); |
| 1400 const bool elide_in_middle = (behavior == ELIDE_MIDDLE); | 1434 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; | 1472 new_text += base::i18n::kRightToLeftMark; |
| 1439 } | 1473 } |
| 1440 render_text->SetText(new_text); | 1474 render_text->SetText(new_text); |
| 1441 } | 1475 } |
| 1442 | 1476 |
| 1443 // Restore styles and baselines without breaking multi-character graphemes. | 1477 // Restore styles and baselines without breaking multi-character graphemes. |
| 1444 render_text->styles_ = styles_; | 1478 render_text->styles_ = styles_; |
| 1445 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1479 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 1446 RestoreBreakList(render_text.get(), &render_text->styles_[style]); | 1480 RestoreBreakList(render_text.get(), &render_text->styles_[style]); |
| 1447 RestoreBreakList(render_text.get(), &render_text->baselines_); | 1481 RestoreBreakList(render_text.get(), &render_text->baselines_); |
| 1482 RestoreBreakList(render_text.get(), &render_text->weights_); | |
| 1448 | 1483 |
| 1449 // We check the width of the whole desired string at once to ensure we | 1484 // We check the width of the whole desired string at once to ensure we |
| 1450 // handle kerning/ligatures/etc. correctly. | 1485 // handle kerning/ligatures/etc. correctly. |
| 1451 const float guess_width = render_text->GetContentWidthF(); | 1486 const float guess_width = render_text->GetContentWidthF(); |
| 1452 if (guess_width == available_width) | 1487 if (guess_width == available_width) |
| 1453 break; | 1488 break; |
| 1454 if (guess_width > available_width) { | 1489 if (guess_width > available_width) { |
| 1455 hi = guess - 1; | 1490 hi = guess - 1; |
| 1456 // Move back on the loop terminating condition when the guess is too wide. | 1491 // Move back on the loop terminating condition when the guess is too wide. |
| 1457 if (hi < lo) | 1492 if (hi < lo) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1544 | 1579 |
| 1545 SetDisplayOffset(display_offset_.x() + delta_x); | 1580 SetDisplayOffset(display_offset_.x() + delta_x); |
| 1546 } | 1581 } |
| 1547 | 1582 |
| 1548 void RenderText::DrawSelection(Canvas* canvas) { | 1583 void RenderText::DrawSelection(Canvas* canvas) { |
| 1549 for (const Rect& s : GetSubstringBounds(selection())) | 1584 for (const Rect& s : GetSubstringBounds(selection())) |
| 1550 canvas->FillRect(s, selection_background_focused_color_); | 1585 canvas->FillRect(s, selection_background_focused_color_); |
| 1551 } | 1586 } |
| 1552 | 1587 |
| 1553 } // namespace gfx | 1588 } // namespace gfx |
| OLD | NEW |