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

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: 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;
1066 // Keep track of the font that is able to display the greatest number of 1065 // 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 1066 // 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. 1067 // in the case where no font is able to display the entire run.
1069 int best_partial_font_missing_char_count = INT_MAX; 1068 int best_partial_font_missing_char_count = INT_MAX;
1070 Font best_partial_font = original_font; 1069 Font best_partial_font = original_font;
1071 Font current_font; 1070 Font current_font;
1072 1071
1073 run->logical_clusters.reset(new WORD[run_length]); 1072 run->logical_clusters.reset(new WORD[run_length]);
1074 while (fonts.NextFont(&current_font)) {
1075 HRESULT hr = ShapeTextRunWithFont(run, current_font);
1076 1073
1077 bool glyphs_missing = false; 1074 // Try to shape with the first font in the fallback list.
1078 if (hr == USP_E_SCRIPT_NOT_IN_FONT) { 1075 fonts.NextFont(&current_font);
1079 glyphs_missing = true; 1076 int missing_count = CountCharsWithMissingGlyphs(run,
1080 } else if (hr == S_OK) { 1077 ShapeTextRunWithFont(run, current_font));
1081 // If |hr| is S_OK, there could still be missing glyphs in the output. 1078 if (missing_count == 0)
1082 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564.aspx 1079 return;
msw 2014/07/10 22:59:50 Should we ever add the original font to |successfu
ckocagil 2014/07/10 23:41:33 I can't see a reason to add the original font. It
msw 2014/07/11 00:08:39 Acknowledged.
1083 const int missing_count = CountCharsWithMissingGlyphs(run); 1080 if (missing_count < best_partial_font_missing_char_count) {
1084 // Track the font that produced the least missing glyphs. 1081 best_partial_font_missing_char_count = missing_count;
msw 2014/07/10 22:59:50 We may as well declare and initialize |best_partia
ckocagil 2014/07/10 23:41:33 Done.
1085 if (missing_count < best_partial_font_missing_char_count) { 1082 best_partial_font = run->font;
1086 best_partial_font_missing_char_count = missing_count; 1083 }
1087 best_partial_font = run->font;
1088 }
1089 glyphs_missing = (missing_count != 0);
1090 } else {
1091 NOTREACHED() << hr;
1092 }
1093 1084
1094 // Use the font if it had glyphs for all characters. 1085 // Try to shape with the cached font from previous runs, if any.
1095 if (!glyphs_missing) { 1086 std::map<std::string, Font>::const_iterator it =
1096 // Save the successful fallback font that was chosen. 1087 successful_substitute_fonts_.find(original_font.GetFontName());
1097 if (tried_fallback) 1088 if (it != successful_substitute_fonts_.end()) {
1098 successful_substitute_fonts_[original_font.GetFontName()] = run->font; 1089 current_font = it->second;
1090 missing_count = CountCharsWithMissingGlyphs(run,
1091 ShapeTextRunWithFont(run, current_font));
1092 if (missing_count == 0) {
1093 successful_substitute_fonts_[original_font.GetFontName()] = run->font;
msw 2014/07/10 22:59:50 Isn't this value already set? Can we skip this?
ckocagil 2014/07/10 23:41:33 Done.
1099 return; 1094 return;
1100 } 1095 }
1101 1096 if (missing_count < best_partial_font_missing_char_count) {
1102 // First, try the cached font from previous runs, if any. 1097 best_partial_font_missing_char_count = missing_count;
1103 if (!tried_cached_font) { 1098 best_partial_font = run->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 } 1099 }
1127 } 1100 }
1128 1101
1102 // Try finding a fallback font using a meta file.
1103 // TODO(msw|asvitkine): Support RenderText's font_list()?
1104 if (ChooseFallbackFont(cached_hdc_, run->font, run_text, run_length,
1105 &current_font)) {
1106 missing_count = CountCharsWithMissingGlyphs(run,
1107 ShapeTextRunWithFont(run, current_font));
1108 if (missing_count == 0) {
1109 successful_substitute_fonts_[original_font.GetFontName()] = run->font;
1110 return;
1111 }
1112 if (missing_count < best_partial_font_missing_char_count) {
1113 best_partial_font_missing_char_count = missing_count;
1114 best_partial_font = run->font;
1115 }
1116 }
1117
1118 // Try the rest of fonts in the fallback list.
1119 while (fonts.NextFont(&current_font)) {
1120 missing_count = CountCharsWithMissingGlyphs(run,
1121 ShapeTextRunWithFont(run, current_font));
1122 if (missing_count < best_partial_font_missing_char_count) {
1123 best_partial_font_missing_char_count = missing_count;
1124 best_partial_font = run->font;
1125 }
1126 if (missing_count == 0) {
1127 successful_substitute_fonts_[original_font.GetFontName()] = run->font;
1128 return;
1129 }
1130 }
1131
1129 // If a font was able to partially display the run, use that now. 1132 // 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)) { 1133 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. 1134 // Re-shape the run only if |best_partial_font| differs from the last font.
1132 if (best_partial_font.GetNativeFont() != run->font.GetNativeFont()) 1135 if (best_partial_font.GetNativeFont() != run->font.GetNativeFont())
1133 ShapeTextRunWithFont(run, best_partial_font); 1136 ShapeTextRunWithFont(run, best_partial_font);
1134 return; 1137 return;
1135 } 1138 }
1136 1139
1137 // If no font was able to partially display the run, replace all glyphs 1140 // 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 1141 // 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, 1209 hr = ScriptShape(cached_hdc_, &run->script_cache, run_text, run_length,
1207 max_glyphs, &run->script_analysis, run->glyphs.get(), 1210 max_glyphs, &run->script_analysis, run->glyphs.get(),
1208 run->logical_clusters.get(), run->visible_attributes.get(), 1211 run->logical_clusters.get(), run->visible_attributes.get(),
1209 &run->glyph_count); 1212 &run->glyph_count);
1210 // Ensure that |kMaxGlyphs| is attempted and the loop terminates afterward. 1213 // Ensure that |kMaxGlyphs| is attempted and the loop terminates afterward.
1211 max_glyphs = std::max(max_glyphs + 1, std::min(max_glyphs * 2, kMaxGlyphs)); 1214 max_glyphs = std::max(max_glyphs + 1, std::min(max_glyphs * 2, kMaxGlyphs));
1212 } 1215 }
1213 return hr; 1216 return hr;
1214 } 1217 }
1215 1218
1216 int RenderTextWin::CountCharsWithMissingGlyphs(internal::TextRun* run) const { 1219 int RenderTextWin::CountCharsWithMissingGlyphs(internal::TextRun* run,
1220 HRESULT shaping_result) const {
1221 if (shaping_result == USP_E_SCRIPT_NOT_IN_FONT)
msw 2014/07/10 22:59:50 nit: if (shaping_result != S_OK) { DCHECK_EQ(shapi
ckocagil 2014/07/10 23:41:33 Done.
1222 return INT_MAX;
1223 if (shaping_result != S_OK) {
1224 NOTREACHED() << shaping_result;
1225 return INT_MAX;
1226 }
1227
1228 // If |hr| is S_OK, there could still be missing glyphs in the output.
1229 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564.aspx
1217 int chars_not_missing_glyphs = 0; 1230 int chars_not_missing_glyphs = 0;
1218 SCRIPT_FONTPROPERTIES properties; 1231 SCRIPT_FONTPROPERTIES properties;
1219 memset(&properties, 0, sizeof(properties)); 1232 memset(&properties, 0, sizeof(properties));
1220 properties.cBytes = sizeof(properties); 1233 properties.cBytes = sizeof(properties);
1221 ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties); 1234 ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties);
1222 1235
1223 const wchar_t* run_text = &(GetLayoutText()[run->range.start()]); 1236 const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
1224 for (size_t char_index = 0; char_index < run->range.length(); ++char_index) { 1237 for (size_t char_index = 0; char_index < run->range.length(); ++char_index) {
1225 const int glyph_index = run->logical_clusters[char_index]; 1238 const int glyph_index = run->logical_clusters[char_index];
1226 DCHECK_GE(glyph_index, 0); 1239 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()); 1293 size_t position = LayoutIndexToTextIndex(run->range.end());
1281 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); 1294 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD);
1282 return SelectionModel(position, CURSOR_FORWARD); 1295 return SelectionModel(position, CURSOR_FORWARD);
1283 } 1296 }
1284 1297
1285 RenderText* RenderText::CreateNativeInstance() { 1298 RenderText* RenderText::CreateNativeInstance() {
1286 return new RenderTextWin; 1299 return new RenderTextWin;
1287 } 1300 }
1288 1301
1289 } // namespace gfx 1302 } // 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