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

Unified Diff: ui/gfx/render_text.cc

Issue 7466048: Fix RenderText cached bounds and offset logic; update clients. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update comments. Created 9 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
« no previous file with comments | « ui/gfx/render_text.h ('k') | views/controls/textfield/native_textfield_views.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/render_text.cc
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index fce00b589bde6b241fb900d7c6efe8b58e815043..2855a072205a3ea668a9b8397b0a154604357311 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -130,10 +130,6 @@ void SelectionModel::Init(size_t start,
RenderText::~RenderText() {
}
-void RenderText::set_display_rect(const Rect& r) {
- display_rect_ = r;
-}
-
void RenderText::SetText(const string16& text) {
size_t old_text_length = text_.length();
text_ = text;
@@ -161,6 +157,7 @@ void RenderText::SetText(const string16& text) {
#ifndef NDEBUG
CheckStyleRanges(style_ranges_, text_.length());
#endif
+ cached_bounds_and_offset_valid_ = false;
}
void RenderText::SetSelectionModel(const SelectionModel& sel) {
@@ -171,7 +168,12 @@ void RenderText::SetSelectionModel(const SelectionModel& sel) {
selection_model_.set_caret_pos(std::min(sel.caret_pos(), text().length()));
selection_model_.set_caret_placement(sel.caret_placement());
- cursor_bounds_valid_ = false;
+ cached_bounds_and_offset_valid_ = false;
+}
+
+void RenderText::SetDisplayRect(const Rect& r) {
+ display_rect_ = r;
+ cached_bounds_and_offset_valid_ = false;
}
size_t RenderText::GetCursorPosition() const {
@@ -328,8 +330,8 @@ void RenderText::ApplyStyleRange(StyleRange style_range) {
#ifndef NDEBUG
CheckStyleRanges(style_ranges_, text_.length());
#endif
- // TODO(xji): only invalidate cursor_bounds if font or underline change.
- cursor_bounds_valid_ = false;
+ // TODO(xji): only invalidate if font or underline changes.
+ cached_bounds_and_offset_valid_ = false;
}
void RenderText::ApplyDefaultStyle() {
@@ -337,7 +339,7 @@ void RenderText::ApplyDefaultStyle() {
StyleRange style = StyleRange(default_style_);
style.range.set_end(text_.length());
style_ranges_.push_back(style);
- cursor_bounds_valid_ = false;
+ cached_bounds_and_offset_valid_ = false;
}
base::i18n::TextDirection RenderText::GetTextDirection() const {
@@ -347,7 +349,7 @@ base::i18n::TextDirection RenderText::GetTextDirection() const {
}
int RenderText::GetStringWidth() {
- return GetSubstringBounds(0, text_.length())[0].width();
+ return default_style_.font.GetStringWidth(text());
}
void RenderText::Draw(Canvas* canvas) {
@@ -363,10 +365,6 @@ void RenderText::Draw(Canvas* canvas) {
for (std::vector<Rect>::const_iterator i = selection.begin();
i < selection.end(); ++i) {
Rect r(*i);
- r.Offset(display_rect_.origin());
- r.Offset(display_offset_);
- // Center the rect vertically in |display_rect_|.
- r.Offset(Point(0, (display_rect_.height() - r.height()) / 2));
canvas->FillRectInt(selection_color, r.x(), r.y(), r.width(), r.height());
}
@@ -376,7 +374,7 @@ void RenderText::Draw(Canvas* canvas) {
// Draw the text.
Rect bounds(display_rect_);
- bounds.Offset(display_offset_);
+ bounds.Offset(GetUpdatedDisplayOffset());
for (StyleRanges::const_iterator i = style_ranges.begin();
i < style_ranges.end(); ++i) {
const Font& font = !i->underline ? i->font :
@@ -403,16 +401,10 @@ void RenderText::Draw(Canvas* canvas) {
}
// Paint cursor. Replace cursor is drawn as rectangle for now.
- if (cursor_visible() && focused()) {
- bounds = CursorBounds();
- bounds.Offset(display_offset_);
- if (!bounds.IsEmpty())
- canvas->DrawRectInt(kCursorColor,
- bounds.x(),
- bounds.y(),
- bounds.width(),
- bounds.height());
- }
+ Rect cursor(GetUpdatedCursorBounds());
+ if (cursor_visible() && focused() && !cursor.IsEmpty())
+ canvas->DrawRectInt(kCursorColor, cursor.x(), cursor.y(),
+ cursor.width(), cursor.height());
}
SelectionModel RenderText::FindCursorPosition(const Point& point) {
@@ -422,7 +414,7 @@ SelectionModel RenderText::FindCursorPosition(const Point& point) {
int right = font.GetStringWidth(text());
int right_pos = text().length();
- int x = point.x();
+ int x = point.x() - (display_rect_.x() + GetUpdatedDisplayOffset().x());
if (x <= left) return SelectionModel(left_pos);
if (x >= right) return SelectionModel(right_pos);
// binary searching the cursor position.
@@ -444,36 +436,29 @@ SelectionModel RenderText::FindCursorPosition(const Point& point) {
return SelectionModel(left_pos);
}
-std::vector<Rect> RenderText::GetSubstringBounds(
- size_t from, size_t to) const {
+std::vector<Rect> RenderText::GetSubstringBounds(size_t from, size_t to) {
size_t start = std::min(from, to);
size_t end = std::max(from, to);
const Font& font = default_style_.font;
int start_x = font.GetStringWidth(text().substr(0, start));
int end_x = font.GetStringWidth(text().substr(0, end));
- std::vector<Rect> bounds;
- bounds.push_back(Rect(start_x, 0, end_x - start_x, font.GetHeight()));
- return bounds;
+ Rect rect(start_x, 0, end_x - start_x, font.GetHeight());
+ rect.Offset(display_rect_.origin());
+ rect.Offset(GetUpdatedDisplayOffset());
+ // Center the rect vertically in |display_rect_|.
+ rect.Offset(Point(0, (display_rect_.height() - rect.height()) / 2));
+ return std::vector<Rect>(1, rect);
}
Rect RenderText::GetCursorBounds(const SelectionModel& selection,
bool insert_mode) {
- size_t cursor_pos = selection.selection_end();
- const Font& font = default_style_.font;
- int x = font.GetStringWidth(text_.substr(0U, cursor_pos));
- DCHECK_GE(x, 0);
- int h = std::min(display_rect_.height(), font.GetHeight());
- Rect bounds(x, (display_rect_.height() - h) / 2, 1, h);
- if (!insert_mode && text_.length() != cursor_pos)
- bounds.set_width(font.GetStringWidth(text_.substr(0, cursor_pos + 1)) - x);
- return bounds;
-}
-
-const Rect& RenderText::CursorBounds() {
- if (cursor_bounds_valid_ == false) {
- UpdateCursorBoundsAndDisplayOffset();
- cursor_bounds_valid_ = true;
- }
+ size_t from = selection.selection_end();
+ size_t to = insert_mode ? from : std::min(text_.length(), from + 1);
+ return GetSubstringBounds(from, to)[0];
+}
+
+const Rect& RenderText::GetUpdatedCursorBounds() {
+ UpdateCachedBoundsAndOffset();
return cursor_bounds_;
}
@@ -481,14 +466,19 @@ RenderText::RenderText()
: text_(),
selection_model_(),
cursor_bounds_(),
- cursor_bounds_valid_(false),
cursor_visible_(false),
insert_mode_(true),
composition_range_(),
style_ranges_(),
default_style_(),
display_rect_(),
- display_offset_() {
+ display_offset_(),
+ cached_bounds_and_offset_valid_(false) {
+}
+
+const Point& RenderText::GetUpdatedDisplayOffset() {
+ UpdateCachedBoundsAndOffset();
+ return display_offset_;
}
SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current,
@@ -584,21 +574,31 @@ bool RenderText::IsPositionAtWordSelectionBoundary(size_t pos) {
(!u_isalnum(text()[pos - 1]) && u_isalnum(text()[pos]));
}
-void RenderText::UpdateCursorBoundsAndDisplayOffset() {
- cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode());
+void RenderText::UpdateCachedBoundsAndOffset() {
+ if (cached_bounds_and_offset_valid_)
+ return;
+ // 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.
+ cached_bounds_and_offset_valid_ = true;
+ cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_);
+ cursor_bounds_.set_width(std::max(cursor_bounds_.width(), 1));
// Update |display_offset_| to ensure the current cursor is visible.
int display_width = display_rect_.width();
int string_width = GetStringWidth();
+ int delta_offset = 0;
if (string_width < display_width) {
// Show all text whenever the text fits to the size.
- display_offset_.set_x(0);
- } else if ((display_offset_.x() + cursor_bounds_.right()) > display_width) {
+ delta_offset = -display_offset_.x();
+ } else if (cursor_bounds_.right() > display_rect_.right()) {
// Pan to show the cursor when it overflows to the right,
- display_offset_.set_x(display_width - cursor_bounds_.right());
- } else if ((display_offset_.x() + cursor_bounds_.x()) < 0) {
+ delta_offset = display_rect_.right() - cursor_bounds_.right();
+ } else if (cursor_bounds_.x() < display_rect_.x()) {
// Pan to show the cursor when it overflows to the left.
- display_offset_.set_x(-cursor_bounds_.x());
+ delta_offset = display_rect_.x() - cursor_bounds_.x();
}
+ display_offset_.Offset(delta_offset, 0);
+ cursor_bounds_.Offset(delta_offset, 0);
}
} // namespace gfx
« no previous file with comments | « ui/gfx/render_text.h ('k') | views/controls/textfield/native_textfield_views.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698