OLD | NEW |
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 "base/i18n/break_iterator.h" | 7 #include "base/i18n/break_iterator.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 return SelectionModel(0, 0, SelectionModel::LEADING); | 230 return SelectionModel(0, 0, SelectionModel::LEADING); |
231 size_t cursor = base::i18n::IsRTL() ? 0 : text().length(); | 231 size_t cursor = base::i18n::IsRTL() ? 0 : text().length(); |
232 internal::TextRun* run = runs_[visual_to_logical_[runs_.size() - 1]]; | 232 internal::TextRun* run = runs_[visual_to_logical_[runs_.size() - 1]]; |
233 bool rtl = run->script_analysis.fRTL; | 233 bool rtl = run->script_analysis.fRTL; |
234 size_t caret = rtl ? run->range.start() : run->range.end() - 1; | 234 size_t caret = rtl ? run->range.start() : run->range.end() - 1; |
235 SelectionModel::CaretPlacement placement = | 235 SelectionModel::CaretPlacement placement = |
236 rtl ? SelectionModel::LEADING : SelectionModel::TRAILING; | 236 rtl ? SelectionModel::LEADING : SelectionModel::TRAILING; |
237 return SelectionModel(cursor, caret, placement); | 237 return SelectionModel(cursor, caret, placement); |
238 } | 238 } |
239 | 239 |
240 size_t RenderTextWin::GetIndexOfPreviousGrapheme(size_t position) { | |
241 return IndexOfAdjacentGrapheme(position, false); | |
242 } | |
243 | |
244 std::vector<Rect> RenderTextWin::GetSubstringBounds(size_t from, size_t to) { | 240 std::vector<Rect> RenderTextWin::GetSubstringBounds(size_t from, size_t to) { |
245 ui::Range range(from, to); | 241 ui::Range range(from, to); |
246 DCHECK(ui::Range(0, text().length()).Contains(range)); | 242 DCHECK(ui::Range(0, text().length()).Contains(range)); |
247 Point display_offset(GetUpdatedDisplayOffset()); | 243 Point display_offset(GetUpdatedDisplayOffset()); |
248 std::vector<Rect> bounds; | 244 std::vector<Rect> bounds; |
249 HRESULT hr = 0; | 245 HRESULT hr = 0; |
250 | 246 |
251 // Add a Rect for each run/selection intersection. | 247 // Add a Rect for each run/selection intersection. |
252 // TODO(msw): The bounds should probably not always be leading the range ends. | 248 // TODO(msw): The bounds should probably not always be leading the range ends. |
253 for (size_t i = 0; i < runs_.size(); ++i) { | 249 for (size_t i = 0; i < runs_.size(); ++i) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 if (!bounds.empty() && rect.SharesEdgeWith(bounds.back())) { | 284 if (!bounds.empty() && rect.SharesEdgeWith(bounds.back())) { |
289 rect = rect.Union(bounds.back()); | 285 rect = rect.Union(bounds.back()); |
290 bounds.pop_back(); | 286 bounds.pop_back(); |
291 } | 287 } |
292 bounds.push_back(rect); | 288 bounds.push_back(rect); |
293 } | 289 } |
294 } | 290 } |
295 return bounds; | 291 return bounds; |
296 } | 292 } |
297 | 293 |
| 294 bool RenderTextWin::IsCursorablePosition(size_t position) { |
| 295 if (position == 0 || position == text().length()) |
| 296 return true; |
| 297 |
| 298 size_t run_index = GetRunContainingPosition(position); |
| 299 if (run_index >= runs_.size()) |
| 300 return false; |
| 301 |
| 302 internal::TextRun* run = runs_[run_index]; |
| 303 size_t start = run->range.start(); |
| 304 if (position == start) |
| 305 return true; |
| 306 return run->logical_clusters[position - start] != |
| 307 run->logical_clusters[position - start - 1]; |
| 308 } |
| 309 |
| 310 size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) { |
| 311 size_t run_index = GetRunContainingPosition(index); |
| 312 internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL; |
| 313 long start = run ? run->range.start() : 0; |
| 314 long length = run ? run->range.length() : text().length(); |
| 315 long ch = index - start; |
| 316 WORD cluster = run ? run->logical_clusters[ch] : 0; |
| 317 |
| 318 if (!next) { |
| 319 do { |
| 320 ch--; |
| 321 } while (ch >= 0 && run && run->logical_clusters[ch] == cluster); |
| 322 } else { |
| 323 while (ch < length && run && run->logical_clusters[ch] == cluster) |
| 324 ch++; |
| 325 } |
| 326 return std::max(static_cast<long>(std::min(ch, length) + start), 0L); |
| 327 } |
| 328 |
298 void RenderTextWin::ItemizeLogicalText() { | 329 void RenderTextWin::ItemizeLogicalText() { |
299 text_is_dirty_ = false; | 330 text_is_dirty_ = false; |
300 STLDeleteContainerPointers(runs_.begin(), runs_.end()); | 331 STLDeleteContainerPointers(runs_.begin(), runs_.end()); |
301 runs_.clear(); | 332 runs_.clear(); |
302 if (text().empty()) | 333 if (text().empty()) |
303 return; | 334 return; |
304 | 335 |
305 const wchar_t* raw_text = text().c_str(); | 336 const wchar_t* raw_text = text().c_str(); |
306 const int text_length = text().length(); | 337 const int text_length = text().length(); |
307 | 338 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 size_t RenderTextWin::GetRunContainingPoint(const Point& point) const { | 485 size_t RenderTextWin::GetRunContainingPoint(const Point& point) const { |
455 // Find the text run containing the argument point (assumed already offset). | 486 // Find the text run containing the argument point (assumed already offset). |
456 size_t run = 0; | 487 size_t run = 0; |
457 for (; run < runs_.size(); ++run) | 488 for (; run < runs_.size(); ++run) |
458 if (runs_[run]->preceding_run_widths <= point.x() && | 489 if (runs_[run]->preceding_run_widths <= point.x() && |
459 runs_[run]->preceding_run_widths + runs_[run]->width > point.x()) | 490 runs_[run]->preceding_run_widths + runs_[run]->width > point.x()) |
460 break; | 491 break; |
461 return run; | 492 return run; |
462 } | 493 } |
463 | 494 |
464 size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) const { | |
465 size_t run_index = GetRunContainingPosition(index); | |
466 internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL; | |
467 long start = run ? run->range.start() : 0; | |
468 long length = run ? run->range.length() : text().length(); | |
469 long ch = index - start; | |
470 WORD cluster = run ? run->logical_clusters[ch] : 0; | |
471 | |
472 if (!next) { | |
473 do { | |
474 ch--; | |
475 } while (ch >= 0 && run && run->logical_clusters[ch] == cluster); | |
476 } else { | |
477 while (ch < length && run && run->logical_clusters[ch] == cluster) | |
478 ch++; | |
479 } | |
480 return std::max(static_cast<long>(std::min(ch, length) + start), 0L); | |
481 } | |
482 | 495 |
483 SelectionModel RenderTextWin::FirstSelectionModelInsideRun( | 496 SelectionModel RenderTextWin::FirstSelectionModelInsideRun( |
484 internal::TextRun* run) const { | 497 internal::TextRun* run) { |
485 size_t caret = run->range.start(); | 498 size_t caret = run->range.start(); |
486 size_t cursor = IndexOfAdjacentGrapheme(caret, true); | 499 size_t cursor = IndexOfAdjacentGrapheme(caret, true); |
487 return SelectionModel(cursor, caret, SelectionModel::TRAILING); | 500 return SelectionModel(cursor, caret, SelectionModel::TRAILING); |
488 } | 501 } |
489 | 502 |
490 SelectionModel RenderTextWin::LastSelectionModelInsideRun( | 503 SelectionModel RenderTextWin::LastSelectionModelInsideRun( |
491 internal::TextRun* run) const { | 504 internal::TextRun* run) { |
492 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), false); | 505 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), false); |
493 return SelectionModel(caret, caret, SelectionModel::LEADING); | 506 return SelectionModel(caret, caret, SelectionModel::LEADING); |
494 } | 507 } |
495 | 508 |
496 SelectionModel RenderTextWin::LeftSelectionModel( | 509 SelectionModel RenderTextWin::LeftSelectionModel( |
497 const SelectionModel& selection) { | 510 const SelectionModel& selection) { |
498 size_t caret = selection.caret_pos(); | 511 size_t caret = selection.caret_pos(); |
499 SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); | 512 SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); |
500 size_t run_index = GetRunContainingPosition(caret); | 513 size_t run_index = GetRunContainingPosition(caret); |
501 DCHECK(run_index < runs_.size()); | 514 DCHECK(run_index < runs_.size()); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 Rect r(GetUpdatedCursorBounds()); | 662 Rect r(GetUpdatedCursorBounds()); |
650 canvas->DrawRectInt(kCursorColor, r.x(), r.y(), r.width(), r.height()); | 663 canvas->DrawRectInt(kCursorColor, r.x(), r.y(), r.width(), r.height()); |
651 } | 664 } |
652 } | 665 } |
653 | 666 |
654 RenderText* RenderText::CreateRenderText() { | 667 RenderText* RenderText::CreateRenderText() { |
655 return new RenderTextWin; | 668 return new RenderTextWin; |
656 } | 669 } |
657 | 670 |
658 } // namespace gfx | 671 } // namespace gfx |
OLD | NEW |