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 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1063 const size_t num_runs = runs_.size(); | 1063 const size_t num_runs = runs_.size(); |
1064 std::vector<UBiDiLevel> levels(num_runs); | 1064 std::vector<UBiDiLevel> levels(num_runs); |
1065 for (size_t i = 0; i < num_runs; ++i) | 1065 for (size_t i = 0; i < num_runs; ++i) |
1066 levels[i] = runs_[i]->level; | 1066 levels[i] = runs_[i]->level; |
1067 visual_to_logical_.resize(num_runs); | 1067 visual_to_logical_.resize(num_runs); |
1068 ubidi_reorderVisual(&levels[0], num_runs, &visual_to_logical_[0]); | 1068 ubidi_reorderVisual(&levels[0], num_runs, &visual_to_logical_[0]); |
1069 logical_to_visual_.resize(num_runs); | 1069 logical_to_visual_.resize(num_runs); |
1070 ubidi_reorderLogical(&levels[0], num_runs, &logical_to_visual_[0]); | 1070 ubidi_reorderLogical(&levels[0], num_runs, &logical_to_visual_[0]); |
1071 } | 1071 } |
1072 | 1072 |
| 1073 bool RenderTextHarfBuzz::CompareFamily( |
| 1074 internal::TextRunHarfBuzz* run, |
| 1075 const std::string& family, |
| 1076 const gfx::FontRenderParams& render_params, |
| 1077 std::string* best_family, |
| 1078 gfx::FontRenderParams* best_render_params, |
| 1079 size_t* best_missing_glyphs) { |
| 1080 if (!ShapeRunWithFont(run, family, render_params)) |
| 1081 return false; |
| 1082 |
| 1083 const size_t missing_glyphs = run->CountMissingGlyphs(); |
| 1084 if (missing_glyphs < *best_missing_glyphs) { |
| 1085 *best_family = family; |
| 1086 *best_render_params = render_params; |
| 1087 *best_missing_glyphs = missing_glyphs; |
| 1088 } |
| 1089 return missing_glyphs == 0; |
| 1090 } |
| 1091 |
1073 void RenderTextHarfBuzz::ShapeRun(internal::TextRunHarfBuzz* run) { | 1092 void RenderTextHarfBuzz::ShapeRun(internal::TextRunHarfBuzz* run) { |
1074 const Font& primary_font = font_list().GetPrimaryFont(); | 1093 const Font& primary_font = font_list().GetPrimaryFont(); |
1075 const std::string primary_font_name = primary_font.GetFontName(); | |
1076 run->font_size = primary_font.GetFontSize(); | 1094 run->font_size = primary_font.GetFontSize(); |
1077 | 1095 |
1078 size_t best_font_missing = std::numeric_limits<size_t>::max(); | 1096 std::string best_family; |
1079 std::string best_font; | 1097 FontRenderParams best_render_params; |
1080 std::string current_font; | 1098 size_t best_missing_glyphs = std::numeric_limits<size_t>::max(); |
1081 | 1099 |
1082 // Try shaping with |primary_font|. | 1100 if (CompareFamily(run, primary_font.GetFontName(), |
1083 if (ShapeRunWithFont(run, primary_font_name)) { | 1101 primary_font.GetFontRenderParams(), |
1084 current_font = primary_font_name; | 1102 &best_family, &best_render_params, &best_missing_glyphs)) |
1085 size_t current_missing = run->CountMissingGlyphs(); | 1103 return; |
1086 if (current_missing == 0) | |
1087 return; | |
1088 if (current_missing < best_font_missing) { | |
1089 best_font_missing = current_missing; | |
1090 best_font = current_font; | |
1091 } | |
1092 } | |
1093 | 1104 |
1094 #if defined(OS_WIN) | 1105 #if defined(OS_WIN) |
1095 Font uniscribe_font; | 1106 Font uniscribe_font; |
1096 const base::char16* run_text = &(GetLayoutText()[run->range.start()]); | 1107 const base::char16* run_text = &(GetLayoutText()[run->range.start()]); |
1097 if (GetUniscribeFallbackFont(primary_font, run_text, run->range.length(), | 1108 if (GetUniscribeFallbackFont(primary_font, run_text, run->range.length(), |
1098 &uniscribe_font) && | 1109 &uniscribe_font) && |
1099 ShapeRunWithFont(run, uniscribe_font.GetFontName())) { | 1110 CompareFamily(run, uniscribe_font.GetFontName(), |
1100 current_font = uniscribe_font.GetFontName(); | 1111 uniscribe_font.GetFontRenderParams(), |
1101 size_t current_missing = run->CountMissingGlyphs(); | 1112 &best_family, &best_render_params, &best_missing_glyphs)) |
1102 if (current_missing == 0) | 1113 return; |
1103 return; | |
1104 if (current_missing < best_font_missing) { | |
1105 best_font_missing = current_missing; | |
1106 best_font = current_font; | |
1107 } | |
1108 } | |
1109 #endif | 1114 #endif |
1110 | 1115 |
1111 // Try shaping with the fonts in the fallback list except the first, which is | 1116 // Skip the first fallback font, which is |primary_font|. |
1112 // |primary_font|. | 1117 std::vector<std::string> fallback_families = |
1113 std::vector<std::string> fonts = GetFallbackFontFamilies(primary_font_name); | 1118 GetFallbackFontFamilies(primary_font.GetFontName()); |
1114 for (size_t i = 1; i < fonts.size(); ++i) { | 1119 for (size_t i = 1; i < fallback_families.size(); ++i) { |
1115 if (!ShapeRunWithFont(run, fonts[i])) | 1120 FontRenderParamsQuery query(false); |
1116 continue; | 1121 query.families.push_back(fallback_families[i]); |
1117 current_font = fonts[i]; | 1122 query.pixel_size = run->font_size; |
1118 size_t current_missing = run->CountMissingGlyphs(); | 1123 query.style = run->font_style; |
1119 if (current_missing == 0) | 1124 FontRenderParams fallback_render_params = GetFontRenderParams(query, NULL); |
| 1125 if (CompareFamily(run, fallback_families[i], fallback_render_params, |
| 1126 &best_family, &best_render_params, &best_missing_glyphs)) |
1120 return; | 1127 return; |
1121 if (current_missing < best_font_missing) { | |
1122 best_font_missing = current_missing; | |
1123 best_font = current_font; | |
1124 } | |
1125 } | 1128 } |
1126 | 1129 |
1127 if (!best_font.empty() && | 1130 if (!best_family.empty() && |
1128 (best_font == current_font || ShapeRunWithFont(run, best_font))) { | 1131 (best_family == run->family || |
| 1132 ShapeRunWithFont(run, best_family, best_render_params))) |
1129 return; | 1133 return; |
1130 } | |
1131 | 1134 |
1132 run->glyph_count = 0; | 1135 run->glyph_count = 0; |
1133 run->width = 0.0f; | 1136 run->width = 0.0f; |
1134 } | 1137 } |
1135 | 1138 |
1136 bool RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run, | 1139 bool RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run, |
1137 const std::string& font_family) { | 1140 const std::string& font_family, |
| 1141 const FontRenderParams& params) { |
1138 const base::string16& text = GetLayoutText(); | 1142 const base::string16& text = GetLayoutText(); |
1139 skia::RefPtr<SkTypeface> skia_face = | 1143 skia::RefPtr<SkTypeface> skia_face = |
1140 internal::CreateSkiaTypeface(font_family, run->font_style); | 1144 internal::CreateSkiaTypeface(font_family, run->font_style); |
1141 if (skia_face == NULL) | 1145 if (skia_face == NULL) |
1142 return false; | 1146 return false; |
1143 run->skia_face = skia_face; | 1147 run->skia_face = skia_face; |
1144 FontRenderParamsQuery query(false); | 1148 run->family = font_family; |
1145 query.families.push_back(font_family); | 1149 run->render_params = params; |
1146 query.pixel_size = run->font_size; | |
1147 query.style = run->font_style; | |
1148 run->render_params = GetFontRenderParams(query, NULL); | |
1149 hb_font_t* harfbuzz_font = CreateHarfBuzzFont( | 1150 hb_font_t* harfbuzz_font = CreateHarfBuzzFont( |
1150 run->skia_face.get(), SkIntToScalar(run->font_size), run->render_params, | 1151 run->skia_face.get(), SkIntToScalar(run->font_size), run->render_params, |
1151 background_is_transparent()); | 1152 background_is_transparent()); |
1152 | 1153 |
1153 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz | 1154 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz |
1154 // buffer holds our text, run information to be used by the shaping engine, | 1155 // buffer holds our text, run information to be used by the shaping engine, |
1155 // and the resulting glyph data. | 1156 // and the resulting glyph data. |
1156 hb_buffer_t* buffer = hb_buffer_create(); | 1157 hb_buffer_t* buffer = hb_buffer_create(); |
1157 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), | 1158 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), |
1158 text.length(), run->range.start(), run->range.length()); | 1159 text.length(), run->range.start(), run->range.length()); |
(...skipping 30 matching lines...) Expand all Loading... |
1189 run->width = std::floor(run->width + 0.5f); | 1190 run->width = std::floor(run->width + 0.5f); |
1190 #endif | 1191 #endif |
1191 } | 1192 } |
1192 | 1193 |
1193 hb_buffer_destroy(buffer); | 1194 hb_buffer_destroy(buffer); |
1194 hb_font_destroy(harfbuzz_font); | 1195 hb_font_destroy(harfbuzz_font); |
1195 return true; | 1196 return true; |
1196 } | 1197 } |
1197 | 1198 |
1198 } // namespace gfx | 1199 } // namespace gfx |
OLD | NEW |