| 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 |