| Index: ui/gfx/render_text_win.cc
|
| ===================================================================
|
| --- ui/gfx/render_text_win.cc (revision 135151)
|
| +++ ui/gfx/render_text_win.cc (working copy)
|
| @@ -606,7 +606,7 @@
|
| string_size_.set_height(0);
|
| for (size_t i = 0; i < runs_.size(); ++i) {
|
| internal::TextRun* run = runs_[i];
|
| - size_t run_length = run->range.length();
|
| + const size_t run_length = run->range.length();
|
| const wchar_t* run_text = &(text()[run->range.start()]);
|
| bool tried_fallback = false;
|
| size_t linked_font_index = 0;
|
| @@ -616,16 +616,11 @@
|
| // Select the font desired for glyph generation.
|
| SelectObject(cached_hdc_, run->font.GetNativeFont());
|
|
|
| - SCRIPT_FONTPROPERTIES properties;
|
| - memset(&properties, 0, sizeof(properties));
|
| - properties.cBytes = sizeof(properties);
|
| -
|
| run->logical_clusters.reset(new WORD[run_length]);
|
| run->glyph_count = 0;
|
| // Max glyph guess: http://msdn.microsoft.com/en-us/library/dd368564.aspx
|
| size_t max_glyphs = static_cast<size_t>(1.5 * run_length + 16);
|
| while (max_glyphs < kMaxGlyphs) {
|
| - bool glyphs_missing = false;
|
| run->glyphs.reset(new WORD[max_glyphs]);
|
| run->visible_attributes.reset(new SCRIPT_VISATTR[max_glyphs]);
|
| hr = ScriptShape(cached_hdc_,
|
| @@ -641,18 +636,15 @@
|
| if (hr == E_OUTOFMEMORY) {
|
| max_glyphs *= 2;
|
| continue;
|
| - } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
|
| + }
|
| +
|
| + bool glyphs_missing = false;
|
| + if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
|
| glyphs_missing = true;
|
| } 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
|
| - ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties);
|
| - for (int i = 0; i < run->glyph_count; ++i) {
|
| - if (run->glyphs[i] == properties.wgDefault) {
|
| - glyphs_missing = true;
|
| - break;
|
| - }
|
| - }
|
| + glyphs_missing = HasMissingGlyphs(run);
|
| }
|
|
|
| // Skip font substitution if there are no missing glyphs.
|
| @@ -767,6 +759,35 @@
|
| SelectObject(cached_hdc_, run->font.GetNativeFont());
|
| }
|
|
|
| +bool RenderTextWin::HasMissingGlyphs(internal::TextRun* run) const {
|
| + SCRIPT_FONTPROPERTIES properties;
|
| + memset(&properties, 0, sizeof(properties));
|
| + properties.cBytes = sizeof(properties);
|
| + ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties);
|
| +
|
| + const wchar_t* run_text = &(text()[run->range.start()]);
|
| + for (size_t char_index = 0; char_index < run->range.length(); ++char_index) {
|
| + const int glyph_index = run->logical_clusters[char_index];
|
| + DCHECK_GE(glyph_index, 0);
|
| + DCHECK_LT(glyph_index, run->glyph_count);
|
| +
|
| + if (run->glyphs[glyph_index] == properties.wgDefault)
|
| + return true;
|
| +
|
| + // Windows Vista sometimes returns glyphs equal to wgBlank (instead of
|
| + // wgDefault), with fZeroWidth set. Treat such cases as having missing
|
| + // glyphs if the corresponding character is not whitespace.
|
| + // See: http://crbug.com/125629
|
| + if (run->glyphs[glyph_index] == properties.wgBlank &&
|
| + run->visible_attributes[glyph_index].fZeroWidth &&
|
| + !IsWhitespace(run_text[char_index])) {
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| const std::vector<Font>* RenderTextWin::GetLinkedFonts(const Font& font) const {
|
| const std::string& font_name = font.GetFontName();
|
| std::map<std::string, std::vector<Font> >::const_iterator it =
|
| @@ -803,13 +824,13 @@
|
| }
|
|
|
| SelectionModel RenderTextWin::FirstSelectionModelInsideRun(
|
| - internal::TextRun* run) {
|
| + const internal::TextRun* run) {
|
| size_t cursor = IndexOfAdjacentGrapheme(run->range.start(), CURSOR_FORWARD);
|
| return SelectionModel(cursor, CURSOR_BACKWARD);
|
| }
|
|
|
| SelectionModel RenderTextWin::LastSelectionModelInsideRun(
|
| - internal::TextRun* run) {
|
| + const internal::TextRun* run) {
|
| size_t caret = IndexOfAdjacentGrapheme(run->range.end(), CURSOR_BACKWARD);
|
| return SelectionModel(caret, CURSOR_FORWARD);
|
| }
|
|
|