fonts: linking #3
Huw D M Davies
h.davies1 at physics.ox.ac.uk
Tue Sep 6 08:03:03 CDT 2005
Huw Davies <huw at codeweavers.com>
Add infrastructure for font linking. WineEngGetLinkedHFont
will be used by ExtTextOut to provide an HFONT that will
contain a valid glyph.
--
Huw Davies
huw at codeweavers.com
--- dlls/gdi/freetype.c 2005-09-06 12:16:39.031822718 +0100
+++ dlls/gdi/freetype.c 2005-09-06 12:32:26.272468016 +0100
@@ -247,6 +247,8 @@ struct tagGdiFont {
SHORT yMin;
OUTLINETEXTMETRICW *potm;
FONTSIGNATURE fs;
+ GdiFont base_font;
+ struct list child_fonts;
LONG ppem;
};
@@ -261,6 +263,7 @@ typedef struct {
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);
@@ -1588,11 +1591,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);
@@ -1829,6 +1850,38 @@ 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);
+ TRACE("font %s %d\n", debugstr_a(new_child->file_name), new_child->index);
+ }
+ ret = TRUE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
/*************************************************************
* WineEngCreateFontInstance
*
@@ -1846,6 +1899,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;
@@ -1922,7 +1983,7 @@ GdiFont WineEngCreateFontInstance(DC *dc
if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry);
- if((csi.fs.fsCsb[0] & face->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
+ if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])
if(face->scalable || can_use_bitmap)
goto found;
}
@@ -1958,7 +2019,7 @@ GdiFont WineEngCreateFontInstance(DC *dc
if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry);
- if(csi.fs.fsCsb[0] & face->fs.fsCsb[0])
+ if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
if(face->scalable || can_use_bitmap)
goto found;
}
@@ -1969,7 +2030,7 @@ GdiFont WineEngCreateFontInstance(DC *dc
family = LIST_ENTRY(family_elem_ptr, Family, entry);
LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry);
- if(csi.fs.fsCsb[0] & face->fs.fsCsb[0])
+ if(csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0]))
if(face->scalable || can_use_bitmap)
goto found;
}
@@ -2002,7 +2063,7 @@ found:
LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry);
if(!(face->Italic ^ it) && !(face->Bold ^ bd) &&
- ((csi.fs.fsCsb[0] & face->fs.fsCsb[0]) || !csi.fs.fsCsb[0])) {
+ ((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0])) {
if(face->scalable)
break;
if(height > 0)
@@ -2026,7 +2087,7 @@ found:
best = NULL;
LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry);
- if((csi.fs.fsCsb[0] & face->fs.fsCsb[0]) || !csi.fs.fsCsb[0]) {
+ if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0]) {
if(face->scalable)
break;
if(height > 0)
@@ -2089,6 +2150,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);
@@ -3218,6 +3280,55 @@ 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;
+}
+
+static 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;
+
+ if(!child_font->font->ft_face)
+ continue;
+ g = get_glyph_index(child_font->font, c);
+ if(g)
+ {
+ *glyph = g;
+ *linked_font = child_font->font;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
/*************************************************************
* WineEngGetCharWidth
@@ -3396,6 +3507,25 @@ 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);
+ TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font);
+ 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;
+}
+
#else /* HAVE_FREETYPE */
BOOL WineEngInit(void)
@@ -3502,4 +3632,8 @@ UINT WineEngGetTextCharsetInfo(GdiFont f
return DEFAULT_CHARSET;
}
+BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
+{
+ return FALSE;
+}
#endif /* HAVE_FREETYPE */
Index: 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 6 Sep 2005 12:56:27 -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);
More information about the wine-patches
mailing list