Hans Leidekker : gdi32: Implement GetFontUnicodeRanges.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Mar 2 06:14:28 CST 2007


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

Author: Hans Leidekker <hans at it.vu.nl>
Date:   Thu Mar  1 20:30:12 2007 +0100

gdi32: Implement GetFontUnicodeRanges.

---

 dlls/gdi32/font.c        |   14 ++++++-
 dlls/gdi32/freetype.c    |   91 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/gdi32/gdi_private.h |    1 +
 dlls/gdi32/tests/font.c  |   38 +++++++++++++++++++
 4 files changed, 142 insertions(+), 2 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index f237612..2578f33 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -3326,9 +3326,19 @@ BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT
 
 /***********************************************************************
  *           GetFontUnicodeRanges    (GDI32.@)
+ *
+ *  Retrieve a list of supported Unicode characters in a font.
+ *
+ *  PARAMS
+ *   hdc  [I] Handle to a device context.
+ *   lpgs [O] GLYPHSET structure specifying supported character ranges.
+ *
+ *  RETURNS
+ *   Success: Number of bytes written to the buffer pointed to by lpgs.
+ *   Failure: 0
+ *
  */
 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
 {
-    FIXME("(%p, %p): stub\n", hdc, lpgs);
-    return 0;
+    return WineEngGetFontUnicodeRanges(hdc, lpgs);
 }
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index abcc0e6..f3676af 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -4398,6 +4398,91 @@ BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
     return ret;
 }
     
+/* Retrieve a list of supported Unicode ranges for a given font.
+ * Can be called with NULL gs to calculate the buffer size. Returns
+ * the number of ranges found.
+ */
+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)
+    {
+        FT_UInt glyph_code;
+        FT_ULong char_code, char_code_prev;
+
+        glyph_code = 0;
+        char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
+
+        TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
+               face->num_glyphs, glyph_code, char_code);
+
+        if (!glyph_code) return 0;
+
+        if (gs)
+        {
+            gs->ranges[0].wcLow = (USHORT)char_code;
+            gs->ranges[0].cGlyphs = 0;
+            gs->cGlyphsSupported = 0;
+        }
+
+        num_ranges = 1;
+        while (glyph_code)
+        {
+            if (char_code < char_code_prev)
+            {
+                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++;
+            }
+            char_code_prev = char_code;
+            char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
+        }
+    }
+    else
+        FIXME("encoding %u not supported\n", face->charmap->encoding);
+
+    return num_ranges;
+}
+
+DWORD WineEngGetFontUnicodeRanges(HDC hdc, LPGLYPHSET glyphset)
+{
+    DWORD size = 0;
+    DC *dc = DC_GetDCPtr(hdc);
+
+    TRACE("(%p, %p)\n", hdc, glyphset);
+
+    if (!dc) return 0;
+
+    if (dc->gdiFont)
+    {
+        DWORD num_ranges = get_font_unicode_ranges(dc->gdiFont->ft_face, glyphset);
+
+        size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
+        if (glyphset)
+        {
+            glyphset->cbThis = size;
+            glyphset->cRanges = num_ranges;
+        }
+    }
+
+    GDI_ReleaseObj(hdc);
+    return size;
+}
 
 /*************************************************************
  *     FontIsLinked
@@ -4813,6 +4898,12 @@ BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
     return FALSE;
 }
 
+DWORD WineEngGetFontUnicodeRanges(HDC hdc, LPGLYPHSET glyphset)
+{
+    FIXME("(%p, %p): stub\n", hdc, glyphset);
+    return 0;
+}
+
 BOOL WINAPI FontIsLinked(HDC hdc)
 {
     return FALSE;
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 07e9d49..e43ac30 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -423,6 +423,7 @@ extern BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar,
                                     UINT count, LPWORD pgi, LPABC buffer);
 extern BOOL WineEngGetCharWidth(GdiFont*, UINT, UINT, LPINT);
 extern DWORD WineEngGetFontData(GdiFont*, DWORD, DWORD, LPVOID, DWORD);
+extern DWORD WineEngGetFontUnicodeRanges(HDC, LPGLYPHSET);
 extern DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count,
                                     LPWORD pgi, DWORD flags);
 extern DWORD WineEngGetGlyphOutline(GdiFont*, UINT glyph, UINT format,
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 0a9f8d3..405d4bd 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -1088,6 +1088,43 @@ static void test_font_charset(void)
         skip("Symbol or Wingdings is not installed\n");
 }
 
+static void test_GetFontUnicodeRanges(void)
+{
+    LOGFONTA lf;
+    HDC hdc;
+    HFONT hfont, hfont_old;
+    DWORD size, i;
+    GLYPHSET *gs;
+
+    memset(&lf, 0, sizeof(lf));
+    lstrcpyA(lf.lfFaceName, "Arial");
+    hfont = create_font("Arial", &lf);
+
+    hdc = GetDC(0);
+    hfont_old = SelectObject(hdc, hfont);
+
+    size = GetFontUnicodeRanges(NULL, NULL);
+    ok(!size, "GetFontUnicodeRanges succeeded unexpectedly\n");
+
+    size = GetFontUnicodeRanges(hdc, NULL);
+    ok(size, "GetFontUnicodeRanges failed unexpectedly\n");
+
+    gs = HeapAlloc(GetProcessHeap(), 0, size);
+
+    size = GetFontUnicodeRanges(hdc, gs);
+    ok(size, "GetFontUnicodeRanges failed\n");
+
+    for (i = 0; i < gs->cRanges; i++)
+        trace("%03d wcLow %04x cGlyphs %u\n", i, gs->ranges[i].wcLow, gs->ranges[i].cGlyphs);
+    trace("found %u ranges\n", gs->cRanges);
+
+    HeapFree(GetProcessHeap(), 0, gs);
+
+    SelectObject(hdc, hfont_old);
+    DeleteObject(hfont);
+    ReleaseDC(NULL, hdc);
+}
+
 START_TEST(font)
 {
     test_logfont();
@@ -1101,4 +1138,5 @@ START_TEST(font)
     test_GetOutlineTextMetrics();
     test_SetTextJustification();
     test_font_charset();
+    test_GetFontUnicodeRanges();
 }




More information about the wine-cvs mailing list