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