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 |