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