| Index: ui/gfx/render_text_win.cc
|
| ===================================================================
|
| --- ui/gfx/render_text_win.cc (revision 145906)
|
| +++ ui/gfx/render_text_win.cc (working copy)
|
| @@ -679,6 +679,12 @@
|
| size_t linked_font_index = 0;
|
| const std::vector<Font>* linked_fonts = NULL;
|
| Font original_font = run->font;
|
| + // Keep track of the font that is able to display the greatest number of
|
| + // characters for which ScriptShape() returned S_OK. This font will be used
|
| + // in the case where no font is able to display the entire run.
|
| + int best_partial_font_missing_char_count = INT_MAX;
|
| + Font best_partial_font = run->font;
|
| + bool using_best_partial_font = false;
|
|
|
| // Select the font desired for glyph generation.
|
| SelectObject(cached_hdc_, run->font.GetNativeFont());
|
| @@ -711,13 +717,20 @@
|
| } else if (hr == S_OK) {
|
| // If |hr| is S_OK, there could still be missing glyphs in the output,
|
| // see: http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564.aspx
|
| - glyphs_missing = HasMissingGlyphs(run);
|
| + const int missing_count = CountCharsWithMissingGlyphs(run);
|
| + // Track the font that produced the least missing glyphs.
|
| + if (missing_count < best_partial_font_missing_char_count) {
|
| + best_partial_font_missing_char_count = missing_count;
|
| + best_partial_font = run->font;
|
| + }
|
| + glyphs_missing = (missing_count != 0);
|
| }
|
|
|
| - // Skip font substitution if there are no missing glyphs.
|
| - if (!glyphs_missing) {
|
| + // Skip font substitution if there are no missing glyphs or if the font
|
| + // with the least missing glyphs is being used as a last resort.
|
| + if (!glyphs_missing || using_best_partial_font) {
|
| // Save the successful fallback font that was chosen.
|
| - if (tried_fallback)
|
| + if (tried_fallback && !using_best_partial_font)
|
| successful_substitute_fonts_[original_font.GetFontName()] = run->font;
|
| break;
|
| }
|
| @@ -765,8 +778,24 @@
|
| linked_fonts = GetLinkedFonts(run->font);
|
| }
|
|
|
| - // None of the linked fonts worked, break out of the loop.
|
| + // None of the fallback fonts were able to display the entire run.
|
| if (linked_font_index == linked_fonts->size()) {
|
| + // If a font was able to partially display the run, use that now.
|
| + if (best_partial_font_missing_char_count != INT_MAX) {
|
| + ApplySubstituteFont(run, best_partial_font);
|
| + using_best_partial_font = true;
|
| + continue;
|
| + }
|
| +
|
| + // If no font was able to partially display the run, replace all glyphs
|
| + // with |wgDefault| to ensure they don't hold garbage values.
|
| + SCRIPT_FONTPROPERTIES properties;
|
| + memset(&properties, 0, sizeof(properties));
|
| + properties.cBytes = sizeof(properties);
|
| + ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties);
|
| + for (int i = 0; i < run->glyph_count; ++i)
|
| + run->glyphs[i] = properties.wgDefault;
|
| +
|
| // TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can
|
| // crash on certain surrogate pairs with SCRIPT_UNDEFINED.
|
| // See https://bugzilla.mozilla.org/show_bug.cgi?id=341500
|
| @@ -841,7 +870,8 @@
|
| SelectObject(cached_hdc_, run->font.GetNativeFont());
|
| }
|
|
|
| -bool RenderTextWin::HasMissingGlyphs(internal::TextRun* run) const {
|
| +int RenderTextWin::CountCharsWithMissingGlyphs(internal::TextRun* run) const {
|
| + int chars_not_missing_glyphs = 0;
|
| SCRIPT_FONTPROPERTIES properties;
|
| memset(&properties, 0, sizeof(properties));
|
| properties.cBytes = sizeof(properties);
|
| @@ -854,7 +884,7 @@
|
| DCHECK_LT(glyph_index, run->glyph_count);
|
|
|
| if (run->glyphs[glyph_index] == properties.wgDefault)
|
| - return true;
|
| + continue;
|
|
|
| // Windows Vista sometimes returns glyphs equal to wgBlank (instead of
|
| // wgDefault), with fZeroWidth set. Treat such cases as having missing
|
| @@ -864,11 +894,14 @@
|
| run->visible_attributes[glyph_index].fZeroWidth &&
|
| !IsWhitespace(run_text[char_index]) &&
|
| !IsUnicodeBidiControlCharacter(run_text[char_index])) {
|
| - return true;
|
| + continue;
|
| }
|
| +
|
| + ++chars_not_missing_glyphs;
|
| }
|
|
|
| - return false;
|
| + DCHECK_LE(chars_not_missing_glyphs, static_cast<int>(run->range.length()));
|
| + return run->range.length() - chars_not_missing_glyphs;
|
| }
|
|
|
| const std::vector<Font>* RenderTextWin::GetLinkedFonts(const Font& font) const {
|
|
|