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

Side by Side Diff: ui/gfx/render_text_win.cc

Issue 8633019: Itemize and layout text lazily in RenderTextWin. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/gfx/render_text_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/render_text_win.h" 5 #include "ui/gfx/render_text_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 TextRun::~TextRun() { 138 TextRun::~TextRun() {
139 ScriptFreeCache(&script_cache); 139 ScriptFreeCache(&script_cache);
140 } 140 }
141 141
142 } // namespace internal 142 } // namespace internal
143 143
144 RenderTextWin::RenderTextWin() 144 RenderTextWin::RenderTextWin()
145 : RenderText(), 145 : RenderText(),
146 script_control_(), 146 script_control_(),
147 script_state_(), 147 script_state_(),
148 string_width_(0) { 148 string_width_(0),
149 needs_layout_(false) {
149 // Omitting default constructors for script_* would leave POD uninitialized. 150 // Omitting default constructors for script_* would leave POD uninitialized.
150 HRESULT hr = 0; 151 HRESULT hr = 0;
151 152
152 // TODO(msw): Call ScriptRecordDigitSubstitution on WM_SETTINGCHANGE message. 153 // TODO(msw): Call ScriptRecordDigitSubstitution on WM_SETTINGCHANGE message.
153 // TODO(msw): Use Chrome/profile locale/language settings? 154 // TODO(msw): Use Chrome/profile locale/language settings?
154 hr = ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &digit_substitute_); 155 hr = ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &digit_substitute_);
155 DCHECK(SUCCEEDED(hr)); 156 DCHECK(SUCCEEDED(hr));
156 157
157 hr = ScriptApplyDigitSubstitution(&digit_substitute_, 158 hr = ScriptApplyDigitSubstitution(&digit_substitute_,
158 &script_control_, 159 &script_control_,
159 &script_state_); 160 &script_state_);
160 DCHECK(SUCCEEDED(hr)); 161 DCHECK(SUCCEEDED(hr));
161 script_control_.fMergeNeutralItems = true; 162 script_control_.fMergeNeutralItems = true;
162 163
163 MoveCursorTo(LeftEndSelectionModel()); 164 MoveCursorTo(LeftEndSelectionModel());
164 } 165 }
165 166
166 RenderTextWin::~RenderTextWin() { 167 RenderTextWin::~RenderTextWin() {
167 STLDeleteContainerPointers(runs_.begin(), runs_.end()); 168 STLDeleteContainerPointers(runs_.begin(), runs_.end());
168 } 169 }
169 170
170 int RenderTextWin::GetStringWidth() { 171 int RenderTextWin::GetStringWidth() {
172 EnsureLayout();
171 return string_width_; 173 return string_width_;
172 } 174 }
173 175
174 void RenderTextWin::Draw(Canvas* canvas) { 176 void RenderTextWin::Draw(Canvas* canvas) {
177 EnsureLayout();
175 DrawSelection(canvas); 178 DrawSelection(canvas);
176 DrawVisualText(canvas); 179 DrawVisualText(canvas);
177 DrawCursor(canvas); 180 DrawCursor(canvas);
178 } 181 }
179 182
180 SelectionModel RenderTextWin::FindCursorPosition(const Point& point) { 183 SelectionModel RenderTextWin::FindCursorPosition(const Point& point) {
181 if (text().empty()) 184 if (text().empty())
182 return SelectionModel(); 185 return SelectionModel();
183 186
187 EnsureLayout();
184 // Find the run that contains the point and adjust the argument location. 188 // Find the run that contains the point and adjust the argument location.
185 Point p(ToTextPoint(point)); 189 Point p(ToTextPoint(point));
186 size_t run_index = GetRunContainingPoint(p); 190 size_t run_index = GetRunContainingPoint(p);
187 if (run_index == runs_.size()) 191 if (run_index == runs_.size())
188 return (p.x() < 0) ? LeftEndSelectionModel() : RightEndSelectionModel(); 192 return (p.x() < 0) ? LeftEndSelectionModel() : RightEndSelectionModel();
189 internal::TextRun* run = runs_[run_index]; 193 internal::TextRun* run = runs_[run_index];
190 194
191 int position = 0, trailing = 0; 195 int position = 0, trailing = 0;
192 HRESULT hr = ScriptXtoCP(p.x() - run->preceding_run_widths, 196 HRESULT hr = ScriptXtoCP(p.x() - run->preceding_run_widths,
193 run->range.length(), 197 run->range.length(),
194 run->glyph_count, 198 run->glyph_count,
195 run->logical_clusters.get(), 199 run->logical_clusters.get(),
196 run->visible_attributes.get(), 200 run->visible_attributes.get(),
197 run->advance_widths.get(), 201 run->advance_widths.get(),
198 &(run->script_analysis), 202 &(run->script_analysis),
199 &position, 203 &position,
200 &trailing); 204 &trailing);
201 DCHECK(SUCCEEDED(hr)); 205 DCHECK(SUCCEEDED(hr));
202 position += run->range.start(); 206 position += run->range.start();
203 207
204 size_t cursor = position + trailing; 208 size_t cursor = position + trailing;
205 DCHECK_GE(cursor, 0U); 209 DCHECK_GE(cursor, 0U);
206 DCHECK_LE(cursor, text().length()); 210 DCHECK_LE(cursor, text().length());
207 return SelectionModel(cursor, position, 211 return SelectionModel(cursor, position,
208 (trailing > 0) ? SelectionModel::TRAILING : SelectionModel::LEADING); 212 (trailing > 0) ? SelectionModel::TRAILING : SelectionModel::LEADING);
209 } 213 }
210 214
211 Rect RenderTextWin::GetCursorBounds(const SelectionModel& selection, 215 Rect RenderTextWin::GetCursorBounds(const SelectionModel& selection,
212 bool insert_mode) { 216 bool insert_mode) {
217 EnsureLayout();
218
213 // Highlight the logical cursor (selection end) when not in insert mode. 219 // Highlight the logical cursor (selection end) when not in insert mode.
214 size_t pos = insert_mode ? selection.caret_pos() : selection.selection_end(); 220 size_t pos = insert_mode ? selection.caret_pos() : selection.selection_end();
215 size_t run_index = GetRunContainingPosition(pos); 221 size_t run_index = GetRunContainingPosition(pos);
216 internal::TextRun* run = run_index == runs_.size() ? NULL : runs_[run_index]; 222 internal::TextRun* run = run_index == runs_.size() ? NULL : runs_[run_index];
217 223
218 int start_x = 0, end_x = 0; 224 int start_x = 0, end_x = 0;
219 if (run) { 225 if (run) {
220 HRESULT hr = 0; 226 HRESULT hr = 0;
221 hr = ScriptCPtoX(pos - run->range.start(), 227 hr = ScriptCPtoX(pos - run->range.start(),
222 false, 228 false,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 rect.set_x(rect.right()); 261 rect.set_x(rect.right());
256 rect.set_width(0); 262 rect.set_width(0);
257 } 263 }
258 rect.set_origin(ToViewPoint(rect.origin())); 264 rect.set_origin(ToViewPoint(rect.origin()));
259 return rect; 265 return rect;
260 } 266 }
261 267
262 SelectionModel RenderTextWin::GetLeftSelectionModel( 268 SelectionModel RenderTextWin::GetLeftSelectionModel(
263 const SelectionModel& selection, 269 const SelectionModel& selection,
264 BreakType break_type) { 270 BreakType break_type) {
271 EnsureLayout();
272
265 if (break_type == LINE_BREAK || text().empty()) 273 if (break_type == LINE_BREAK || text().empty())
266 return LeftEndSelectionModel(); 274 return LeftEndSelectionModel();
267 if (break_type == CHARACTER_BREAK) 275 if (break_type == CHARACTER_BREAK)
268 return LeftSelectionModel(selection); 276 return LeftSelectionModel(selection);
269 // TODO(msw): Implement word breaking. 277 // TODO(msw): Implement word breaking.
270 return RenderText::GetLeftSelectionModel(selection, break_type); 278 return RenderText::GetLeftSelectionModel(selection, break_type);
271 } 279 }
272 280
273 SelectionModel RenderTextWin::GetRightSelectionModel( 281 SelectionModel RenderTextWin::GetRightSelectionModel(
274 const SelectionModel& selection, 282 const SelectionModel& selection,
275 BreakType break_type) { 283 BreakType break_type) {
284 EnsureLayout();
285
276 if (break_type == LINE_BREAK || text().empty()) 286 if (break_type == LINE_BREAK || text().empty())
277 return RightEndSelectionModel(); 287 return RightEndSelectionModel();
278 if (break_type == CHARACTER_BREAK) 288 if (break_type == CHARACTER_BREAK)
279 return RightSelectionModel(selection); 289 return RightSelectionModel(selection);
280 // TODO(msw): Implement word breaking. 290 // TODO(msw): Implement word breaking.
281 return RenderText::GetRightSelectionModel(selection, break_type); 291 return RenderText::GetRightSelectionModel(selection, break_type);
282 } 292 }
283 293
284 SelectionModel RenderTextWin::LeftEndSelectionModel() { 294 SelectionModel RenderTextWin::LeftEndSelectionModel() {
285 if (text().empty()) 295 if (text().empty())
286 return SelectionModel(0, 0, SelectionModel::LEADING); 296 return SelectionModel(0, 0, SelectionModel::LEADING);
297
298 EnsureLayout();
287 size_t cursor = base::i18n::IsRTL() ? text().length() : 0; 299 size_t cursor = base::i18n::IsRTL() ? text().length() : 0;
288 internal::TextRun* run = runs_[visual_to_logical_[0]]; 300 internal::TextRun* run = runs_[visual_to_logical_[0]];
289 bool rtl = run->script_analysis.fRTL; 301 bool rtl = run->script_analysis.fRTL;
290 size_t caret = rtl ? run->range.end() - 1 : run->range.start(); 302 size_t caret = rtl ? run->range.end() - 1 : run->range.start();
291 SelectionModel::CaretPlacement placement = 303 SelectionModel::CaretPlacement placement =
292 rtl ? SelectionModel::TRAILING : SelectionModel::LEADING; 304 rtl ? SelectionModel::TRAILING : SelectionModel::LEADING;
293 return SelectionModel(cursor, caret, placement); 305 return SelectionModel(cursor, caret, placement);
294 } 306 }
295 307
296 SelectionModel RenderTextWin::RightEndSelectionModel() { 308 SelectionModel RenderTextWin::RightEndSelectionModel() {
297 if (text().empty()) 309 if (text().empty())
298 return SelectionModel(0, 0, SelectionModel::LEADING); 310 return SelectionModel(0, 0, SelectionModel::LEADING);
311
312 EnsureLayout();
299 size_t cursor = base::i18n::IsRTL() ? 0 : text().length(); 313 size_t cursor = base::i18n::IsRTL() ? 0 : text().length();
300 internal::TextRun* run = runs_[visual_to_logical_[runs_.size() - 1]]; 314 internal::TextRun* run = runs_[visual_to_logical_[runs_.size() - 1]];
301 bool rtl = run->script_analysis.fRTL; 315 bool rtl = run->script_analysis.fRTL;
302 size_t caret = rtl ? run->range.start() : run->range.end() - 1; 316 size_t caret = rtl ? run->range.start() : run->range.end() - 1;
303 SelectionModel::CaretPlacement placement = 317 SelectionModel::CaretPlacement placement =
304 rtl ? SelectionModel::LEADING : SelectionModel::TRAILING; 318 rtl ? SelectionModel::LEADING : SelectionModel::TRAILING;
305 return SelectionModel(cursor, caret, placement); 319 return SelectionModel(cursor, caret, placement);
306 } 320 }
307 321
308 std::vector<Rect> RenderTextWin::GetSubstringBounds(size_t from, size_t to) { 322 std::vector<Rect> RenderTextWin::GetSubstringBounds(size_t from, size_t to) {
323 DCHECK(!needs_layout_);
309 ui::Range range(from, to); 324 ui::Range range(from, to);
310 DCHECK(ui::Range(0, text().length()).Contains(range)); 325 DCHECK(ui::Range(0, text().length()).Contains(range));
311 Point display_offset(GetUpdatedDisplayOffset()); 326 Point display_offset(GetUpdatedDisplayOffset());
312 std::vector<Rect> bounds; 327 std::vector<Rect> bounds;
313 HRESULT hr = 0; 328 HRESULT hr = 0;
314 329
315 // Add a Rect for each run/selection intersection. 330 // Add a Rect for each run/selection intersection.
316 // TODO(msw): The bounds should probably not always be leading the range ends. 331 // TODO(msw): The bounds should probably not always be leading the range ends.
317 for (size_t i = 0; i < runs_.size(); ++i) { 332 for (size_t i = 0; i < runs_.size(); ++i) {
318 internal::TextRun* run = runs_[visual_to_logical_[i]]; 333 internal::TextRun* run = runs_[visual_to_logical_[i]];
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 bounds.push_back(rect); 371 bounds.push_back(rect);
357 } 372 }
358 } 373 }
359 return bounds; 374 return bounds;
360 } 375 }
361 376
362 bool RenderTextWin::IsCursorablePosition(size_t position) { 377 bool RenderTextWin::IsCursorablePosition(size_t position) {
363 if (position == 0 || position == text().length()) 378 if (position == 0 || position == text().length())
364 return true; 379 return true;
365 380
381 EnsureLayout();
366 size_t run_index = GetRunContainingPosition(position); 382 size_t run_index = GetRunContainingPosition(position);
367 if (run_index >= runs_.size()) 383 if (run_index >= runs_.size())
368 return false; 384 return false;
369 385
370 internal::TextRun* run = runs_[run_index]; 386 internal::TextRun* run = runs_[run_index];
371 size_t start = run->range.start(); 387 size_t start = run->range.start();
372 if (position == start) 388 if (position == start)
373 return true; 389 return true;
374 return run->logical_clusters[position - start] != 390 return run->logical_clusters[position - start] !=
375 run->logical_clusters[position - start - 1]; 391 run->logical_clusters[position - start - 1];
376 } 392 }
377 393
378 void RenderTextWin::UpdateLayout() { 394 void RenderTextWin::UpdateLayout() {
379 // TODO(msw): Skip complex processing if ScriptIsComplex returns false. 395 // Layout is performed lazily as needed for drawing/metrics.
380 ItemizeLogicalText(); 396 needs_layout_ = true;
381 if (!runs_.empty())
382 LayoutVisualText();
383 } 397 }
384 398
385 size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) { 399 size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) {
400 EnsureLayout();
386 size_t run_index = GetRunContainingPosition(index); 401 size_t run_index = GetRunContainingPosition(index);
387 internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL; 402 internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL;
388 int start = run ? run->range.start() : 0; 403 int start = run ? run->range.start() : 0;
389 int length = run ? run->range.length() : text().length(); 404 int length = run ? run->range.length() : text().length();
390 int ch = index - start; 405 int ch = index - start;
391 WORD cluster = run ? run->logical_clusters[ch] : 0; 406 WORD cluster = run ? run->logical_clusters[ch] : 0;
392 407
393 if (!next) { 408 if (!next) {
394 do { 409 do {
395 ch--; 410 ch--;
396 } while (ch >= 0 && run && run->logical_clusters[ch] == cluster); 411 } while (ch >= 0 && run && run->logical_clusters[ch] == cluster);
397 } else { 412 } else {
398 while (ch < length && run && run->logical_clusters[ch] == cluster) 413 while (ch < length && run && run->logical_clusters[ch] == cluster)
399 ch++; 414 ch++;
400 } 415 }
401 return std::max(std::min(ch, length) + start, 0); 416 return std::max(std::min(ch, length) + start, 0);
402 } 417 }
403 418
419 void RenderTextWin::EnsureLayout() {
420 if (!needs_layout_)
421 return;
422 // TODO(msw): Skip complex processing if ScriptIsComplex returns false.
423 ItemizeLogicalText();
424 if (!runs_.empty())
425 LayoutVisualText();
426 needs_layout_ = false;
427 }
428
404 void RenderTextWin::ItemizeLogicalText() { 429 void RenderTextWin::ItemizeLogicalText() {
405 STLDeleteContainerPointers(runs_.begin(), runs_.end()); 430 STLDeleteContainerPointers(runs_.begin(), runs_.end());
406 runs_.clear(); 431 runs_.clear();
432 string_width_ = 0;
407 if (text().empty()) 433 if (text().empty())
408 return; 434 return;
409 435
410 const wchar_t* raw_text = text().c_str(); 436 const wchar_t* raw_text = text().c_str();
411 const int text_length = text().length(); 437 const int text_length = text().length();
412 438
413 HRESULT hr = E_OUTOFMEMORY; 439 HRESULT hr = E_OUTOFMEMORY;
414 int script_items_count = 0; 440 int script_items_count = 0;
415 std::vector<SCRIPT_ITEM> script_items; 441 std::vector<SCRIPT_ITEM> script_items;
416 for (size_t n = kGuessItems; hr == E_OUTOFMEMORY && n < kMaxItems; n *= 2) { 442 for (size_t n = kGuessItems; hr == E_OUTOFMEMORY && n < kMaxItems; n *= 2) {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 internal::TextRun* run = runs_[visual_to_logical_[i]]; 575 internal::TextRun* run = runs_[visual_to_logical_[i]];
550 run->preceding_run_widths = preceding_run_widths; 576 run->preceding_run_widths = preceding_run_widths;
551 const ABC& abc = run->abc_widths; 577 const ABC& abc = run->abc_widths;
552 run->width = abc.abcA + abc.abcB + abc.abcC; 578 run->width = abc.abcA + abc.abcB + abc.abcC;
553 preceding_run_widths += run->width; 579 preceding_run_widths += run->width;
554 } 580 }
555 string_width_ = preceding_run_widths; 581 string_width_ = preceding_run_widths;
556 } 582 }
557 583
558 size_t RenderTextWin::GetRunContainingPosition(size_t position) const { 584 size_t RenderTextWin::GetRunContainingPosition(size_t position) const {
585 DCHECK(!needs_layout_);
559 // Find the text run containing the argument position. 586 // Find the text run containing the argument position.
560 size_t run = 0; 587 size_t run = 0;
561 for (; run < runs_.size(); ++run) 588 for (; run < runs_.size(); ++run)
562 if (runs_[run]->range.start() <= position && 589 if (runs_[run]->range.start() <= position &&
563 runs_[run]->range.end() > position) 590 runs_[run]->range.end() > position)
564 break; 591 break;
565 return run; 592 return run;
566 } 593 }
567 594
568 size_t RenderTextWin::GetRunContainingPoint(const Point& point) const { 595 size_t RenderTextWin::GetRunContainingPoint(const Point& point) const {
596 DCHECK(!needs_layout_);
569 // Find the text run containing the argument point (assumed already offset). 597 // Find the text run containing the argument point (assumed already offset).
570 size_t run = 0; 598 size_t run = 0;
571 for (; run < runs_.size(); ++run) 599 for (; run < runs_.size(); ++run)
572 if (runs_[run]->preceding_run_widths <= point.x() && 600 if (runs_[run]->preceding_run_widths <= point.x() &&
573 runs_[run]->preceding_run_widths + runs_[run]->width > point.x()) 601 runs_[run]->preceding_run_widths + runs_[run]->width > point.x())
574 break; 602 break;
575 return run; 603 return run;
576 } 604 }
577 605
578 SelectionModel RenderTextWin::FirstSelectionModelInsideRun( 606 SelectionModel RenderTextWin::FirstSelectionModelInsideRun(
579 internal::TextRun* run) { 607 internal::TextRun* run) {
580 size_t caret = run->range.start(); 608 size_t caret = run->range.start();
581 size_t cursor = IndexOfAdjacentGrapheme(caret, true); 609 size_t cursor = IndexOfAdjacentGrapheme(caret, true);
582 return SelectionModel(cursor, caret, SelectionModel::TRAILING); 610 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
583 } 611 }
584 612
585 SelectionModel RenderTextWin::LastSelectionModelInsideRun( 613 SelectionModel RenderTextWin::LastSelectionModelInsideRun(
586 internal::TextRun* run) { 614 internal::TextRun* run) {
587 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), false); 615 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), false);
588 return SelectionModel(caret, caret, SelectionModel::LEADING); 616 return SelectionModel(caret, caret, SelectionModel::LEADING);
589 } 617 }
590 618
591 SelectionModel RenderTextWin::LeftSelectionModel( 619 SelectionModel RenderTextWin::LeftSelectionModel(
592 const SelectionModel& selection) { 620 const SelectionModel& selection) {
621 DCHECK(!needs_layout_);
593 size_t caret = selection.caret_pos(); 622 size_t caret = selection.caret_pos();
594 SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); 623 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
595 size_t run_index = GetRunContainingPosition(caret); 624 size_t run_index = GetRunContainingPosition(caret);
596 DCHECK(run_index < runs_.size()); 625 DCHECK(run_index < runs_.size());
597 internal::TextRun* run = runs_[run_index]; 626 internal::TextRun* run = runs_[run_index];
598 627
599 // If the caret's associated character is in a LTR run. 628 // If the caret's associated character is in a LTR run.
600 if (!run->script_analysis.fRTL) { 629 if (!run->script_analysis.fRTL) {
601 if (caret_placement == SelectionModel::TRAILING) 630 if (caret_placement == SelectionModel::TRAILING)
602 return SelectionModel(caret, caret, SelectionModel::LEADING); 631 return SelectionModel(caret, caret, SelectionModel::LEADING);
(...skipping 16 matching lines...) Expand all
619 size_t visual_index = logical_to_visual_[run_index]; 648 size_t visual_index = logical_to_visual_[run_index];
620 if (visual_index == 0) 649 if (visual_index == 0)
621 return LeftEndSelectionModel(); 650 return LeftEndSelectionModel();
622 internal::TextRun* prev = runs_[visual_to_logical_[visual_index - 1]]; 651 internal::TextRun* prev = runs_[visual_to_logical_[visual_index - 1]];
623 return prev->script_analysis.fRTL ? FirstSelectionModelInsideRun(prev) : 652 return prev->script_analysis.fRTL ? FirstSelectionModelInsideRun(prev) :
624 LastSelectionModelInsideRun(prev); 653 LastSelectionModelInsideRun(prev);
625 } 654 }
626 655
627 SelectionModel RenderTextWin::RightSelectionModel( 656 SelectionModel RenderTextWin::RightSelectionModel(
628 const SelectionModel& selection) { 657 const SelectionModel& selection) {
658 DCHECK(!needs_layout_);
629 size_t caret = selection.caret_pos(); 659 size_t caret = selection.caret_pos();
630 SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); 660 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
631 size_t run_index = GetRunContainingPosition(caret); 661 size_t run_index = GetRunContainingPosition(caret);
632 DCHECK(run_index < runs_.size()); 662 DCHECK(run_index < runs_.size());
633 internal::TextRun* run = runs_[run_index]; 663 internal::TextRun* run = runs_[run_index];
634 664
635 // If the caret's associated character is in a LTR run. 665 // If the caret's associated character is in a LTR run.
636 if (!run->script_analysis.fRTL) { 666 if (!run->script_analysis.fRTL) {
637 if (caret_placement == SelectionModel::LEADING) { 667 if (caret_placement == SelectionModel::LEADING) {
638 size_t cursor = IndexOfAdjacentGrapheme(caret, true); 668 size_t cursor = IndexOfAdjacentGrapheme(caret, true);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 Rect r(GetUpdatedCursorBounds()); 764 Rect r(GetUpdatedCursorBounds());
735 canvas->DrawRectInt(kCursorColor, r.x(), r.y(), r.width(), r.height()); 765 canvas->DrawRectInt(kCursorColor, r.x(), r.y(), r.width(), r.height());
736 } 766 }
737 } 767 }
738 768
739 RenderText* RenderText::CreateRenderText() { 769 RenderText* RenderText::CreateRenderText() {
740 return new RenderTextWin; 770 return new RenderTextWin;
741 } 771 }
742 772
743 } // namespace gfx 773 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/render_text_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698