Index: ui/gfx/render_text.cc |
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc |
index 7019918df3959526af5504e2f57a75ee02ec8cd5..57d3246cd53c358b3d3dc4da67444abcfb6fe1e0 100644 |
--- a/ui/gfx/render_text.cc |
+++ b/ui/gfx/render_text.cc |
@@ -434,6 +434,24 @@ RenderText* RenderText::CreateInstanceForEditing() { |
return new RenderTextHarfBuzz; |
} |
+std::unique_ptr<RenderText> RenderText::CreateInstanceOfSameStyle( |
+ const base::string16& text) const { |
+ std::unique_ptr<RenderText> render_text = CreateInstanceOfSameType(); |
+ // |SetText()| must be called before styles are set. |
+ render_text->directionality_mode_ = directionality_mode_; |
+ render_text->cursor_enabled_ = cursor_enabled_; |
+ render_text->set_truncate_length(truncate_length_); |
+ render_text->font_list_ = font_list_; |
+ render_text->text_ = text; |
+ render_text->styles_ = styles_; |
+ render_text->baselines_ = baselines_; |
+ render_text->colors_ = colors_; |
+ render_text->multiline_ = multiline_; |
+ render_text->SetDisplayRect(display_rect_); |
+ render_text->OnTextAttributeChanged(); |
+ return render_text; |
+} |
+ |
void RenderText::SetText(const base::string16& text) { |
DCHECK(!composition_range_.IsValid()); |
if (text_ == text) |
@@ -525,6 +543,15 @@ void RenderText::SetMultiline(bool multiline) { |
} |
} |
+void RenderText::SetMaxLines(size_t max_lines) { |
+ max_lines_ = max_lines; |
+ OnDisplayTextAttributeChanged(); |
+} |
+ |
+size_t RenderText::GetNumLines() { |
+ return lines_.size(); |
+} |
+ |
void RenderText::SetWordWrapBehavior(WordWrapBehavior behavior) { |
if (word_wrap_behavior_ == behavior) |
return; |
@@ -982,13 +1009,13 @@ RenderText::RenderText() |
text_elided_(false), |
min_line_height_(0), |
multiline_(false), |
+ max_lines_(0), |
word_wrap_behavior_(IGNORE_LONG_WORDS), |
replace_newline_chars_with_symbols_(true), |
subpixel_rendering_suppressed_(false), |
clip_to_display_rect_(true), |
baseline_(kInvalidBaseline), |
- cached_bounds_and_offset_valid_(false) { |
-} |
+ cached_bounds_and_offset_valid_(false) {} |
SelectionModel RenderText::GetAdjacentSelectionModel( |
const SelectionModel& current, |
@@ -1021,25 +1048,54 @@ void RenderText::OnTextColorChanged() { |
} |
void RenderText::UpdateDisplayText(float text_width) { |
- // TODO(oshima): Consider support eliding for multi-line text. |
- // This requires max_line support first. |
- if (multiline_ || |
- elide_behavior() == NO_ELIDE || |
- elide_behavior() == FADE_TAIL || |
- text_width < display_rect_.width() || |
+ // TODO(krb): Consider other elision modes for multiline. |
+ if ((multiline_ && (!max_lines_ || elide_behavior() != ELIDE_TAIL)) || |
+ elide_behavior() == NO_ELIDE || elide_behavior() == FADE_TAIL || |
+ (text_width > 0 && text_width < display_rect_.width()) || |
layout_text_.empty()) { |
text_elided_ = false; |
display_text_.clear(); |
return; |
} |
- // This doesn't trim styles so ellipsis may get rendered as a different |
- // style than the preceding text. See crbug.com/327850. |
- display_text_.assign(Elide(layout_text_, |
- text_width, |
- static_cast<float>(display_rect_.width()), |
- elide_behavior_)); |
+ if (!multiline_) { |
+ // This doesn't trim styles so ellipsis may get rendered as a different |
+ // style than the preceding text. See crbug.com/327850. |
+ display_text_.assign(Elide(layout_text_, text_width, |
+ static_cast<float>(display_rect_.width()), |
+ elide_behavior_)); |
+ } else { |
+ bool was_elided = text_elided_; |
+ text_elided_ = false; |
+ display_text_.clear(); |
+ std::unique_ptr<RenderText> render_text( |
+ CreateInstanceOfSameStyle(layout_text_)); |
+ //render_text->SetMultiline(true); |
+ //render_text->SetDisplayRect(display_rect_); |
+ // Have it arrange words on |lines_|. |
+ //render_text->OnLayoutTextAttributeChanged(false); |
+ render_text->EnsureLayout(); |
+ |
+ if (render_text->lines_.size() > max_lines_) { |
+ size_t start_of_elision = render_text->lines_[max_lines_ - 1] |
+ .segments.front() |
+ .char_range.start(); |
+ base::string16 text_to_elide = layout_text_.substr(start_of_elision); |
+ display_text_.assign(layout_text_.substr(0, start_of_elision) + |
+ Elide(text_to_elide, 0, |
+ static_cast<float>(display_rect_.width()), |
+ ELIDE_TAIL)); |
+ // Have GetLineBreaks() re-calculate. |
+ line_breaks_.SetMax(0); |
+ } else { |
+ // If elision changed, re-calculate. |
+ if (was_elided) |
+ line_breaks_.SetMax(0); |
+ // Initial state above is fine. |
+ return; |
+ } |
+ } |
text_elided_ = display_text_ != layout_text_; |
if (!text_elided_) |
display_text_.clear(); |
@@ -1351,16 +1407,11 @@ base::string16 RenderText::Elide(const base::string16& text, |
TRACE_EVENT0("ui", "RenderText::Elide"); |
// Create a RenderText copy with attributes that affect the rendering width. |
- std::unique_ptr<RenderText> render_text = CreateInstanceOfSameType(); |
- render_text->SetFontList(font_list_); |
- render_text->SetDirectionalityMode(directionality_mode_); |
- render_text->SetCursorEnabled(cursor_enabled_); |
- render_text->set_truncate_length(truncate_length_); |
- render_text->styles_ = styles_; |
- render_text->baselines_ = baselines_; |
- render_text->colors_ = colors_; |
+ bool orig_multiline = multiline_; |
+ multiline_ = false; |
+ std::unique_ptr<RenderText> render_text = CreateInstanceOfSameStyle(text); |
+ multiline_ = orig_multiline; |
if (text_width == 0) { |
- render_text->SetText(text); |
text_width = render_text->GetContentWidthF(); |
} |
if (text_width <= available_width) |