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

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

Issue 382793004: RenderTextWin: Unroll the loop in LayoutTextRun for clarity (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comments addressed Created 6 years, 5 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
« no previous file with comments | « ui/gfx/render_text_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_win.h" 5 #include "ui/gfx/render_text_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/i18n/break_iterator.h" 9 #include "base/i18n/break_iterator.h"
10 #include "base/i18n/char_iterator.h" 10 #include "base/i18n/char_iterator.h"
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after
1054 preceding_run_widths += run->width; 1054 preceding_run_widths += run->width;
1055 } 1055 }
1056 string_width_ = preceding_run_widths; 1056 string_width_ = preceding_run_widths;
1057 } 1057 }
1058 1058
1059 void RenderTextWin::LayoutTextRun(internal::TextRun* run) { 1059 void RenderTextWin::LayoutTextRun(internal::TextRun* run) {
1060 const size_t run_length = run->range.length(); 1060 const size_t run_length = run->range.length();
1061 const wchar_t* run_text = &(GetLayoutText()[run->range.start()]); 1061 const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
1062 Font original_font = run->font; 1062 Font original_font = run->font;
1063 LinkedFontsIterator fonts(original_font); 1063 LinkedFontsIterator fonts(original_font);
1064 bool tried_cached_font = false; 1064
1065 bool tried_fallback = false; 1065 run->logical_clusters.reset(new WORD[run_length]);
1066
1067 // Try to shape with the first font in the fallback list.
msw 2014/07/11 00:08:39 nit: maybe mention that it's |original_font|?
ckocagil 2014/07/11 01:29:25 Done.
1068 Font current_font;
1069 fonts.NextFont(&current_font);
1070 int missing_count = CountCharsWithMissingGlyphs(run,
1071 ShapeTextRunWithFont(run, current_font));
1072 if (missing_count == 0)
1073 return;
1074
1066 // Keep track of the font that is able to display the greatest number of 1075 // Keep track of the font that is able to display the greatest number of
1067 // characters for which ScriptShape() returned S_OK. This font will be used 1076 // characters for which ScriptShape() returned S_OK. This font will be used
1068 // in the case where no font is able to display the entire run. 1077 // in the case where no font is able to display the entire run.
1069 int best_partial_font_missing_char_count = INT_MAX; 1078 int best_partial_font_missing_char_count = missing_count;
1070 Font best_partial_font = original_font; 1079 Font best_partial_font = current_font;
1071 Font current_font;
1072 1080
1073 run->logical_clusters.reset(new WORD[run_length]); 1081 // Try to shape with the cached font from previous runs, if any.
1074 while (fonts.NextFont(&current_font)) { 1082 std::map<std::string, Font>::const_iterator it =
1075 HRESULT hr = ShapeTextRunWithFont(run, current_font); 1083 successful_substitute_fonts_.find(original_font.GetFontName());
1076 1084 if (it != successful_substitute_fonts_.end()) {
1077 bool glyphs_missing = false; 1085 current_font = it->second;
1078 if (hr == USP_E_SCRIPT_NOT_IN_FONT) { 1086 missing_count = CountCharsWithMissingGlyphs(run,
1079 glyphs_missing = true; 1087 ShapeTextRunWithFont(run, current_font));
1080 } else if (hr == S_OK) { 1088 if (missing_count == 0)
1081 // If |hr| is S_OK, there could still be missing glyphs in the output.
1082 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564.aspx
1083 const int missing_count = CountCharsWithMissingGlyphs(run);
1084 // Track the font that produced the least missing glyphs.
1085 if (missing_count < best_partial_font_missing_char_count) {
1086 best_partial_font_missing_char_count = missing_count;
1087 best_partial_font = run->font;
1088 }
1089 glyphs_missing = (missing_count != 0);
1090 } else {
1091 NOTREACHED() << hr;
1092 }
1093
1094 // Use the font if it had glyphs for all characters.
1095 if (!glyphs_missing) {
1096 // Save the successful fallback font that was chosen.
1097 if (tried_fallback)
1098 successful_substitute_fonts_[original_font.GetFontName()] = run->font;
1099 return; 1089 return;
1100 } 1090 if (missing_count < best_partial_font_missing_char_count) {
1101 1091 best_partial_font_missing_char_count = missing_count;
1102 // First, try the cached font from previous runs, if any. 1092 best_partial_font = current_font;
1103 if (!tried_cached_font) {
1104 tried_cached_font = true;
1105
1106 std::map<std::string, Font>::const_iterator it =
1107 successful_substitute_fonts_.find(original_font.GetFontName());
1108 if (it != successful_substitute_fonts_.end()) {
1109 fonts.SetNextFont(it->second);
1110 continue;
1111 }
1112 }
1113
1114 // If there are missing glyphs, first try finding a fallback font using a
1115 // meta file, if it hasn't yet been attempted for this run.
1116 // TODO(msw|asvitkine): Support RenderText's font_list()?
1117 if (!tried_fallback) {
1118 tried_fallback = true;
1119
1120 Font fallback_font;
1121 if (ChooseFallbackFont(cached_hdc_, run->font, run_text, run_length,
1122 &fallback_font)) {
1123 fonts.SetNextFont(fallback_font);
1124 continue;
1125 }
1126 } 1093 }
1127 } 1094 }
1128 1095
1096 // Try finding a fallback font using a meta file.
1097 // TODO(msw|asvitkine): Support RenderText's font_list()?
1098 if (ChooseFallbackFont(cached_hdc_, run->font, run_text, run_length,
1099 &current_font)) {
1100 missing_count = CountCharsWithMissingGlyphs(run,
1101 ShapeTextRunWithFont(run, current_font));
1102 if (missing_count == 0) {
1103 successful_substitute_fonts_[original_font.GetFontName()] = current_font;
1104 return;
1105 }
1106 if (missing_count < best_partial_font_missing_char_count) {
1107 best_partial_font_missing_char_count = missing_count;
1108 best_partial_font = current_font;
1109 }
1110 }
1111
1112 // Try the rest of fonts in the fallback list.
1113 while (fonts.NextFont(&current_font)) {
1114 missing_count = CountCharsWithMissingGlyphs(run,
1115 ShapeTextRunWithFont(run, current_font));
1116 if (missing_count == 0) {
1117 successful_substitute_fonts_[original_font.GetFontName()] = current_font;
1118 return;
1119 }
1120 if (missing_count < best_partial_font_missing_char_count) {
1121 best_partial_font_missing_char_count = missing_count;
1122 best_partial_font = current_font;
1123 }
1124 }
1125
1129 // If a font was able to partially display the run, use that now. 1126 // If a font was able to partially display the run, use that now.
1130 if (best_partial_font_missing_char_count < static_cast<int>(run_length)) { 1127 if (best_partial_font_missing_char_count < static_cast<int>(run_length)) {
1131 // Re-shape the run only if |best_partial_font| differs from the last font. 1128 // Re-shape the run only if |best_partial_font| differs from the last font.
1132 if (best_partial_font.GetNativeFont() != run->font.GetNativeFont()) 1129 if (best_partial_font.GetNativeFont() != run->font.GetNativeFont())
1133 ShapeTextRunWithFont(run, best_partial_font); 1130 ShapeTextRunWithFont(run, best_partial_font);
1134 return; 1131 return;
1135 } 1132 }
1136 1133
1137 // If no font was able to partially display the run, replace all glyphs 1134 // If no font was able to partially display the run, replace all glyphs
1138 // with |wgDefault| from the original font to ensure to they don't hold 1135 // with |wgDefault| from the original font to ensure to they don't hold
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 hr = ScriptShape(cached_hdc_, &run->script_cache, run_text, run_length, 1203 hr = ScriptShape(cached_hdc_, &run->script_cache, run_text, run_length,
1207 max_glyphs, &run->script_analysis, run->glyphs.get(), 1204 max_glyphs, &run->script_analysis, run->glyphs.get(),
1208 run->logical_clusters.get(), run->visible_attributes.get(), 1205 run->logical_clusters.get(), run->visible_attributes.get(),
1209 &run->glyph_count); 1206 &run->glyph_count);
1210 // Ensure that |kMaxGlyphs| is attempted and the loop terminates afterward. 1207 // Ensure that |kMaxGlyphs| is attempted and the loop terminates afterward.
1211 max_glyphs = std::max(max_glyphs + 1, std::min(max_glyphs * 2, kMaxGlyphs)); 1208 max_glyphs = std::max(max_glyphs + 1, std::min(max_glyphs * 2, kMaxGlyphs));
1212 } 1209 }
1213 return hr; 1210 return hr;
1214 } 1211 }
1215 1212
1216 int RenderTextWin::CountCharsWithMissingGlyphs(internal::TextRun* run) const { 1213 int RenderTextWin::CountCharsWithMissingGlyphs(internal::TextRun* run,
1214 HRESULT shaping_result) const {
1215 if (shaping_result != S_OK) {
1216 DCHECK_EQ(shaping_result, USP_E_SCRIPT_NOT_IN_FONT);
1217 return INT_MAX;
1218 }
1219
1220 // If |hr| is S_OK, there could still be missing glyphs in the output.
1221 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564.aspx
1217 int chars_not_missing_glyphs = 0; 1222 int chars_not_missing_glyphs = 0;
1218 SCRIPT_FONTPROPERTIES properties; 1223 SCRIPT_FONTPROPERTIES properties;
1219 memset(&properties, 0, sizeof(properties)); 1224 memset(&properties, 0, sizeof(properties));
1220 properties.cBytes = sizeof(properties); 1225 properties.cBytes = sizeof(properties);
1221 ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties); 1226 ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties);
1222 1227
1223 const wchar_t* run_text = &(GetLayoutText()[run->range.start()]); 1228 const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
1224 for (size_t char_index = 0; char_index < run->range.length(); ++char_index) { 1229 for (size_t char_index = 0; char_index < run->range.length(); ++char_index) {
1225 const int glyph_index = run->logical_clusters[char_index]; 1230 const int glyph_index = run->logical_clusters[char_index];
1226 DCHECK_GE(glyph_index, 0); 1231 DCHECK_GE(glyph_index, 0);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1280 size_t position = LayoutIndexToTextIndex(run->range.end()); 1285 size_t position = LayoutIndexToTextIndex(run->range.end());
1281 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); 1286 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD);
1282 return SelectionModel(position, CURSOR_FORWARD); 1287 return SelectionModel(position, CURSOR_FORWARD);
1283 } 1288 }
1284 1289
1285 RenderText* RenderText::CreateNativeInstance() { 1290 RenderText* RenderText::CreateNativeInstance() {
1286 return new RenderTextWin; 1291 return new RenderTextWin;
1287 } 1292 }
1288 1293
1289 } // namespace gfx 1294 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/render_text_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698