Akihiro Sagawa : gdi32: Use ANSI character code as glyph index for bitmap fonts.

Alexandre Julliard julliard at winehq.org
Wed Dec 11 13:05:46 CST 2013


Module: wine
Branch: master
Commit: a88a121059a51f6370daa85c2990c202b4e93ac9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a88a121059a51f6370daa85c2990c202b4e93ac9

Author: Akihiro Sagawa <sagawa.aki at gmail.com>
Date:   Wed Dec 11 21:11:17 2013 +0900

gdi32: Use ANSI character code as glyph index for bitmap fonts.

---

 dlls/gdi32/freetype.c   |   10 +++-
 dlls/gdi32/tests/font.c |  129 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 716c74d..bbf5847 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -6216,8 +6216,14 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
           font->font_desc.matrix.eM21, font->font_desc.matrix.eM22);
 
     if(format & GGO_GLYPH_INDEX) {
-        glyph_index = glyph;
-        original_index = glyph;
+        if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) {
+            /* Windows bitmap font, e.g. Small Fonts, uses ANSI character code
+               as glyph index. "Tresure Adventure Game" depends on this. */
+            glyph_index = pFT_Get_Char_Index(font->ft_face, glyph);
+            TRACE("translate glyph index %04x -> %04x\n", glyph, glyph_index);
+        } else
+            glyph_index = glyph;
+        original_index = glyph_index;
 	format &= ~GGO_GLYPH_INDEX;
         /* TODO: Window also turns off tategaki for glyphs passed in by index
             if their unicode code points fall outside of the range that is
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index a629b10..cbeb9c3 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -5704,6 +5704,134 @@ static void test_fake_bold_font(void)
 
 }
 
+static void test_bitmap_font_glyph_index(void)
+{
+    const WCHAR text[] = {'#','!','/','b','i','n','/','s','h',0};
+    const struct {
+        LPCSTR face;
+        BYTE charset;
+    } bitmap_font_list[] = {
+        { "Courier", ANSI_CHARSET },
+        { "Small Fonts", ANSI_CHARSET },
+        { "Fixedsys", DEFAULT_CHARSET },
+        { "System", DEFAULT_CHARSET }
+    };
+    HDC hdc;
+    LOGFONTA lf;
+    HFONT hFont;
+    CHAR facename[LF_FACESIZE];
+    BITMAPINFO bmi;
+    HBITMAP hBmp[2];
+    void *pixels[2];
+    int i, j;
+    DWORD ret;
+    BITMAP bmp;
+    TEXTMETRICA tm;
+    CHARSETINFO ci;
+    BYTE chr = '\xA9';
+
+    hdc = CreateCompatibleDC(0);
+    ok(hdc != NULL, "CreateCompatibleDC failed\n");
+
+    memset(&bmi, 0, sizeof(bmi));
+    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bmi.bmiHeader.biBitCount = 32;
+    bmi.bmiHeader.biPlanes = 1;
+    bmi.bmiHeader.biWidth = 128;
+    bmi.bmiHeader.biHeight = 32;
+    bmi.bmiHeader.biCompression = BI_RGB;
+
+    for (i = 0; i < sizeof(bitmap_font_list)/sizeof(bitmap_font_list[0]); i++) {
+        memset(&lf, 0, sizeof(lf));
+        lf.lfCharSet = bitmap_font_list[i].charset;
+        strcpy(lf.lfFaceName, bitmap_font_list[i].face);
+        hFont = CreateFontIndirectA(&lf);
+        ok(hFont != NULL, "Can't create font (%s:%d)\n", lf.lfFaceName, lf.lfCharSet);
+        hFont = SelectObject(hdc, hFont);
+        ret = GetTextMetricsA(hdc, &tm);
+        ok(ret, "GetTextMetric failed\n");
+        ret = GetTextFaceA(hdc, sizeof(facename), facename);
+        ok(ret, "GetTextFace failed\n");
+        if (tm.tmPitchAndFamily & TMPF_TRUETYPE) {
+            skip("TrueType font (%s) was selected for \"%s\"\n", facename, bitmap_font_list[i].face);
+            continue;
+        }
+        if (lstrcmpiA(facename, lf.lfFaceName) != 0) {
+            skip("expected %s, got %s\n", lf.lfFaceName, facename);
+            continue;
+        }
+
+        for (j = 0; j < 2; j++) {
+            HBITMAP hBmpPrev;
+            hBmp[j] = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pixels[j], NULL, 0);
+            ok(hBmp[j] != NULL, "Can't create DIB\n");
+            hBmpPrev = SelectObject(hdc, hBmp[j]);
+            switch (j) {
+            case 0:
+                ret = ExtTextOutW(hdc, 0, 0, 0, NULL, text, lstrlenW(text), NULL);
+                break;
+            case 1:
+            {
+                int len = lstrlenW(text);
+                LPWORD indices = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WORD));
+                ret = GetGlyphIndicesW(hdc, text, len, indices, 0);
+                ok(ret, "GetGlyphIndices failed\n");
+                ok(memcmp(indices, text, sizeof(WORD) * len) == 0,
+                   "Glyph indices and text are different for %s:%d\n", lf.lfFaceName, tm.tmCharSet);
+                ret = ExtTextOutW(hdc, 0, 0, ETO_GLYPH_INDEX, NULL, indices, len, NULL);
+                HeapFree(GetProcessHeap(), 0, indices);
+                break;
+            }
+            }
+            ok(ret, "ExtTextOutW failed\n");
+            SelectObject(hdc, hBmpPrev);
+        }
+
+        GetObjectA(hBmp[0], sizeof(bmp), &bmp);
+        ok(memcmp(pixels[0], pixels[1], bmp.bmHeight * bmp.bmWidthBytes) == 0,
+           "Images are different (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
+
+        ret = TranslateCharsetInfo((LPDWORD)(DWORD_PTR)tm.tmCharSet, &ci, TCI_SRCCHARSET);
+        if (!ret) {
+            skip("Can't get charset info for (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
+            goto next;
+        }
+        if (IsDBCSLeadByteEx(ci.ciACP, chr)) {
+            skip("High-ascii character is not defined in codepage %d\n", ci.ciACP);
+            goto next;
+        }
+
+        for (j = 0; j < 2; j++) {
+            HBITMAP hBmpPrev;
+            WORD code;
+            hBmpPrev = SelectObject(hdc, hBmp[j]);
+            switch (j) {
+            case 0:
+                ret = ExtTextOutA(hdc, 100, 0, 0, NULL, (LPCSTR)&chr, 1, NULL);
+                break;
+            case 1:
+                ret = GetGlyphIndicesA(hdc, (LPCSTR)&chr, 1, &code, 0);
+                ok(ret, "GetGlyphIndices failed\n");
+                ok(code == chr, "expected %02x, got %02x (%s:%d)\n", chr, code, lf.lfFaceName, tm.tmCharSet);
+                ret = ExtTextOutA(hdc, 100, 0, ETO_GLYPH_INDEX, NULL, (LPCSTR)&code, 1, NULL);
+                break;
+            }
+            ok(ret, "ExtTextOutA failed\n");
+            SelectObject(hdc, hBmpPrev);
+        }
+
+        ok(memcmp(pixels[0], pixels[1], bmp.bmHeight * bmp.bmWidthBytes) == 0,
+           "Images are different (%s:%d)\n", lf.lfFaceName, tm.tmCharSet);
+    next:
+        for (j = 0; j < 2; j++)
+            DeleteObject(hBmp[j]);
+        hFont = SelectObject(hdc, hFont);
+        DeleteObject(hFont);
+    }
+
+    DeleteDC(hdc);
+}
+
 START_TEST(font)
 {
     init();
@@ -5764,6 +5892,7 @@ START_TEST(font)
     test_vertical_order();
     test_GetCharWidth32();
     test_fake_bold_font();
+    test_bitmap_font_glyph_index();
 
     /* These tests should be last test until RemoveFontResource
      * is properly implemented.




More information about the wine-cvs mailing list