| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/i18n/break_iterator.h" | 9 #include "base/i18n/break_iterator.h" |
| 10 #include "base/i18n/rtl.h" | 10 #include "base/i18n/rtl.h" |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 visual_index += (direction == CURSOR_LEFT) ? -1 : 1; | 310 visual_index += (direction == CURSOR_LEFT) ? -1 : 1; |
| 311 if (visual_index < 0 || visual_index >= static_cast<int>(runs_.size())) | 311 if (visual_index < 0 || visual_index >= static_cast<int>(runs_.size())) |
| 312 return EdgeSelectionModel(direction); | 312 return EdgeSelectionModel(direction); |
| 313 run = runs_[visual_to_logical_[visual_index]]; | 313 run = runs_[visual_to_logical_[visual_index]]; |
| 314 } | 314 } |
| 315 bool forward_motion = run->script_analysis.fRTL == (direction == CURSOR_LEFT); | 315 bool forward_motion = run->script_analysis.fRTL == (direction == CURSOR_LEFT); |
| 316 return forward_motion ? FirstSelectionModelInsideRun(run) : | 316 return forward_motion ? FirstSelectionModelInsideRun(run) : |
| 317 LastSelectionModelInsideRun(run); | 317 LastSelectionModelInsideRun(run); |
| 318 } | 318 } |
| 319 | 319 |
| 320 // TODO(msw): Implement word breaking for Windows. | |
| 321 SelectionModel RenderTextWin::AdjacentWordSelectionModel( | |
| 322 const SelectionModel& selection, | |
| 323 VisualCursorDirection direction) { | |
| 324 if (obscured()) | |
| 325 return EdgeSelectionModel(direction); | |
| 326 | |
| 327 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); | |
| 328 bool success = iter.Init(); | |
| 329 DCHECK(success); | |
| 330 if (!success) | |
| 331 return selection; | |
| 332 | |
| 333 size_t pos; | |
| 334 if (direction == CURSOR_RIGHT) { | |
| 335 pos = std::min(selection.caret_pos() + 1, text().length()); | |
| 336 while (iter.Advance()) { | |
| 337 pos = iter.pos(); | |
| 338 if (iter.IsWord() && pos > selection.caret_pos()) | |
| 339 break; | |
| 340 } | |
| 341 } else { // direction == CURSOR_LEFT | |
| 342 // Notes: We always iterate words from the beginning. | |
| 343 // This is probably fast enough for our usage, but we may | |
| 344 // want to modify WordIterator so that it can start from the | |
| 345 // middle of string and advance backwards. | |
| 346 pos = std::max<int>(selection.caret_pos() - 1, 0); | |
| 347 while (iter.Advance()) { | |
| 348 if (iter.IsWord()) { | |
| 349 size_t begin = iter.pos() - iter.GetString().length(); | |
| 350 if (begin == selection.caret_pos()) { | |
| 351 // The cursor is at the beginning of a word. | |
| 352 // Move to previous word. | |
| 353 break; | |
| 354 } else if (iter.pos() >= selection.caret_pos()) { | |
| 355 // The cursor is in the middle or at the end of a word. | |
| 356 // Move to the top of current word. | |
| 357 pos = begin; | |
| 358 break; | |
| 359 } else { | |
| 360 pos = iter.pos() - iter.GetString().length(); | |
| 361 } | |
| 362 } | |
| 363 } | |
| 364 } | |
| 365 return SelectionModel(pos, CURSOR_FORWARD); | |
| 366 } | |
| 367 | |
| 368 ui::Range RenderTextWin::GetGlyphBounds(size_t index) { | 320 ui::Range RenderTextWin::GetGlyphBounds(size_t index) { |
| 369 const size_t run_index = | 321 const size_t run_index = |
| 370 GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD)); | 322 GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD)); |
| 371 // Return edge bounds if the index is invalid or beyond the layout text size. | 323 // Return edge bounds if the index is invalid or beyond the layout text size. |
| 372 if (run_index >= runs_.size()) | 324 if (run_index >= runs_.size()) |
| 373 return ui::Range(string_size_.width()); | 325 return ui::Range(string_size_.width()); |
| 374 internal::TextRun* run = runs_[run_index]; | 326 internal::TextRun* run = runs_[run_index]; |
| 375 const size_t layout_index = TextIndexToLayoutIndex(index); | 327 const size_t layout_index = TextIndexToLayoutIndex(index); |
| 376 return ui::Range(GetGlyphXBoundary(run, layout_index, false), | 328 return ui::Range(GetGlyphXBoundary(run, layout_index, false), |
| 377 GetGlyphXBoundary(run, layout_index, true)); | 329 GetGlyphXBoundary(run, layout_index, true)); |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 size_t position = LayoutIndexToTextIndex(run->range.end()); | 841 size_t position = LayoutIndexToTextIndex(run->range.end()); |
| 890 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); | 842 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); |
| 891 return SelectionModel(position, CURSOR_FORWARD); | 843 return SelectionModel(position, CURSOR_FORWARD); |
| 892 } | 844 } |
| 893 | 845 |
| 894 RenderText* RenderText::CreateInstance() { | 846 RenderText* RenderText::CreateInstance() { |
| 895 return new RenderTextWin; | 847 return new RenderTextWin; |
| 896 } | 848 } |
| 897 | 849 |
| 898 } // namespace gfx | 850 } // namespace gfx |
| OLD | NEW |