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

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: Mike's comments 2 Created 7 years, 4 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 1fcf18cede44fce180c344fe8bef925595ee935e..8897aef31244104e5d239b70853bd00a6e7ffb42 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -301,6 +301,8 @@ void StyleIterator::UpdatePosition(size_t position) {
style_[i] = styles_[i].GetBreak(position);
}
+Line::Line() : preceding_heights(0), baseline(0) {}
+
} // namespace internal
RenderText::~RenderText() {
@@ -308,6 +310,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.
@@ -394,9 +398,18 @@ void RenderText::SetObscuredRevealIndex(int index) {
ResetLayout();
}
+void RenderText::SetMultiline(bool multiline) {
+ if (multiline != multiline_) {
+ multiline_ = multiline;
+ cached_bounds_and_offset_valid_ = false;
+ ResetLayout();
+ }
+}
+
void RenderText::SetDisplayRect(const Rect& r) {
display_rect_ = r;
cached_bounds_and_offset_valid_ = false;
+ lines_.clear();
}
void RenderText::SetCursorPosition(size_t position) {
@@ -775,6 +788,7 @@ RenderText::RenderText()
obscured_(false),
obscured_reveal_index_(-1),
truncate_length_(0),
+ multiline_(false),
fade_head_(false),
fade_tail_(false),
background_is_transparent_(false),
@@ -818,6 +832,25 @@ const base::string16& RenderText::GetLayoutText() const {
return layout_text_.empty() ? text_ : layout_text_;
}
+const BreakList<size_t>& RenderText::GetLineBreaks() {
+ const string16& layout_text = GetLayoutText();
+ const size_t text_length = layout_text.length();
+ if (line_breaks_.max() == 0) {
Alexei Svitkine (slow) 2013/08/26 21:34:41 Nit: Make this an early return and put the above t
ckocagil 2013/08/28 18:01:45 Done.
+ line_breaks_.SetValue(0);
+ line_breaks_.SetMax(text_length);
+ base::i18n::BreakIterator iter(layout_text,
+ base::i18n::BreakIterator::BREAK_LINE);
+ bool success = iter.Init();
+ DCHECK(success);
+ if (success) {
+ do {
+ line_breaks_.ApplyValue(iter.pos(), ui::Range(iter.pos(), text_length));
+ } while (iter.Advance());
+ }
+ }
+ return line_breaks_;
+}
+
void RenderText::ApplyCompositionAndSelectionStyles() {
// Save the underline and color breaks to undo the temporary styles later.
DCHECK(!composition_and_selection_styles_applied_);
@@ -844,30 +877,80 @@ 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;
Alexei Svitkine (slow) 2013/08/27 15:40:38 size_t?
ckocagil 2013/08/28 19:16:26 Done.
+ while (line < lines_.size() && x > lines_[line].size.width()) {
+ x -= lines_[line].size.width();
+ ++line;
+ }
+ return Point(x, point.y()) + GetLineOffset(line);
}
-Vector2d RenderText::GetAlignmentOffset() {
+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 segment 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];
+ const ui::Range intersection = segment->x_range.Intersect(x);
+ if (!intersection.is_empty()) {
+ Rect rect(line_x + intersection.start() - segment->x_range.start(),
+ 0, intersection.length(), lines_[line].size.height());
+ rects.push_back(rect + offset);
+ }
+ line_x += segment->x_range.length();
+ }
+ }
+
+ return rects;
+}
+
+Vector2d RenderText::GetAlignmentOffset(size_t line_number) {
+ DCHECK_LT(line_number, lines_.size());
Vector2d offset;
if (horizontal_alignment_ != ALIGN_LEFT) {
- offset.set_x(display_rect().width() - GetContentWidth());
+ const int width = lines_[line_number].size.width() +
+ (cursor_enabled_ ? 1 : 0);
+ 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);
}
@@ -875,14 +958,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(GetPrimaryFont(),
@@ -914,7 +996,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(
@@ -948,6 +1030,7 @@ void RenderText::MoveCursorTo(size_t position, bool select) {
void RenderText::UpdateLayoutText() {
layout_text_.clear();
+ line_breaks_.SetMax(0);
if (obscured_) {
size_t obscured_text_length =
@@ -984,6 +1067,8 @@ 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