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

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: 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') | ui/gfx/render_text_unittest.cc » ('J')
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 // Returns the boundary between a special and a regular character. Special
307 // vice versa. Unusual characters are defined by |IsUnusualBlockCode|. 307 // characters are brackets or characters that satisfy |IsUnusualBlockCode|.
308 size_t FindUnusualCharacter(const base::string16& text, 308 size_t FindRunBreakingCharacter(const base::string16& text,
309 size_t run_start, 309 size_t run_start,
310 size_t run_break) { 310 size_t run_break) {
311 static const char kBrackets[] = { '(', ')', '{', '}', '<', '>' };
msw 2014/09/02 18:20:25 nit: add a comma after the last element.
ckocagil 2014/09/03 01:22:29 Done.
312 static const char* kBrackets_end = kBrackets + arraysize(kBrackets);
msw 2014/09/02 18:20:25 nit: kBracketsEnd.
ckocagil 2014/09/03 01:22:29 Done.
311 const int32 run_length = static_cast<int32>(run_break - run_start); 313 const int32 run_length = static_cast<int32>(run_break - run_start);
312 base::i18n::UTF16CharIterator iter(text.c_str() + run_start, 314 base::i18n::UTF16CharIterator iter(text.c_str() + run_start,
313 run_length); 315 run_length);
314 const UBlockCode first_block_code = ublock_getCode(iter.get()); 316 const UChar32 first_char = iter.get();
315 const bool first_block_unusual = IsUnusualBlockCode(first_block_code); 317 const UBlockCode first_block = ublock_getCode(first_char);
318 const bool first_parenthesis =
msw 2014/09/02 18:20:25 nit: |first_bracket| to match |kBrackets|; ditto f
ckocagil 2014/09/03 01:22:29 Done.
319 std::find(kBrackets, kBrackets_end, first_char) != kBrackets_end;
msw 2014/09/02 18:20:25 How about adding a helper function IsBracket[Chara
ckocagil 2014/09/03 01:22:29 Done.
320 const bool first_block_unusual = IsUnusualBlockCode(first_block);
321
316 while (iter.Advance() && iter.array_pos() < run_length) { 322 while (iter.Advance() && iter.array_pos() < run_length) {
317 const UBlockCode current_block_code = ublock_getCode(iter.get()); 323 const UChar32 current_char = iter.get();
318 if (current_block_code != first_block_code && 324 const UBlockCode current_block = ublock_getCode(current_char);
319 (first_block_unusual || IsUnusualBlockCode(current_block_code))) { 325 const bool current_parenthesis =
326 std::find(kBrackets, kBrackets_end, current_char) != kBrackets_end;
327 const bool block_break = current_block != first_block &&
328 (first_block_unusual || IsUnusualBlockCode(current_block));
329 if (block_break || first_parenthesis != current_parenthesis)
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 // This is a workaround until we can do partial font fallback in runs. Break
msw 2014/09/02 18:20:25 I'm not sure we'll want to do partial font fallbac
ckocagil 2014/09/03 01:22:29 I'd like to go ahead and implement partial font fa
1021 // This avoids using their fallback fonts for more characters than needed, 1041 // runs at certain characters that need to be rendered separately to prevent
1022 // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913 1042 // either an unusual character from forcing a fallback on the entire run,
msw 2014/09/02 18:20:25 nit: "fallback font" here and below.
ckocagil 2014/09/03 01:22:29 Done.
1043 // or brackets from being affected by a fallback.
1044 // http://crbug.com/278913, http://crbug.com/396776
1023 if (run_break > run->range.start()) 1045 if (run_break > run->range.start())
1024 run_break = FindUnusualCharacter(text, run->range.start(), run_break); 1046 run_break = FindRunBreakingCharacter(text, run->range.start(), run_break);
1025 1047
1026 DCHECK(IsValidCodePointIndex(text, run_break)); 1048 DCHECK(IsValidCodePointIndex(text, run_break));
1027 style.UpdatePosition(LayoutIndexToTextIndex(run_break)); 1049 style.UpdatePosition(LayoutIndexToTextIndex(run_break));
1028 run->range.set_end(run_break); 1050 run->range.set_end(run_break);
1029 1051
1030 runs_.push_back(run); 1052 runs_.push_back(run);
1031 } 1053 }
1032 1054
1033 // Undo the temporarily applied composition underlines and selection colors. 1055 // Undo the temporarily applied composition underlines and selection colors.
1034 UndoCompositionAndSelectionStyles(); 1056 UndoCompositionAndSelectionStyles();
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 run->width = std::floor(run->width + 0.5f); 1182 run->width = std::floor(run->width + 0.5f);
1161 #endif 1183 #endif
1162 } 1184 }
1163 1185
1164 hb_buffer_destroy(buffer); 1186 hb_buffer_destroy(buffer);
1165 hb_font_destroy(harfbuzz_font); 1187 hb_font_destroy(harfbuzz_font);
1166 return true; 1188 return true;
1167 } 1189 }
1168 1190
1169 } // namespace gfx 1191 } // namespace gfx
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/render_text_unittest.cc » ('j') | ui/gfx/render_text_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698