Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Unified Diff: ui/gfx/render_text.cc

Issue 16867016: Windows implementation of multiline RenderText (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fit whole runs, remove single-line stuff Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/gfx/render_text.cc
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index d3c6bea6ffe682b03d68e8e071f991769e5edaa8..25eeb7772f3d24b7e91594e7b626fc9d15000843 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.
@@ -399,6 +401,7 @@ void RenderText::SetObscuredRevealIndex(int index) {
void RenderText::SetDisplayRect(const Rect& r) {
display_rect_ = r;
cached_bounds_and_offset_valid_ = false;
+ lines_valid_ = false;
}
void RenderText::SetCursorPosition(size_t position) {
@@ -691,18 +694,52 @@ Rect RenderText::GetCursorBounds(const SelectionModel& caret,
// since there is nothing to overtype.
if ((GetTextDirection() == base::i18n::RIGHT_TO_LEFT) == (caret_pos == 0))
x = size.width();
- } else {
- size_t grapheme_start = (caret_affinity == CURSOR_FORWARD) ?
- caret_pos : IndexOfAdjacentGrapheme(caret_pos, CURSOR_BACKWARD);
- ui::Range xspan(GetGlyphBounds(grapheme_start));
- if (insert_mode) {
- x = (caret_affinity == CURSOR_BACKWARD) ? xspan.end() : xspan.start();
- } else { // overtype mode
- x = xspan.GetMin();
- width = xspan.length();
+ } else {
+ size_t grapheme_start = (caret_affinity == CURSOR_FORWARD) ?
+ caret_pos : IndexOfAdjacentGrapheme(caret_pos, CURSOR_BACKWARD);
+ ui::Range xspan(GetGlyphBounds(grapheme_start));
+ if (insert_mode) {
+ x = (caret_affinity == CURSOR_BACKWARD) ? xspan.end() : xspan.start();
+ } else { // overtype mode
+ x = xspan.GetMin();
+ width = xspan.length();
+ }
+ }
+ return Rect(ToViewPoint(Point(x, 0)), Size(width, size.height()));
+}
+
+std::vector<Rect> RenderText::RangeToViewRects(const ui::Range& x) {
msw 2013/07/17 06:47:18 This function should be defined in the order it's
ckocagil 2013/07/19 19:40:50 Done.
+ std::vector<Rect> rects;
+
+ if (!multiline()) {
+ Point start(x.GetMin(), 0);
+ rects.push_back(Rect(ToViewPoint(start), Size(x.length(),
msw 2013/07/17 06:47:18 nit: inline start and break the line before 'Size(
ckocagil 2013/07/19 19:40:50 Done.
+ 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 Rect(ToViewPoint(Point(x, 0)), Size(width, size.height()));
+
+ return rects;
}
const Rect& RenderText::GetUpdatedCursorBounds() {
@@ -765,11 +802,13 @@ RenderText::RenderText()
obscured_(false),
obscured_reveal_index_(-1),
truncate_length_(0),
+ multiline_(false),
fade_head_(false),
fade_tail_(false),
background_is_transparent_(false),
clip_to_display_rect_(true),
- cached_bounds_and_offset_valid_(false) {
+ cached_bounds_and_offset_valid_(false),
+ lines_valid_(false) {
}
const Vector2d& RenderText::GetUpdatedDisplayOffset() {
@@ -834,30 +873,46 @@ void RenderText::UndoCompositionAndSelectionStyles() {
composition_and_selection_styles_applied_ = false;
}
-Vector2d RenderText::GetTextOffset() {
+Vector2d RenderText::GetLineOffset(int line) {
Vector2d offset = display_rect().OffsetFromOrigin();
- offset.Add(GetUpdatedDisplayOffset());
- offset.Add(GetAlignmentOffset());
+ if (!multiline())
+ offset.Add(GetUpdatedDisplayOffset());
+ else
+ offset.Add(Vector2d(0, lines()[line].preceding_heights));
msw 2013/07/17 06:47:18 Does this need to add a per-line horizontal offset
ckocagil 2013/07/19 19:40:50 Which horizontal offset? I don't see your point.
msw 2013/08/15 02:44:17 Nevermind! The line's alignment offset is added ri
+ offset.Add(GetAlignmentOffset(line));
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_valid_);
+ 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);
}
-Vector2d RenderText::GetAlignmentOffset() {
+Vector2d RenderText::GetAlignmentOffset(int line) {
+ int width = lines()[line].width;
msw 2013/07/17 06:47:18 nit: make this const, maybe DCHECK lines_ validity
ckocagil 2013/07/19 19:40:50 Done.
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);
}
@@ -865,14 +920,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);
@@ -903,7 +957,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(
@@ -967,12 +1021,23 @@ void RenderText::UpdateLayoutText() {
iter.setIndex32(truncate_length_ - 1);
layout_text_.assign(text.substr(0, iter.getIndex()) + ui::kEllipsisUTF16);
}
+
+ line_breaks_.clear();
+ base::i18n::BreakIterator iter(GetLayoutText(),
+ base::i18n::BreakIterator::BREAK_LINE);
+ bool success = iter.Init();
+ CHECK(success);
+ do {
+ line_breaks_.push_back(iter.pos());
+ } 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.

Powered by Google App Engine
This is Rietveld 408576698