Commit e0872b64 authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Move the text metrics cache into the generic font structure.

parent a89595a2
...@@ -463,14 +463,20 @@ void free_gdi_font( struct gdi_font *font ) ...@@ -463,14 +463,20 @@ void free_gdi_font( struct gdi_font *font )
if (font->private) font_funcs->destroy_font( font ); if (font->private) font_funcs->destroy_font( font );
free_font_handle( font->handle ); free_font_handle( font->handle );
for (i = 0; i < font->gm_size; i++) HeapFree( GetProcessHeap(), 0, font->gm[i] ); for (i = 0; i < font->gm_size; i++) HeapFree( GetProcessHeap(), 0, font->gm[i] );
HeapFree( GetProcessHeap(), 0, font->otm.otmpFamilyName );
HeapFree( GetProcessHeap(), 0, font->otm.otmpStyleName );
HeapFree( GetProcessHeap(), 0, font->otm.otmpFaceName );
HeapFree( GetProcessHeap(), 0, font->otm.otmpFullName );
HeapFree( GetProcessHeap(), 0, font->gm ); HeapFree( GetProcessHeap(), 0, font->gm );
HeapFree( GetProcessHeap(), 0, font->name );
HeapFree( GetProcessHeap(), 0, font ); HeapFree( GetProcessHeap(), 0, font );
} }
void set_gdi_font_name( struct gdi_font *font, const WCHAR *name ) void set_gdi_font_names( struct gdi_font *font, const WCHAR *family_name, const WCHAR *style_name,
const WCHAR *full_name )
{ {
font->name = strdupW( name ); font->otm.otmpFamilyName = (char *)strdupW( family_name );
font->otm.otmpStyleName = (char *)strdupW( style_name );
font->otm.otmpFaceName = (char *)strdupW( full_name );
} }
struct glyph_metrics struct glyph_metrics
...@@ -1187,13 +1193,77 @@ static DWORD CDECL font_GetKerningPairs( PHYSDEV dev, DWORD count, KERNINGPAIR * ...@@ -1187,13 +1193,77 @@ static DWORD CDECL font_GetKerningPairs( PHYSDEV dev, DWORD count, KERNINGPAIR *
} }
static void scale_outline_font_metrics( const struct gdi_font *font, OUTLINETEXTMETRICW *otm )
{
double scale_x, scale_y;
if (font->aveWidth)
{
scale_x = (double)font->aveWidth;
scale_x /= (double)font->otm.otmTextMetrics.tmAveCharWidth;
}
else
scale_x = font->scale_y;
scale_x *= fabs(font->matrix.eM11);
scale_y = font->scale_y * fabs(font->matrix.eM22);
/* Windows scales these values as signed integers even if they are unsigned */
#define SCALE_X(x) (x) = GDI_ROUND((int)(x) * (scale_x))
#define SCALE_Y(y) (y) = GDI_ROUND((int)(y) * (scale_y))
SCALE_Y(otm->otmTextMetrics.tmHeight);
SCALE_Y(otm->otmTextMetrics.tmAscent);
SCALE_Y(otm->otmTextMetrics.tmDescent);
SCALE_Y(otm->otmTextMetrics.tmInternalLeading);
SCALE_Y(otm->otmTextMetrics.tmExternalLeading);
SCALE_X(otm->otmTextMetrics.tmOverhang);
if (font->fake_bold)
{
if (!font->scalable) otm->otmTextMetrics.tmOverhang++;
otm->otmTextMetrics.tmAveCharWidth++;
otm->otmTextMetrics.tmMaxCharWidth++;
}
SCALE_X(otm->otmTextMetrics.tmAveCharWidth);
SCALE_X(otm->otmTextMetrics.tmMaxCharWidth);
SCALE_Y(otm->otmAscent);
SCALE_Y(otm->otmDescent);
SCALE_Y(otm->otmLineGap);
SCALE_Y(otm->otmsCapEmHeight);
SCALE_Y(otm->otmsXHeight);
SCALE_Y(otm->otmrcFontBox.top);
SCALE_Y(otm->otmrcFontBox.bottom);
SCALE_X(otm->otmrcFontBox.left);
SCALE_X(otm->otmrcFontBox.right);
SCALE_Y(otm->otmMacAscent);
SCALE_Y(otm->otmMacDescent);
SCALE_Y(otm->otmMacLineGap);
SCALE_X(otm->otmptSubscriptSize.x);
SCALE_Y(otm->otmptSubscriptSize.y);
SCALE_X(otm->otmptSubscriptOffset.x);
SCALE_Y(otm->otmptSubscriptOffset.y);
SCALE_X(otm->otmptSuperscriptSize.x);
SCALE_Y(otm->otmptSuperscriptSize.y);
SCALE_X(otm->otmptSuperscriptOffset.x);
SCALE_Y(otm->otmptSuperscriptOffset.y);
SCALE_Y(otm->otmsStrikeoutSize);
SCALE_Y(otm->otmsStrikeoutPosition);
SCALE_Y(otm->otmsUnderscoreSize);
SCALE_Y(otm->otmsUnderscorePosition);
#undef SCALE_X
#undef SCALE_Y
}
/************************************************************* /*************************************************************
* font_GetOutlineTextMetrics * font_GetOutlineTextMetrics
*/ */
static UINT CDECL font_GetOutlineTextMetrics( PHYSDEV dev, UINT size, OUTLINETEXTMETRICW *metrics ) static UINT CDECL font_GetOutlineTextMetrics( PHYSDEV dev, UINT size, OUTLINETEXTMETRICW *metrics )
{ {
struct font_physdev *physdev = get_font_dev( dev ); struct font_physdev *physdev = get_font_dev( dev );
UINT ret; UINT ret = 0;
if (!physdev->font) if (!physdev->font)
{ {
...@@ -1204,7 +1274,27 @@ static UINT CDECL font_GetOutlineTextMetrics( PHYSDEV dev, UINT size, OUTLINETEX ...@@ -1204,7 +1274,27 @@ static UINT CDECL font_GetOutlineTextMetrics( PHYSDEV dev, UINT size, OUTLINETEX
if (!physdev->font->scalable) return 0; if (!physdev->font->scalable) return 0;
EnterCriticalSection( &font_cs ); EnterCriticalSection( &font_cs );
ret = font_funcs->pGetOutlineTextMetrics( physdev->font, size, metrics ); if (font_funcs->set_outline_text_metrics( physdev->font ))
{
ret = physdev->font->otm.otmSize;
if (metrics && size >= physdev->font->otm.otmSize)
{
WCHAR *ptr = (WCHAR *)(metrics + 1);
*metrics = physdev->font->otm;
metrics->otmpFamilyName = (char *)ptr - (ULONG_PTR)metrics;
strcpyW( ptr, (WCHAR *)physdev->font->otm.otmpFamilyName );
ptr += strlenW(ptr) + 1;
metrics->otmpStyleName = (char *)ptr - (ULONG_PTR)metrics;
strcpyW( ptr, (WCHAR *)physdev->font->otm.otmpStyleName );
ptr += strlenW(ptr) + 1;
metrics->otmpFaceName = (char *)ptr - (ULONG_PTR)metrics;
strcpyW( ptr, (WCHAR *)physdev->font->otm.otmpFaceName );
ptr += strlenW(ptr) + 1;
metrics->otmpFullName = (char *)ptr - (ULONG_PTR)metrics;
strcpyW( ptr, (WCHAR *)physdev->font->otm.otmpFullName );
scale_outline_font_metrics( physdev->font, metrics );
}
}
LeaveCriticalSection( &font_cs ); LeaveCriticalSection( &font_cs );
return ret; return ret;
} }
...@@ -1301,23 +1391,68 @@ static INT CDECL font_GetTextFace( PHYSDEV dev, INT count, WCHAR *str ) ...@@ -1301,23 +1391,68 @@ static INT CDECL font_GetTextFace( PHYSDEV dev, INT count, WCHAR *str )
dev = GET_NEXT_PHYSDEV( dev, pGetTextFace ); dev = GET_NEXT_PHYSDEV( dev, pGetTextFace );
return dev->funcs->pGetTextFace( dev, count, str ); return dev->funcs->pGetTextFace( dev, count, str );
} }
len = strlenW( physdev->font->name ) + 1; len = strlenW( get_gdi_font_name(physdev->font) ) + 1;
if (str) if (str)
{ {
lstrcpynW( str, physdev->font->name, count ); lstrcpynW( str, get_gdi_font_name(physdev->font), count );
len = min( count, len ); len = min( count, len );
} }
return len; return len;
} }
static void scale_font_metrics( struct gdi_font *font, TEXTMETRICW *tm )
{
double scale_x, scale_y;
/* Make sure that the font has sane width/height ratio */
if (font->aveWidth && (font->aveWidth + tm->tmHeight - 1) / tm->tmHeight > 100)
{
WARN( "Ignoring too large font->aveWidth %d\n", font->aveWidth );
font->aveWidth = 0;
}
if (font->aveWidth)
{
scale_x = (double)font->aveWidth;
scale_x /= (double)font->otm.otmTextMetrics.tmAveCharWidth;
}
else
scale_x = font->scale_y;
scale_x *= fabs(font->matrix.eM11);
scale_y = font->scale_y * fabs(font->matrix.eM22);
#define SCALE_X(x) (x) = GDI_ROUND((x) * scale_x)
#define SCALE_Y(y) (y) = GDI_ROUND((y) * scale_y)
SCALE_Y(tm->tmHeight);
SCALE_Y(tm->tmAscent);
SCALE_Y(tm->tmDescent);
SCALE_Y(tm->tmInternalLeading);
SCALE_Y(tm->tmExternalLeading);
SCALE_X(tm->tmOverhang);
if (font->fake_bold)
{
if (!font->scalable) tm->tmOverhang++;
tm->tmAveCharWidth++;
tm->tmMaxCharWidth++;
}
SCALE_X(tm->tmAveCharWidth);
SCALE_X(tm->tmMaxCharWidth);
#undef SCALE_X
#undef SCALE_Y
}
/************************************************************* /*************************************************************
* font_GetTextMetrics * font_GetTextMetrics
*/ */
static BOOL CDECL font_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics ) static BOOL CDECL font_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
{ {
struct font_physdev *physdev = get_font_dev( dev ); struct font_physdev *physdev = get_font_dev( dev );
BOOL ret; BOOL ret = FALSE;
if (!physdev->font) if (!physdev->font)
{ {
...@@ -1326,7 +1461,13 @@ static BOOL CDECL font_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics ) ...@@ -1326,7 +1461,13 @@ static BOOL CDECL font_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
} }
EnterCriticalSection( &font_cs ); EnterCriticalSection( &font_cs );
ret = font_funcs->pGetTextMetrics( physdev->font, metrics ); if (font_funcs->set_outline_text_metrics( physdev->font ) ||
font_funcs->set_bitmap_text_metrics( physdev->font ))
{
*metrics = physdev->font->otm.otmTextMetrics;
scale_font_metrics( physdev->font, metrics );
ret = TRUE;
}
LeaveCriticalSection( &font_cs ); LeaveCriticalSection( &font_cs );
return ret; return ret;
} }
......
...@@ -312,6 +312,7 @@ struct gdi_font ...@@ -312,6 +312,7 @@ struct gdi_font
DWORD refcount; DWORD refcount;
DWORD gm_size; DWORD gm_size;
struct glyph_metrics **gm; struct glyph_metrics **gm;
OUTLINETEXTMETRICW otm;
/* the following members can be accessed without locking, they are never modified after creation */ /* the following members can be accessed without locking, they are never modified after creation */
void *private; /* font backend private data */ void *private; /* font backend private data */
DWORD handle; DWORD handle;
...@@ -337,7 +338,6 @@ struct gdi_font ...@@ -337,7 +338,6 @@ struct gdi_font
BOOL fake_italic : 1; BOOL fake_italic : 1;
BOOL fake_bold : 1; BOOL fake_bold : 1;
BOOL scalable : 1; BOOL scalable : 1;
WCHAR *name;
void *data_ptr; void *data_ptr;
SIZE_T data_size; SIZE_T data_size;
FILETIME writetime; FILETIME writetime;
...@@ -360,8 +360,6 @@ struct font_backend_funcs ...@@ -360,8 +360,6 @@ struct font_backend_funcs
BOOL (CDECL *pGetCharWidthInfo)( struct gdi_font *font, struct char_width_info *info ); BOOL (CDECL *pGetCharWidthInfo)( struct gdi_font *font, struct char_width_info *info );
DWORD (CDECL *pGetFontUnicodeRanges)( struct gdi_font *font, GLYPHSET *glyphset ); DWORD (CDECL *pGetFontUnicodeRanges)( struct gdi_font *font, GLYPHSET *glyphset );
DWORD (CDECL *pGetKerningPairs)( struct gdi_font *font, DWORD count, KERNINGPAIR *pairs ); DWORD (CDECL *pGetKerningPairs)( struct gdi_font *font, DWORD count, KERNINGPAIR *pairs );
UINT (CDECL *pGetOutlineTextMetrics)( struct gdi_font *font, UINT size, OUTLINETEXTMETRICW *metrics );
BOOL (CDECL *pGetTextMetrics)( struct gdi_font *font, TEXTMETRICW *metrics );
struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont, UINT *aa_flags, UINT default_aa_flags ); struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont, UINT *aa_flags, UINT default_aa_flags );
INT (CDECL *pAddFontResourceEx)( LPCWSTR file, DWORD flags, PVOID pdv ); INT (CDECL *pAddFontResourceEx)( LPCWSTR file, DWORD flags, PVOID pdv );
...@@ -377,6 +375,8 @@ struct font_backend_funcs ...@@ -377,6 +375,8 @@ struct font_backend_funcs
UINT (CDECL *get_default_glyph)( struct gdi_font *gdi_font ); UINT (CDECL *get_default_glyph)( struct gdi_font *gdi_font );
DWORD (CDECL *get_glyph_outline)( struct gdi_font *font, UINT glyph, UINT format, DWORD (CDECL *get_glyph_outline)( struct gdi_font *font, UINT glyph, UINT format,
GLYPHMETRICS *gm, ABC *abc, DWORD buflen, void *buf, const MAT2 *mat ); GLYPHMETRICS *gm, ABC *abc, DWORD buflen, void *buf, const MAT2 *mat );
BOOL (CDECL *set_outline_text_metrics)( struct gdi_font *font );
BOOL (CDECL *set_bitmap_text_metrics)( struct gdi_font *font );
void (CDECL *destroy_font)( struct gdi_font *font ); void (CDECL *destroy_font)( struct gdi_font *font );
}; };
...@@ -385,7 +385,9 @@ extern void free_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN; ...@@ -385,7 +385,9 @@ extern void free_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern void cache_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN; extern void cache_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern struct gdi_font *find_cached_gdi_font( const LOGFONTW *lf, const FMAT2 *matrix, extern struct gdi_font *find_cached_gdi_font( const LOGFONTW *lf, const FMAT2 *matrix,
BOOL can_use_bitmap ) DECLSPEC_HIDDEN; BOOL can_use_bitmap ) DECLSPEC_HIDDEN;
extern void set_gdi_font_name( struct gdi_font *font, const WCHAR *name ) DECLSPEC_HIDDEN; static inline const WCHAR *get_gdi_font_name( struct gdi_font *font ) { return (WCHAR *)font->otm.otmpFamilyName; }
extern void set_gdi_font_names( struct gdi_font *font, const WCHAR *family_name, const WCHAR *style_name,
const WCHAR *full_name ) DECLSPEC_HIDDEN;
extern BOOL get_gdi_font_glyph_metrics( struct gdi_font *font, UINT index, extern BOOL get_gdi_font_glyph_metrics( struct gdi_font *font, UINT index,
GLYPHMETRICS *gm, ABC *abc ) DECLSPEC_HIDDEN; GLYPHMETRICS *gm, ABC *abc ) DECLSPEC_HIDDEN;
extern void set_gdi_font_glyph_metrics( struct gdi_font *font, UINT index, extern void set_gdi_font_glyph_metrics( struct gdi_font *font, UINT index,
......
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