OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_harfbuzz.h" | 5 #include "ui/gfx/render_text_harfbuzz.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/i18n/bidi_line_iterator.h" | 9 #include "base/i18n/bidi_line_iterator.h" |
10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 size_t position = LayoutIndexToTextIndex(run->range.end()); | 856 size_t position = LayoutIndexToTextIndex(run->range.end()); |
857 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); | 857 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); |
858 return SelectionModel(position, CURSOR_FORWARD); | 858 return SelectionModel(position, CURSOR_FORWARD); |
859 } | 859 } |
860 | 860 |
861 void RenderTextHarfBuzz::ItemizeText() { | 861 void RenderTextHarfBuzz::ItemizeText() { |
862 const base::string16& text = GetLayoutText(); | 862 const base::string16& text = GetLayoutText(); |
863 const bool is_text_rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; | 863 const bool is_text_rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; |
864 DCHECK_NE(0U, text.length()); | 864 DCHECK_NE(0U, text.length()); |
865 | 865 |
866 // If ICU fails to itemize the text, we create a run that spans the entire | 866 // If ICU fails to itemize the text, we set |fake_runs| and create a run that |
867 // text. This is needed because leaving the runs set empty causes some clients | 867 // spans the entire text. This is needed because early returning and leaving |
868 // to misbehave since they expect non-zero text metrics from a non-empty text. | 868 // the runs set empty causes some clients to crash/misbehave since they expect |
| 869 // non-zero text metrics from a non-empty text. |
869 base::i18n::BiDiLineIterator bidi_iterator; | 870 base::i18n::BiDiLineIterator bidi_iterator; |
870 if (!bidi_iterator.Open(text, is_text_rtl, false)) { | 871 bool fake_runs = !bidi_iterator.Open(text, is_text_rtl, false); |
871 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; | |
872 run->range = Range(0, text.length()); | |
873 runs_.push_back(run); | |
874 visual_to_logical_ = logical_to_visual_ = std::vector<int32_t>(1, 0); | |
875 return; | |
876 } | |
877 | 872 |
878 // Temporarily apply composition underlines and selection colors. | 873 // Temporarily apply composition underlines and selection colors. |
879 ApplyCompositionAndSelectionStyles(); | 874 ApplyCompositionAndSelectionStyles(); |
880 | 875 |
881 // Build the list of runs from the script items and ranged styles. Use an | 876 // Build the list of runs from the script items and ranged styles. Use an |
882 // empty color BreakList to avoid breaking runs at color boundaries. | 877 // empty color BreakList to avoid breaking runs at color boundaries. |
883 BreakList<SkColor> empty_colors; | 878 BreakList<SkColor> empty_colors; |
884 empty_colors.SetMax(text.length()); | 879 empty_colors.SetMax(text.length()); |
885 internal::StyleIterator style(empty_colors, styles()); | 880 internal::StyleIterator style(empty_colors, styles()); |
886 | 881 |
887 for (size_t run_break = 0; run_break < text.length();) { | 882 for (size_t run_break = 0; run_break < text.length();) { |
888 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; | 883 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; |
889 run->range.set_start(run_break); | 884 run->range.set_start(run_break); |
890 run->font_style = (style.style(BOLD) ? Font::BOLD : 0) | | 885 run->font_style = (style.style(BOLD) ? Font::BOLD : 0) | |
891 (style.style(ITALIC) ? Font::ITALIC : 0); | 886 (style.style(ITALIC) ? Font::ITALIC : 0); |
892 run->strike = style.style(STRIKE); | 887 run->strike = style.style(STRIKE); |
893 run->diagonal_strike = style.style(DIAGONAL_STRIKE); | 888 run->diagonal_strike = style.style(DIAGONAL_STRIKE); |
894 run->underline = style.style(UNDERLINE); | 889 run->underline = style.style(UNDERLINE); |
895 | 890 |
896 int32 script_item_break = 0; | 891 if (fake_runs) { |
897 bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); | 892 run_break = text.length(); |
898 // Odd BiDi embedding levels correspond to RTL runs. | 893 } else { |
899 run->is_rtl = (run->level % 2) == 1; | 894 int32 script_item_break = 0; |
900 // Find the length and script of this script run. | 895 bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); |
901 script_item_break = ScriptInterval(text, run_break, | 896 // Find the length and script of this script run. |
902 script_item_break - run_break, &run->script) + run_break; | 897 script_item_break = ScriptInterval(text, run_break, |
| 898 script_item_break - run_break, &run->script) + run_break; |
903 | 899 |
904 // Find the next break and advance the iterators as needed. | 900 // Find the next break and advance the iterators as needed. |
905 run_break = std::min(static_cast<size_t>(script_item_break), | 901 run_break = std::min(static_cast<size_t>(script_item_break), |
906 TextIndexToLayoutIndex(style.GetRange().end())); | 902 TextIndexToLayoutIndex(style.GetRange().end())); |
907 | 903 |
908 // Break runs adjacent to character substrings in certain code blocks. | 904 // Break runs adjacent to character substrings in certain code blocks. |
909 // This avoids using their fallback fonts for more characters than needed, | 905 // This avoids using their fallback fonts for more characters than needed, |
910 // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913 | 906 // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913 |
911 if (run_break > run->range.start()) { | 907 if (run_break > run->range.start()) { |
912 const size_t run_start = run->range.start(); | 908 const size_t run_start = run->range.start(); |
913 const int32 run_length = static_cast<int32>(run_break - run_start); | 909 const int32 run_length = static_cast<int32>(run_break - run_start); |
914 base::i18n::UTF16CharIterator iter(text.c_str() + run_start, | 910 base::i18n::UTF16CharIterator iter(text.c_str() + run_start, |
915 run_length); | 911 run_length); |
916 const UBlockCode first_block_code = ublock_getCode(iter.get()); | 912 const UBlockCode first_block_code = ublock_getCode(iter.get()); |
917 const bool first_block_unusual = IsUnusualBlockCode(first_block_code); | 913 const bool first_block_unusual = IsUnusualBlockCode(first_block_code); |
918 while (iter.Advance() && iter.array_pos() < run_length) { | 914 while (iter.Advance() && iter.array_pos() < run_length) { |
919 const UBlockCode current_block_code = ublock_getCode(iter.get()); | 915 const UBlockCode current_block_code = ublock_getCode(iter.get()); |
920 if (current_block_code != first_block_code && | 916 if (current_block_code != first_block_code && |
921 (first_block_unusual || IsUnusualBlockCode(current_block_code))) { | 917 (first_block_unusual || IsUnusualBlockCode(current_block_code))) { |
922 run_break = run_start + iter.array_pos(); | 918 run_break = run_start + iter.array_pos(); |
923 break; | 919 break; |
| 920 } |
924 } | 921 } |
925 } | 922 } |
926 } | 923 } |
927 | 924 |
928 DCHECK(IsValidCodePointIndex(text, run_break)); | 925 DCHECK(IsValidCodePointIndex(text, run_break)); |
929 style.UpdatePosition(LayoutIndexToTextIndex(run_break)); | 926 style.UpdatePosition(LayoutIndexToTextIndex(run_break)); |
930 run->range.set_end(run_break); | 927 run->range.set_end(run_break); |
931 | 928 UBiDiDirection direction = ubidi_getBaseDirection( |
| 929 text.c_str() + run->range.start(), run->range.length()); |
| 930 if (direction == UBIDI_NEUTRAL) |
| 931 run->is_rtl = is_text_rtl; |
| 932 else |
| 933 run->is_rtl = direction == UBIDI_RTL; |
932 runs_.push_back(run); | 934 runs_.push_back(run); |
933 } | 935 } |
934 | 936 |
935 // Undo the temporarily applied composition underlines and selection colors. | 937 // Undo the temporarily applied composition underlines and selection colors. |
936 UndoCompositionAndSelectionStyles(); | 938 UndoCompositionAndSelectionStyles(); |
937 | 939 |
938 const size_t num_runs = runs_.size(); | 940 const size_t num_runs = runs_.size(); |
939 std::vector<UBiDiLevel> levels(num_runs); | 941 std::vector<UBiDiLevel> levels(num_runs); |
940 for (size_t i = 0; i < num_runs; ++i) | 942 for (size_t i = 0; i < num_runs; ++i) |
941 levels[i] = runs_[i]->level; | 943 levels[i] = runs_[i]->level; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 run->positions[i].set(run->width + x_offset, y_offset); | 992 run->positions[i].set(run->width + x_offset, y_offset); |
991 run->width += | 993 run->width += |
992 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_advance)); | 994 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_advance)); |
993 } | 995 } |
994 | 996 |
995 hb_buffer_destroy(buffer); | 997 hb_buffer_destroy(buffer); |
996 hb_font_destroy(harfbuzz_font); | 998 hb_font_destroy(harfbuzz_font); |
997 } | 999 } |
998 | 1000 |
999 } // namespace gfx | 1001 } // namespace gfx |
OLD | NEW |