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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 size_t RenderTextWin::GetRunContainingPoint(const Point& point) const { | 473 size_t RenderTextWin::GetRunContainingPoint(const Point& point) const { |
443 // Find the text run containing the argument point (assumed already offset). | 474 // Find the text run containing the argument point (assumed already offset). |
444 size_t run = 0; | 475 size_t run = 0; |
445 for (; run < runs_.size(); ++run) | 476 for (; run < runs_.size(); ++run) |
446 if (runs_[run]->preceding_run_widths <= point.x() && | 477 if (runs_[run]->preceding_run_widths <= point.x() && |
447 runs_[run]->preceding_run_widths + runs_[run]->width > point.x()) | 478 runs_[run]->preceding_run_widths + runs_[run]->width > point.x()) |
448 break; | 479 break; |
449 return run; | 480 return run; |
450 } | 481 } |
451 | 482 |
452 size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) const { | |
453 size_t run_index = GetRunContainingPosition(index); | |
454 internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL; | |
455 long start = run ? run->range.start() : 0; | |
456 long length = run ? run->range.length() : text().length(); | |
457 long ch = index - start; | |
458 WORD cluster = run ? run->logical_clusters[ch] : 0; | |
459 | |
460 if (!next) { | |
461 do { | |
462 ch--; | |
463 } while (ch >= 0 && run && run->logical_clusters[ch] == cluster); | |
464 } else { | |
465 while (ch < length && run && run->logical_clusters[ch] == cluster) | |
466 ch++; | |
467 } | |
468 return std::max(static_cast<long>(std::min(ch, length) + start), 0L); | |
469 } | |
470 | 483 |
471 SelectionModel RenderTextWin::FirstSelectionModelInsideRun( | 484 SelectionModel RenderTextWin::FirstSelectionModelInsideRun( |
472 internal::TextRun* run) const { | 485 internal::TextRun* run) { |
473 size_t caret = run->range.start(); | 486 size_t caret = run->range.start(); |
474 size_t cursor = IndexOfAdjacentGrapheme(caret, true); | 487 size_t cursor = IndexOfAdjacentGrapheme(caret, true); |
475 return SelectionModel(cursor, caret, SelectionModel::TRAILING); | 488 return SelectionModel(cursor, caret, SelectionModel::TRAILING); |
476 } | 489 } |
477 | 490 |
478 SelectionModel RenderTextWin::LastSelectionModelInsideRun( | 491 SelectionModel RenderTextWin::LastSelectionModelInsideRun( |
479 internal::TextRun* run) const { | 492 internal::TextRun* run) { |
480 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), false); | 493 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), false); |
481 return SelectionModel(caret, caret, SelectionModel::LEADING); | 494 return SelectionModel(caret, caret, SelectionModel::LEADING); |
482 } | 495 } |
483 | 496 |
484 SelectionModel RenderTextWin::LeftSelectionModel( | 497 SelectionModel RenderTextWin::LeftSelectionModel( |
485 const SelectionModel& selection) { | 498 const SelectionModel& selection) { |
486 size_t caret = selection.caret_pos(); | 499 size_t caret = selection.caret_pos(); |
487 SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); | 500 SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); |
488 size_t run_index = GetRunContainingPosition(caret); | 501 size_t run_index = GetRunContainingPosition(caret); |
489 DCHECK(run_index < runs_.size()); | 502 DCHECK(run_index < runs_.size()); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 Rect r(GetUpdatedCursorBounds()); | 650 Rect r(GetUpdatedCursorBounds()); |
638 canvas->DrawRectInt(kCursorColor, r.x(), r.y(), r.width(), r.height()); | 651 canvas->DrawRectInt(kCursorColor, r.x(), r.y(), r.width(), r.height()); |
639 } | 652 } |
640 } | 653 } |
641 | 654 |
642 RenderText* RenderText::CreateRenderText() { | 655 RenderText* RenderText::CreateRenderText() { |
643 return new RenderTextWin; | 656 return new RenderTextWin; |
644 } | 657 } |
645 | 658 |
646 } // namespace gfx | 659 } // namespace gfx |
OLD | NEW |