gdi32: Add a helper to load a font without using a face.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7b291a094d
commit
0bf2c11d43
|
@ -3624,81 +3624,6 @@ static void unmap_font_file( struct font_mapping *mapping )
|
||||||
|
|
||||||
static LONG load_VDMX(GdiFont*, LONG);
|
static LONG load_VDMX(GdiFont*, LONG);
|
||||||
|
|
||||||
static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height)
|
|
||||||
{
|
|
||||||
struct gdi_font *gdi_font = font->gdi_font;
|
|
||||||
FT_Error err;
|
|
||||||
FT_Face ft_face;
|
|
||||||
void *data_ptr;
|
|
||||||
DWORD data_size;
|
|
||||||
|
|
||||||
TRACE("%s/%p, %ld, %d x %d\n", debugstr_w(face->file), face->font_data_ptr, face->face_index, width, height);
|
|
||||||
|
|
||||||
if (face->file)
|
|
||||||
{
|
|
||||||
char *filename = wine_get_unix_file_name( face->file );
|
|
||||||
font->mapping = map_font_file( filename );
|
|
||||||
HeapFree( GetProcessHeap(), 0, filename );
|
|
||||||
if (!font->mapping)
|
|
||||||
{
|
|
||||||
WARN("failed to map %s\n", debugstr_w(face->file));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
data_ptr = font->mapping->data;
|
|
||||||
data_size = font->mapping->size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data_ptr = face->font_data_ptr;
|
|
||||||
data_size = face->font_data_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pFT_New_Memory_Face(library, data_ptr, data_size, face->face_index, &ft_face);
|
|
||||||
if(err) {
|
|
||||||
ERR("FT_New_Face rets %d\n", err);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set it here, as load_VDMX needs it */
|
|
||||||
font->ft_face = ft_face;
|
|
||||||
gdi_font->scalable = FT_IS_SCALABLE(ft_face);
|
|
||||||
gdi_font->face_index = face->face_index;
|
|
||||||
|
|
||||||
if(FT_IS_SCALABLE(ft_face)) {
|
|
||||||
FT_ULong len;
|
|
||||||
DWORD header;
|
|
||||||
|
|
||||||
/* load the VDMX table if we have one */
|
|
||||||
gdi_font->ppem = load_VDMX(font, height);
|
|
||||||
if(gdi_font->ppem == 0)
|
|
||||||
gdi_font->ppem = calc_ppem_for_height(ft_face, height);
|
|
||||||
TRACE("height %d => ppem %d\n", height, gdi_font->ppem);
|
|
||||||
|
|
||||||
if((err = pFT_Set_Pixel_Sizes(ft_face, 0, gdi_font->ppem)) != 0)
|
|
||||||
WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", 0, gdi_font->ppem, err);
|
|
||||||
|
|
||||||
/* see if it's a TTC */
|
|
||||||
len = sizeof(header);
|
|
||||||
if (!pFT_Load_Sfnt_Table(ft_face, 0, 0, (void*)&header, &len)) {
|
|
||||||
if (header == MS_TTCF_TAG)
|
|
||||||
{
|
|
||||||
len = sizeof(gdi_font->ttc_item_offset);
|
|
||||||
if (pFT_Load_Sfnt_Table(ft_face, 0, (3 + face->face_index) * sizeof(DWORD),
|
|
||||||
(void*)&gdi_font->ttc_item_offset, &len))
|
|
||||||
gdi_font->ttc_item_offset = 0;
|
|
||||||
else
|
|
||||||
gdi_font->ttc_item_offset = GET_BE_DWORD(gdi_font->ttc_item_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gdi_font->ppem = height;
|
|
||||||
if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
|
|
||||||
WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", width, height, err);
|
|
||||||
}
|
|
||||||
return ft_face;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static UINT get_nearest_charset(const WCHAR *family_name, Face *face, UINT *cp)
|
static UINT get_nearest_charset(const WCHAR *family_name, Face *face, UINT *cp)
|
||||||
{
|
{
|
||||||
/* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
|
/* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
|
||||||
|
@ -4340,28 +4265,32 @@ static const char* get_opentype_script(const struct gdi_font *font)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VOID * get_GSUB_vert_feature(const GdiFont *font)
|
static const void *get_GSUB_vert_feature( struct gdi_font *font, void **GSUB_table )
|
||||||
{
|
{
|
||||||
const GSUB_Header *header;
|
GSUB_Header *header;
|
||||||
const GSUB_Script *script;
|
const GSUB_Script *script;
|
||||||
const GSUB_LangSys *language;
|
const GSUB_LangSys *language;
|
||||||
const GSUB_Feature *feature;
|
const GSUB_Feature *feature;
|
||||||
|
DWORD length = freetype_get_font_data( font, MS_GSUB_TAG, 0, NULL, 0 );
|
||||||
|
|
||||||
if (!font->GSUB_Table)
|
if (length == GDI_ERROR) return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
header = font->GSUB_Table;
|
header = HeapAlloc( GetProcessHeap(), 0, length );
|
||||||
|
freetype_get_font_data( font, MS_GSUB_TAG, 0, header, length );
|
||||||
|
TRACE( "Loaded GSUB table of %i bytes\n", length );
|
||||||
|
|
||||||
script = GSUB_get_script_table(header, get_opentype_script(font->gdi_font));
|
script = GSUB_get_script_table(header, get_opentype_script(font));
|
||||||
if (!script)
|
if (!script)
|
||||||
{
|
{
|
||||||
TRACE("Script not found\n");
|
TRACE("Script not found\n");
|
||||||
|
HeapFree( GetProcessHeap(), 0, header );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
|
language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */
|
||||||
if (!language)
|
if (!language)
|
||||||
{
|
{
|
||||||
TRACE("Language not found\n");
|
TRACE("Language not found\n");
|
||||||
|
HeapFree( GetProcessHeap(), 0, header );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
feature = GSUB_get_feature(header, language, "vrt2");
|
feature = GSUB_get_feature(header, language, "vrt2");
|
||||||
|
@ -4370,11 +4299,101 @@ static const VOID * get_GSUB_vert_feature(const GdiFont *font)
|
||||||
if (!feature)
|
if (!feature)
|
||||||
{
|
{
|
||||||
TRACE("vrt2/vert feature not found\n");
|
TRACE("vrt2/vert feature not found\n");
|
||||||
|
HeapFree( GetProcessHeap(), 0, header );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
*GSUB_table = header;
|
||||||
return feature;
|
return feature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD get_ttc_offset( FT_Face ft_face, UINT face_index )
|
||||||
|
{
|
||||||
|
FT_ULong len;
|
||||||
|
DWORD header, offset;
|
||||||
|
|
||||||
|
/* see if it's a TTC */
|
||||||
|
len = sizeof(header);
|
||||||
|
if (pFT_Load_Sfnt_Table( ft_face, 0, 0, (void *)&header, &len )) return 0;
|
||||||
|
if (header != MS_TTCF_TAG) return 0;
|
||||||
|
|
||||||
|
len = sizeof(offset);
|
||||||
|
if (pFT_Load_Sfnt_Table( ft_face, 0, (3 + face_index) * sizeof(DWORD), (void *)&offset, &len ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return GET_BE_DWORD( offset );
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL load_font( struct gdi_font *gdi_font )
|
||||||
|
{
|
||||||
|
GdiFont *font = get_font_ptr( gdi_font );
|
||||||
|
INT width = 0, height;
|
||||||
|
FT_Face ft_face;
|
||||||
|
void *data_ptr;
|
||||||
|
SIZE_T data_size;
|
||||||
|
|
||||||
|
if (gdi_font->file[0])
|
||||||
|
{
|
||||||
|
char *filename = wine_get_unix_file_name( gdi_font->file );
|
||||||
|
font->mapping = map_font_file( filename );
|
||||||
|
HeapFree( GetProcessHeap(), 0, filename );
|
||||||
|
if (!font->mapping)
|
||||||
|
{
|
||||||
|
WARN("failed to map %s\n", debugstr_w(gdi_font->file));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
data_ptr = font->mapping->data;
|
||||||
|
data_size = font->mapping->size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data_ptr = gdi_font->data_ptr;
|
||||||
|
data_size = gdi_font->data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pFT_New_Memory_Face( library, data_ptr, data_size, gdi_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)
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
HeapFree( GetProcessHeap(), 0, family_name );
|
||||||
|
HeapFree( GetProcessHeap(), 0, style_name );
|
||||||
|
HeapFree( GetProcessHeap(), 0, full_name );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gdi_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 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Bitmap_Size size;
|
||||||
|
|
||||||
|
get_bitmap_size( ft_face, &size );
|
||||||
|
width = size.x_ppem >> 6;
|
||||||
|
height = size.y_ppem >> 6;
|
||||||
|
gdi_font->ppem = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
pFT_Set_Pixel_Sizes( ft_face, width, height );
|
||||||
|
pick_charmap( ft_face, gdi_font->charset );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* freetype_SelectFont
|
* freetype_SelectFont
|
||||||
*/
|
*/
|
||||||
|
@ -4386,7 +4405,7 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a
|
||||||
Face *face, *best, *best_bitmap;
|
Face *face, *best, *best_bitmap;
|
||||||
Family *family, *last_resort_family;
|
Family *family, *last_resort_family;
|
||||||
const struct list *face_list;
|
const struct list *face_list;
|
||||||
INT height, width = 0;
|
INT height;
|
||||||
unsigned int score = 0, new_score;
|
unsigned int score = 0, new_score;
|
||||||
signed int diff = 0, newdiff;
|
signed int diff = 0, newdiff;
|
||||||
BOOL bd, it, can_use_bitmap, want_vertical;
|
BOOL bd, it, can_use_bitmap, want_vertical;
|
||||||
|
@ -4694,7 +4713,6 @@ found_face:
|
||||||
|
|
||||||
TRACE("not in cache\n");
|
TRACE("not in cache\n");
|
||||||
gdi_font = alloc_gdi_font( face->file, face->font_data_ptr, face->font_data_size );
|
gdi_font = alloc_gdi_font( face->file, face->font_data_ptr, face->font_data_size );
|
||||||
ret = get_font_ptr( gdi_font );
|
|
||||||
|
|
||||||
gdi_font->matrix = dcmat;
|
gdi_font->matrix = dcmat;
|
||||||
gdi_font->lf = lf;
|
gdi_font->lf = lf;
|
||||||
|
@ -4702,6 +4720,11 @@ found_face:
|
||||||
gdi_font->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
|
gdi_font->fake_italic = (it && !(face->ntmFlags & NTM_ITALIC));
|
||||||
gdi_font->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
|
gdi_font->fake_bold = (bd && !(face->ntmFlags & NTM_BOLD));
|
||||||
gdi_font->fs = face->fs;
|
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,
|
||||||
|
face->style_name, face->full_name );
|
||||||
|
|
||||||
if(csi.fs.fsCsb[0]) {
|
if(csi.fs.fsCsb[0]) {
|
||||||
gdi_font->charset = lf.lfCharSet;
|
gdi_font->charset = lf.lfCharSet;
|
||||||
|
@ -4746,46 +4769,20 @@ found_face:
|
||||||
/* The jump between unscaled and doubled is delayed by 1 */
|
/* The jump between unscaled and doubled is delayed by 1 */
|
||||||
else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
|
else if (scale == 2 && scaled_height - height > (face->size.height / 4 - 1)) scale--;
|
||||||
gdi_font->scale_y = scale;
|
gdi_font->scale_y = scale;
|
||||||
|
|
||||||
width = face->size.x_ppem >> 6;
|
|
||||||
height = face->size.y_ppem >> 6;
|
|
||||||
}
|
}
|
||||||
TRACE("font scale y: %f\n", gdi_font->scale_y);
|
TRACE("font scale y: %f\n", gdi_font->scale_y);
|
||||||
|
|
||||||
ret->ft_face = OpenFontFace(ret, face, width, height);
|
if (!load_font( gdi_font ))
|
||||||
|
|
||||||
if (!ret->ft_face)
|
|
||||||
{
|
{
|
||||||
free_gdi_font( gdi_font );
|
free_gdi_font( gdi_font );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ret = get_font_ptr( gdi_font );
|
||||||
gdi_font->ntmFlags = face->ntmFlags;
|
|
||||||
gdi_font->aa_flags = HIWORD( face->flags );
|
|
||||||
|
|
||||||
pick_charmap( ret->ft_face, gdi_font->charset );
|
|
||||||
|
|
||||||
set_gdi_font_names( gdi_font, psub ? psub->from.name : family->family_name,
|
|
||||||
face->style_name, face->full_name );
|
|
||||||
create_child_font_list(ret);
|
|
||||||
|
|
||||||
if (face->flags & ADDFONT_VERTICAL_FONT) /* We need to try to load the GSUB table */
|
if (face->flags & ADDFONT_VERTICAL_FONT) /* We need to try to load the GSUB table */
|
||||||
{
|
ret->vert_feature = get_GSUB_vert_feature( gdi_font, &ret->GSUB_Table );
|
||||||
int length = freetype_get_font_data(gdi_font, MS_GSUB_TAG , 0, NULL, 0);
|
|
||||||
if (length != GDI_ERROR)
|
create_child_font_list(ret);
|
||||||
{
|
|
||||||
ret->GSUB_Table = HeapAlloc(GetProcessHeap(),0,length);
|
|
||||||
freetype_get_font_data(gdi_font, MS_GSUB_TAG , 0, ret->GSUB_Table, length);
|
|
||||||
TRACE("Loaded GSUB table of %i bytes\n",length);
|
|
||||||
ret->vert_feature = get_GSUB_vert_feature(ret);
|
|
||||||
if (!ret->vert_feature)
|
|
||||||
{
|
|
||||||
TRACE("Vertical feature not found\n");
|
|
||||||
HeapFree(GetProcessHeap(), 0, ret->GSUB_Table);
|
|
||||||
ret->GSUB_Table = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont);
|
TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont);
|
||||||
|
|
||||||
|
@ -4949,8 +4946,6 @@ static void GetEnumStructs(Face *face, const WCHAR *family_name, LPENUMLOGFONTEX
|
||||||
NEWTEXTMETRICEXW *pntm)
|
NEWTEXTMETRICEXW *pntm)
|
||||||
{
|
{
|
||||||
struct gdi_font *gdi_font;
|
struct gdi_font *gdi_font;
|
||||||
GdiFont *font;
|
|
||||||
LONG width, height;
|
|
||||||
|
|
||||||
if (face->cached_enum_data)
|
if (face->cached_enum_data)
|
||||||
{
|
{
|
||||||
|
@ -4961,25 +4956,17 @@ static void GetEnumStructs(Face *face, const WCHAR *family_name, LPENUMLOGFONTEX
|
||||||
}
|
}
|
||||||
|
|
||||||
gdi_font = alloc_gdi_font( face->file, face->font_data_ptr, face->font_data_size );
|
gdi_font = alloc_gdi_font( face->file, face->font_data_ptr, face->font_data_size );
|
||||||
font = get_font_ptr( gdi_font );
|
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 );
|
||||||
|
|
||||||
if(face->scalable) {
|
if (!load_font( gdi_font ))
|
||||||
height = 100;
|
|
||||||
width = 0;
|
|
||||||
} else {
|
|
||||||
height = face->size.y_ppem >> 6;
|
|
||||||
width = face->size.x_ppem >> 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(font->ft_face = OpenFontFace(font, face, width, height)))
|
|
||||||
{
|
{
|
||||||
free_gdi_font(gdi_font);
|
free_gdi_font(gdi_font);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_gdi_font_names( gdi_font, family_name, face->style_name, face->full_name );
|
|
||||||
gdi_font->ntmFlags = face->ntmFlags;
|
|
||||||
|
|
||||||
if (freetype_set_outline_text_metrics(gdi_font))
|
if (freetype_set_outline_text_metrics(gdi_font))
|
||||||
{
|
{
|
||||||
memcpy(&pntm->ntmTm, &gdi_font->otm.otmTextMetrics, sizeof(TEXTMETRICW));
|
memcpy(&pntm->ntmTm, &gdi_font->otm.otmTextMetrics, sizeof(TEXTMETRICW));
|
||||||
|
@ -6899,25 +6886,23 @@ static BOOL load_child_font(GdiFont *font, CHILD_FONT *child)
|
||||||
child_face = best_face ? best_face : child->face;
|
child_face = best_face ? best_face : child->face;
|
||||||
|
|
||||||
child_font = alloc_gdi_font( child_face->file, child_face->font_data_ptr, child_face->font_data_size );
|
child_font = alloc_gdi_font( child_face->file, child_face->font_data_ptr, child_face->font_data_size );
|
||||||
child->font = get_font_ptr( child_font );
|
|
||||||
child->font->ft_face = OpenFontFace( child->font, child_face, 0, -gdi_font->ppem );
|
|
||||||
if(!child->font->ft_face)
|
|
||||||
{
|
|
||||||
free_gdi_font(child_font);
|
|
||||||
child->font = NULL;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
child_font->fake_italic = italic && !( child_face->ntmFlags & NTM_ITALIC );
|
child_font->fake_italic = italic && !( child_face->ntmFlags & NTM_ITALIC );
|
||||||
child_font->fake_bold = bold && !( child_face->ntmFlags & NTM_BOLD );
|
child_font->fake_bold = bold && !( child_face->ntmFlags & NTM_BOLD );
|
||||||
child_font->lf = gdi_font->lf;
|
child_font->lf = gdi_font->lf;
|
||||||
child_font->matrix = gdi_font->matrix;
|
child_font->matrix = gdi_font->matrix;
|
||||||
child_font->can_use_bitmap = gdi_font->can_use_bitmap;
|
child_font->can_use_bitmap = gdi_font->can_use_bitmap;
|
||||||
|
child_font->face_index = child_face->face_index;
|
||||||
child_font->ntmFlags = child_face->ntmFlags;
|
child_font->ntmFlags = child_face->ntmFlags;
|
||||||
child_font->aa_flags = HIWORD( child_face->flags );
|
child_font->aa_flags = HIWORD( child_face->flags );
|
||||||
child_font->scale_y = gdi_font->scale_y;
|
child_font->scale_y = gdi_font->scale_y;
|
||||||
set_gdi_font_names( child_font, child_face->family->family_name,
|
set_gdi_font_names( child_font, child_face->family->family_name,
|
||||||
child_face->style_name, child_face->full_name );
|
child_face->style_name, child_face->full_name );
|
||||||
|
if (!load_font( child_font ))
|
||||||
|
{
|
||||||
|
free_gdi_font(child_font);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
child->font = get_font_ptr( child_font );
|
||||||
child->font->base_font = font;
|
child->font->base_font = font;
|
||||||
TRACE("created child font %p for base %p\n", child->font, font);
|
TRACE("created child font %p for base %p\n", child->font, font);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in New Issue