Reviewed by Darin Adler.
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 16 Dec 2007 01:33:57 +0000 (01:33 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 16 Dec 2007 01:33:57 +0000 (01:33 +0000)
        - fix <rdar://problem/5636090> Text in Georgia, Armenian, Inuktitut, Cree, or Cherokee (KA, HY, IU, CR, CHR) draws as all missing glyphs

        * platform/graphics/win/FontCacheWin.cpp:
        (WebCore::metaFileEnumProc): Added. Called during metafile record
        enumeration and extracts the font from the create font record.
        (WebCore::FontCache::getFontDataForCharacters): If font linking fails,
        let Uniscribe draw the characters and see what font it chooses.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@28765 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/platform/graphics/win/FontCacheWin.cpp

index 82210d747372d73d9568a68a7bd6f8e8937f74f9..a5b40ad35e16112e4ec7adb7cd50e80098e2f553 100644 (file)
@@ -1,3 +1,15 @@
+2007-12-15  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Darin Adler.
+
+        - fix <rdar://problem/5636090> Text in Georgia, Armenian, Inuktitut, Cree, or Cherokee (KA, HY, IU, CR, CHR) draws as all missing glyphs
+
+        * platform/graphics/win/FontCacheWin.cpp:
+        (WebCore::metaFileEnumProc): Added. Called during metafile record
+        enumeration and extracts the font from the create font record.
+        (WebCore::FontCache::getFontDataForCharacters): If font linking fails,
+        let Uniscribe draw the characters and see what font it chooses.
+
 2007-12-15  Darin Adler  <darin@apple.com>
 
         * WebCore.pro: Roll my last change out. Was wrong and didn't fix the build.
index 42c01c554485df4e0e74f78c39073525acc6d183..22e5e43e43a9f7f27b140aad4fabee9fc4d23ec8 100644 (file)
@@ -63,6 +63,15 @@ IMLangFontLink2* FontCache::getFontLinkInterface()
     return langFontLink;
 }
 
+static int CALLBACK metaFileEnumProc(HDC hdc, HANDLETABLE* table, CONST ENHMETARECORD* record, int tableEntries, LPARAM hfontPtr)
+{
+    if (record->iType == EMR_EXTCREATEFONTINDIRECTW) {
+        const EMREXTCREATEFONTINDIRECTW* createFontRecord = reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record);
+        *reinterpret_cast<HFONT*>(hfontPtr) = CreateFontIndirect(&createFontRecord->elfw.elfLogFont);
+    }
+    return true;
+}
+
 const FontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
 {
     // IMLangFontLink::MapFont Method does what we want.
@@ -89,25 +98,49 @@ const FontData* FontCache::getFontDataForCharacters(const Font& font, const UCha
             LOGFONT lf;
             GetObject(result, sizeof(LOGFONT), &lf);
             langFontLink->ReleaseFont(result);
-
             hfont = CreateFontIndirect(&lf);
-            SelectObject(hdc, hfont);
-
-            WCHAR name[LF_FACESIZE];
-            GetTextFace(hdc, LF_FACESIZE, name);
-            
-            String familyName(name);
-            if (!familyName.isEmpty()) {
-                FontPlatformData* result = getCachedFontPlatformData(font.fontDescription(), familyName);
-                if (result)
-                    fontData = getCachedFontData(result);
-            }
         }
     }
 
-    SelectObject(hdc, oldFont);
-    if (hfont)
+    if (!hfont) {
+        // Font linking failed but Uniscribe might still be able to find a fallback font.
+        // To find out what Uniscribe would do, we make it draw into a metafile and intercept
+        // calls to CreateFontIndirect().
+        HDC metaFileDc = CreateEnhMetaFile(hdc, NULL, NULL, NULL);
+        SelectObject(metaFileDc, hfont ? hfont : primaryFont);
+
+        bool scriptStringOutSucceeded = false;
+        SCRIPT_STRING_ANALYSIS ssa;
+
+        // FIXME: If length is greater than 1, we actually return the font for the last character.
+        // This function should be renamed getFontDataForCharacter and take a single 32-bit character.
+        if (SUCCEEDED(ScriptStringAnalyse(metaFileDc, characters, length, 0, -1, SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK,
+            0, NULL, NULL, NULL, NULL, NULL, &ssa))) {
+            scriptStringOutSucceeded = SUCCEEDED(ScriptStringOut(ssa, 0, 0, 0, NULL, 0, 0, FALSE));
+            ScriptStringFree(&ssa);
+        }
+        HENHMETAFILE metaFile = CloseEnhMetaFile(metaFileDc);
+        if (scriptStringOutSucceeded)
+            EnumEnhMetaFile(0, metaFile, metaFileEnumProc, &hfont, NULL);
+        DeleteEnhMetaFile(metaFile);
+    }
+
+    if (hfont) {
+        SelectObject(hdc, hfont);
+        WCHAR name[LF_FACESIZE];
+        GetTextFace(hdc, LF_FACESIZE, name);
+
+        String familyName(name);
+        if (!familyName.isEmpty()) {
+            FontPlatformData* result = getCachedFontPlatformData(font.fontDescription(), familyName);
+            if (result)
+                fontData = getCachedFontData(result);
+        }
+
+        SelectObject(hdc, oldFont);
         DeleteObject(hfont);
+    }
+
     ReleaseDC(0, hdc);
     return fontData;
 }