Commit 3915b167 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

Add infrastructure for font linking. WineEngGetLinkedHFont will be

used by ExtTextOut to provide an HFONT that will contain a valid glyph.
parent 4b1a8436
...@@ -247,6 +247,8 @@ struct tagGdiFont { ...@@ -247,6 +247,8 @@ struct tagGdiFont {
SHORT yMin; SHORT yMin;
OUTLINETEXTMETRICW *potm; OUTLINETEXTMETRICW *potm;
FONTSIGNATURE fs; FONTSIGNATURE fs;
GdiFont base_font;
struct list child_fonts;
LONG ppem; LONG ppem;
}; };
...@@ -261,6 +263,7 @@ typedef struct { ...@@ -261,6 +263,7 @@ typedef struct {
static struct list gdi_font_list = LIST_INIT(gdi_font_list); static struct list gdi_font_list = LIST_INIT(gdi_font_list);
static struct list unused_gdi_font_list = LIST_INIT(unused_gdi_font_list); static struct list unused_gdi_font_list = LIST_INIT(unused_gdi_font_list);
#define UNUSED_CACHE_SIZE 10 #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 system_links = LIST_INIT(system_links);
static struct list font_list = LIST_INIT(font_list); static struct list font_list = LIST_INIT(font_list);
...@@ -1588,11 +1591,29 @@ static GdiFont alloc_font(void) ...@@ -1588,11 +1591,29 @@ static GdiFont alloc_font(void)
ret->potm = NULL; ret->potm = NULL;
ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0; ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
list_init(&ret->hfontlist); list_init(&ret->hfontlist);
list_init(&ret->child_fonts);
return ret; return ret;
} }
static void free_font(GdiFont font) 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); if (font->ft_face) pFT_Done_Face(font->ft_face);
HeapFree(GetProcessHeap(), 0, font->potm); HeapFree(GetProcessHeap(), 0, font->potm);
HeapFree(GetProcessHeap(), 0, font->name); HeapFree(GetProcessHeap(), 0, font->name);
...@@ -1829,6 +1850,38 @@ static GdiFont find_in_cache(HFONT hfont, LOGFONTW *plf, XFORM *pxf, BOOL can_us ...@@ -1829,6 +1850,38 @@ static GdiFont find_in_cache(HFONT hfont, LOGFONTW *plf, XFORM *pxf, BOOL can_us
return NULL; 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 * WineEngCreateFontInstance
* *
...@@ -1846,6 +1899,14 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) ...@@ -1846,6 +1899,14 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
CHARSETINFO csi; CHARSETINFO csi;
HFONTLIST *hflist; 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; if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE; can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
...@@ -1922,7 +1983,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) ...@@ -1922,7 +1983,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
if(!strcmpiW(family->FamilyName, lf.lfFaceName)) { if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
LIST_FOR_EACH(face_elem_ptr, &family->faces) { LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry); 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) if(face->scalable || can_use_bitmap)
goto found; goto found;
} }
...@@ -1958,7 +2019,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) ...@@ -1958,7 +2019,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
if(!strcmpiW(family->FamilyName, lf.lfFaceName)) { if(!strcmpiW(family->FamilyName, lf.lfFaceName)) {
LIST_FOR_EACH(face_elem_ptr, &family->faces) { LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry); 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) if(face->scalable || can_use_bitmap)
goto found; goto found;
} }
...@@ -1969,7 +2030,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) ...@@ -1969,7 +2030,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
family = LIST_ENTRY(family_elem_ptr, Family, entry); family = LIST_ENTRY(family_elem_ptr, Family, entry);
LIST_FOR_EACH(face_elem_ptr, &family->faces) { LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry); 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) if(face->scalable || can_use_bitmap)
goto found; goto found;
} }
...@@ -2002,7 +2063,7 @@ found: ...@@ -2002,7 +2063,7 @@ found:
LIST_FOR_EACH(face_elem_ptr, &family->faces) { LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry); face = LIST_ENTRY(face_elem_ptr, Face, entry);
if(!(face->Italic ^ it) && !(face->Bold ^ bd) && 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) if(face->scalable)
break; break;
if(height > 0) if(height > 0)
...@@ -2026,7 +2087,7 @@ found: ...@@ -2026,7 +2087,7 @@ found:
best = NULL; best = NULL;
LIST_FOR_EACH(face_elem_ptr, &family->faces) { LIST_FOR_EACH(face_elem_ptr, &family->faces) {
face = LIST_ENTRY(face_elem_ptr, Face, entry); 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) if(face->scalable)
break; break;
if(height > 0) if(height > 0)
...@@ -2089,6 +2150,7 @@ found: ...@@ -2089,6 +2150,7 @@ found:
ret->name = strdupW(family->FamilyName); ret->name = strdupW(family->FamilyName);
ret->underline = lf.lfUnderline ? 0xff : 0; ret->underline = lf.lfUnderline ? 0xff : 0;
ret->strikeout = lf.lfStrikeOut ? 0xff : 0; ret->strikeout = lf.lfStrikeOut ? 0xff : 0;
create_child_font_list(ret);
TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont); TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont);
...@@ -3218,6 +3280,55 @@ end: ...@@ -3218,6 +3280,55 @@ end:
return ret; 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 * WineEngGetCharWidth
...@@ -3396,6 +3507,25 @@ UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags) ...@@ -3396,6 +3507,25 @@ UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
return font->charset; 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 */ #else /* HAVE_FREETYPE */
BOOL WineEngInit(void) BOOL WineEngInit(void)
...@@ -3502,4 +3632,8 @@ UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags) ...@@ -3502,4 +3632,8 @@ UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
return DEFAULT_CHARSET; return DEFAULT_CHARSET;
} }
BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph)
{
return FALSE;
}
#endif /* HAVE_FREETYPE */ #endif /* HAVE_FREETYPE */
...@@ -366,6 +366,7 @@ extern DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count, ...@@ -366,6 +366,7 @@ extern DWORD WineEngGetGlyphIndices(GdiFont font, LPCWSTR lpstr, INT count,
extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format, extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format,
LPGLYPHMETRICS, DWORD buflen, LPVOID buf, LPGLYPHMETRICS, DWORD buflen, LPVOID buf,
const MAT2*); const MAT2*);
extern BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph);
extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW); extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW);
extern UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags); extern UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags);
extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE); extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment