[Wine-patches] [eterhack] gdi32: Fix problems with "Symbol type A" font (eterbug #2609).

Alexander Morozov amorozov на etersoft.ru
Пт Июл 31 20:14:39 MSD 2009


----------- следующая часть -----------
From 9e2212922d1bec8c65ad56591e5c347d44e86e39 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Fri, 31 Jul 2009 19:47:46 +0400
Subject: [eterhack] gdi32: Fix problems with "Symbol type A" font (eterbug #2609).

---
 dlls/gdi32/freetype.c |  128 +++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 107 insertions(+), 21 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index a4a2068..0a3194a 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -4487,19 +4487,36 @@ static FT_UInt get_GSUB_vert_glyph(const GdiFont *font, UINT glyph)
 
 static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph)
 {
-    FT_UInt glyphId;
+    FT_UInt glyphId = 0;
 
-    if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
+    if(font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
+    {
+        if(glyph < 0x100)
+            glyphId = pFT_Get_Char_Index(font->ft_face, glyph + 0xf000);
+        if(glyph >= 0xf020 && glyph < 0xf100)
+            glyphId = pFT_Get_Char_Index(font->ft_face, glyph - 0xf000);
+        if(glyphId)
+            return get_GSUB_vert_glyph(font,glyphId);
+    }
+
+    if(font->ft_face->charmap->encoding == FT_ENCODING_NONE ||
+       font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
+    {
         WCHAR wc = (WCHAR)glyph;
         BOOL default_used;
         BOOL *default_used_pointer;
         FT_UInt ret;
         char buf;
+        UINT codepage;
         default_used_pointer = NULL;
         default_used = FALSE;
         if (codepage_sets_default_used(font->codepage))
             default_used_pointer = &default_used;
-        if(!WideCharToMultiByte(font->codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
+        if (font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
+            codepage = CP_ACP;
+        else
+            codepage = font->codepage;
+        if(!WideCharToMultiByte(codepage, 0, &wc, 1, &buf, sizeof(buf), NULL, default_used_pointer) || default_used)
             ret = 0;
         else
             ret = pFT_Get_Char_Index(font->ft_face, (unsigned char)buf);
@@ -4507,8 +4524,6 @@ static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph)
         return get_GSUB_vert_glyph(font,ret);
     }
 
-    if(font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL && glyph < 0x100)
-        glyph = glyph + 0xf000;
     glyphId = pFT_Get_Char_Index(font->ft_face, glyph);
     return get_GSUB_vert_glyph(font,glyphId);
 }
@@ -6135,6 +6150,31 @@ BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
     LeaveCriticalSection( &freetype_cs );
     return ret;
 }
+
+int cmp_wchar(const void *w1, const void *w2)
+{
+    return *(WCHAR *)w1 - *(WCHAR *)w2;
+}
+
+void add_glyph(GLYPHSET *gs, FT_ULong char_code, FT_ULong char_code_prev,
+               DWORD *num_ranges)
+{
+    if (char_code - char_code_prev > 1)
+    {
+        ++*num_ranges;
+        if (gs)
+        {
+            gs->ranges[*num_ranges - 1].wcLow = (USHORT)char_code;
+            gs->ranges[*num_ranges - 1].cGlyphs = 1;
+            gs->cGlyphsSupported++;
+        }
+    }
+    else if (gs)
+    {
+        gs->ranges[*num_ranges - 1].cGlyphs++;
+        gs->cGlyphsSupported++;
+    }
+}
     
 /* Retrieve a list of supported Unicode ranges for a given font.
  * Can be called with NULL gs to calculate the buffer size. Returns
@@ -6144,7 +6184,9 @@ static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
 {
     DWORD num_ranges = 0;
 
-    if (face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char)
+    if (!pFT_Get_First_Char) return 0;
+
+    if (face->charmap->encoding == FT_ENCODING_UNICODE)
     {
         FT_UInt glyph_code;
         FT_ULong char_code, char_code_prev;
@@ -6172,25 +6214,69 @@ static DWORD get_font_unicode_ranges(FT_Face face, GLYPHSET *gs)
                 ERR("expected increasing char code from FT_Get_Next_Char\n");
                 return 0;
             }
-            if (char_code - char_code_prev > 1)
-            {
-                num_ranges++;
-                if (gs)
-                {
-                    gs->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
-                    gs->ranges[num_ranges - 1].cGlyphs = 1;
-                    gs->cGlyphsSupported++;
-                }
-            }
-            else if (gs)
-            {
-                gs->ranges[num_ranges - 1].cGlyphs++;
-                gs->cGlyphsSupported++;
-            }
+            add_glyph(gs, char_code, char_code_prev, &num_ranges);
             char_code_prev = char_code;
             char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
         }
     }
+    else if (face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
+    {
+        FT_UInt glyph_code = 0;
+        FT_ULong char_code, prev_char, cur_char;
+        ULONG p;
+        WCHAR wchars[0x1e0];
+        unsigned char chars[0x100];
+
+        char_code = pFT_Get_First_Char(face, &glyph_code);
+
+        TRACE("face encoding FT_ENCODING_MS_SYMBOL, number of glyphs %ld, first glyph %u, first char %04lx\n",
+               face->num_glyphs, glyph_code, char_code);
+
+        if (!glyph_code) return 0;
+
+        for (p = 0; p < 0x100; ++p) chars[p] = p;
+        MultiByteToWideChar(CP_ACP, 0, (LPSTR)chars, 0x100, wchars, 0x100);
+        MultiByteToWideChar(CP_SYMBOL, 0, (LPSTR)chars + 0x20, 0xe0, wchars + 0x100, 0xe0);
+        qsort(wchars, 0x1e0, sizeof(WCHAR), cmp_wchar);
+
+        while (glyph_code && char_code < 0x100)
+            char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
+
+        if (wchars[0] <= char_code || !glyph_code)
+        {
+            cur_char = wchars[0];
+            p = 1;
+        }
+        else
+        {
+            cur_char = char_code;
+            p = 0;
+        }
+        prev_char = cur_char;
+        if (gs)
+        {
+            gs->ranges[0].wcLow = cur_char;
+            gs->ranges[0].cGlyphs = 0;
+            gs->cGlyphsSupported = 0;
+        }
+        num_ranges = 1;
+        while (glyph_code || p <= 0x1e0)
+        {
+            if (cur_char < prev_char)
+            {
+                ERR("expected increasing char code\n");
+                return 0;
+            }
+            add_glyph(gs, cur_char, prev_char, &num_ranges);
+            prev_char = cur_char;
+            if (cur_char == char_code)
+                char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
+            if ((p < 0x1e0 && wchars[p] <= char_code) || !glyph_code)
+                cur_char = wchars[p++];
+            else
+                cur_char = char_code;
+        }
+    }
     else
         FIXME("encoding %u not supported\n", face->charmap->encoding);
 
-- 
1.6.3.3



Подробная информация о списке рассылки Wine-patches