Modified: trunk/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp (101058 => 101059)
--- trunk/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp 2011-11-23 10:02:27 UTC (rev 101058)
+++ trunk/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp 2011-11-23 10:10:29 UTC (rev 101059)
@@ -106,6 +106,10 @@
*style = getStyleFromLogfont(logfont);
}
+// This memory DC will NOT be released but it's OK
+// since we want to keep it for the whole life span of the process.
+HDC UniscribeHelper::m_cachedDC = 0;
+
static bool canUseGlyphIndex(const SCRIPT_ITEM& run)
{
// On early version of Uniscribe, ScriptShape() sets run.a.fNoGlyphIndex
@@ -622,8 +626,6 @@
Vector<SCRIPT_GLYPHPROP, cUniscribeHelperStackChars> glyphProps;
int ascent = m_ascent;
WORD spaceGlyph = m_spaceGlyph;
- HDC tempDC = 0;
- HGDIOBJ oldFont = 0;
HRESULT hr;
// When used to fill up glyph pages for simple scripts in non-BMP,
// we don't want any font fallback in this class. The simple script
@@ -665,11 +667,16 @@
ZeroMemory(&shaping.m_glyphs[0],
sizeof(shaping.m_glyphs[0]) * shaping.m_glyphs.size());
#endif
+ // If our DC is already created, select the font in it so we can use it now.
+ // Otherwise, we'll create it as needed afterward...
+ if (m_cachedDC)
+ SelectObject(m_cachedDC, hfont);
+
// Firefox sets SCRIPT_ANALYSIS.SCRIPT_STATE.fDisplayZWG to true
// here. Is that what we want? It will display control characters.
if (gScriptShapeOpenTypeFunc) {
TEXTRANGE_PROPERTIES* rangeProps = m_featureRecords.size() ? &m_rangeProperties : 0;
- hr = gScriptShapeOpenTypeFunc(tempDC, scriptCache, &run.a,
+ hr = gScriptShapeOpenTypeFunc(m_cachedDC, scriptCache, &run.a,
scriptTag, 0, &itemLength,
&rangeProps, rangeProps ? 1 : 0,
input, itemLength, numGlyphs,
@@ -677,30 +684,25 @@
&shaping.m_glyphs[0], &glyphProps[0],
&generatedGlyphs);
} else {
- hr = ScriptShape(tempDC, scriptCache, input, itemLength,
+ hr = ScriptShape(m_cachedDC, scriptCache, input, itemLength,
numGlyphs, &run.a,
&shaping.m_glyphs[0], &shaping.m_logs[0],
&shaping.m_visualAttributes[0], &generatedGlyphs);
}
- if (hr == E_PENDING) {
- // Allocate the DC.
- tempDC = GetDC(0);
- oldFont = SelectObject(tempDC, hfont);
+ // We receive E_PENDING when we need to try again with a Drawing Context,
+ // but we don't want to retry again if we already tried with non-zero DC.
+ if (hr == E_PENDING && !m_cachedDC) {
+ EnsureCachedDCCreated();
continue;
- } else if (hr == E_OUTOFMEMORY) {
+ }
+ if (hr == E_OUTOFMEMORY) {
numGlyphs *= 2;
continue;
- } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(shaping, run, fontProperties) && canUseGlyphIndex(run)))
+ }
+ if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(shaping, run, fontProperties) && canUseGlyphIndex(run)))
break;
- // The current font can't render this run. clear DC and try
- // next font.
- if (tempDC) {
- SelectObject(tempDC, oldFont);
- ReleaseDC(0, tempDC);
- tempDC = 0;
- }
-
+ // The current font can't render this run, try next font.
if (!m_disableFontFallback &&
nextWinFontData(&hfont, &scriptCache, &fontProperties, &ascent)) {
// The primary font does not support this run. Try next font.
@@ -786,10 +788,7 @@
}
shaping.m_advance.resize(generatedGlyphs);
shaping.m_offsets.resize(generatedGlyphs);
- if (tempDC) {
- SelectObject(tempDC, oldFont);
- ReleaseDC(0, tempDC);
- }
+
// On failure, our logs don't mean anything, so zero those out.
if (!result)
shaping.m_logs.clear();
@@ -797,6 +796,20 @@
return result;
}
+void UniscribeHelper::EnsureCachedDCCreated()
+{
+ if (m_cachedDC)
+ return;
+ // Allocate a memory DC that is compatible with the Desktop DC since we don't have any window,
+ // and we don't want to use the Desktop DC directly since it can have nasty side effects
+ // as identified in Chrome Issue http://crbug.com/59315.
+ HDC screenDC = ::GetDC(0);
+ m_cachedDC = ::CreateCompatibleDC(screenDC);
+ ASSERT(m_cachedDC);
+
+ int result = ::ReleaseDC(0, screenDC);
+ ASSERT(result == 1);
+}
void UniscribeHelper::fillShapes()
{
m_shapes.resize(m_runs.size());
@@ -836,30 +849,15 @@
// Compute placements. Note that offsets is documented incorrectly
// and is actually an array.
-
- // DC that we lazily create if Uniscribe commands us to.
- // (this does not happen often because scriptCache is already
- // updated when calling ScriptShape).
- HDC tempDC = 0;
- HGDIOBJ oldFont = 0;
- HRESULT hr;
- while (true) {
- shaping.m_prePadding = 0;
- hr = ScriptPlace(tempDC, shaping.m_scriptCache,
- &shaping.m_glyphs[0],
- static_cast<int>(shaping.m_glyphs.size()),
- &shaping.m_visualAttributes[0], &m_runs[i].a,
- &shaping.m_advance[0], &shaping.m_offsets[0],
- &shaping.m_abc);
- if (hr != E_PENDING)
- break;
-
- // Allocate the DC and run the loop again.
- tempDC = GetDC(0);
- oldFont = SelectObject(tempDC, shaping.m_hfont);
- }
-
- if (FAILED(hr)) {
+ EnsureCachedDCCreated();
+ SelectObject(m_cachedDC, shaping.m_hfont);
+ shaping.m_prePadding = 0;
+ if (FAILED(ScriptPlace(m_cachedDC, shaping.m_scriptCache,
+ &shaping.m_glyphs[0],
+ static_cast<int>(shaping.m_glyphs.size()),
+ &shaping.m_visualAttributes[0], &m_runs[i].a,
+ &shaping.m_advance[0], &shaping.m_offsets[0],
+ &shaping.m_abc))) {
// Some error we don't know how to handle. Nuke all of our data
// since we can't deal with partially valid data later.
m_runs.clear();
@@ -867,11 +865,6 @@
m_shapes.clear();
m_screenOrder.clear();
}
-
- if (tempDC) {
- SelectObject(tempDC, oldFont);
- ReleaseDC(0, tempDC);
- }
}
adjustSpaceAdvances();