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 <algorithm> | 7 #include <algorithm> |
| 8 #include <climits> | 8 #include <climits> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 canvas_->DrawLine(start_, end, paint_); | 342 canvas_->DrawLine(start_, end, paint_); |
| 343 | 343 |
| 344 if (clipped) | 344 if (clipped) |
| 345 canvas_->Restore(); | 345 canvas_->Restore(); |
| 346 | 346 |
| 347 x += pieces_[i].first; | 347 x += pieces_[i].first; |
| 348 } | 348 } |
| 349 } | 349 } |
| 350 | 350 |
| 351 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 351 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
| 352 const BreakList<BaselineStyle>& baselines, | |
| 352 const std::vector<BreakList<bool> >& styles) | 353 const std::vector<BreakList<bool> >& styles) |
| 353 : colors_(colors), | 354 : colors_(colors), |
| 355 baselines_(baselines), | |
| 354 styles_(styles) { | 356 styles_(styles) { |
| 355 color_ = colors_.breaks().begin(); | 357 color_ = colors_.breaks().begin(); |
| 358 baseline_ = baselines_.breaks().begin(); | |
| 356 for (size_t i = 0; i < styles_.size(); ++i) | 359 for (size_t i = 0; i < styles_.size(); ++i) |
| 357 style_.push_back(styles_[i].breaks().begin()); | 360 style_.push_back(styles_[i].breaks().begin()); |
| 358 } | 361 } |
| 359 | 362 |
| 360 StyleIterator::~StyleIterator() {} | 363 StyleIterator::~StyleIterator() {} |
| 361 | 364 |
| 362 Range StyleIterator::GetRange() const { | 365 Range StyleIterator::GetRange() const { |
| 363 Range range(colors_.GetRange(color_)); | 366 Range range(colors_.GetRange(color_)); |
| 367 range = range.Intersect(baselines_.GetRange(baseline_)); | |
| 364 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 368 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 365 range = range.Intersect(styles_[i].GetRange(style_[i])); | 369 range = range.Intersect(styles_[i].GetRange(style_[i])); |
| 366 return range; | 370 return range; |
| 367 } | 371 } |
| 368 | 372 |
| 369 void StyleIterator::UpdatePosition(size_t position) { | 373 void StyleIterator::UpdatePosition(size_t position) { |
| 370 color_ = colors_.GetBreak(position); | 374 color_ = colors_.GetBreak(position); |
| 375 baseline_ = baselines_.GetBreak(position); | |
| 371 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 376 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
| 372 style_[i] = styles_[i].GetBreak(position); | 377 style_[i] = styles_[i].GetBreak(position); |
| 373 } | 378 } |
| 374 | 379 |
| 375 LineSegment::LineSegment() : width(0), run(0) {} | 380 LineSegment::LineSegment() : width(0), run(0) {} |
| 376 | 381 |
| 377 LineSegment::~LineSegment() {} | 382 LineSegment::~LineSegment() {} |
| 378 | 383 |
| 379 Line::Line() : preceding_heights(0), baseline(0) {} | 384 Line::Line() : preceding_heights(0), baseline(0) {} |
| 380 | 385 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 RenderText* RenderText::CreateInstanceForEditing() { | 421 RenderText* RenderText::CreateInstanceForEditing() { |
| 417 return new RenderTextHarfBuzz; | 422 return new RenderTextHarfBuzz; |
| 418 } | 423 } |
| 419 | 424 |
| 420 void RenderText::SetText(const base::string16& text) { | 425 void RenderText::SetText(const base::string16& text) { |
| 421 DCHECK(!composition_range_.IsValid()); | 426 DCHECK(!composition_range_.IsValid()); |
| 422 if (text_ == text) | 427 if (text_ == text) |
| 423 return; | 428 return; |
| 424 text_ = text; | 429 text_ = text; |
| 425 | 430 |
| 426 // Adjust ranged styles and colors to accommodate a new text length. | 431 // Adjust ranged styles and colors to accommodate a new text length. |
|
msw
2015/02/18 17:07:23
nit: Adjust ranged styles, baselines, and colors..
dschuyler
2015/02/18 22:36:02
Done.
| |
| 427 // Clear style ranges as they might break new text graphemes and apply | 432 // Clear style ranges as they might break new text graphemes and apply |
| 428 // the first style to the whole text instead. | 433 // the first style to the whole text instead. |
| 429 const size_t text_length = text_.length(); | 434 const size_t text_length = text_.length(); |
| 430 colors_.SetMax(text_length); | 435 colors_.SetMax(text_length); |
| 436 baselines_.SetMax(text_length); | |
|
msw
2015/02/18 17:07:23
You'll need to clear the baseline values here, lik
dschuyler
2015/02/18 22:36:02
Done.
| |
| 431 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) { | 437 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) { |
| 432 BreakList<bool>& break_list = styles_[style]; | 438 BreakList<bool>& break_list = styles_[style]; |
| 433 break_list.SetValue(break_list.breaks().begin()->second); | 439 break_list.SetValue(break_list.breaks().begin()->second); |
| 434 break_list.SetMax(text_length); | 440 break_list.SetMax(text_length); |
| 435 } | 441 } |
| 436 cached_bounds_and_offset_valid_ = false; | 442 cached_bounds_and_offset_valid_ = false; |
| 437 | 443 |
| 438 // Reset selection model. SetText should always followed by SetSelectionModel | 444 // Reset selection model. SetText should always followed by SetSelectionModel |
| 439 // or SetCursorPosition in upper layer. | 445 // or SetCursorPosition in upper layer. |
| 440 SetSelectionModel(SelectionModel()); | 446 SetSelectionModel(SelectionModel()); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 661 } | 667 } |
| 662 | 668 |
| 663 void RenderText::SetColor(SkColor value) { | 669 void RenderText::SetColor(SkColor value) { |
| 664 colors_.SetValue(value); | 670 colors_.SetValue(value); |
| 665 } | 671 } |
| 666 | 672 |
| 667 void RenderText::ApplyColor(SkColor value, const Range& range) { | 673 void RenderText::ApplyColor(SkColor value, const Range& range) { |
| 668 colors_.ApplyValue(value, range); | 674 colors_.ApplyValue(value, range); |
| 669 } | 675 } |
| 670 | 676 |
| 677 void RenderText::SetBaselineStyle(BaselineStyle value) { | |
| 678 baselines_.SetValue(value); | |
| 679 } | |
| 680 | |
| 681 void RenderText::ApplyBaselineStyle(BaselineStyle value, const Range& range) { | |
| 682 baselines_.ApplyValue(value, range); | |
| 683 } | |
| 684 | |
| 671 void RenderText::SetStyle(TextStyle style, bool value) { | 685 void RenderText::SetStyle(TextStyle style, bool value) { |
| 672 styles_[style].SetValue(value); | 686 styles_[style].SetValue(value); |
| 673 | 687 |
| 674 cached_bounds_and_offset_valid_ = false; | 688 cached_bounds_and_offset_valid_ = false; |
| 675 ResetLayout(); | 689 ResetLayout(); |
| 676 } | 690 } |
| 677 | 691 |
| 678 void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) { | 692 void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) { |
| 679 // Do not change styles mid-grapheme to avoid breaking ligatures. | 693 // Do not change styles mid-grapheme to avoid breaking ligatures. |
| 680 const size_t start = IsValidCursorIndex(range.start()) ? range.start() : | 694 const size_t start = IsValidCursorIndex(range.start()) ? range.start() : |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 918 text_direction_(base::i18n::UNKNOWN_DIRECTION), | 932 text_direction_(base::i18n::UNKNOWN_DIRECTION), |
| 919 cursor_enabled_(true), | 933 cursor_enabled_(true), |
| 920 cursor_visible_(false), | 934 cursor_visible_(false), |
| 921 insert_mode_(true), | 935 insert_mode_(true), |
| 922 cursor_color_(kDefaultColor), | 936 cursor_color_(kDefaultColor), |
| 923 selection_color_(kDefaultColor), | 937 selection_color_(kDefaultColor), |
| 924 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 938 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
| 925 focused_(false), | 939 focused_(false), |
| 926 composition_range_(Range::InvalidRange()), | 940 composition_range_(Range::InvalidRange()), |
| 927 colors_(kDefaultColor), | 941 colors_(kDefaultColor), |
| 942 baselines_(NORMAL_BASELINE), | |
| 928 styles_(NUM_TEXT_STYLES), | 943 styles_(NUM_TEXT_STYLES), |
| 929 composition_and_selection_styles_applied_(false), | 944 composition_and_selection_styles_applied_(false), |
| 930 obscured_(false), | 945 obscured_(false), |
| 931 obscured_reveal_index_(-1), | 946 obscured_reveal_index_(-1), |
| 932 truncate_length_(0), | 947 truncate_length_(0), |
| 933 elide_behavior_(NO_ELIDE), | 948 elide_behavior_(NO_ELIDE), |
| 934 replace_newline_chars_with_symbols_(true), | 949 replace_newline_chars_with_symbols_(true), |
| 935 min_line_height_(0), | 950 min_line_height_(0), |
| 936 multiline_(false), | 951 multiline_(false), |
| 937 background_is_transparent_(false), | 952 background_is_transparent_(false), |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1252 if (behavior == ELIDE_EMAIL) | 1267 if (behavior == ELIDE_EMAIL) |
| 1253 return ElideEmail(text, available_width); | 1268 return ElideEmail(text, available_width); |
| 1254 | 1269 |
| 1255 // Create a RenderText copy with attributes that affect the rendering width. | 1270 // Create a RenderText copy with attributes that affect the rendering width. |
| 1256 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); | 1271 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); |
| 1257 render_text->SetFontList(font_list_); | 1272 render_text->SetFontList(font_list_); |
| 1258 render_text->SetDirectionalityMode(directionality_mode_); | 1273 render_text->SetDirectionalityMode(directionality_mode_); |
| 1259 render_text->SetCursorEnabled(cursor_enabled_); | 1274 render_text->SetCursorEnabled(cursor_enabled_); |
| 1260 render_text->set_truncate_length(truncate_length_); | 1275 render_text->set_truncate_length(truncate_length_); |
| 1261 render_text->styles_ = styles_; | 1276 render_text->styles_ = styles_; |
| 1277 render_text->baselines_ = baselines_; | |
| 1262 render_text->colors_ = colors_; | 1278 render_text->colors_ = colors_; |
| 1263 render_text->SetText(text); | 1279 render_text->SetText(text); |
| 1264 if (render_text->GetContentWidthF() <= available_width) | 1280 if (render_text->GetContentWidthF() <= available_width) |
| 1265 return text; | 1281 return text; |
| 1266 | 1282 |
| 1267 const base::string16 ellipsis = base::string16(kEllipsisUTF16); | 1283 const base::string16 ellipsis = base::string16(kEllipsisUTF16); |
| 1268 const bool insert_ellipsis = (behavior != TRUNCATE); | 1284 const bool insert_ellipsis = (behavior != TRUNCATE); |
| 1269 const bool elide_in_middle = (behavior == ELIDE_MIDDLE); | 1285 const bool elide_in_middle = (behavior == ELIDE_MIDDLE); |
| 1270 const bool elide_at_beginning = (behavior == ELIDE_HEAD); | 1286 const bool elide_at_beginning = (behavior == ELIDE_HEAD); |
| 1271 StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning); | 1287 StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning); |
| 1272 | 1288 |
| 1273 render_text->SetText(ellipsis); | 1289 render_text->SetText(ellipsis); |
| 1274 const float ellipsis_width = render_text->GetContentWidthF(); | 1290 const float ellipsis_width = render_text->GetContentWidthF(); |
| 1275 | 1291 |
| 1276 if (insert_ellipsis && (ellipsis_width > available_width)) | 1292 if (insert_ellipsis && (ellipsis_width > available_width)) |
| 1277 return base::string16(); | 1293 return base::string16(); |
| 1278 | 1294 |
| 1279 // Use binary search to compute the elided text. | 1295 // Use binary search to compute the elided text. |
| 1280 size_t lo = 0; | 1296 size_t lo = 0; |
| 1281 size_t hi = text.length() - 1; | 1297 size_t hi = text.length() - 1; |
| 1282 const base::i18n::TextDirection text_direction = GetTextDirection(); | 1298 const base::i18n::TextDirection text_direction = GetTextDirection(); |
| 1283 for (size_t guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) { | 1299 for (size_t guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) { |
| 1284 // Restore colors. They will be truncated to size by SetText. | 1300 // Restore colors. They will be truncated to size by SetText. |
| 1285 render_text->colors_ = colors_; | 1301 render_text->colors_ = colors_; |
| 1302 render_text->baselines_ = baselines_; | |
|
msw
2015/02/18 17:07:23
With the change to clear the baseline values on Se
dschuyler
2015/02/18 22:36:02
I moved the restore break list code out to a separ
| |
| 1286 base::string16 new_text = | 1303 base::string16 new_text = |
| 1287 slicer.CutString(guess, insert_ellipsis && behavior != ELIDE_TAIL); | 1304 slicer.CutString(guess, insert_ellipsis && behavior != ELIDE_TAIL); |
| 1288 render_text->SetText(new_text); | 1305 render_text->SetText(new_text); |
| 1289 | 1306 |
| 1290 // This has to be an additional step so that the ellipsis is rendered with | 1307 // This has to be an additional step so that the ellipsis is rendered with |
| 1291 // same style as trailing part of the text. | 1308 // same style as trailing part of the text. |
| 1292 if (insert_ellipsis && behavior == ELIDE_TAIL) { | 1309 if (insert_ellipsis && behavior == ELIDE_TAIL) { |
| 1293 // When ellipsis follows text whose directionality is not the same as that | 1310 // When ellipsis follows text whose directionality is not the same as that |
| 1294 // of the whole text, it will be rendered with the directionality of the | 1311 // of the whole text, it will be rendered with the directionality of the |
| 1295 // whole text. Since we want ellipsis to indicate continuation of the | 1312 // whole text. Since we want ellipsis to indicate continuation of the |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1425 SetDisplayOffset(display_offset_.x() + delta_x); | 1442 SetDisplayOffset(display_offset_.x() + delta_x); |
| 1426 } | 1443 } |
| 1427 | 1444 |
| 1428 void RenderText::DrawSelection(Canvas* canvas) { | 1445 void RenderText::DrawSelection(Canvas* canvas) { |
| 1429 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 1446 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
| 1430 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) | 1447 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) |
| 1431 canvas->FillRect(*i, selection_background_focused_color_); | 1448 canvas->FillRect(*i, selection_background_focused_color_); |
| 1432 } | 1449 } |
| 1433 | 1450 |
| 1434 } // namespace gfx | 1451 } // namespace gfx |
| OLD | NEW |