| 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/char_iterator.h" | 10 #include "base/i18n/char_iterator.h" |
| 11 #include "base/i18n/rtl.h" | 11 #include "base/i18n/rtl.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "base/win/windows_version.h" | 15 #include "base/win/windows_version.h" |
| 16 #include "third_party/icu/source/common/unicode/uchar.h" | 16 #include "third_party/icu/source/common/unicode/uchar.h" |
| 17 #include "ui/base/text/utf16_indexing.h" | |
| 18 #include "ui/gfx/canvas.h" | 17 #include "ui/gfx/canvas.h" |
| 19 #include "ui/gfx/font_fallback_win.h" | 18 #include "ui/gfx/font_fallback_win.h" |
| 20 #include "ui/gfx/font_smoothing_win.h" | 19 #include "ui/gfx/font_smoothing_win.h" |
| 21 #include "ui/gfx/platform_font_win.h" | 20 #include "ui/gfx/platform_font_win.h" |
| 21 #include "ui/gfx/utf16_indexing.h" |
| 22 | 22 |
| 23 namespace gfx { | 23 namespace gfx { |
| 24 | 24 |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 // The maximum length of text supported for Uniscribe layout and display. | 27 // The maximum length of text supported for Uniscribe layout and display. |
| 28 // This empirically chosen value should prevent major performance degradations. | 28 // This empirically chosen value should prevent major performance degradations. |
| 29 // TODO(msw): Support longer text, partial layout/painting, etc. | 29 // TODO(msw): Support longer text, partial layout/painting, etc. |
| 30 const size_t kMaxUniscribeTextLength = 10000; | 30 const size_t kMaxUniscribeTextLength = 10000; |
| 31 | 31 |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 bounds.pop_back(); | 406 bounds.pop_back(); |
| 407 } | 407 } |
| 408 bounds.push_back(rect); | 408 bounds.push_back(rect); |
| 409 } | 409 } |
| 410 } | 410 } |
| 411 return bounds; | 411 return bounds; |
| 412 } | 412 } |
| 413 | 413 |
| 414 size_t RenderTextWin::TextIndexToLayoutIndex(size_t index) const { | 414 size_t RenderTextWin::TextIndexToLayoutIndex(size_t index) const { |
| 415 DCHECK_LE(index, text().length()); | 415 DCHECK_LE(index, text().length()); |
| 416 ptrdiff_t i = obscured() ? ui::UTF16IndexToOffset(text(), 0, index) : index; | 416 ptrdiff_t i = obscured() ? gfx::UTF16IndexToOffset(text(), 0, index) : index; |
| 417 CHECK_GE(i, 0); | 417 CHECK_GE(i, 0); |
| 418 // Clamp layout indices to the length of the text actually used for layout. | 418 // Clamp layout indices to the length of the text actually used for layout. |
| 419 return std::min<size_t>(GetLayoutText().length(), i); | 419 return std::min<size_t>(GetLayoutText().length(), i); |
| 420 } | 420 } |
| 421 | 421 |
| 422 size_t RenderTextWin::LayoutIndexToTextIndex(size_t index) const { | 422 size_t RenderTextWin::LayoutIndexToTextIndex(size_t index) const { |
| 423 if (!obscured()) | 423 if (!obscured()) |
| 424 return index; | 424 return index; |
| 425 | 425 |
| 426 DCHECK_LE(index, GetLayoutText().length()); | 426 DCHECK_LE(index, GetLayoutText().length()); |
| 427 const size_t text_index = ui::UTF16OffsetToIndex(text(), 0, index); | 427 const size_t text_index = gfx::UTF16OffsetToIndex(text(), 0, index); |
| 428 DCHECK_LE(text_index, text().length()); | 428 DCHECK_LE(text_index, text().length()); |
| 429 return text_index; | 429 return text_index; |
| 430 } | 430 } |
| 431 | 431 |
| 432 bool RenderTextWin::IsCursorablePosition(size_t position) { | 432 bool RenderTextWin::IsCursorablePosition(size_t position) { |
| 433 if (position == 0 || position == text().length()) | 433 if (position == 0 || position == text().length()) |
| 434 return true; | 434 return true; |
| 435 EnsureLayout(); | 435 EnsureLayout(); |
| 436 | 436 |
| 437 // Check that the index is at a valid code point (not mid-surrgate-pair), | 437 // Check that the index is at a valid code point (not mid-surrgate-pair), |
| 438 // that it is not truncated from layout text (its glyph is shown on screen), | 438 // that it is not truncated from layout text (its glyph is shown on screen), |
| 439 // and that its glyph has distinct bounds (not mid-multi-character-grapheme). | 439 // and that its glyph has distinct bounds (not mid-multi-character-grapheme). |
| 440 // An example of a multi-character-grapheme that is not a surrogate-pair is: | 440 // An example of a multi-character-grapheme that is not a surrogate-pair is: |
| 441 // \x0915\x093f - (ki) - one of many Devanagari biconsonantal conjuncts. | 441 // \x0915\x093f - (ki) - one of many Devanagari biconsonantal conjuncts. |
| 442 return ui::IsValidCodePointIndex(text(), position) && | 442 return gfx::IsValidCodePointIndex(text(), position) && |
| 443 position < LayoutIndexToTextIndex(GetLayoutText().length()) && | 443 position < LayoutIndexToTextIndex(GetLayoutText().length()) && |
| 444 GetGlyphBounds(position) != GetGlyphBounds(position - 1); | 444 GetGlyphBounds(position) != GetGlyphBounds(position - 1); |
| 445 } | 445 } |
| 446 | 446 |
| 447 void RenderTextWin::ResetLayout() { | 447 void RenderTextWin::ResetLayout() { |
| 448 // Layout is performed lazily as needed for drawing/metrics. | 448 // Layout is performed lazily as needed for drawing/metrics. |
| 449 needs_layout_ = true; | 449 needs_layout_ = true; |
| 450 } | 450 } |
| 451 | 451 |
| 452 void RenderTextWin::EnsureLayout() { | 452 void RenderTextWin::EnsureLayout() { |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 run->script_analysis = script_item->a; | 592 run->script_analysis = script_item->a; |
| 593 | 593 |
| 594 // Find the next break and advance the iterators as needed. | 594 // Find the next break and advance the iterators as needed. |
| 595 const size_t script_item_break = (script_item + 1)->iCharPos; | 595 const size_t script_item_break = (script_item + 1)->iCharPos; |
| 596 run_break = std::min(script_item_break, | 596 run_break = std::min(script_item_break, |
| 597 TextIndexToLayoutIndex(style.GetRange().end())); | 597 TextIndexToLayoutIndex(style.GetRange().end())); |
| 598 | 598 |
| 599 // Clamp run lengths to avoid exceeding the maximum supported glyph count. | 599 // Clamp run lengths to avoid exceeding the maximum supported glyph count. |
| 600 if ((run_break - run->range.start()) > max_run_length) { | 600 if ((run_break - run->range.start()) > max_run_length) { |
| 601 run_break = run->range.start() + max_run_length; | 601 run_break = run->range.start() + max_run_length; |
| 602 if (!ui::IsValidCodePointIndex(layout_text, run_break)) | 602 if (!gfx::IsValidCodePointIndex(layout_text, run_break)) |
| 603 --run_break; | 603 --run_break; |
| 604 } | 604 } |
| 605 | 605 |
| 606 // Break runs between characters in different code blocks. This avoids using | 606 // Break runs between characters in different code blocks. This avoids using |
| 607 // fallback fonts for more characters than needed. http://crbug.com/278913 | 607 // fallback fonts for more characters than needed. http://crbug.com/278913 |
| 608 if (run_break > run->range.start()) { | 608 if (run_break > run->range.start()) { |
| 609 const size_t run_start = run->range.start(); | 609 const size_t run_start = run->range.start(); |
| 610 const int32 run_length = static_cast<int32>(run_break - run_start); | 610 const int32 run_length = static_cast<int32>(run_break - run_start); |
| 611 base::i18n::UTF16CharIterator iter(layout_text.c_str() + run_start, | 611 base::i18n::UTF16CharIterator iter(layout_text.c_str() + run_start, |
| 612 run_length); | 612 run_length); |
| 613 const UBlockCode first_block_code = ublock_getCode(iter.get()); | 613 const UBlockCode first_block_code = ublock_getCode(iter.get()); |
| 614 while (iter.Advance() && iter.array_pos() < run_length) { | 614 while (iter.Advance() && iter.array_pos() < run_length) { |
| 615 if (ublock_getCode(iter.get()) != first_block_code) { | 615 if (ublock_getCode(iter.get()) != first_block_code) { |
| 616 run_break = run_start + iter.array_pos(); | 616 run_break = run_start + iter.array_pos(); |
| 617 break; | 617 break; |
| 618 } | 618 } |
| 619 } | 619 } |
| 620 } | 620 } |
| 621 | 621 |
| 622 DCHECK(ui::IsValidCodePointIndex(layout_text, run_break)); | 622 DCHECK(gfx::IsValidCodePointIndex(layout_text, run_break)); |
| 623 | 623 |
| 624 style.UpdatePosition(LayoutIndexToTextIndex(run_break)); | 624 style.UpdatePosition(LayoutIndexToTextIndex(run_break)); |
| 625 if (script_item_break == run_break) | 625 if (script_item_break == run_break) |
| 626 script_item++; | 626 script_item++; |
| 627 run->range.set_end(run_break); | 627 run->range.set_end(run_break); |
| 628 runs_.push_back(run); | 628 runs_.push_back(run); |
| 629 } | 629 } |
| 630 | 630 |
| 631 // Undo the temporarily applied composition underlines and selection colors. | 631 // Undo the temporarily applied composition underlines and selection colors. |
| 632 UndoCompositionAndSelectionStyles(); | 632 UndoCompositionAndSelectionStyles(); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 size_t position = LayoutIndexToTextIndex(run->range.end()); | 922 size_t position = LayoutIndexToTextIndex(run->range.end()); |
| 923 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); | 923 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); |
| 924 return SelectionModel(position, CURSOR_FORWARD); | 924 return SelectionModel(position, CURSOR_FORWARD); |
| 925 } | 925 } |
| 926 | 926 |
| 927 RenderText* RenderText::CreateInstance() { | 927 RenderText* RenderText::CreateInstance() { |
| 928 return new RenderTextWin; | 928 return new RenderTextWin; |
| 929 } | 929 } |
| 930 | 930 |
| 931 } // namespace gfx | 931 } // namespace gfx |
| OLD | NEW |