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/logging.h" | 11 #include "base/logging.h" |
11 #include "base/string_split.h" | 12 #include "base/string_split.h" |
12 #include "base/string_util.h" | 13 #include "base/string_util.h" |
13 #include "base/threading/thread_restrictions.h" | 14 #include "base/threading/thread_restrictions.h" |
14 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
15 #include "base/win/registry.h" | 16 #include "base/win/registry.h" |
16 #include "base/win/windows_version.h" | 17 #include "base/win/windows_version.h" |
17 #include "ui/gfx/canvas.h" | 18 #include "ui/gfx/canvas.h" |
18 #include "ui/gfx/font_smoothing_win.h" | 19 #include "ui/gfx/font_smoothing_win.h" |
19 #include "ui/gfx/platform_font_win.h" | 20 #include "ui/gfx/platform_font_win.h" |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 memset(&script_control_, 0, sizeof(script_control_)); | 296 memset(&script_control_, 0, sizeof(script_control_)); |
296 memset(&script_state_, 0, sizeof(script_state_)); | 297 memset(&script_state_, 0, sizeof(script_state_)); |
297 | 298 |
298 MoveCursorTo(EdgeSelectionModel(CURSOR_LEFT)); | 299 MoveCursorTo(EdgeSelectionModel(CURSOR_LEFT)); |
299 } | 300 } |
300 | 301 |
301 RenderTextWin::~RenderTextWin() { | 302 RenderTextWin::~RenderTextWin() { |
302 } | 303 } |
303 | 304 |
304 base::i18n::TextDirection RenderTextWin::GetTextDirection() { | 305 base::i18n::TextDirection RenderTextWin::GetTextDirection() { |
305 // TODO(benrg): Code moved from RenderText::GetTextDirection. Needs to be | 306 EnsureLayout(); |
306 // replaced by a correct Windows implementation. | 307 return (script_state_.uBidiLevel == 0) ? |
307 if (base::i18n::IsRTL()) | 308 base::i18n::LEFT_TO_RIGHT : base::i18n::RIGHT_TO_LEFT; |
308 return base::i18n::RIGHT_TO_LEFT; | |
309 return base::i18n::LEFT_TO_RIGHT; | |
310 } | 309 } |
311 | 310 |
312 Size RenderTextWin::GetStringSize() { | 311 Size RenderTextWin::GetStringSize() { |
313 EnsureLayout(); | 312 EnsureLayout(); |
314 return string_size_; | 313 return string_size_; |
315 } | 314 } |
316 | 315 |
317 int RenderTextWin::GetBaseline() { | 316 int RenderTextWin::GetBaseline() { |
318 EnsureLayout(); | 317 EnsureLayout(); |
319 return common_baseline_; | 318 return common_baseline_; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 | 357 |
359 return spans; | 358 return spans; |
360 } | 359 } |
361 | 360 |
362 SelectionModel RenderTextWin::AdjacentCharSelectionModel( | 361 SelectionModel RenderTextWin::AdjacentCharSelectionModel( |
363 const SelectionModel& selection, | 362 const SelectionModel& selection, |
364 VisualCursorDirection direction) { | 363 VisualCursorDirection direction) { |
365 DCHECK(!needs_layout_); | 364 DCHECK(!needs_layout_); |
366 internal::TextRun* run; | 365 internal::TextRun* run; |
367 size_t run_index = GetRunContainingCaret(selection); | 366 size_t run_index = GetRunContainingCaret(selection); |
368 if (run_index == runs_.size()) { | 367 if (run_index >= runs_.size()) { |
369 // The cursor is not in any run: we're at the visual and logical edge. | 368 // The cursor is not in any run: we're at the visual and logical edge. |
370 SelectionModel edge = EdgeSelectionModel(direction); | 369 SelectionModel edge = EdgeSelectionModel(direction); |
371 if (edge.caret_pos() == selection.caret_pos()) | 370 if (edge.caret_pos() == selection.caret_pos()) |
372 return edge; | 371 return edge; |
373 run = direction == CURSOR_RIGHT ? runs_.front() : runs_.back(); | 372 int visual_index = (direction == CURSOR_RIGHT) ? 0 : runs_.size() - 1; |
| 373 run = runs_[visual_to_logical_[visual_index]]; |
374 } else { | 374 } else { |
375 // If the cursor is moving within the current run, just move it by one | 375 // If the cursor is moving within the current run, just move it by one |
376 // grapheme in the appropriate direction. | 376 // grapheme in the appropriate direction. |
377 run = runs_[run_index]; | 377 run = runs_[run_index]; |
378 size_t caret = selection.caret_pos(); | 378 size_t caret = selection.caret_pos(); |
379 bool forward_motion = | 379 bool forward_motion = |
380 run->script_analysis.fRTL == (direction == CURSOR_LEFT); | 380 run->script_analysis.fRTL == (direction == CURSOR_LEFT); |
381 if (forward_motion) { | 381 if (forward_motion) { |
382 if (caret < run->range.end()) { | 382 if (caret < run->range.end()) { |
383 caret = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD); | 383 caret = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD); |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 renderer.DrawDecorations(x, y, run->width, style); | 589 renderer.DrawDecorations(x, y, run->width, style); |
590 | 590 |
591 x = glyph_x; | 591 x = glyph_x; |
592 } | 592 } |
593 } | 593 } |
594 | 594 |
595 void RenderTextWin::ItemizeLogicalText() { | 595 void RenderTextWin::ItemizeLogicalText() { |
596 runs_.reset(); | 596 runs_.reset(); |
597 string_size_ = Size(0, GetFont().GetHeight()); | 597 string_size_ = Size(0, GetFont().GetHeight()); |
598 common_baseline_ = 0; | 598 common_baseline_ = 0; |
| 599 |
| 600 // Use the first strong character direction as the base text direction. |
| 601 // TODO(msw): Use the application text direction instead of LTR by default? |
| 602 script_state_.uBidiLevel = |
| 603 (base::i18n::GetFirstStrongCharacterDirection(text()) == |
| 604 base::i18n::RIGHT_TO_LEFT) ? 1 : 0; |
| 605 |
599 if (text().empty()) | 606 if (text().empty()) |
600 return; | 607 return; |
601 | 608 |
602 const wchar_t* raw_text = text().c_str(); | 609 const wchar_t* raw_text = text().c_str(); |
603 const int text_length = text().length(); | 610 const int text_length = text().length(); |
604 | 611 |
605 HRESULT hr = E_OUTOFMEMORY; | 612 HRESULT hr = E_OUTOFMEMORY; |
606 int script_items_count = 0; | 613 int script_items_count = 0; |
607 std::vector<SCRIPT_ITEM> script_items; | 614 std::vector<SCRIPT_ITEM> script_items; |
608 for (size_t n = kGuessItems; hr == E_OUTOFMEMORY && n < kMaxItems; n *= 2) { | 615 for (size_t n = kGuessItems; hr == E_OUTOFMEMORY && n < kMaxItems; n *= 2) { |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
909 const internal::TextRun* run) { | 916 const internal::TextRun* run) { |
910 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), CURSOR_BACKWARD); | 917 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), CURSOR_BACKWARD); |
911 return SelectionModel(caret, CURSOR_FORWARD); | 918 return SelectionModel(caret, CURSOR_FORWARD); |
912 } | 919 } |
913 | 920 |
914 RenderText* RenderText::CreateRenderText() { | 921 RenderText* RenderText::CreateRenderText() { |
915 return new RenderTextWin; | 922 return new RenderTextWin; |
916 } | 923 } |
917 | 924 |
918 } // namespace gfx | 925 } // namespace gfx |
OLD | NEW |