Index: ui/gfx/render_text_win.cc |
=================================================================== |
--- ui/gfx/render_text_win.cc (revision 111778) |
+++ ui/gfx/render_text_win.cc (working copy) |
@@ -145,7 +145,8 @@ |
: RenderText(), |
script_control_(), |
script_state_(), |
- string_width_(0) { |
+ string_width_(0), |
+ needs_layout_(false) { |
// Omitting default constructors for script_* would leave POD uninitialized. |
HRESULT hr = 0; |
@@ -168,10 +169,12 @@ |
} |
int RenderTextWin::GetStringWidth() { |
+ EnsureLayout(); |
return string_width_; |
} |
void RenderTextWin::Draw(Canvas* canvas) { |
+ EnsureLayout(); |
DrawSelection(canvas); |
DrawVisualText(canvas); |
DrawCursor(canvas); |
@@ -181,6 +184,7 @@ |
if (text().empty()) |
return SelectionModel(); |
+ EnsureLayout(); |
// Find the run that contains the point and adjust the argument location. |
Point p(ToTextPoint(point)); |
size_t run_index = GetRunContainingPoint(p); |
@@ -210,6 +214,8 @@ |
Rect RenderTextWin::GetCursorBounds(const SelectionModel& selection, |
bool insert_mode) { |
+ EnsureLayout(); |
+ |
// Highlight the logical cursor (selection end) when not in insert mode. |
size_t pos = insert_mode ? selection.caret_pos() : selection.selection_end(); |
size_t run_index = GetRunContainingPosition(pos); |
@@ -262,6 +268,8 @@ |
SelectionModel RenderTextWin::GetLeftSelectionModel( |
const SelectionModel& selection, |
BreakType break_type) { |
+ EnsureLayout(); |
+ |
if (break_type == LINE_BREAK || text().empty()) |
return LeftEndSelectionModel(); |
if (break_type == CHARACTER_BREAK) |
@@ -273,6 +281,8 @@ |
SelectionModel RenderTextWin::GetRightSelectionModel( |
const SelectionModel& selection, |
BreakType break_type) { |
+ EnsureLayout(); |
+ |
if (break_type == LINE_BREAK || text().empty()) |
return RightEndSelectionModel(); |
if (break_type == CHARACTER_BREAK) |
@@ -284,6 +294,8 @@ |
SelectionModel RenderTextWin::LeftEndSelectionModel() { |
if (text().empty()) |
return SelectionModel(0, 0, SelectionModel::LEADING); |
+ |
+ EnsureLayout(); |
size_t cursor = base::i18n::IsRTL() ? text().length() : 0; |
internal::TextRun* run = runs_[visual_to_logical_[0]]; |
bool rtl = run->script_analysis.fRTL; |
@@ -296,6 +308,8 @@ |
SelectionModel RenderTextWin::RightEndSelectionModel() { |
if (text().empty()) |
return SelectionModel(0, 0, SelectionModel::LEADING); |
+ |
+ EnsureLayout(); |
size_t cursor = base::i18n::IsRTL() ? 0 : text().length(); |
internal::TextRun* run = runs_[visual_to_logical_[runs_.size() - 1]]; |
bool rtl = run->script_analysis.fRTL; |
@@ -306,6 +320,7 @@ |
} |
std::vector<Rect> RenderTextWin::GetSubstringBounds(size_t from, size_t to) { |
+ DCHECK(!needs_layout_); |
ui::Range range(from, to); |
DCHECK(ui::Range(0, text().length()).Contains(range)); |
Point display_offset(GetUpdatedDisplayOffset()); |
@@ -363,6 +378,7 @@ |
if (position == 0 || position == text().length()) |
return true; |
+ EnsureLayout(); |
size_t run_index = GetRunContainingPosition(position); |
if (run_index >= runs_.size()) |
return false; |
@@ -376,13 +392,12 @@ |
} |
void RenderTextWin::UpdateLayout() { |
- // TODO(msw): Skip complex processing if ScriptIsComplex returns false. |
- ItemizeLogicalText(); |
- if (!runs_.empty()) |
- LayoutVisualText(); |
+ // Layout is performed lazily as needed for drawing/metrics. |
+ needs_layout_ = true; |
} |
size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) { |
+ EnsureLayout(); |
size_t run_index = GetRunContainingPosition(index); |
internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL; |
int start = run ? run->range.start() : 0; |
@@ -401,9 +416,20 @@ |
return std::max(std::min(ch, length) + start, 0); |
} |
+void RenderTextWin::EnsureLayout() { |
+ if (!needs_layout_) |
+ return; |
+ // TODO(msw): Skip complex processing if ScriptIsComplex returns false. |
+ ItemizeLogicalText(); |
+ if (!runs_.empty()) |
+ LayoutVisualText(); |
+ needs_layout_ = false; |
+} |
+ |
void RenderTextWin::ItemizeLogicalText() { |
STLDeleteContainerPointers(runs_.begin(), runs_.end()); |
runs_.clear(); |
+ string_width_ = 0; |
if (text().empty()) |
return; |
@@ -556,6 +582,7 @@ |
} |
size_t RenderTextWin::GetRunContainingPosition(size_t position) const { |
+ DCHECK(!needs_layout_); |
// Find the text run containing the argument position. |
size_t run = 0; |
for (; run < runs_.size(); ++run) |
@@ -566,6 +593,7 @@ |
} |
size_t RenderTextWin::GetRunContainingPoint(const Point& point) const { |
+ DCHECK(!needs_layout_); |
// Find the text run containing the argument point (assumed already offset). |
size_t run = 0; |
for (; run < runs_.size(); ++run) |
@@ -590,6 +618,7 @@ |
SelectionModel RenderTextWin::LeftSelectionModel( |
const SelectionModel& selection) { |
+ DCHECK(!needs_layout_); |
size_t caret = selection.caret_pos(); |
SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); |
size_t run_index = GetRunContainingPosition(caret); |
@@ -626,6 +655,7 @@ |
SelectionModel RenderTextWin::RightSelectionModel( |
const SelectionModel& selection) { |
+ DCHECK(!needs_layout_); |
size_t caret = selection.caret_pos(); |
SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); |
size_t run_index = GetRunContainingPosition(caret); |