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

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: comments addressed 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..5005eea5311b8e6a0719e2a40b74907ecd71f7d8 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -301,6 +301,21 @@ void StyleIterator::UpdatePosition(size_t position) {
style_[i] = styles_[i].GetBreak(position);
}
+Line::Line() : width(0), height(0), preceding_heights(0), baseline(0) {}
+
+Line::Line(Line& other) {
+ *this = other;
+}
+
+Line& Line::operator=(Line& other) {
+ width = other.width;
+ height = other.height;
+ preceding_heights = other.preceding_heights;
+ baseline = other.baseline;
+ segments.swap(other.segments);
+ return *this;
+}
+
} // namespace internal
RenderText::~RenderText() {
@@ -308,6 +323,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.
@@ -384,6 +401,14 @@ void RenderText::SetObscured(bool obscured) {
}
}
+void RenderText::SetMultiline(bool multiline) {
+ if (multiline != multiline_) {
+ multiline_ = multiline;
+ cached_bounds_and_offset_valid_ = false;
+ ResetLayout();
+ }
+}
+
void RenderText::SetObscuredRevealIndex(int index) {
if (obscured_reveal_index_ == index)
return;
@@ -397,6 +422,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) {
@@ -775,6 +801,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 +845,23 @@ const base::string16& RenderText::GetLayoutText() const {
return layout_text_.empty() ? text_ : layout_text_;
}
+const BreakList<size_t>& RenderText::GetLineBreaks() {
+ if (line_breaks_.max() == 0) {
+ 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);
+ bool success = iter.Init();
+ CHECK(success);
+ do {
+ line_breaks_.ApplyValue(iter.pos(), ui::Range(iter.pos(),
+ layout_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 +888,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 + (cursor_enabled_ ? 1 : 0);
Alexei Svitkine (slow) 2013/08/16 18:32:34 Nit: lines_
ckocagil 2013/08/20 00:09:06 Done (throughout the file).
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);
}
@@ -875,14 +970,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 +1008,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(
@@ -978,12 +1072,16 @@ void RenderText::UpdateLayoutText() {
iter.setIndex32(truncate_length_ - 1);
layout_text_.assign(text.substr(0, iter.getIndex()) + ui::kEllipsisUTF16);
}
+
+ line_breaks_.SetMax(0);
}
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