Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: ui/gfx/render_text_harfbuzz.cc

Issue 522343002: RenderTextHarfBuzz: Break runs at parentheses so they aren't affected by font fallbacks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments addressed Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ui/gfx/render_text_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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_bracket = IsBracket(first_char);
msw 2014/09/03 18:14:58 nit: order this before or after the |first_block[_
322 const bool first_block_unusual = IsUnusualBlockCode(first_block);
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/render_text_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698