summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authorasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-13 20:03:36 +0000
committerasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-13 20:03:36 +0000
commitb55c0da7f98a5821ed4e3fb9e94d17badecf5219 (patch)
treebb0198228da204dcd9b6f005526d94a12e7d56e4 /ui/gfx
parent8331aedb373af684b9b645ab43a04ba8c662e3fc (diff)
downloadchromium_src-b55c0da7f98a5821ed4e3fb9e94d17badecf5219.zip
chromium_src-b55c0da7f98a5821ed4e3fb9e94d17badecf5219.tar.gz
chromium_src-b55c0da7f98a5821ed4e3fb9e94d17badecf5219.tar.bz2
Always try metafile font fallback in the case of missing glyphs in RenderTextWin.
Before this patch, if ScriptShape() returned E_OK but there were missing glyphs, we would only try font linking and not metafile font fallback. For Armenian text (and probably others), ScriptShape() returns E_OK with missing glyphs, but font linking won't find the right font. The metafile approach is needed. This change makes sure the metafile font fallback path is always taken first, before trying font linking to find the missing font. BUG=105550, 122974 TEST=Under Windows with use_canvas_skia=1 enabled, go to http://akumb.am. Make sure the tab title is displayed correctly. Review URL: http://codereview.chromium.org/10010047 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132250 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r--ui/gfx/render_text_win.cc95
-rw-r--r--ui/gfx/render_text_win.h3
2 files changed, 53 insertions, 45 deletions
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc
index 470a499..b50ccad 100644
--- a/ui/gfx/render_text_win.cc
+++ b/ui/gfx/render_text_win.cc
@@ -597,7 +597,6 @@ void RenderTextWin::LayoutVisualText() {
bool tried_fallback = false;
size_t linked_font_index = 0;
const std::vector<Font>* linked_fonts = NULL;
- const int font_size = run->font.GetFontSize();
// Select the font desired for glyph generation.
SelectObject(cached_hdc_, run->font.GetNativeFont());
@@ -612,6 +611,7 @@ void RenderTextWin::LayoutVisualText() {
// 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_,
@@ -626,66 +626,62 @@ void RenderTextWin::LayoutVisualText() {
&(run->glyph_count));
if (hr == E_OUTOFMEMORY) {
max_glyphs *= 2;
+ continue;
+ } else 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
- //
- // If there are missing glyphs, use font linking to try to find a
- // matching font.
- bool glyphs_missing = false;
- for (int i = 0; i < run->glyph_count; i++) {
+ for (int i = 0; i < run->glyph_count; ++i) {
if (run->glyphs[i] == font_properties.wgDefault) {
glyphs_missing = true;
break;
}
}
- // No glyphs missing - good to go.
- if (!glyphs_missing)
- break;
-
- // First time through, get the linked fonts list.
- if (linked_fonts == NULL)
- linked_fonts = GetLinkedFonts(run->font);
+ }
- // None of the linked fonts worked - break out of the loop.
- if (linked_font_index == linked_fonts->size())
- break;
+ // Skip font substitution if there are no missing glyphs.
+ if (!glyphs_missing)
+ break;
- // Try the next linked font.
- run->font = linked_fonts->at(linked_font_index++);
- DeriveFontIfNecessary(font_size, run->font_style, &run->font);
- ScriptFreeCache(&run->script_cache);
- SelectObject(cached_hdc_, run->font.GetNativeFont());
- } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
- // Only try font fallback if it hasn't yet been attempted for this run.
- if (tried_fallback) {
- // 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
- // And http://maxradi.us/documents/uniscribe/
- run->script_analysis.eScript = SCRIPT_UNDEFINED;
- // Reset |hr| to 0 to not trigger the DCHECK() below when a font is
- // not found that can display the text. This is expected behavior
- // under Windows XP without additional language packs installed and
- // may also happen on newer versions when trying to display text in
- // an obscure script that the system doesn't have the right font for.
- hr = 0;
- break;
- }
+ // If there are missing glyphs, first try finding a fallback font using a
+ // meta file, if it hasn't yet been attempted for this run.
+ // TODO(msw|asvitkine): Support RenderText's font_list()?
+ // TODO(msw|asvitkine): Cache previous successful replacement fonts?
+ if (!tried_fallback) {
+ tried_fallback = true;
- // The run's font doesn't contain the required glyphs, use an alternate.
- // TODO(msw): support RenderText's font_list().
+ Font fallback_font;
if (ChooseFallbackFont(cached_hdc_, run->font, run_text, run_length,
- &run->font)) {
- DeriveFontIfNecessary(font_size, run->font_style, &run->font);
- ScriptFreeCache(&run->script_cache);
- SelectObject(cached_hdc_, run->font.GetNativeFont());
+ &fallback_font)) {
+ ApplySubstituteFont(run, fallback_font);
+ continue;
}
+ }
- tried_fallback = true;
- } else {
+ // The meta file approach did not yield a replacement font, try to find
+ // one using font linking. First time through, get the linked fonts list.
+ if (linked_fonts == NULL)
+ linked_fonts = GetLinkedFonts(run->font);
+
+ // None of the linked fonts worked, break out of the loop.
+ if (linked_font_index == linked_fonts->size()) {
+ // 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
+ // And http://maxradi.us/documents/uniscribe/
+ run->script_analysis.eScript = SCRIPT_UNDEFINED;
+ // Reset |hr| to 0 to not trigger the DCHECK() below when a font is
+ // not found that can display the text. This is expected behavior
+ // under Windows XP without additional language packs installed and
+ // may also happen on newer versions when trying to display text in
+ // an obscure script that the system doesn't have the right font for.
+ hr = 0;
break;
}
+
+ // Try the next linked font.
+ ApplySubstituteFont(run, linked_fonts->at(linked_font_index++));
}
DCHECK(SUCCEEDED(hr));
string_size_.set_height(std::max(string_size_.height(),
@@ -734,6 +730,15 @@ void RenderTextWin::LayoutVisualText() {
string_size_.set_width(preceding_run_widths);
}
+void RenderTextWin::ApplySubstituteFont(internal::TextRun* run,
+ const Font& font) {
+ const int font_size = run->font.GetFontSize();
+ run->font = font;
+ DeriveFontIfNecessary(font_size, run->font_style, &run->font);
+ ScriptFreeCache(&run->script_cache);
+ SelectObject(cached_hdc_, run->font.GetNativeFont());
+}
+
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 =
diff --git a/ui/gfx/render_text_win.h b/ui/gfx/render_text_win.h
index d79c877..6e9059e 100644
--- a/ui/gfx/render_text_win.h
+++ b/ui/gfx/render_text_win.h
@@ -95,6 +95,9 @@ class RenderTextWin : public RenderText {
void ItemizeLogicalText();
void LayoutVisualText();
+ // Helper function to update the font on a text run after font substitution.
+ void ApplySubstituteFont(internal::TextRun* run, const Font& font);
+
// Returns a vector of linked fonts corresponding to |font|.
const std::vector<Font>* GetLinkedFonts(const Font& font) const;