| 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 <limits> | 7 #include <limits> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/i18n/bidi_line_iterator.h" | 10 #include "base/i18n/bidi_line_iterator.h" |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 hb_font_make_immutable(harfbuzz_font); | 296 hb_font_make_immutable(harfbuzz_font); |
| 297 return harfbuzz_font; | 297 return harfbuzz_font; |
| 298 } | 298 } |
| 299 | 299 |
| 300 // Returns true if characters of |block_code| may trigger font fallback. | 300 // Returns true if characters of |block_code| may trigger font fallback. |
| 301 bool IsUnusualBlockCode(UBlockCode block_code) { | 301 bool IsUnusualBlockCode(UBlockCode block_code) { |
| 302 return block_code == UBLOCK_GEOMETRIC_SHAPES || | 302 return block_code == UBLOCK_GEOMETRIC_SHAPES || |
| 303 block_code == UBLOCK_MISCELLANEOUS_SYMBOLS; | 303 block_code == UBLOCK_MISCELLANEOUS_SYMBOLS; |
| 304 } | 304 } |
| 305 | 305 |
| 306 // Returns the index of the first unusual character after a usual character or | 306 bool IsBracket(UChar32 character) { |
| 307 // vice versa. Unusual characters are defined by |IsUnusualBlockCode|. | 307 static const char kBrackets[] = { '(', ')', '{', '}', '<', '>', }; |
| 308 size_t FindUnusualCharacter(const base::string16& text, | 308 static const char* kBracketsEnd = kBrackets + arraysize(kBrackets); |
| 309 size_t run_start, | 309 return std::find(kBrackets, kBracketsEnd, character) != kBracketsEnd; |
| 310 size_t run_break) { | 310 } |
| 311 |
| 312 // Returns the boundary between a special and a regular character. Special |
| 313 // characters are brackets or characters that satisfy |IsUnusualBlockCode|. |
| 314 size_t FindRunBreakingCharacter(const base::string16& text, |
| 315 size_t run_start, |
| 316 size_t run_break) { |
| 311 const int32 run_length = static_cast<int32>(run_break - run_start); | 317 const int32 run_length = static_cast<int32>(run_break - run_start); |
| 312 base::i18n::UTF16CharIterator iter(text.c_str() + run_start, | 318 base::i18n::UTF16CharIterator iter(text.c_str() + run_start, run_length); |
| 313 run_length); | 319 const UChar32 first_char = iter.get(); |
| 314 const UBlockCode first_block_code = ublock_getCode(iter.get()); | 320 const UBlockCode first_block = ublock_getCode(first_char); |
| 315 const bool first_block_unusual = IsUnusualBlockCode(first_block_code); | 321 const bool first_block_unusual = IsUnusualBlockCode(first_block); |
| 322 const bool first_bracket = IsBracket(first_char); |
| 323 |
| 316 while (iter.Advance() && iter.array_pos() < run_length) { | 324 while (iter.Advance() && iter.array_pos() < run_length) { |
| 317 const UBlockCode current_block_code = ublock_getCode(iter.get()); | 325 const UChar32 current_char = iter.get(); |
| 318 if (current_block_code != first_block_code && | 326 const UBlockCode current_block = ublock_getCode(current_char); |
| 319 (first_block_unusual || IsUnusualBlockCode(current_block_code))) { | 327 const bool block_break = current_block != first_block && |
| 328 (first_block_unusual || IsUnusualBlockCode(current_block)); |
| 329 if (block_break || first_bracket != IsBracket(current_char)) |
| 320 return run_start + iter.array_pos(); | 330 return run_start + iter.array_pos(); |
| 321 } | |
| 322 } | 331 } |
| 323 return run_break; | 332 return run_break; |
| 324 } | 333 } |
| 325 | 334 |
| 326 // If the given scripts match, returns the one that isn't USCRIPT_COMMON or | 335 // If the given scripts match, returns the one that isn't USCRIPT_COMMON or |
| 327 // USCRIPT_INHERITED, i.e. the more specific one. Otherwise returns | 336 // USCRIPT_INHERITED, i.e. the more specific one. Otherwise returns |
| 328 // USCRIPT_INVALID_CODE. | 337 // USCRIPT_INVALID_CODE. |
| 329 UScriptCode ScriptIntersect(UScriptCode first, UScriptCode second) { | 338 UScriptCode ScriptIntersect(UScriptCode first, UScriptCode second) { |
| 330 if (first == second || | 339 if (first == second || |
| 331 (second > USCRIPT_INVALID_CODE && second <= USCRIPT_INHERITED)) { | 340 (second > USCRIPT_INVALID_CODE && second <= USCRIPT_INHERITED)) { |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 if (offset < end) { | 609 if (offset < end) { |
| 601 return SelectionModel(LayoutIndexToTextIndex( | 610 return SelectionModel(LayoutIndexToTextIndex( |
| 602 run.glyph_to_char[i] + (run.is_rtl ? 0 : 1)), | 611 run.glyph_to_char[i] + (run.is_rtl ? 0 : 1)), |
| 603 (run.is_rtl ? CURSOR_FORWARD : CURSOR_BACKWARD)); | 612 (run.is_rtl ? CURSOR_FORWARD : CURSOR_BACKWARD)); |
| 604 } | 613 } |
| 605 } | 614 } |
| 606 return EdgeSelectionModel(CURSOR_RIGHT); | 615 return EdgeSelectionModel(CURSOR_RIGHT); |
| 607 } | 616 } |
| 608 | 617 |
| 609 std::vector<RenderText::FontSpan> RenderTextHarfBuzz::GetFontSpansForTesting() { | 618 std::vector<RenderText::FontSpan> RenderTextHarfBuzz::GetFontSpansForTesting() { |
| 610 NOTIMPLEMENTED(); | 619 EnsureLayout(); |
| 611 return std::vector<RenderText::FontSpan>(); | 620 |
| 621 std::vector<RenderText::FontSpan> spans; |
| 622 for (size_t i = 0; i < runs_.size(); ++i) { |
| 623 SkString family_name; |
| 624 runs_[i]->skia_face->getFamilyName(&family_name); |
| 625 Font font(family_name.c_str(), runs_[i]->font_size); |
| 626 spans.push_back(RenderText::FontSpan(font, |
| 627 Range(LayoutIndexToTextIndex(runs_[i]->range.start()), |
| 628 LayoutIndexToTextIndex(runs_[i]->range.end())))); |
| 629 } |
| 630 |
| 631 return spans; |
| 612 } | 632 } |
| 613 | 633 |
| 614 Range RenderTextHarfBuzz::GetGlyphBounds(size_t index) { | 634 Range RenderTextHarfBuzz::GetGlyphBounds(size_t index) { |
| 615 EnsureLayout(); | 635 EnsureLayout(); |
| 616 const size_t run_index = | 636 const size_t run_index = |
| 617 GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD)); | 637 GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD)); |
| 618 // Return edge bounds if the index is invalid or beyond the layout text size. | 638 // Return edge bounds if the index is invalid or beyond the layout text size. |
| 619 if (run_index >= runs_.size()) | 639 if (run_index >= runs_.size()) |
| 620 return Range(GetStringSize().width()); | 640 return Range(GetStringSize().width()); |
| 621 const size_t layout_index = TextIndexToLayoutIndex(index); | 641 const size_t layout_index = TextIndexToLayoutIndex(index); |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 // Odd BiDi embedding levels correspond to RTL runs. | 1030 // Odd BiDi embedding levels correspond to RTL runs. |
| 1011 run->is_rtl = (run->level % 2) == 1; | 1031 run->is_rtl = (run->level % 2) == 1; |
| 1012 // Find the length and script of this script run. | 1032 // Find the length and script of this script run. |
| 1013 script_item_break = ScriptInterval(text, run_break, | 1033 script_item_break = ScriptInterval(text, run_break, |
| 1014 script_item_break - run_break, &run->script) + run_break; | 1034 script_item_break - run_break, &run->script) + run_break; |
| 1015 | 1035 |
| 1016 // Find the next break and advance the iterators as needed. | 1036 // Find the next break and advance the iterators as needed. |
| 1017 run_break = std::min(static_cast<size_t>(script_item_break), | 1037 run_break = std::min(static_cast<size_t>(script_item_break), |
| 1018 TextIndexToLayoutIndex(style.GetRange().end())); | 1038 TextIndexToLayoutIndex(style.GetRange().end())); |
| 1019 | 1039 |
| 1020 // Break runs adjacent to character substrings in certain code blocks. | 1040 // Break runs at certain characters that need to be rendered separately to |
| 1021 // This avoids using their fallback fonts for more characters than needed, | 1041 // prevent either an unusual character from forcing a fallback font on the |
| 1022 // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913 | 1042 // entire run, or brackets from being affected by a fallback font. |
| 1043 // http://crbug.com/278913, http://crbug.com/396776 |
| 1023 if (run_break > run->range.start()) | 1044 if (run_break > run->range.start()) |
| 1024 run_break = FindUnusualCharacter(text, run->range.start(), run_break); | 1045 run_break = FindRunBreakingCharacter(text, run->range.start(), run_break); |
| 1025 | 1046 |
| 1026 DCHECK(IsValidCodePointIndex(text, run_break)); | 1047 DCHECK(IsValidCodePointIndex(text, run_break)); |
| 1027 style.UpdatePosition(LayoutIndexToTextIndex(run_break)); | 1048 style.UpdatePosition(LayoutIndexToTextIndex(run_break)); |
| 1028 run->range.set_end(run_break); | 1049 run->range.set_end(run_break); |
| 1029 | 1050 |
| 1030 runs_.push_back(run); | 1051 runs_.push_back(run); |
| 1031 } | 1052 } |
| 1032 | 1053 |
| 1033 // Undo the temporarily applied composition underlines and selection colors. | 1054 // Undo the temporarily applied composition underlines and selection colors. |
| 1034 UndoCompositionAndSelectionStyles(); | 1055 UndoCompositionAndSelectionStyles(); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 run->width = std::floor(run->width + 0.5f); | 1181 run->width = std::floor(run->width + 0.5f); |
| 1161 #endif | 1182 #endif |
| 1162 } | 1183 } |
| 1163 | 1184 |
| 1164 hb_buffer_destroy(buffer); | 1185 hb_buffer_destroy(buffer); |
| 1165 hb_font_destroy(harfbuzz_font); | 1186 hb_font_destroy(harfbuzz_font); |
| 1166 return true; | 1187 return true; |
| 1167 } | 1188 } |
| 1168 | 1189 |
| 1169 } // namespace gfx | 1190 } // namespace gfx |
| OLD | NEW |