| 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 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 | 360 |
| 360 if (clipped) | 361 if (clipped) |
| 361 canvas_->Restore(); | 362 canvas_->Restore(); |
| 362 | 363 |
| 363 x += pieces_[i].first; | 364 x += pieces_[i].first; |
| 364 } | 365 } |
| 365 } | 366 } |
| 366 | 367 |
| 367 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 368 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
| 368 const BreakList<BaselineStyle>& baselines, | 369 const BreakList<BaselineStyle>& baselines, |
| 370 const BreakList<Font::Weight>& weights, |
| 369 const std::vector<BreakList<bool>>& styles) | 371 const std::vector<BreakList<bool>>& styles) |
| 370 : colors_(colors), baselines_(baselines), styles_(styles) { | 372 : colors_(colors), |
| 373 baselines_(baselines), |
| 374 weights_(weights), |
| 375 styles_(styles) { |
| 371 color_ = colors_.breaks().begin(); | 376 color_ = colors_.breaks().begin(); |
| 372 baseline_ = baselines_.breaks().begin(); | 377 baseline_ = baselines_.breaks().begin(); |
| 378 weight_ = weights_.breaks().begin(); |
| 373 for (size_t i = 0; i < styles_.size(); ++i) | 379 for (size_t i = 0; i < styles_.size(); ++i) |
| 374 style_.push_back(styles_[i].breaks().begin()); | 380 style_.push_back(styles_[i].breaks().begin()); |
| 375 } | 381 } |
| 376 | 382 |
| 377 StyleIterator::~StyleIterator() {} | 383 StyleIterator::~StyleIterator() {} |
| 378 | 384 |
| 379 Range StyleIterator::GetRange() const { | 385 Range StyleIterator::GetRange() const { |
| 380 Range range(colors_.GetRange(color_)); | 386 Range range(colors_.GetRange(color_)); |
| 381 range = range.Intersect(baselines_.GetRange(baseline_)); | 387 range = range.Intersect(baselines_.GetRange(baseline_)); |
| 388 range = range.Intersect(weights_.GetRange(weight_)); |
| 382 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 389 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 383 range = range.Intersect(styles_[i].GetRange(style_[i])); | 390 range = range.Intersect(styles_[i].GetRange(style_[i])); |
| 384 return range; | 391 return range; |
| 385 } | 392 } |
| 386 | 393 |
| 387 void StyleIterator::UpdatePosition(size_t position) { | 394 void StyleIterator::UpdatePosition(size_t position) { |
| 388 color_ = colors_.GetBreak(position); | 395 color_ = colors_.GetBreak(position); |
| 389 baseline_ = baselines_.GetBreak(position); | 396 baseline_ = baselines_.GetBreak(position); |
| 397 weight_ = weights_.GetBreak(position); |
| 390 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 398 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 391 style_[i] = styles_[i].GetBreak(position); | 399 style_[i] = styles_[i].GetBreak(position); |
| 392 } | 400 } |
| 393 | 401 |
| 394 LineSegment::LineSegment() : run(0) {} | 402 LineSegment::LineSegment() : run(0) {} |
| 395 | 403 |
| 396 LineSegment::~LineSegment() {} | 404 LineSegment::~LineSegment() {} |
| 397 | 405 |
| 398 Line::Line() : preceding_heights(0), baseline(0) {} | 406 Line::Line() : preceding_heights(0), baseline(0) {} |
| 399 | 407 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 std::unique_ptr<RenderText> render_text = CreateInstanceOfSameType(); | 447 std::unique_ptr<RenderText> render_text = CreateInstanceOfSameType(); |
| 440 // |SetText()| must be called before styles are set. | 448 // |SetText()| must be called before styles are set. |
| 441 render_text->SetText(text); | 449 render_text->SetText(text); |
| 442 render_text->SetFontList(font_list_); | 450 render_text->SetFontList(font_list_); |
| 443 render_text->SetDirectionalityMode(directionality_mode_); | 451 render_text->SetDirectionalityMode(directionality_mode_); |
| 444 render_text->SetCursorEnabled(cursor_enabled_); | 452 render_text->SetCursorEnabled(cursor_enabled_); |
| 445 render_text->set_truncate_length(truncate_length_); | 453 render_text->set_truncate_length(truncate_length_); |
| 446 render_text->styles_ = styles_; | 454 render_text->styles_ = styles_; |
| 447 render_text->baselines_ = baselines_; | 455 render_text->baselines_ = baselines_; |
| 448 render_text->colors_ = colors_; | 456 render_text->colors_ = colors_; |
| 457 render_text->weights_ = weights_; |
| 449 return render_text; | 458 return render_text; |
| 450 } | 459 } |
| 451 | 460 |
| 452 void RenderText::SetText(const base::string16& text) { | 461 void RenderText::SetText(const base::string16& text) { |
| 453 DCHECK(!composition_range_.IsValid()); | 462 DCHECK(!composition_range_.IsValid()); |
| 454 if (text_ == text) | 463 if (text_ == text) |
| 455 return; | 464 return; |
| 456 text_ = text; | 465 text_ = text; |
| 457 UpdateStyleLengths(); | 466 UpdateStyleLengths(); |
| 458 | 467 |
| 459 // Clear style ranges as they might break new text graphemes and apply | 468 // Clear style ranges as they might break new text graphemes and apply |
| 460 // the first style to the whole text instead. | 469 // the first style to the whole text instead. |
| 461 colors_.SetValue(colors_.breaks().begin()->second); | 470 colors_.SetValue(colors_.breaks().begin()->second); |
| 462 baselines_.SetValue(baselines_.breaks().begin()->second); | 471 baselines_.SetValue(baselines_.breaks().begin()->second); |
| 472 weights_.SetValue(weights_.breaks().begin()->second); |
| 463 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 473 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 464 styles_[style].SetValue(styles_[style].breaks().begin()->second); | 474 styles_[style].SetValue(styles_[style].breaks().begin()->second); |
| 465 cached_bounds_and_offset_valid_ = false; | 475 cached_bounds_and_offset_valid_ = false; |
| 466 | 476 |
| 467 // Reset selection model. SetText should always followed by SetSelectionModel | 477 // Reset selection model. SetText should always followed by SetSelectionModel |
| 468 // or SetCursorPosition in upper layer. | 478 // or SetCursorPosition in upper layer. |
| 469 SetSelectionModel(SelectionModel()); | 479 SetSelectionModel(SelectionModel()); |
| 470 | 480 |
| 471 // Invalidate the cached text direction if it depends on the text contents. | 481 // Invalidate the cached text direction if it depends on the text contents. |
| 472 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) | 482 if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 488 if (horizontal_alignment_ != alignment) { | 498 if (horizontal_alignment_ != alignment) { |
| 489 horizontal_alignment_ = alignment; | 499 horizontal_alignment_ = alignment; |
| 490 display_offset_ = Vector2d(); | 500 display_offset_ = Vector2d(); |
| 491 cached_bounds_and_offset_valid_ = false; | 501 cached_bounds_and_offset_valid_ = false; |
| 492 } | 502 } |
| 493 } | 503 } |
| 494 | 504 |
| 495 void RenderText::SetFontList(const FontList& font_list) { | 505 void RenderText::SetFontList(const FontList& font_list) { |
| 496 font_list_ = font_list; | 506 font_list_ = font_list; |
| 497 const int font_style = font_list.GetFontStyle(); | 507 const int font_style = font_list.GetFontStyle(); |
| 498 SetStyle(BOLD, (font_style & gfx::Font::BOLD) != 0); | 508 weights_.SetValue(font_list.GetFontWeight()); |
| 499 SetStyle(ITALIC, (font_style & gfx::Font::ITALIC) != 0); | 509 styles_[ITALIC].SetValue((font_style & Font::ITALIC) != 0); |
| 500 SetStyle(UNDERLINE, (font_style & gfx::Font::UNDERLINE) != 0); | 510 styles_[UNDERLINE].SetValue((font_style & Font::UNDERLINE) != 0); |
| 501 baseline_ = kInvalidBaseline; | 511 baseline_ = kInvalidBaseline; |
| 502 cached_bounds_and_offset_valid_ = false; | 512 cached_bounds_and_offset_valid_ = false; |
| 503 OnLayoutTextAttributeChanged(false); | 513 OnLayoutTextAttributeChanged(false); |
| 504 } | 514 } |
| 505 | 515 |
| 506 void RenderText::SetCursorEnabled(bool cursor_enabled) { | 516 void RenderText::SetCursorEnabled(bool cursor_enabled) { |
| 507 cursor_enabled_ = cursor_enabled; | 517 cursor_enabled_ = cursor_enabled; |
| 508 cached_bounds_and_offset_valid_ = false; | 518 cached_bounds_and_offset_valid_ = false; |
| 509 } | 519 } |
| 510 | 520 |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 const size_t end = IsValidCursorIndex(range.end()) ? range.end() : | 769 const size_t end = IsValidCursorIndex(range.end()) ? range.end() : |
| 760 IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); | 770 IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD); |
| 761 styles_[style].ApplyValue(value, Range(start, end)); | 771 styles_[style].ApplyValue(value, Range(start, end)); |
| 762 | 772 |
| 763 cached_bounds_and_offset_valid_ = false; | 773 cached_bounds_and_offset_valid_ = false; |
| 764 // TODO(oshima|msw): Not all style change requires layout changes. | 774 // TODO(oshima|msw): Not all style change requires layout changes. |
| 765 // Consider optimizing based on the type of change. | 775 // Consider optimizing based on the type of change. |
| 766 OnLayoutTextAttributeChanged(false); | 776 OnLayoutTextAttributeChanged(false); |
| 767 } | 777 } |
| 768 | 778 |
| 779 void RenderText::SetWeight(Font::Weight weight) { |
| 780 weights_.SetValue(weight); |
| 781 |
| 782 cached_bounds_and_offset_valid_ = false; |
| 783 OnLayoutTextAttributeChanged(false); |
| 784 } |
| 785 |
| 786 void RenderText::ApplyWeight(Font::Weight weight, const Range& range) { |
| 787 weights_.ApplyValue(weight, range); |
| 788 |
| 789 cached_bounds_and_offset_valid_ = false; |
| 790 OnLayoutTextAttributeChanged(false); |
| 791 } |
| 792 |
| 769 bool RenderText::GetStyle(TextStyle style) const { | 793 bool RenderText::GetStyle(TextStyle style) const { |
| 770 return (styles_[style].breaks().size() == 1) && | 794 return (styles_[style].breaks().size() == 1) && |
| 771 styles_[style].breaks().front().second; | 795 styles_[style].breaks().front().second; |
| 772 } | 796 } |
| 773 | 797 |
| 774 void RenderText::SetDirectionalityMode(DirectionalityMode mode) { | 798 void RenderText::SetDirectionalityMode(DirectionalityMode mode) { |
| 775 if (mode == directionality_mode_) | 799 if (mode == directionality_mode_) |
| 776 return; | 800 return; |
| 777 | 801 |
| 778 directionality_mode_ = mode; | 802 directionality_mode_ = mode; |
| 779 text_direction_ = base::i18n::UNKNOWN_DIRECTION; | 803 text_direction_ = base::i18n::UNKNOWN_DIRECTION; |
| 780 cached_bounds_and_offset_valid_ = false; | 804 cached_bounds_and_offset_valid_ = false; |
| 781 OnLayoutTextAttributeChanged(false); | 805 OnLayoutTextAttributeChanged(false); |
| 782 } | 806 } |
| 783 | 807 |
| 784 base::i18n::TextDirection RenderText::GetDisplayTextDirection() { | 808 base::i18n::TextDirection RenderText::GetDisplayTextDirection() { |
| 785 return GetTextDirection(GetDisplayText()); | 809 return GetTextDirection(GetDisplayText()); |
| 786 } | 810 } |
| 787 | 811 |
| 788 VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() { | 812 VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() { |
| 789 return GetDisplayTextDirection() == base::i18n::LEFT_TO_RIGHT ? | 813 return GetDisplayTextDirection() == base::i18n::LEFT_TO_RIGHT ? |
| 790 CURSOR_RIGHT : CURSOR_LEFT; | 814 CURSOR_RIGHT : CURSOR_LEFT; |
| 791 } | 815 } |
| 792 | 816 |
| 793 SizeF RenderText::GetStringSizeF() { | 817 SizeF RenderText::GetStringSizeF() { |
| 794 return gfx::SizeF(GetStringSize()); | 818 return SizeF(GetStringSize()); |
| 795 } | 819 } |
| 796 | 820 |
| 797 float RenderText::GetContentWidthF() { | 821 float RenderText::GetContentWidthF() { |
| 798 const float string_size = GetStringSizeF().width(); | 822 const float string_size = GetStringSizeF().width(); |
| 799 // The cursor is drawn one pixel beyond the int-enclosed text bounds. | 823 // The cursor is drawn one pixel beyond the int-enclosed text bounds. |
| 800 return cursor_enabled_ ? std::ceil(string_size) + 1 : string_size; | 824 return cursor_enabled_ ? std::ceil(string_size) + 1 : string_size; |
| 801 } | 825 } |
| 802 | 826 |
| 803 int RenderText::GetContentWidth() { | 827 int RenderText::GetContentWidth() { |
| 804 return ToCeiledInt(GetContentWidthF()); | 828 return ToCeiledInt(GetContentWidthF()); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 cursor_enabled_(true), | 1014 cursor_enabled_(true), |
| 991 cursor_visible_(false), | 1015 cursor_visible_(false), |
| 992 insert_mode_(true), | 1016 insert_mode_(true), |
| 993 cursor_color_(kDefaultColor), | 1017 cursor_color_(kDefaultColor), |
| 994 selection_color_(kDefaultColor), | 1018 selection_color_(kDefaultColor), |
| 995 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 1019 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
| 996 focused_(false), | 1020 focused_(false), |
| 997 composition_range_(Range::InvalidRange()), | 1021 composition_range_(Range::InvalidRange()), |
| 998 colors_(kDefaultColor), | 1022 colors_(kDefaultColor), |
| 999 baselines_(NORMAL_BASELINE), | 1023 baselines_(NORMAL_BASELINE), |
| 1024 weights_(Font::Weight::NORMAL), |
| 1000 styles_(NUM_TEXT_STYLES), | 1025 styles_(NUM_TEXT_STYLES), |
| 1001 composition_and_selection_styles_applied_(false), | 1026 composition_and_selection_styles_applied_(false), |
| 1002 obscured_(false), | 1027 obscured_(false), |
| 1003 obscured_reveal_index_(-1), | 1028 obscured_reveal_index_(-1), |
| 1004 truncate_length_(0), | 1029 truncate_length_(0), |
| 1005 elide_behavior_(NO_ELIDE), | 1030 elide_behavior_(NO_ELIDE), |
| 1006 text_elided_(false), | 1031 text_elided_(false), |
| 1007 min_line_height_(0), | 1032 min_line_height_(0), |
| 1008 multiline_(false), | 1033 multiline_(false), |
| 1009 max_lines_(0), | 1034 max_lines_(0), |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1301 ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index; | 1326 ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index; |
| 1302 CHECK_GE(i, 0); | 1327 CHECK_GE(i, 0); |
| 1303 // Clamp indices to the length of the given layout or display text. | 1328 // Clamp indices to the length of the given layout or display text. |
| 1304 return std::min<size_t>(given_text.length(), i); | 1329 return std::min<size_t>(given_text.length(), i); |
| 1305 } | 1330 } |
| 1306 | 1331 |
| 1307 void RenderText::UpdateStyleLengths() { | 1332 void RenderText::UpdateStyleLengths() { |
| 1308 const size_t text_length = text_.length(); | 1333 const size_t text_length = text_.length(); |
| 1309 colors_.SetMax(text_length); | 1334 colors_.SetMax(text_length); |
| 1310 baselines_.SetMax(text_length); | 1335 baselines_.SetMax(text_length); |
| 1336 weights_.SetMax(text_length); |
| 1311 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1337 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 1312 styles_[style].SetMax(text_length); | 1338 styles_[style].SetMax(text_length); |
| 1313 } | 1339 } |
| 1314 | 1340 |
| 1315 // static | 1341 // static |
| 1316 bool RenderText::RangeContainsCaret(const Range& range, | 1342 bool RenderText::RangeContainsCaret(const Range& range, |
| 1317 size_t caret_pos, | 1343 size_t caret_pos, |
| 1318 LogicalCursorDirection caret_affinity) { | 1344 LogicalCursorDirection caret_affinity) { |
| 1319 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). | 1345 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). |
| 1320 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? | 1346 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 new_text += base::i18n::kRightToLeftMark; | 1479 new_text += base::i18n::kRightToLeftMark; |
| 1454 } | 1480 } |
| 1455 render_text->SetText(new_text); | 1481 render_text->SetText(new_text); |
| 1456 } | 1482 } |
| 1457 | 1483 |
| 1458 // Restore styles and baselines without breaking multi-character graphemes. | 1484 // Restore styles and baselines without breaking multi-character graphemes. |
| 1459 render_text->styles_ = styles_; | 1485 render_text->styles_ = styles_; |
| 1460 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1486 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| 1461 RestoreBreakList(render_text.get(), &render_text->styles_[style]); | 1487 RestoreBreakList(render_text.get(), &render_text->styles_[style]); |
| 1462 RestoreBreakList(render_text.get(), &render_text->baselines_); | 1488 RestoreBreakList(render_text.get(), &render_text->baselines_); |
| 1489 render_text->weights_ = weights_; |
| 1490 RestoreBreakList(render_text.get(), &render_text->weights_); |
| 1463 | 1491 |
| 1464 // We check the width of the whole desired string at once to ensure we | 1492 // We check the width of the whole desired string at once to ensure we |
| 1465 // handle kerning/ligatures/etc. correctly. | 1493 // handle kerning/ligatures/etc. correctly. |
| 1466 const float guess_width = render_text->GetContentWidthF(); | 1494 const float guess_width = render_text->GetContentWidthF(); |
| 1467 if (guess_width == available_width) | 1495 if (guess_width == available_width) |
| 1468 break; | 1496 break; |
| 1469 if (guess_width > available_width) { | 1497 if (guess_width > available_width) { |
| 1470 hi = guess - 1; | 1498 hi = guess - 1; |
| 1471 // Move back on the loop terminating condition when the guess is too wide. | 1499 // Move back on the loop terminating condition when the guess is too wide. |
| 1472 if (hi < lo) | 1500 if (hi < lo) |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1559 | 1587 |
| 1560 SetDisplayOffset(display_offset_.x() + delta_x); | 1588 SetDisplayOffset(display_offset_.x() + delta_x); |
| 1561 } | 1589 } |
| 1562 | 1590 |
| 1563 void RenderText::DrawSelection(Canvas* canvas) { | 1591 void RenderText::DrawSelection(Canvas* canvas) { |
| 1564 for (const Rect& s : GetSubstringBounds(selection())) | 1592 for (const Rect& s : GetSubstringBounds(selection())) |
| 1565 canvas->FillRect(s, selection_background_focused_color_); | 1593 canvas->FillRect(s, selection_background_focused_color_); |
| 1566 } | 1594 } |
| 1567 | 1595 |
| 1568 } // namespace gfx | 1596 } // namespace gfx |
| OLD | NEW |