fonts: font linking

Huw D M Davies h.davies1 at physics.ox.ac.uk
Mon Aug 29 11:05:04 CDT 2005


        Huw Davies <huw at codeweavers.com>
        Implement font linking.
-- 
Huw Davies
huw at codeweavers.com
Index: dlls/gdi/font.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/font.c,v
retrieving revision 1.15
diff -u -p -r1.15 font.c
--- dlls/gdi/font.c	23 Aug 2005 09:38:59 -0000	1.15
+++ dlls/gdi/font.c	29 Aug 2005 16:01:53 -0000
@@ -1795,12 +1795,6 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x,
 
     if(flags & ETO_GLYPH_INDEX)
         glyphs = (const WORD*)reordered_str;
-    else if(dc->gdiFont)
-    {
-        glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
-        GetGlyphIndicesW(hdc, reordered_str, count, (WORD*)glyphs, 0);
-        flags |= ETO_GLYPH_INDEX;
-    }
 
     if(lprect)
         TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
@@ -1891,7 +1885,7 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x,
                 deltas[i] = tmpsz.cx;
             }
             
-            if (dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
+            if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
             {
                 deltas[i] = deltas[i] + dc->breakExtra;
             }
@@ -1979,8 +1973,74 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x,
         }
     }
 
-    ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
-                                 (flags & ETO_GLYPH_INDEX) ? glyphs: reordered_str, count, deltas);
+    if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
+    {
+        HFONT orig_font = dc->hFont, cur_font;
+        UINT glyph;
+        WORD *glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
+        INT span = 0, *offsets = NULL, i;
+
+        for(i = 0; i < count; i++)
+        {
+            WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
+            if(cur_font != dc->hFont)
+            {
+                if(span)
+                {
+                    if(!offsets)
+                    {
+                        int j;
+                        offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
+                        offsets[0] = 0;
+                        if(!deltas)
+                        {
+                            SIZE tmpsz;
+                            for(j = 1; j < count; j++)
+                            {
+                                GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
+                                offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
+                            }
+                        }
+                        else
+                        {
+                            for(j = 1; j < count; j++)
+                                offsets[j] = offsets[j-1] + deltas[j];
+                        }
+                    }
+                    dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
+                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
+                                           glyphs, span, deltas ? deltas + i - span : NULL);
+                    span = 0;
+                }
+                SelectObject(hdc, cur_font);
+            }
+            glyphs[span++] = glyph;
+
+            if(i == count - 1)
+            {
+                ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
+                                             y - (offsets ? offsets[count - span] * sinEsc : 0),
+                                             (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
+                                             glyphs, span, deltas ? deltas + count - span : NULL);
+                SelectObject(hdc, orig_font);
+                HeapFree(GetProcessHeap(), 0, glyphs); 
+                HeapFree(GetProcessHeap(), 0, offsets);
+           }
+        }
+    }
+    else
+    {
+        WORD *glyphs = NULL;
+        if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
+        {
+            glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
+            GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
+            flags |= ETO_GLYPH_INDEX;
+        }
+        ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
+                                     (flags & ETO_GLYPH_INDEX) ? glyphs: reordered_str, count, deltas);
+        HeapFree(GetProcessHeap(), 0, glyphs);
+    }
 
     if (lf.lfUnderline || lf.lfStrikeOut)
     {
@@ -2045,8 +2105,6 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x,
 
 done:
     HeapFree(GetProcessHeap(), 0, deltas);
-    if(glyphs && glyphs != reordered_str)
-        HeapFree(GetProcessHeap(), 0, (WORD*)glyphs);
     if(reordered_str != str)
         HeapFree(GetProcessHeap(), 0, reordered_str);
 
Index: dlls/gdi/freetype.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/freetype.c,v
retrieving revision 1.92
diff -u -p -r1.92 freetype.c
--- dlls/gdi/freetype.c	19 Aug 2005 09:58:32 -0000	1.92
+++ dlls/gdi/freetype.c	29 Aug 2005 16:01:53 -0000
@@ -219,6 +219,13 @@ typedef struct tagHFONTLIST {
     HFONT hfont;
 } HFONTLIST;
 
+typedef struct {
+    struct list entry;
+    char *file_name;
+    INT index;
+    GdiFont font;
+} CHILD_FONT;
+
 struct tagGdiFont {
     struct list entry;
     FT_Face ft_face;
@@ -239,13 +246,24 @@ struct tagGdiFont {
     SHORT yMin;
     OUTLINETEXTMETRICW *potm;
     FONTSIGNATURE fs;
+    GdiFont base_font;
+    struct list child_fonts;
+    LONG ppem;
 };
 
+typedef struct {
+    struct list entry;
+    WCHAR *font_name;
+    struct list links;
+} SYSTEM_LINKS;
+
 #define INIT_GM_SIZE 128
 
 static struct list gdi_font_list = LIST_INIT(gdi_font_list);
 static struct list unused_gdi_font_list = LIST_INIT(unused_gdi_font_list);
 #define UNUSED_CACHE_SIZE 10
+static struct list child_font_list = LIST_INIT(child_font_list);
+static struct list system_links = LIST_INIT(system_links);
 
 static struct list font_list = LIST_INIT(font_list);
 
@@ -658,6 +676,15 @@ static LPWSTR strdupW(LPWSTR p)
     return ret;
 }
 
+static LPSTR strdupA(LPSTR p)
+{
+    LPSTR ret;
+    DWORD len = (strlen(p) + 1);
+    ret = HeapAlloc(GetProcessHeap(), 0, len);
+    memcpy(ret, p, len);
+    return ret;
+}
+
 static void split_subst_info(NameCs *nc, LPSTR str)
 {
     CHAR *p = strrchr(str, ',');
@@ -804,6 +831,89 @@ static void LoadReplaceList(void)
     }
 }
 
+/*************************************************************
+ * init_system_links
+ */
+static BOOL init_system_links(void)
+{
+    static const WCHAR system_link[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
+                                        'W','i','n','d','o','w','s',' ','N','T','\\',
+                                        'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','F','o','n','t','L','i','n','k','\\',
+                                        'S','y','s','t','e','m','L','i','n','k',0};
+    HKEY hkey;
+    BOOL ret = FALSE;
+    DWORD type, max_val, max_data, val_len, data_len, index;
+    WCHAR *value, *data;
+    WCHAR *entry, *next;
+    SYSTEM_LINKS *font_link;
+
+    if(RegOpenKeyW(HKEY_LOCAL_MACHINE, system_link, &hkey) == ERROR_SUCCESS)
+    {
+        RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_val, &max_data, NULL, NULL);
+        value = HeapAlloc(GetProcessHeap(), 0, (max_val + 1) * sizeof(WCHAR));
+        data = HeapAlloc(GetProcessHeap(), 0, max_data);
+        val_len = max_val + 1;
+        data_len = max_data;
+        index = 0;
+        while(RegEnumValueW(hkey, index++, value, &val_len, NULL, &type, (LPBYTE)data, &data_len) == ERROR_SUCCESS)
+        {
+            TRACE("%s: %s\n", debugstr_w(value), debugstr_w(data));
+
+            font_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*font_link));
+            font_link->font_name = strdupW(value);
+            list_init(&font_link->links);
+            for(entry = data; entry && *entry != 0; entry = next)
+            {
+                WCHAR *face_name;
+                INT index;
+                CHILD_FONT *child_font;
+
+                while(isspaceW(*entry))
+                      entry++;
+
+                next = strchrW(entry, ' ');
+                if(next)
+                    *next++ = 0;
+                
+                face_name = strchrW(entry, ',');
+                if(!face_name)
+                    index = 0;
+                else
+                {
+                    FIXME("don't yet handle ttc's correctly in linking.  Assuming index 0\n");
+                    *face_name++ = 0;
+                    while(isspaceW(*face_name))
+                        face_name++;
+
+                    index = 0;
+                }
+                child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
+
+                /* FIXME: we should do better than this.  Probably we should search fontconfig's fontpath
+                   for the named ttf file and certainly look in Window's fonts directory */
+                child_font->file_name = wine_get_unix_file_name(entry);
+                if(!child_font->file_name)
+                {
+                    DWORD len = WideCharToMultiByte( CP_UNIXCP, 0, entry, -1, NULL, 0, NULL, NULL );
+                    child_font->file_name = HeapAlloc( GetProcessHeap(), 0, len );
+                    WideCharToMultiByte( CP_UNIXCP, 0, entry, -1, child_font->file_name, len, NULL, NULL );
+                }
+                child_font->index = index;
+                child_font->font = NULL;
+                list_add_tail(&font_link->links, &child_font->entry);
+            }
+
+            list_add_tail(&system_links, &font_link->entry);
+            val_len = max_val + 1;
+            data_len = max_data;
+        }
+              
+        HeapFree(GetProcessHeap(), 0, value);
+        HeapFree(GetProcessHeap(), 0, data);
+        RegCloseKey(hkey);
+    }
+    return ret;
+}
 
 static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
 {
@@ -1263,6 +1373,8 @@ BOOL WineEngInit(void)
     LoadReplaceList();
     update_reg_entries();
 
+    init_system_links();
+    
     ReleaseMutex(font_mutex);
     return TRUE;
 sym_not_found:
@@ -1323,8 +1435,8 @@ static FT_Face OpenFontFile(GdiFont font
 {
     FT_Error err;
     FT_Face ft_face;
-    LONG ppem;
 
+    TRACE("%s, %ld, %ld x %ld\n", debugstr_a(file), face_index, width, height);
     err = pFT_New_Face(library, file, face_index, &ft_face);
     if(err) {
         ERR("FT_New_Face rets %d\n", err);
@@ -1336,12 +1448,12 @@ static FT_Face OpenFontFile(GdiFont font
 
     if(FT_IS_SCALABLE(ft_face)) {
         /* load the VDMX table if we have one */
-        ppem = load_VDMX(font, height);
-        if(ppem == 0)
-            ppem = calc_ppem_for_height(ft_face, height);
+        font->ppem = load_VDMX(font, height);
+        if(font->ppem == 0)
+            font->ppem = calc_ppem_for_height(ft_face, height);
 
-        if((err = pFT_Set_Pixel_Sizes(ft_face, 0, ppem)) != 0)
-            WARN("FT_Set_Pixel_Sizes %d, %ld rets %x\n", 0, ppem, err);
+        if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0)
+            WARN("FT_Set_Pixel_Sizes %d, %ld rets %x\n", 0, font->ppem, err);
     } else {
         if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
             WARN("FT_Set_Pixel_Sizes %ld, %ld rets %x\n", width, height, err);
@@ -1393,11 +1505,29 @@ static GdiFont alloc_font(void)
     ret->potm = NULL;
     ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
     list_init(&ret->hfontlist);
+    list_init(&ret->child_fonts);
     return ret;
 }
 
 static void free_font(GdiFont font)
 {
+    struct list *cursor, *cursor2;
+
+    LIST_FOR_EACH_SAFE(cursor, cursor2, &font->child_fonts)
+    {
+        CHILD_FONT *child = LIST_ENTRY(cursor, CHILD_FONT, entry);
+        struct list *first_hfont;
+        HFONTLIST *hfontlist;
+        list_remove(cursor);
+        first_hfont = list_head(&child->font->hfontlist);
+        hfontlist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
+        DeleteObject(hfontlist->hfont);
+        HeapFree(GetProcessHeap(), 0, hfontlist);
+        free_font(child->font);
+        HeapFree(GetProcessHeap(), 0, child->file_name);
+        HeapFree(GetProcessHeap(), 0, child);
+    }
+
     if (font->ft_face) pFT_Done_Face(font->ft_face);
     HeapFree(GetProcessHeap(), 0, font->potm);
     HeapFree(GetProcessHeap(), 0, font->name);
@@ -1634,6 +1764,37 @@ static GdiFont find_in_cache(HFONT hfont
     return NULL;
 }
 
+    
+/*************************************************************
+ * create_child_font_list
+ */
+static BOOL create_child_font_list(GdiFont font)
+{
+    BOOL ret = FALSE;
+    SYSTEM_LINKS *font_link;
+    CHILD_FONT *font_link_entry, *new_child;
+
+    LIST_FOR_EACH_ENTRY(font_link, &system_links, SYSTEM_LINKS, entry)
+    {
+        if(!strcmpW(font_link->font_name, font->name))
+        {
+            TRACE("found entry in system list\n");
+            LIST_FOR_EACH_ENTRY(font_link_entry, &font_link->links, CHILD_FONT, entry)
+            {
+                new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
+                new_child->file_name = strdupA(font_link_entry->file_name);
+                new_child->index = font_link_entry->index;
+                new_child->font = NULL;
+                list_add_tail(&font->child_fonts, &new_child->entry);
+            }
+            ret = TRUE;
+            break;
+        }
+    }
+
+    return ret;
+}
+
 /*************************************************************
  * WineEngCreateFontInstance
  *
@@ -1651,6 +1812,14 @@ GdiFont WineEngCreateFontInstance(DC *dc
     CHARSETINFO csi;
     HFONTLIST *hflist;
 
+    LIST_FOR_EACH_ENTRY(ret, &child_font_list, struct tagGdiFont, entry)
+    {
+        struct list *first_hfont = list_head(&ret->hfontlist);
+        hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry);
+        if(hflist->hfont == hfont)
+            return ret;
+    }
+
     if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
     can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
 
@@ -1894,6 +2063,7 @@ found:
     ret->name = strdupW(family->FamilyName);
     ret->underline = lf.lfUnderline ? 0xff : 0;
     ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
+    create_child_font_list(ret);
 
     TRACE("caching: gdiFont=%p  hfont=%p\n", ret, hfont);
 
@@ -3023,6 +3193,53 @@ end:
     return ret;
 }
 
+static BOOL load_child_font(GdiFont font, CHILD_FONT *child)
+{
+    HFONTLIST *hfontlist;
+    child->font = alloc_font();
+    child->font->ft_face = OpenFontFile(child->font, child->file_name, child->index, 0, -font->ppem);
+    if(!child->font->ft_face)
+        return FALSE;
+
+    child->font->orientation = font->orientation;
+    hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist));
+    hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf);
+    list_add_head(&child->font->hfontlist, &hfontlist->entry);
+    child->font->base_font = font;
+    list_add_head(&child_font_list, &child->font->entry);
+    TRACE("created child font hfont %p for base %p child %p\n", hfontlist->hfont, font, child->font);
+    return TRUE;
+}
+
+BOOL get_glyph_index_linked(GdiFont font, UINT c, GdiFont *linked_font, FT_UInt *glyph)
+{
+    FT_UInt g;
+    CHILD_FONT *child_font;
+
+    if(font->base_font)
+        font = font->base_font;
+
+    *linked_font = font;
+
+    if((*glyph = get_glyph_index(font, c)))
+        return TRUE;
+
+    LIST_FOR_EACH_ENTRY(child_font, &font->child_fonts, CHILD_FONT, entry)
+    {
+        if(!child_font->font)
+            if(!load_child_font(font, child_font))
+                continue;
+
+        g = get_glyph_index(child_font->font, c);
+        if(g)
+        {
+            *glyph = g;
+            *linked_font = child_font->font;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
 
 /*************************************************************
  * WineEngGetCharWidth
@@ -3034,14 +3251,15 @@ BOOL WineEngGetCharWidth(GdiFont font, U
     UINT c;
     GLYPHMETRICS gm;
     FT_UInt glyph_index;
+    GdiFont linked_font;
 
     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
 
     for(c = firstChar; c <= lastChar; c++) {
-        glyph_index = get_glyph_index(font, c);
-        WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
+        get_glyph_index_linked(font, c, &linked_font, &glyph_index);
+        WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
                                &gm, 0, NULL, NULL);
-	buffer[c - firstChar] = font->gm[glyph_index].adv;
+	buffer[c - firstChar] = linked_font->gm[glyph_index].adv;
     }
     return TRUE;
 }
@@ -3056,6 +3274,7 @@ BOOL WineEngGetCharABCWidths(GdiFont fon
     UINT c;
     GLYPHMETRICS gm;
     FT_UInt glyph_index;
+    GdiFont linked_font;
 
     TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
 
@@ -3063,13 +3282,13 @@ BOOL WineEngGetCharABCWidths(GdiFont fon
         return FALSE;
 
     for(c = firstChar; c <= lastChar; c++) {
-        glyph_index = get_glyph_index(font, c);
-        WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
+        get_glyph_index_linked(font, c, &linked_font, &glyph_index);
+        WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
                                &gm, 0, NULL, NULL);
-	buffer[c - firstChar].abcA = font->gm[glyph_index].lsb;
-	buffer[c - firstChar].abcB = font->gm[glyph_index].bbx;
-	buffer[c - firstChar].abcC = font->gm[glyph_index].adv - font->gm[glyph_index].lsb -
-	  font->gm[glyph_index].bbx;
+	buffer[c - firstChar].abcA = linked_font->gm[glyph_index].lsb;
+	buffer[c - firstChar].abcB = linked_font->gm[glyph_index].bbx;
+	buffer[c - firstChar].abcC = linked_font->gm[glyph_index].adv - linked_font->gm[glyph_index].lsb -
+	  linked_font->gm[glyph_index].bbx;
     }
     return TRUE;
 }
@@ -3085,6 +3304,7 @@ BOOL WineEngGetTextExtentPoint(GdiFont f
     GLYPHMETRICS gm;
     TEXTMETRICW tm;
     FT_UInt glyph_index;
+    GdiFont linked_font;
 
     TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count,
 	  size);
@@ -3094,10 +3314,10 @@ BOOL WineEngGetTextExtentPoint(GdiFont f
     size->cy = tm.tmHeight;
 
     for(idx = 0; idx < count; idx++) {
-	glyph_index = get_glyph_index(font, wstr[idx]);
-        WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
+        get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
+        WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
                                &gm, 0, NULL, NULL);
-	size->cx += font->gm[glyph_index].adv;
+	size->cx += linked_font->gm[glyph_index].adv;
     }
     TRACE("return %ld,%ld\n", size->cx, size->cy);
     return TRUE;
@@ -3201,6 +3421,42 @@ UINT WineEngGetTextCharsetInfo(GdiFont f
     return font->charset;
 }
 
+BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
+{
+    GdiFont font = dc->gdiFont, linked_font;
+    struct list *first_hfont;
+    BOOL ret;
+
+    ret = get_glyph_index_linked(font, c, &linked_font, glyph);
+
+    if(font == linked_font)
+        *new_hfont = dc->hFont;
+    else
+    {
+        first_hfont = list_head(&linked_font->hfontlist);
+        *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont;
+    }
+
+    return ret;
+}
+    
+
+/*************************************************************
+ *     FontIsLinked
+ */
+BOOL WINAPI FontIsLinked(HDC hdc)
+{
+    DC *dc = DC_GetDCPtr(hdc);
+    BOOL ret = FALSE;
+
+    if(!dc) return FALSE;
+    if(dc->gdiFont && !list_empty(&dc->gdiFont->child_fonts))
+        ret = TRUE;
+    GDI_ReleaseObj(hdc);
+    TRACE("returning %d\n", ret);
+    return ret;
+}
+
 #else /* HAVE_FREETYPE */
 
 BOOL WineEngInit(void)
@@ -3307,4 +3563,13 @@ UINT WineEngGetTextCharsetInfo(GdiFont f
     return DEFAULT_CHARSET;
 }
 
+BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
+{
+    return FALSE;
+}
+
+BOOL WINAPI FontIsLinked(HDC hdc)
+{
+    return FALSE;
+}
 #endif /* HAVE_FREETYPE */
Index: dlls/gdi/gdi32.spec
===================================================================
RCS file: /home/wine/wine/dlls/gdi/gdi32.spec,v
retrieving revision 1.51
diff -u -p -r1.51 gdi32.spec
--- dlls/gdi/gdi32.spec	15 Aug 2005 09:45:40 -0000	1.51
+++ dlls/gdi/gdi32.spec	29 Aug 2005 16:01:53 -0000
@@ -125,7 +125,7 @@
 @ stdcall FixBrushOrgEx(long long long ptr)
 @ stdcall FlattenPath(long)
 @ stdcall FloodFill(long long long long)
-# @ stub FontIsLinked
+@ stdcall FontIsLinked(long)
 @ stdcall FrameRgn(long long long long long)
 @ stub FreeImageColorMatcher
 # @ stub GdiAddFontResourceW
Index: dlls/gdi/gdi_private.h
===================================================================
RCS file: /home/wine/wine/dlls/gdi/gdi_private.h,v
retrieving revision 1.26
diff -u -p -r1.26 gdi_private.h
--- dlls/gdi/gdi_private.h	23 Aug 2005 09:38:59 -0000	1.26
+++ dlls/gdi/gdi_private.h	29 Aug 2005 16:01:53 -0000
@@ -366,6 +366,7 @@ extern DWORD WineEngGetGlyphIndices(GdiF
 extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format,
                                     LPGLYPHMETRICS, DWORD buflen, LPVOID buf,
                                     const MAT2*);
+extern BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph);
 extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW);
 extern UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags);
 extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE);
@@ -431,3 +432,5 @@ extern BOOL REGION_FrameRgn( HRGN dest, 
 /* Undocumented value for DIB's iUsage: Indicates a mono DIB w/o pal enties */
 #define DIB_PAL_MONO 2
 #endif /* __WINE_GDI_PRIVATE_H */
+
+BOOL WINAPI FontIsLinked(HDC);



More information about the wine-patches mailing list