gdi32: Add a helper to get the FreeType face and cleanup private data.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-10-29 14:53:18 +01:00
parent 044315c0b3
commit 402281b668
1 changed files with 166 additions and 177 deletions

View File

@ -281,21 +281,21 @@ typedef struct tagFamily {
struct list *replacement;
} Family;
typedef struct tagGdiFont GdiFont;
typedef struct {
struct list entry;
Face *face;
GdiFont *font;
} CHILD_FONT;
struct tagGdiFont {
struct gdi_font *gdi_font;
struct font_private_data
{
FT_Face ft_face;
struct font_mapping *mapping;
};
static inline GdiFont *get_font_ptr( struct gdi_font *font ) { return font->private; }
static inline FT_Face get_ft_face( struct gdi_font *font )
{
return ((struct font_private_data *)font->private)->ft_face;
}
typedef struct {
struct list entry;
@ -2274,7 +2274,6 @@ static void populate_system_links(const WCHAR *name, const WCHAR *const *values)
child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
child_font->face = face;
child_font->font = NULL;
font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
TRACE("Adding file %s index %ld\n", debugstr_w(child_font->face->file),
@ -2355,7 +2354,6 @@ static void init_system_links(void)
child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
child_font->face = face;
child_font->font = NULL;
font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
TRACE("Adding file %s index %ld\n",
@ -2414,7 +2412,6 @@ skip_internal:
{
child_font = HeapAlloc(GetProcessHeap(), 0, sizeof(*child_font));
child_font->face = face;
child_font->font = NULL;
system_font_link->fs.fsCsb[0] |= face->fs.fsCsb[0];
system_font_link->fs.fsCsb[1] |= face->fs.fsCsb[1];
TRACE("Found Tahoma in %s index %ld\n",
@ -2430,7 +2427,6 @@ skip_internal:
CHILD_FONT *new_child;
new_child = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_child));
new_child->face = font_link_entry->face;
new_child->font = NULL;
new_child->face->refcount++;
system_font_link->fs.fsCsb[0] |= font_link_entry->face->fs.fsCsb[0];
system_font_link->fs.fsCsb[1] |= font_link_entry->face->fs.fsCsb[1];
@ -3222,7 +3218,7 @@ static void unmap_font_file( struct font_mapping *mapping )
}
}
static LONG load_VDMX(GdiFont*, LONG);
static LONG load_VDMX(struct gdi_font *font, LONG height);
static UINT get_nearest_charset(const WCHAR *family_name, Face *face, UINT *cp)
{
@ -3269,13 +3265,13 @@ static UINT get_nearest_charset(const WCHAR *family_name, Face *face, UINT *cp)
/*************************************************************
* freetype_destroy_font
*/
static void CDECL freetype_destroy_font( struct gdi_font *gdi_font )
static void CDECL freetype_destroy_font( struct gdi_font *font )
{
GdiFont *font = get_font_ptr( gdi_font );
struct font_private_data *data = font->private;
if (font->ft_face) pFT_Done_Face(font->ft_face);
if (font->mapping) unmap_font_file( font->mapping );
HeapFree(GetProcessHeap(), 0, font);
if (data->ft_face) pFT_Done_Face( data->ft_face );
if (data->mapping) unmap_font_file( data->mapping );
HeapFree( GetProcessHeap(), 0, data );
}
/*************************************************************
@ -3284,7 +3280,7 @@ static void CDECL freetype_destroy_font( struct gdi_font *gdi_font )
static DWORD CDECL freetype_get_font_data( struct gdi_font *font, DWORD table, DWORD offset,
void *buf, DWORD cbData)
{
FT_Face ft_face = get_font_ptr(font)->ft_face;
FT_Face ft_face = get_ft_face( font );
FT_ULong len;
FT_Error err;
@ -3354,9 +3350,8 @@ typedef struct {
WORD yMin;
} VDMX_vTable;
static LONG load_VDMX(GdiFont *font, LONG height)
static LONG load_VDMX(struct gdi_font *font, LONG height)
{
struct gdi_font *gdi_font = font->gdi_font;
VDMX_Header hdr;
VDMX_group group;
BYTE devXRatio, devYRatio;
@ -3365,7 +3360,7 @@ static LONG load_VDMX(GdiFont *font, LONG height)
LONG ppem = 0;
int i;
result = freetype_get_font_data(gdi_font, MS_VDMX_TAG, 0, &hdr, sizeof(hdr));
result = freetype_get_font_data(font, MS_VDMX_TAG, 0, &hdr, sizeof(hdr));
if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */
return ppem;
@ -3382,7 +3377,7 @@ static LONG load_VDMX(GdiFont *font, LONG height)
Ratios ratio;
offset = sizeof(hdr) + (i * sizeof(Ratios));
freetype_get_font_data(gdi_font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
freetype_get_font_data(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios));
offset = -1;
TRACE("Ratios[%d] %d %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio);
@ -3399,7 +3394,7 @@ static LONG load_VDMX(GdiFont *font, LONG height)
WORD group_offset;
offset = sizeof(hdr) + numRatios * sizeof(ratio) + i * sizeof(group_offset);
freetype_get_font_data(gdi_font, MS_VDMX_TAG, offset, &group_offset, sizeof(group_offset));
freetype_get_font_data(font, MS_VDMX_TAG, offset, &group_offset, sizeof(group_offset));
offset = GET_BE_WORD(group_offset);
break;
}
@ -3407,7 +3402,7 @@ static LONG load_VDMX(GdiFont *font, LONG height)
if(offset == -1) return 0;
if(freetype_get_font_data(gdi_font, MS_VDMX_TAG, offset, &group, sizeof(group)) != GDI_ERROR) {
if(freetype_get_font_data(font, MS_VDMX_TAG, offset, &group, sizeof(group)) != GDI_ERROR) {
USHORT recs;
BYTE startsz, endsz;
WORD *vTable;
@ -3419,7 +3414,7 @@ static LONG load_VDMX(GdiFont *font, LONG height)
TRACE("recs=%d startsz=%d endsz=%d\n", recs, startsz, endsz);
vTable = HeapAlloc(GetProcessHeap(), 0, recs * sizeof(VDMX_vTable));
result = freetype_get_font_data(gdi_font, MS_VDMX_TAG, offset + sizeof(group), vTable, recs * sizeof(VDMX_vTable));
result = freetype_get_font_data(font, MS_VDMX_TAG, offset + sizeof(group), vTable, recs * sizeof(VDMX_vTable));
if(result == GDI_ERROR) {
FIXME("Failed to retrieve vTable\n");
goto end;
@ -3432,9 +3427,9 @@ static LONG load_VDMX(GdiFont *font, LONG height)
ppem = GET_BE_WORD(vTable[i * 3]);
if(yMax + -yMin == height) {
gdi_font->yMax = yMax;
gdi_font->yMin = yMin;
TRACE("ppem %d found; height=%d yMax=%d yMin=%d\n", ppem, height, gdi_font->yMax, gdi_font->yMin);
font->yMax = yMax;
font->yMin = yMin;
TRACE("ppem %d found; height=%d yMax=%d yMin=%d\n", ppem, height, font->yMax, font->yMin);
break;
}
if(yMax + -yMin > height) {
@ -3442,14 +3437,14 @@ static LONG load_VDMX(GdiFont *font, LONG height)
ppem = 0;
goto end; /* failed */
}
gdi_font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
gdi_font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
ppem = GET_BE_WORD(vTable[i * 3]);
TRACE("ppem %d found; height=%d yMax=%d yMin=%d\n", ppem, height, gdi_font->yMax, gdi_font->yMin);
TRACE("ppem %d found; height=%d yMax=%d yMin=%d\n", ppem, height, font->yMax, font->yMin);
break;
}
}
if(!gdi_font->yMax) {
if(!font->yMax) {
ppem = 0;
TRACE("ppem not found for height %d\n", height);
}
@ -3472,9 +3467,9 @@ static LONG load_VDMX(GdiFont *font, LONG height)
}
if(yPelHeight == ppem) {
gdi_font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
gdi_font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
TRACE("ppem %d found; yMax=%d yMin=%d\n", ppem, gdi_font->yMax, gdi_font->yMin);
font->yMax = GET_BE_WORD(vTable[(i * 3) + 1]);
font->yMin = GET_BE_WORD(vTable[(i * 3) + 2]);
TRACE("ppem %d found; yMax=%d yMin=%d\n", ppem, font->yMax, font->yMin);
break;
}
}
@ -3639,9 +3634,9 @@ static FT_Encoding pick_charmap( FT_Face face, int charset )
return *encs;
}
static BOOL get_gasp_flags( struct gdi_font *gdi_font, WORD *flags )
static BOOL get_gasp_flags( struct gdi_font *font, WORD *flags )
{
GdiFont *font = get_font_ptr( gdi_font );
FT_Face ft_face = get_ft_face( font );
DWORD size;
WORD buf[16]; /* Enough for seven ranges before we need to alloc */
WORD *alloced = NULL, *ptr = buf;
@ -3649,7 +3644,7 @@ static BOOL get_gasp_flags( struct gdi_font *gdi_font, WORD *flags )
BOOL ret = FALSE;
*flags = 0;
size = freetype_get_font_data( gdi_font, MS_GASP_TAG, 0, NULL, 0 );
size = freetype_get_font_data( font, MS_GASP_TAG, 0, NULL, 0 );
if (size == GDI_ERROR) return FALSE;
if (size < 4 * sizeof(WORD)) return FALSE;
if (size > sizeof(buf))
@ -3658,7 +3653,7 @@ static BOOL get_gasp_flags( struct gdi_font *gdi_font, WORD *flags )
if (!ptr) return FALSE;
}
freetype_get_font_data( gdi_font, MS_GASP_TAG, 0, ptr, size );
freetype_get_font_data( font, MS_GASP_TAG, 0, ptr, size );
version = GET_BE_WORD( *ptr++ );
num_recs = GET_BE_WORD( *ptr++ );
@ -3672,10 +3667,10 @@ static BOOL get_gasp_flags( struct gdi_font *gdi_font, WORD *flags )
while (num_recs--)
{
*flags = GET_BE_WORD( *(ptr + 1) );
if (font->ft_face->size->metrics.y_ppem <= GET_BE_WORD( *ptr )) break;
if (ft_face->size->metrics.y_ppem <= GET_BE_WORD( *ptr )) break;
ptr += 2;
}
TRACE( "got flags %04x for ppem %d\n", *flags, font->ft_face->size->metrics.y_ppem );
TRACE( "got flags %04x for ppem %d\n", *flags, ft_face->size->metrics.y_ppem );
ret = TRUE;
done:
@ -3788,64 +3783,63 @@ static DWORD get_ttc_offset( FT_Face ft_face, UINT face_index )
/*************************************************************
* freetype_load_font
*/
static BOOL CDECL freetype_load_font( struct gdi_font *gdi_font )
static BOOL CDECL freetype_load_font( struct gdi_font *font )
{
GdiFont *font;
struct font_private_data *data;
INT width = 0, height;
FT_Face ft_face;
void *data_ptr;
SIZE_T data_size;
if (!(font = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*font) ))) return FALSE;
gdi_font->private = font;
font->gdi_font = gdi_font;
if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) return FALSE;
font->private = data;
if (gdi_font->file[0])
if (font->file[0])
{
char *filename = wine_get_unix_file_name( gdi_font->file );
font->mapping = map_font_file( filename );
char *filename = wine_get_unix_file_name( font->file );
data->mapping = map_font_file( filename );
HeapFree( GetProcessHeap(), 0, filename );
if (!font->mapping)
if (!data->mapping)
{
WARN("failed to map %s\n", debugstr_w(gdi_font->file));
WARN("failed to map %s\n", debugstr_w(font->file));
return FALSE;
}
data_ptr = font->mapping->data;
data_size = font->mapping->size;
data_ptr = data->mapping->data;
data_size = data->mapping->size;
}
else
{
data_ptr = gdi_font->data_ptr;
data_size = gdi_font->data_size;
data_ptr = font->data_ptr;
data_size = font->data_size;
}
if (pFT_New_Memory_Face( library, data_ptr, data_size, gdi_font->face_index, &ft_face )) return FALSE;
if (pFT_New_Memory_Face( library, data_ptr, data_size, font->face_index, &ft_face )) return FALSE;
font->ft_face = ft_face;
gdi_font->scalable = FT_IS_SCALABLE( ft_face );
if (!gdi_font->fs.fsCsb[0]) get_fontsig( ft_face, &gdi_font->fs );
if (!gdi_font->ntmFlags) gdi_font->ntmFlags = get_ntm_flags( ft_face );
if (!gdi_font->aa_flags) gdi_font->aa_flags = ADDFONT_AA_FLAGS( default_aa_flags );
if (!gdi_font->otm.otmpFamilyName)
data->ft_face = ft_face;
font->scalable = FT_IS_SCALABLE( ft_face );
if (!font->fs.fsCsb[0]) get_fontsig( ft_face, &font->fs );
if (!font->ntmFlags) font->ntmFlags = get_ntm_flags( ft_face );
if (!font->aa_flags) font->aa_flags = ADDFONT_AA_FLAGS( default_aa_flags );
if (!font->otm.otmpFamilyName)
{
WCHAR *family_name = ft_face_get_family_name( ft_face, GetSystemDefaultLCID() );
WCHAR *style_name = ft_face_get_style_name( ft_face, GetSystemDefaultLangID() );
WCHAR *full_name = ft_face_get_full_name( ft_face, GetSystemDefaultLangID() );
set_gdi_font_names( gdi_font, family_name, style_name, full_name );
set_gdi_font_names( font, family_name, style_name, full_name );
HeapFree( GetProcessHeap(), 0, family_name );
HeapFree( GetProcessHeap(), 0, style_name );
HeapFree( GetProcessHeap(), 0, full_name );
}
if (gdi_font->scalable)
if (font->scalable)
{
/* load the VDMX table if we have one */
gdi_font->ppem = load_VDMX( font, gdi_font->lf.lfHeight );
if (gdi_font->ppem == 0) gdi_font->ppem = calc_ppem_for_height( ft_face, gdi_font->lf.lfHeight );
TRACE( "height %d => ppem %d\n", gdi_font->lf.lfHeight, gdi_font->ppem );
height = gdi_font->ppem;
gdi_font->ttc_item_offset = get_ttc_offset( ft_face, gdi_font->face_index );
font->ppem = load_VDMX( font, font->lf.lfHeight );
if (font->ppem == 0) font->ppem = calc_ppem_for_height( ft_face, font->lf.lfHeight );
TRACE( "height %d => ppem %d\n", font->lf.lfHeight, font->ppem );
height = font->ppem;
font->ttc_item_offset = get_ttc_offset( ft_face, font->face_index );
}
else
{
@ -3854,11 +3848,11 @@ static BOOL CDECL freetype_load_font( struct gdi_font *gdi_font )
get_bitmap_size( ft_face, &size );
width = size.x_ppem >> 6;
height = size.y_ppem >> 6;
gdi_font->ppem = height;
font->ppem = height;
}
pFT_Set_Pixel_Sizes( ft_face, width, height );
pick_charmap( ft_face, gdi_font->charset );
pick_charmap( ft_face, font->charset );
return TRUE;
}
@ -3869,8 +3863,7 @@ static BOOL CDECL freetype_load_font( struct gdi_font *gdi_font )
static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *aa_flags,
UINT default_aa_flags )
{
struct gdi_font *gdi_font;
GdiFont *ret;
struct gdi_font *font;
Face *face, *best, *best_bitmap;
Family *family, *last_resort_family;
const struct list *face_list;
@ -3925,9 +3918,8 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
dcmat.eM21, dcmat.eM22);
/* check the cache first */
if ((gdi_font = find_cached_gdi_font( &lf, &dcmat, can_use_bitmap ))) {
ret = get_font_ptr( gdi_font );
TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
if ((font = find_cached_gdi_font( &lf, &dcmat, can_use_bitmap ))) {
TRACE("returning cached gdiFont(%p) for hFont %p\n", font, hfont);
goto done;
}
@ -4181,31 +4173,31 @@ found_face:
height = lf.lfHeight;
TRACE("not in cache\n");
gdi_font = alloc_gdi_font( face->file, face->font_data_ptr, face->font_data_size );
font = alloc_gdi_font( face->file, face->font_data_ptr, face->font_data_size );
gdi_font->matrix = dcmat;
gdi_font->lf = lf;
gdi_font->can_use_bitmap = can_use_bitmap;
gdi_font->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
gdi_font->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
gdi_font->fs = face->fs;
gdi_font->face_index = face->face_index;
gdi_font->ntmFlags = face->ntmFlags;
gdi_font->aa_flags = HIWORD( face->flags );
set_gdi_font_names( gdi_font, psub ? psub->from.name : family->family_name,
font->matrix = dcmat;
font->lf = lf;
font->can_use_bitmap = can_use_bitmap;
font->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
font->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
font->fs = face->fs;
font->face_index = face->face_index;
font->ntmFlags = face->ntmFlags;
font->aa_flags = HIWORD( face->flags );
set_gdi_font_names( font, psub ? psub->from.name : family->family_name,
face->style_name, face->full_name );
if(csi.fs.fsCsb[0]) {
gdi_font->charset = lf.lfCharSet;
gdi_font->codepage = csi.ciACP;
font->charset = lf.lfCharSet;
font->codepage = csi.ciACP;
}
else
gdi_font->charset = get_nearest_charset( family->family_name, face, &gdi_font->codepage );
font->charset = get_nearest_charset( family->family_name, face, &font->codepage );
TRACE( "Chosen: %s (%s/%p:%ld)\n", debugstr_w(face->full_name), debugstr_w(face->file),
face->font_data_ptr, face->face_index );
gdi_font->aveWidth = height ? lf.lfWidth : 0;
font->aveWidth = height ? lf.lfWidth : 0;
if(!face->scalable) {
/* Windows uses integer scaling factors for bitmap fonts */
@ -4213,18 +4205,17 @@ found_face:
struct gdi_font *cachedfont;
/* FIXME: rotation of bitmap fonts is ignored */
height = abs(GDI_ROUND( (double)height * gdi_font->matrix.eM22 ));
if (gdi_font->aveWidth)
gdi_font->aveWidth = (double)gdi_font->aveWidth * gdi_font->matrix.eM11;
gdi_font->matrix.eM11 = gdi_font->matrix.eM22 = 1.0;
height = abs(GDI_ROUND( (double)height * font->matrix.eM22 ));
if (font->aveWidth)
font->aveWidth = (double)font->aveWidth * font->matrix.eM11;
font->matrix.eM11 = font->matrix.eM22 = 1.0;
dcmat.eM11 = dcmat.eM22 = 1.0;
/* As we changed the matrix, we need to search the cache for the font again,
* otherwise we might explode the cache. */
if((cachedfont = find_cached_gdi_font( &lf, &dcmat, can_use_bitmap ))) {
TRACE("Found cached font after non-scalable matrix rescale!\n");
free_gdi_font( gdi_font );
gdi_font = cachedfont;
ret = get_font_ptr( gdi_font );
free_gdi_font( font );
font = cachedfont;
goto done;
}
@ -4237,27 +4228,26 @@ found_face:
if (scale > 2 && scaled_height - height > face->size.height / 4) scale--;
/* The jump between unscaled and doubled is delayed by 1 */
else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
gdi_font->scale_y = scale;
font->scale_y = scale;
}
TRACE("font scale y: %f\n", gdi_font->scale_y);
TRACE("font scale y: %f\n", font->scale_y);
if (!freetype_load_font( gdi_font ))
if (!freetype_load_font( font ))
{
free_gdi_font( gdi_font );
free_gdi_font( font );
return NULL;
}
ret = get_font_ptr( gdi_font );
if (face->flags & ADDFONT_VERTICAL_FONT) /* We need to try to load the GSUB table */
gdi_font->vert_feature = get_GSUB_vert_feature( gdi_font );
font->vert_feature = get_GSUB_vert_feature( font );
create_child_font_list( gdi_font );
create_child_font_list( font );
TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont);
TRACE("caching: gdiFont=%p hfont=%p\n", font, hfont);
cache_gdi_font( gdi_font );
cache_gdi_font( font );
done:
if (ret)
if (font)
{
switch (lf.lfQuality)
{
@ -4268,7 +4258,7 @@ done:
case CLEARTYPE_QUALITY:
case CLEARTYPE_NATURAL_QUALITY:
default:
if (!*aa_flags) *aa_flags = gdi_font->aa_flags;
if (!*aa_flags) *aa_flags = font->aa_flags;
if (!*aa_flags) *aa_flags = default_aa_flags;
/* fixup the antialiasing flags for that font */
@ -4285,10 +4275,10 @@ done:
case GGO_GRAY4_BITMAP:
case GGO_GRAY8_BITMAP:
case WINE_GGO_GRAY16_BITMAP:
if ((!antialias_fakes || (!gdi_font->fake_bold && !gdi_font->fake_italic)) && is_hinting_enabled())
if ((!antialias_fakes || (!font->fake_bold && !font->fake_italic)) && is_hinting_enabled())
{
WORD gasp_flags;
if (get_gasp_flags( gdi_font, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY))
if (get_gasp_flags( font, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY))
{
TRACE( "font %s %d aa disabled by GASP\n",
debugstr_w(lf.lfFaceName), lf.lfHeight );
@ -4299,7 +4289,7 @@ done:
}
TRACE( "%p %s %d aa %x\n", hfont, debugstr_w(lf.lfFaceName), lf.lfHeight, *aa_flags );
}
return gdi_font;
return font;
}
static INT load_script_name( UINT id, WCHAR buffer[LF_FACESIZE] )
@ -4414,7 +4404,7 @@ static UINT get_font_type( const NEWTEXTMETRICEXW *ntm )
static void GetEnumStructs(Face *face, const WCHAR *family_name, LPENUMLOGFONTEXW pelf,
NEWTEXTMETRICEXW *pntm)
{
struct gdi_font *gdi_font;
struct gdi_font *font;
if (face->cached_enum_data)
{
@ -4424,33 +4414,33 @@ static void GetEnumStructs(Face *face, const WCHAR *family_name, LPENUMLOGFONTEX
return;
}
gdi_font = alloc_gdi_font( face->file, face->font_data_ptr, face->font_data_size );
gdi_font->lf.lfHeight = 100;
gdi_font->face_index = face->face_index;
gdi_font->ntmFlags = face->ntmFlags;
set_gdi_font_names( gdi_font, family_name, face->style_name, face->full_name );
font = alloc_gdi_font( face->file, face->font_data_ptr, face->font_data_size );
font->lf.lfHeight = 100;
font->face_index = face->face_index;
font->ntmFlags = face->ntmFlags;
set_gdi_font_names( font, family_name, face->style_name, face->full_name );
if (!freetype_load_font( gdi_font ))
if (!freetype_load_font( font ))
{
free_gdi_font(gdi_font);
free_gdi_font(font);
return;
}
if (freetype_set_outline_text_metrics(gdi_font))
if (freetype_set_outline_text_metrics(font))
{
memcpy(&pntm->ntmTm, &gdi_font->otm.otmTextMetrics, sizeof(TEXTMETRICW));
memcpy(&pntm->ntmTm, &font->otm.otmTextMetrics, sizeof(TEXTMETRICW));
pntm->ntmTm.ntmSizeEM = gdi_font->otm.otmEMSquare;
pntm->ntmTm.ntmCellHeight = gdi_font->ntmCellHeight;
pntm->ntmTm.ntmAvgWidth = gdi_font->ntmAvgWidth;
pntm->ntmTm.ntmSizeEM = font->otm.otmEMSquare;
pntm->ntmTm.ntmCellHeight = font->ntmCellHeight;
pntm->ntmTm.ntmAvgWidth = font->ntmAvgWidth;
lstrcpynW(pelf->elfLogFont.lfFaceName, (WCHAR *)gdi_font->otm.otmpFamilyName, LF_FACESIZE);
lstrcpynW(pelf->elfFullName, (WCHAR *)gdi_font->otm.otmpFaceName, LF_FULLFACESIZE);
lstrcpynW(pelf->elfStyle, (WCHAR *)gdi_font->otm.otmpStyleName, LF_FACESIZE);
lstrcpynW(pelf->elfLogFont.lfFaceName, (WCHAR *)font->otm.otmpFamilyName, LF_FACESIZE);
lstrcpynW(pelf->elfFullName, (WCHAR *)font->otm.otmpFaceName, LF_FULLFACESIZE);
lstrcpynW(pelf->elfStyle, (WCHAR *)font->otm.otmpStyleName, LF_FACESIZE);
}
else if (freetype_set_bitmap_text_metrics( gdi_font ))
else if (freetype_set_bitmap_text_metrics( font ))
{
memcpy(&pntm->ntmTm, &gdi_font->otm.otmTextMetrics, sizeof(TEXTMETRICW));
memcpy(&pntm->ntmTm, &font->otm.otmTextMetrics, sizeof(TEXTMETRICW));
pntm->ntmTm.ntmSizeEM = pntm->ntmTm.tmHeight - pntm->ntmTm.tmInternalLeading;
pntm->ntmTm.ntmCellHeight = pntm->ntmTm.tmHeight;
@ -4487,7 +4477,7 @@ static void GetEnumStructs(Face *face, const WCHAR *family_name, LPENUMLOGFONTEX
face->cached_enum_data->ntm = *pntm;
}
free_gdi_font(gdi_font);
free_gdi_font(font);
}
static BOOL family_matches(Family *family, const WCHAR *face_name)
@ -4621,15 +4611,16 @@ static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
}
static FT_UInt get_glyph_index_symbol(const GdiFont *font, UINT glyph)
static FT_UInt get_glyph_index_symbol( struct gdi_font *font, UINT glyph )
{
FT_Face ft_face = get_ft_face( font );
FT_UInt ret;
if (glyph < 0x100) glyph += 0xf000;
/* there are a number of old pre-Unicode "broken" TTFs, which
do have symbols at U+00XX instead of U+f0XX */
if (!(ret = pFT_Get_Char_Index(font->ft_face, glyph)))
ret = pFT_Get_Char_Index(font->ft_face, glyph - 0xf000);
if (!(ret = pFT_Get_Char_Index(ft_face, glyph)))
ret = pFT_Get_Char_Index(ft_face, glyph - 0xf000);
return ret;
}
@ -4637,13 +4628,13 @@ static FT_UInt get_glyph_index_symbol(const GdiFont *font, UINT glyph)
/*************************************************************
* freetype_get_glyph_index
*/
static BOOL CDECL freetype_get_glyph_index( struct gdi_font *gdi_font, UINT *glyph, BOOL use_encoding )
static BOOL CDECL freetype_get_glyph_index( struct gdi_font *font, UINT *glyph, BOOL use_encoding )
{
GdiFont *font = get_font_ptr( gdi_font );
FT_Face ft_face = get_ft_face( font );
if (!use_encoding ^ (font->ft_face->charmap->encoding == FT_ENCODING_NONE)) return FALSE;
if (!use_encoding ^ (ft_face->charmap->encoding == FT_ENCODING_NONE)) return FALSE;
if (font->ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
if (ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
{
if (!(*glyph = get_glyph_index_symbol( font, *glyph )))
{
@ -4655,26 +4646,26 @@ static BOOL CDECL freetype_get_glyph_index( struct gdi_font *gdi_font, UINT *gly
}
return TRUE;
}
*glyph = pFT_Get_Char_Index( font->ft_face, *glyph );
*glyph = pFT_Get_Char_Index( ft_face, *glyph );
return TRUE;
}
/*************************************************************
* freetype_get_default_glyph
*/
static UINT CDECL freetype_get_default_glyph( struct gdi_font *gdi_font )
static UINT CDECL freetype_get_default_glyph( struct gdi_font *font )
{
GdiFont *font = get_font_ptr( gdi_font );
FT_Face ft_face = get_ft_face( font );
FT_WinFNT_HeaderRec winfnt;
TT_OS2 *pOS2;
if ((pOS2 = pFT_Get_Sfnt_Table( font->ft_face, ft_sfnt_os2 )))
if ((pOS2 = pFT_Get_Sfnt_Table( ft_face, ft_sfnt_os2 )))
{
UINT glyph = pOS2->usDefaultChar;
freetype_get_glyph_index( gdi_font, &glyph, TRUE );
freetype_get_glyph_index( font, &glyph, TRUE );
return glyph;
}
if (!pFT_Get_WinFNT_Header( font->ft_face, &winfnt )) return winfnt.default_char + winfnt.first_char;
if (!pFT_Get_WinFNT_Header( ft_face, &winfnt )) return winfnt.default_char + winfnt.first_char;
return 32;
}
@ -4873,7 +4864,7 @@ static FT_Vector get_advance_metric(struct gdi_font *incoming_font, struct gdi_f
!(incoming_font->otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
UINT avg_advance;
em_scale = MulDiv(incoming_font->ppem, 1 << 16,
get_font_ptr(incoming_font)->ft_face->units_per_EM);
get_ft_face(incoming_font)->units_per_EM);
avg_advance = pFT_MulFix(incoming_font->ntmAvgWidth, em_scale);
fixed_pitch_full = (avg_advance > 0 &&
(base_advance + 63) >> 6 ==
@ -5571,7 +5562,7 @@ static DWORD CDECL freetype_get_glyph_outline( struct gdi_font *font, UINT glyph
const MAT2 *lpmat, BOOL tategaki )
{
struct gdi_font *base_font = font->base_font ? font->base_font : font;
FT_Face ft_face = get_font_ptr( base_font )->ft_face;
FT_Face ft_face = get_ft_face( base_font );
FT_Glyph_Metrics metrics;
FT_Error err;
FT_BBox bbox;
@ -5580,8 +5571,7 @@ static DWORD CDECL freetype_get_glyph_outline( struct gdi_font *font, UINT glyph
BOOL needsTransform = FALSE;
BOOL vertical_metrics;
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
buflen, buf, lpmat);
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm, buflen, buf, lpmat);
TRACE("font transform %f %f %f %f\n",
font->matrix.eM11, font->matrix.eM12,
@ -5710,7 +5700,7 @@ static DWORD CDECL freetype_get_glyph_outline( struct gdi_font *font, UINT glyph
*/
static BOOL CDECL freetype_set_bitmap_text_metrics( struct gdi_font *font )
{
FT_Face ft_face = get_font_ptr( font )->ft_face;
FT_Face ft_face = get_ft_face( font );
FT_WinFNT_HeaderRec winfnt_header;
if (font->otm.otmSize) return TRUE; /* already set */
@ -5788,7 +5778,7 @@ static BOOL face_has_symbol_charmap(FT_Face ft_face)
*/
static BOOL CDECL freetype_set_outline_text_metrics( struct gdi_font *font )
{
FT_Face ft_face = get_font_ptr( font )->ft_face;
FT_Face ft_face = get_ft_face( font );
UINT needed;
TT_OS2 *pOS2;
TT_HoriHeader *pHori;
@ -6060,20 +6050,19 @@ static BOOL CDECL freetype_set_outline_text_metrics( struct gdi_font *font )
return TRUE;
}
/*************************************************************
* freetype_get_char_width_info
*/
static BOOL CDECL freetype_get_char_width_info( struct gdi_font *font, struct char_width_info *info )
{
FT_Face face = get_font_ptr(font)->ft_face;
FT_Face ft_face = get_ft_face( font );
TT_HoriHeader *pHori;
TRACE("%p, %p\n", font, info);
if ((pHori = pFT_Get_Sfnt_Table(face, ft_sfnt_hhea)))
if ((pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea)))
{
FT_Fixed em_scale = MulDiv(font->ppem, 1 << 16, face->units_per_EM);
FT_Fixed em_scale = MulDiv(font->ppem, 1 << 16, ft_face->units_per_EM);
info->lsb = (SHORT)pFT_MulFix(pHori->min_Left_Side_Bearing, em_scale);
info->rsb = (SHORT)pFT_MulFix(pHori->min_Right_Side_Bearing, em_scale);
return TRUE;
@ -6091,19 +6080,19 @@ static BOOL CDECL freetype_get_char_width_info( struct gdi_font *font, struct ch
*/
static DWORD CDECL freetype_get_unicode_ranges( struct gdi_font *font, GLYPHSET *gs )
{
FT_Face face = get_font_ptr(font)->ft_face;
FT_Face ft_face = get_ft_face( font );
DWORD num_ranges = 0;
if (face->charmap->encoding == FT_ENCODING_UNICODE)
if (ft_face->charmap->encoding == FT_ENCODING_UNICODE)
{
FT_UInt glyph_code;
FT_ULong char_code, char_code_prev;
glyph_code = 0;
char_code_prev = char_code = pFT_Get_First_Char(face, &glyph_code);
char_code_prev = char_code = pFT_Get_First_Char(ft_face, &glyph_code);
TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
face->num_glyphs, glyph_code, char_code);
ft_face->num_glyphs, glyph_code, char_code);
if (!glyph_code) return 0;
@ -6138,12 +6127,12 @@ static DWORD CDECL freetype_get_unicode_ranges( struct gdi_font *font, GLYPHSET
gs->cGlyphsSupported++;
}
char_code_prev = char_code;
char_code = pFT_Get_Next_Char(face, char_code, &glyph_code);
char_code = pFT_Get_Next_Char(ft_face, char_code, &glyph_code);
}
}
else
{
DWORD encoding = RtlUlongByteSwap(face->charmap->encoding);
DWORD encoding = RtlUlongByteSwap(ft_face->charmap->encoding);
FIXME("encoding %s not supported\n", debugstr_an((char *)&encoding, 4));
}
@ -6194,16 +6183,16 @@ struct TT_kern_pair
short value;
};
static DWORD parse_format0_kern_subtable(GdiFont *font,
static DWORD parse_format0_kern_subtable(struct gdi_font *font,
const struct TT_format0_kern_subtable *tt_f0_ks,
const USHORT *glyph_to_char,
KERNINGPAIR *kern_pair, DWORD cPairs)
{
struct gdi_font *gdi_font = font->gdi_font;
FT_Face ft_face = get_ft_face( font );
USHORT i, nPairs;
const struct TT_kern_pair *tt_kern_pair;
TRACE("font height %d, units_per_EM %d\n", gdi_font->ppem, font->ft_face->units_per_EM);
TRACE("font height %d, units_per_EM %d\n", font->ppem, ft_face->units_per_EM);
nPairs = GET_BE_WORD(tt_f0_ks->nPairs);
@ -6223,18 +6212,18 @@ static DWORD parse_format0_kern_subtable(GdiFont *font,
kern_pair->wFirst = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].left)];
kern_pair->wSecond = glyph_to_char[GET_BE_WORD(tt_kern_pair[i].right)];
/* this algorithm appears to better match what Windows does */
kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * gdi_font->ppem;
kern_pair->iKernAmount = (short)GET_BE_WORD(tt_kern_pair[i].value) * font->ppem;
if (kern_pair->iKernAmount < 0)
{
kern_pair->iKernAmount -= font->ft_face->units_per_EM / 2;
kern_pair->iKernAmount -= gdi_font->ppem;
kern_pair->iKernAmount -= ft_face->units_per_EM / 2;
kern_pair->iKernAmount -= font->ppem;
}
else if (kern_pair->iKernAmount > 0)
{
kern_pair->iKernAmount += font->ft_face->units_per_EM / 2;
kern_pair->iKernAmount += gdi_font->ppem;
kern_pair->iKernAmount += ft_face->units_per_EM / 2;
kern_pair->iKernAmount += font->ppem;
}
kern_pair->iKernAmount /= font->ft_face->units_per_EM;
kern_pair->iKernAmount /= ft_face->units_per_EM;
TRACE("left %u right %u value %d\n",
kern_pair->wFirst, kern_pair->wSecond, kern_pair->iKernAmount);
@ -6248,9 +6237,9 @@ static DWORD parse_format0_kern_subtable(GdiFont *font,
/*************************************************************
* freetype_get_kerning_pairs
*/
static DWORD CDECL freetype_get_kerning_pairs( struct gdi_font *gdi_font, KERNINGPAIR **pairs )
static DWORD CDECL freetype_get_kerning_pairs( struct gdi_font *font, KERNINGPAIR **pairs )
{
GdiFont *font = get_font_ptr(gdi_font);
FT_Face ft_face = get_ft_face( font );
DWORD length, count = 0;
void *buf;
const struct TT_kern_table *tt_kern_table;
@ -6258,7 +6247,7 @@ static DWORD CDECL freetype_get_kerning_pairs( struct gdi_font *gdi_font, KERNIN
USHORT i, nTables;
USHORT *glyph_to_char;
length = freetype_get_font_data(gdi_font, MS_KERN_TAG, 0, NULL, 0);
length = freetype_get_font_data(font, MS_KERN_TAG, 0, NULL, 0);
if (length == GDI_ERROR)
{
@ -6269,7 +6258,7 @@ static DWORD CDECL freetype_get_kerning_pairs( struct gdi_font *gdi_font, KERNIN
buf = HeapAlloc(GetProcessHeap(), 0, length);
if (!buf) return 0;
freetype_get_font_data(gdi_font, MS_KERN_TAG, 0, buf, length);
freetype_get_font_data(font, MS_KERN_TAG, 0, buf, length);
/* build a glyph index to char code map */
glyph_to_char = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USHORT) * 65536);
@ -6279,16 +6268,16 @@ static DWORD CDECL freetype_get_kerning_pairs( struct gdi_font *gdi_font, KERNIN
return 0;
}
if (font->ft_face->charmap->encoding == FT_ENCODING_UNICODE)
if (ft_face->charmap->encoding == FT_ENCODING_UNICODE)
{
FT_UInt glyph_code;
FT_ULong char_code;
glyph_code = 0;
char_code = pFT_Get_First_Char(font->ft_face, &glyph_code);
char_code = pFT_Get_First_Char(ft_face, &glyph_code);
TRACE("face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %lu\n",
font->ft_face->num_glyphs, glyph_code, char_code);
ft_face->num_glyphs, glyph_code, char_code);
while (glyph_code)
{
@ -6301,12 +6290,12 @@ static DWORD CDECL freetype_get_kerning_pairs( struct gdi_font *gdi_font, KERNIN
if (glyph_code <= 65535 && !glyph_to_char[glyph_code])
glyph_to_char[glyph_code] = (USHORT)char_code;
char_code = pFT_Get_Next_Char(font->ft_face, char_code, &glyph_code);
char_code = pFT_Get_Next_Char(ft_face, char_code, &glyph_code);
}
}
else
{
DWORD encoding = RtlUlongByteSwap(font->ft_face->charmap->encoding);
DWORD encoding = RtlUlongByteSwap(ft_face->charmap->encoding);
ULONG n;
FIXME("encoding %s not supported\n", debugstr_an((char *)&encoding, 4));