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

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: nit 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, which is
1068 // |original_font|.
1069 Font current_font;
1070 fonts.NextFont(&current_font);
1071 int missing_count = CountCharsWithMissingGlyphs(run,
1072 ShapeTextRunWithFont(run, current_font));
1073 if (missing_count == 0)
1074 return;
1075
1066 // Keep track of the font that is able to display the greatest number of 1076 // 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 1077 // 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. 1078 // in the case where no font is able to display the entire run.
1069 int best_partial_font_missing_char_count = INT_MAX; 1079 int best_partial_font_missing_char_count = missing_count;
1070 Font best_partial_font = original_font; 1080 Font best_partial_font = current_font;
1071 Font current_font;
1072 1081
1073 run->logical_clusters.reset(new WORD[run_length]); 1082 // Try to shape with the cached font from previous runs, if any.
1074 while (fonts.NextFont(&current_font)) { 1083 std::map<std::string, Font>::const_iterator it =
1075 HRESULT hr = ShapeTextRunWithFont(run, current_font); 1084 successful_substitute_fonts_.find(original_font.GetFontName());
1076 1085 if (it != successful_substitute_fonts_.end()) {
1077 bool glyphs_missing = false; 1086 current_font = it->second;
1078 if (hr == USP_E_SCRIPT_NOT_IN_FONT) { 1087 missing_count = CountCharsWithMissingGlyphs(run,
1079 glyphs_missing = true; 1088 ShapeTextRunWithFont(run, current_font));
1080 } else if (hr == S_OK) { 1089 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; 1090 return;
1100 } 1091 if (missing_count < best_partial_font_missing_char_count) {
1101 1092 best_partial_font_missing_char_count = missing_count;
1102 // First, try the cached font from previous runs, if any. 1093 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 } 1094 }
1127 } 1095 }
1128 1096
1097 // Try finding a fallback font using a meta file.
1098 // TODO(msw|asvitkine): Support RenderText's font_list()?
1099 if (ChooseFallbackFont(cached_hdc_, run->font, run_text, run_length,
1100 &current_font)) {
1101 missing_count = CountCharsWithMissingGlyphs(run,
1102 ShapeTextRunWithFont(run, current_font));
Alexei Svitkine (slow) 2014/07/15 19:48:20 If these two functions are always called together
1103 if (missing_count == 0) {
1104 successful_substitute_fonts_[original_font.GetFontName()] = current_font;
1105 return;
1106 }
1107 if (missing_count < best_partial_font_missing_char_count) {
1108 best_partial_font_missing_char_count = missing_count;
1109 best_partial_font = current_font;
1110 }
1111 }
1112
1113 // Try the rest of fonts in the fallback list.
1114 while (fonts.NextFont(&current_font)) {
Alexei Svitkine (slow) 2014/07/15 19:48:20 Now that you're not calling SetNextFont() on |font
1115 missing_count = CountCharsWithMissingGlyphs(run,
1116 ShapeTextRunWithFont(run, current_font));
1117 if (missing_count == 0) {
1118 successful_substitute_fonts_[original_font.GetFontName()] = current_font;
1119 return;
1120 }
1121 if (missing_count < best_partial_font_missing_char_count) {
1122 best_partial_font_missing_char_count = missing_count;
1123 best_partial_font = current_font;
1124 }
1125 }
1126
1129 // If a font was able to partially display the run, use that now. 1127 // 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)) { 1128 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. 1129 // Re-shape the run only if |best_partial_font| differs from the last font.
1132 if (best_partial_font.GetNativeFont() != run->font.GetNativeFont()) 1130 if (best_partial_font.GetNativeFont() != run->font.GetNativeFont())
1133 ShapeTextRunWithFont(run, best_partial_font); 1131 ShapeTextRunWithFont(run, best_partial_font);
1134 return; 1132 return;
1135 } 1133 }
1136 1134
1137 // If no font was able to partially display the run, replace all glyphs 1135 // 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 1136 // 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, 1204 hr = ScriptShape(cached_hdc_, &run->script_cache, run_text, run_length,
1207 max_glyphs, &run->script_analysis, run->glyphs.get(), 1205 max_glyphs, &run->script_analysis, run->glyphs.get(),
1208 run->logical_clusters.get(), run->visible_attributes.get(), 1206 run->logical_clusters.get(), run->visible_attributes.get(),
1209 &run->glyph_count); 1207 &run->glyph_count);
1210 // Ensure that |kMaxGlyphs| is attempted and the loop terminates afterward. 1208 // Ensure that |kMaxGlyphs| is attempted and the loop terminates afterward.
1211 max_glyphs = std::max(max_glyphs + 1, std::min(max_glyphs * 2, kMaxGlyphs)); 1209 max_glyphs = std::max(max_glyphs + 1, std::min(max_glyphs * 2, kMaxGlyphs));
1212 } 1210 }
1213 return hr; 1211 return hr;
1214 } 1212 }
1215 1213
1216 int RenderTextWin::CountCharsWithMissingGlyphs(internal::TextRun* run) const { 1214 int RenderTextWin::CountCharsWithMissingGlyphs(internal::TextRun* run,
1215 HRESULT shaping_result) const {
1216 if (shaping_result != S_OK) {
1217 DCHECK_EQ(shaping_result, USP_E_SCRIPT_NOT_IN_FONT);
Alexei Svitkine (slow) 2014/07/15 19:48:20 Nit: The expected value constant should be the fir
1218 return INT_MAX;
Alexei Svitkine (slow) 2014/07/15 19:48:20 What does it mean for INT_MAX to be returned by th
1219 }
1220
1221 // If |hr| is S_OK, there could still be missing glyphs in the output.
1222 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564.aspx
1217 int chars_not_missing_glyphs = 0; 1223 int chars_not_missing_glyphs = 0;
1218 SCRIPT_FONTPROPERTIES properties; 1224 SCRIPT_FONTPROPERTIES properties;
1219 memset(&properties, 0, sizeof(properties)); 1225 memset(&properties, 0, sizeof(properties));
1220 properties.cBytes = sizeof(properties); 1226 properties.cBytes = sizeof(properties);
1221 ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties); 1227 ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties);
1222 1228
1223 const wchar_t* run_text = &(GetLayoutText()[run->range.start()]); 1229 const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
1224 for (size_t char_index = 0; char_index < run->range.length(); ++char_index) { 1230 for (size_t char_index = 0; char_index < run->range.length(); ++char_index) {
1225 const int glyph_index = run->logical_clusters[char_index]; 1231 const int glyph_index = run->logical_clusters[char_index];
1226 DCHECK_GE(glyph_index, 0); 1232 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()); 1286 size_t position = LayoutIndexToTextIndex(run->range.end());
1281 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); 1287 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD);
1282 return SelectionModel(position, CURSOR_FORWARD); 1288 return SelectionModel(position, CURSOR_FORWARD);
1283 } 1289 }
1284 1290
1285 RenderText* RenderText::CreateNativeInstance() { 1291 RenderText* RenderText::CreateNativeInstance() {
1286 return new RenderTextWin; 1292 return new RenderTextWin;
1287 } 1293 }
1288 1294
1289 } // namespace gfx 1295 } // 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