Chromium Code Reviews| Index: ui/gfx/render_text.cc |
| diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc |
| index 91f9f42bd89ad69dad47646e52c08516e9cad394..cff0bc0fdc1bb3ef7419e3d2fa476cde3922ee4d 100644 |
| --- a/ui/gfx/render_text.cc |
| +++ b/ui/gfx/render_text.cc |
| @@ -308,6 +308,8 @@ RenderText::~RenderText() { |
| void RenderText::SetText(const base::string16& text) { |
| DCHECK(!composition_range_.IsValid()); |
| + if (text_ == text) |
| + return; |
| text_ = text; |
| // Adjust ranged styles and colors to accommodate a new text length. |
| @@ -397,6 +399,7 @@ void RenderText::SetObscuredRevealIndex(int index) { |
| void RenderText::SetDisplayRect(const Rect& r) { |
| display_rect_ = r; |
| cached_bounds_and_offset_valid_ = false; |
| + lines_.clear(); |
| } |
| void RenderText::SetCursorPosition(size_t position) { |
| @@ -763,6 +766,7 @@ RenderText::RenderText() |
| obscured_(false), |
| obscured_reveal_index_(-1), |
| truncate_length_(0), |
| + multiline_(false), |
| fade_head_(false), |
| fade_tail_(false), |
| background_is_transparent_(false), |
| @@ -832,30 +836,81 @@ void RenderText::UndoCompositionAndSelectionStyles() { |
| composition_and_selection_styles_applied_ = false; |
| } |
| -Vector2d RenderText::GetTextOffset() { |
| +Vector2d RenderText::GetLineOffset(size_t line_number) { |
| Vector2d offset = display_rect().OffsetFromOrigin(); |
| - offset.Add(GetUpdatedDisplayOffset()); |
| - offset.Add(GetAlignmentOffset()); |
| + if (!multiline()) |
| + offset.Add(GetUpdatedDisplayOffset()); |
| + else |
| + offset.Add(Vector2d(0, lines()[line_number].preceding_heights)); |
| + offset.Add(GetAlignmentOffset(line_number)); |
| return offset; |
| } |
| Point RenderText::ToTextPoint(const Point& point) { |
| - return point - GetTextOffset(); |
| + return point - GetLineOffset(0); |
| + // TODO(ckocagil): implement multiline. |
| } |
| Point RenderText::ToViewPoint(const Point& point) { |
| - return point + GetTextOffset(); |
| + if (!multiline()) |
| + return point + GetLineOffset(0); |
| + |
| + // TODO(ckocagil): refactor this to traverse all line segments to support rtl. |
| + DCHECK(!lines_.empty()); |
| + int x = point.x(); |
| + unsigned int line = 0; |
| + while (line < lines_.size() && x > lines()[line].width) { |
| + x -= lines()[line].width; |
| + ++line; |
| + } |
| + return Point(x, point.y()) + GetLineOffset(line); |
| +} |
| + |
| +std::vector<Rect> RenderText::TextBoundsToViewBounds(const ui::Range& x) { |
| + std::vector<Rect> rects; |
| + |
| + if (!multiline()) { |
| + rects.push_back(Rect(ToViewPoint(Point(x.GetMin(), 0)), |
| + Size(x.length(), GetStringSize().height()))); |
| + return rects; |
| + } |
| + |
| + EnsureLayout(); |
| + |
| + // Each line segments keeps its position in text coordinates. Traverse all |
| + // line segments and if the segment intersects with the given range, add the |
| + // view rect corresponding to the intersection to |rects|. |
| + for (size_t line = 0; line < lines().size(); ++line) { |
| + int line_x = 0; |
| + Vector2d offset = GetLineOffset(line); |
| + for (size_t i = 0; i < lines()[line].segments.size(); ++i) { |
| + const internal::LineSegment* segment = lines()[line].segments[i]; |
| + ui::Range intersection = segment->x_pos.Intersect(x); |
| + if (!intersection.is_empty()) { |
| + Rect rect(line_x + intersection.start() - segment->x_pos.start(), |
| + 0, intersection.length(), lines()[line].height); |
| + rect += offset; |
| + rects.push_back(rect); |
| + } |
| + line_x += segment->x_pos.length(); |
| + } |
| + } |
| + |
| + return rects; |
| } |
| -Vector2d RenderText::GetAlignmentOffset() { |
| + |
| +Vector2d RenderText::GetAlignmentOffset(size_t line_number) { |
| + DCHECK(!lines_.empty()); |
| + const int width = lines()[line_number].width; |
| Vector2d offset; |
| if (horizontal_alignment_ != ALIGN_LEFT) { |
| - offset.set_x(display_rect().width() - GetContentWidth()); |
| + offset.set_x(display_rect().width() - width); |
| if (horizontal_alignment_ == ALIGN_CENTER) |
| offset.set_x(offset.x() / 2); |
| } |
| if (vertical_alignment_ != ALIGN_TOP) { |
| - offset.set_y(display_rect().height() - GetStringSize().height()); |
| + offset.set_y(display_rect().height() - GetMultilineTextSize().height()); |
| if (vertical_alignment_ == ALIGN_VCENTER) |
| offset.set_y(offset.y() / 2); |
| } |
| @@ -863,14 +918,13 @@ Vector2d RenderText::GetAlignmentOffset() { |
| } |
| void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { |
| - if (!fade_head() && !fade_tail()) |
| + if (multiline() || !fade_head() && !fade_tail()) |
| return; |
| - const int text_width = GetStringSize().width(); |
| const int display_width = display_rect().width(); |
| // If the text fits as-is, no need to fade. |
| - if (text_width <= display_width) |
| + if (GetStringSize().width() <= display_width) |
| return; |
| int gradient_width = CalculateFadeGradientWidth(GetFont(), display_width); |
| @@ -901,7 +955,7 @@ void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { |
| } |
| Rect text_rect = display_rect(); |
| - text_rect.Inset(GetAlignmentOffset().x(), 0, 0, 0); |
| + text_rect.Inset(GetAlignmentOffset(0).x(), 0, 0, 0); |
| // TODO(msw): Use the actual text colors corresponding to each faded part. |
| skia::RefPtr<SkShader> shader = CreateFadeShader( |
| @@ -965,12 +1019,26 @@ void RenderText::UpdateLayoutText() { |
| iter.setIndex32(truncate_length_ - 1); |
| layout_text_.assign(text.substr(0, iter.getIndex()) + ui::kEllipsisUTF16); |
| } |
| + |
| + const string16& layout_text = GetLayoutText(); |
| + line_breaks_.SetValue(0); |
| + line_breaks_.SetMax(layout_text.length()); |
| + base::i18n::BreakIterator iter(layout_text, |
| + base::i18n::BreakIterator::BREAK_LINE); |
|
Alexei Svitkine (slow)
2013/07/22 20:52:05
There's a comment in download_item_view.cc that BR
ckocagil
2013/08/07 12:59:20
Done, it's completely lazy now.
|
| + bool success = iter.Init(); |
| + CHECK(success); |
| + do { |
| + line_breaks_.ApplyValue(iter.pos(), |
| + ui::Range(iter.pos(), layout_text.length())); |
| + } while (iter.Advance()); |
| } |
| void RenderText::UpdateCachedBoundsAndOffset() { |
| if (cached_bounds_and_offset_valid_) |
| return; |
| + // TODO(ckocagil): Add vertical offset support for scrolling multi-line text. |
| + |
| // First, set the valid flag true to calculate the current cursor bounds using |
| // the stale |display_offset_|. Applying |delta_offset| at the end of this |
| // function will set |cursor_bounds_| and |display_offset_| to correct values. |