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

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

Issue 435583003: RenderTextHarfBuzz: Check CreateSkiaTypeface return value against NULL (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add tests Created 6 years, 4 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 | Annotate | Revision Log
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 <map> 7 #include <map>
8 8
9 #include "base/debug/leak_annotations.h" 9 #include "base/debug/leak_annotations.h"
10 #include "base/i18n/bidi_line_iterator.h" 10 #include "base/i18n/bidi_line_iterator.h"
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 447
448 TextRunHarfBuzz::~TextRunHarfBuzz() {} 448 TextRunHarfBuzz::~TextRunHarfBuzz() {}
449 449
450 void TextRunHarfBuzz::GetClusterAt(size_t pos, 450 void TextRunHarfBuzz::GetClusterAt(size_t pos,
451 Range* chars, 451 Range* chars,
452 Range* glyphs) const { 452 Range* glyphs) const {
453 DCHECK(range.Contains(Range(pos, pos + 1))); 453 DCHECK(range.Contains(Range(pos, pos + 1)));
454 DCHECK(chars); 454 DCHECK(chars);
455 DCHECK(glyphs); 455 DCHECK(glyphs);
456 456
457 if (glyph_count == 0) {
458 *chars = range;
459 *glyphs = Range();
460 return;
461 }
462
457 if (is_rtl) { 463 if (is_rtl) {
458 GetClusterAtImpl(pos, range, glyph_to_char.rbegin(), glyph_to_char.rend(), 464 GetClusterAtImpl(pos, range, glyph_to_char.rbegin(), glyph_to_char.rend(),
459 true, chars, glyphs); 465 true, chars, glyphs);
460 return; 466 return;
461 } 467 }
462 468
463 GetClusterAtImpl(pos, range, glyph_to_char.begin(), glyph_to_char.end(), 469 GetClusterAtImpl(pos, range, glyph_to_char.begin(), glyph_to_char.end(),
464 false, chars, glyphs); 470 false, chars, glyphs);
465 } 471 }
466 472
(...skipping 17 matching lines...) Expand all
484 size_t missing = 0; 490 size_t missing = 0;
485 for (size_t i = 0; i < glyph_count; ++i) 491 for (size_t i = 0; i < glyph_count; ++i)
486 missing += (glyphs[i] == kMissingGlyphId) ? 1 : 0; 492 missing += (glyphs[i] == kMissingGlyphId) ? 1 : 0;
487 return missing; 493 return missing;
488 } 494 }
489 495
490 Range TextRunHarfBuzz::GetGraphemeBounds( 496 Range TextRunHarfBuzz::GetGraphemeBounds(
491 base::i18n::BreakIterator* grapheme_iterator, 497 base::i18n::BreakIterator* grapheme_iterator,
492 size_t text_index) { 498 size_t text_index) {
493 DCHECK_LT(text_index, range.end()); 499 DCHECK_LT(text_index, range.end());
500 if (glyph_count == 0)
501 return Range(preceding_run_widths, preceding_run_widths + width);
494 502
495 Range chars; 503 Range chars;
496 Range glyphs; 504 Range glyphs;
497 GetClusterAt(text_index, &chars, &glyphs); 505 GetClusterAt(text_index, &chars, &glyphs);
498 const int cluster_begin_x = SkScalarRoundToInt(positions[glyphs.start()].x()); 506 const int cluster_begin_x = SkScalarRoundToInt(positions[glyphs.start()].x());
499 const int cluster_end_x = glyphs.end() < glyph_count ? 507 const int cluster_end_x = glyphs.end() < glyph_count ?
500 SkScalarRoundToInt(positions[glyphs.end()].x()) : width; 508 SkScalarRoundToInt(positions[glyphs.end()].x()) : width;
501 509
502 // A cluster consists of a number of code points and corresponds to a number 510 // A cluster consists of a number of code points and corresponds to a number
503 // of glyphs that should be drawn together. A cluster can contain multiple 511 // of glyphs that should be drawn together. A cluster can contain multiple
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
1001 ubidi_reorderVisual(&levels[0], num_runs, &visual_to_logical_[0]); 1009 ubidi_reorderVisual(&levels[0], num_runs, &visual_to_logical_[0]);
1002 logical_to_visual_.resize(num_runs); 1010 logical_to_visual_.resize(num_runs);
1003 ubidi_reorderLogical(&levels[0], num_runs, &logical_to_visual_[0]); 1011 ubidi_reorderLogical(&levels[0], num_runs, &logical_to_visual_[0]);
1004 } 1012 }
1005 1013
1006 void RenderTextHarfBuzz::ShapeRun(internal::TextRunHarfBuzz* run) { 1014 void RenderTextHarfBuzz::ShapeRun(internal::TextRunHarfBuzz* run) {
1007 const Font& primary_font = font_list().GetPrimaryFont(); 1015 const Font& primary_font = font_list().GetPrimaryFont();
1008 const std::string primary_font_name = primary_font.GetFontName(); 1016 const std::string primary_font_name = primary_font.GetFontName();
1009 run->font_size = primary_font.GetFontSize(); 1017 run->font_size = primary_font.GetFontSize();
1010 1018
1019 size_t best_font_missing = std::numeric_limits<size_t>::max();
1020 std::string best_font;
1021 std::string current_font;
1022
1011 // Try shaping with |primary_font|. 1023 // Try shaping with |primary_font|.
1012 ShapeRunWithFont(run, primary_font_name); 1024 if (ShapeRunWithFont(run, primary_font_name)) {
1013 size_t best_font_missing = run->CountMissingGlyphs(); 1025 current_font = primary_font_name;
1014 if (best_font_missing == 0) 1026 size_t current_missing = run->CountMissingGlyphs();
1015 return; 1027 if (current_missing == 0)
1016 std::string best_font = primary_font_name; 1028 return;
1029 if (current_missing < best_font_missing) {
1030 best_font_missing = current_missing;
1031 best_font = primary_font_name;
msw 2014/08/02 18:05:33 nit: s/primary_font_name/current_font/
ckocagil 2014/08/03 03:36:54 Done.
1032 }
1033 }
1017 1034
1018 #if defined(OS_WIN) 1035 #if defined(OS_WIN)
1019 Font uniscribe_font; 1036 Font uniscribe_font;
1020 const base::char16* run_text = &(GetLayoutText()[run->range.start()]); 1037 const base::char16* run_text = &(GetLayoutText()[run->range.start()]);
1021 if (GetUniscribeFallbackFont(primary_font, run_text, run->range.length(), 1038 if (GetUniscribeFallbackFont(primary_font, run_text, run->range.length(),
1022 &uniscribe_font)) { 1039 &uniscribe_font) &&
1023 ShapeRunWithFont(run, uniscribe_font.GetFontName()); 1040 ShapeRunWithFont(run, uniscribe_font.GetFontName())) {
1041 current_font = uniscribe_font.GetFontName();
1024 size_t current_missing = run->CountMissingGlyphs(); 1042 size_t current_missing = run->CountMissingGlyphs();
1025 if (current_missing == 0) 1043 if (current_missing == 0)
1026 return; 1044 return;
1027 if (current_missing < best_font_missing) { 1045 if (current_missing < best_font_missing) {
1028 best_font_missing = current_missing; 1046 best_font_missing = current_missing;
1029 best_font = uniscribe_font.GetFontName(); 1047 best_font = uniscribe_font.GetFontName();
msw 2014/08/02 18:05:33 nit: s/uniscribe_font.GetFontName()/current_font/
ckocagil 2014/08/03 03:36:54 Done.
1030 } 1048 }
1031 } 1049 }
1032 #endif 1050 #endif
1033 1051
1034 // Try shaping with the fonts in the fallback list except the first, which is 1052 // Try shaping with the fonts in the fallback list except the first, which is
1035 // |primary_font|. 1053 // |primary_font|.
1036 std::vector<std::string> fonts = GetFallbackFontFamilies(primary_font_name); 1054 std::vector<std::string> fonts = GetFallbackFontFamilies(primary_font_name);
1037 for (size_t i = 1; i < fonts.size(); ++i) { 1055 for (size_t i = 1; i < fonts.size(); ++i) {
1038 ShapeRunWithFont(run, fonts[i]); 1056 if (!ShapeRunWithFont(run, fonts[i]))
1057 continue;
1058 current_font = fonts[i];
1039 size_t current_missing = run->CountMissingGlyphs(); 1059 size_t current_missing = run->CountMissingGlyphs();
1040 if (current_missing == 0) 1060 if (current_missing == 0)
1041 return; 1061 return;
1042 if (current_missing < best_font_missing) { 1062 if (current_missing < best_font_missing) {
1043 best_font_missing = current_missing; 1063 best_font_missing = current_missing;
1044 best_font = fonts[i]; 1064 best_font = fonts[i];
msw 2014/08/02 18:05:33 nit: s/fonts[i]/current_font/
ckocagil 2014/08/03 03:36:54 Done.
1045 } 1065 }
1046 } 1066 }
1047 1067
1048 ShapeRunWithFont(run, best_font); 1068 if (!best_font.empty() &&
1069 (best_font == current_font || ShapeRunWithFont(run, best_font))) {
1070 return;
1071 }
1072
1073 run->glyph_count = 0;
1074 run->width = 0;
1049 } 1075 }
1050 1076
1051 void RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run, 1077 bool RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run,
1052 const std::string& font_family) { 1078 const std::string& font_family) {
1053 const base::string16& text = GetLayoutText(); 1079 const base::string16& text = GetLayoutText();
1054 run->skia_face = internal::CreateSkiaTypeface(font_family, run->font_style); 1080 skia::RefPtr<SkTypeface> skia_face =
1081 internal::CreateSkiaTypeface(font_family, run->font_style);
1082 if (skia_face == NULL)
1083 return false;
1084 run->skia_face = skia_face;
1055 hb_font_t* harfbuzz_font = CreateHarfBuzzFont(run->skia_face.get(), 1085 hb_font_t* harfbuzz_font = CreateHarfBuzzFont(run->skia_face.get(),
1056 run->font_size); 1086 run->font_size);
1057 1087
1058 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz 1088 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz
1059 // buffer holds our text, run information to be used by the shaping engine, 1089 // buffer holds our text, run information to be used by the shaping engine,
1060 // and the resulting glyph data. 1090 // and the resulting glyph data.
1061 hb_buffer_t* buffer = hb_buffer_create(); 1091 hb_buffer_t* buffer = hb_buffer_create();
1062 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), 1092 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()),
1063 text.length(), run->range.start(), run->range.length()); 1093 text.length(), run->range.start(), run->range.length());
1064 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); 1094 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script));
(...skipping 22 matching lines...) Expand all
1087 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_offset)); 1117 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_offset));
1088 const int y_offset = 1118 const int y_offset =
1089 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].y_offset)); 1119 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].y_offset));
1090 run->positions[i].set(run->width + x_offset, -y_offset); 1120 run->positions[i].set(run->width + x_offset, -y_offset);
1091 run->width += 1121 run->width +=
1092 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_advance)); 1122 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_advance));
1093 } 1123 }
1094 1124
1095 hb_buffer_destroy(buffer); 1125 hb_buffer_destroy(buffer);
1096 hb_font_destroy(harfbuzz_font); 1126 hb_font_destroy(harfbuzz_font);
1127 return true;
1097 } 1128 }
1098 1129
1099 } // namespace gfx 1130 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698