dwrite: Evaluate IsSymbolFont() flag at font level.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2020-01-23 12:24:12 +03:00 committed by Alexandre Julliard
parent 107599531a
commit 0b0a2ce8fd
5 changed files with 88 additions and 61 deletions

View File

@ -183,6 +183,14 @@ struct fontfacecached
#define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1) #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
#define GLYPH_MAX 65536 #define GLYPH_MAX 65536
enum font_flags
{
FONT_IS_SYMBOL = 1 << 0,
FONTFACE_IS_MONOSPACED = 1 << 1,
FONTFACE_HAS_KERNING_PAIRS = 1 << 2,
FONTFACE_HAS_VERTICAL_VARIANTS = 1 << 3
};
struct dwrite_fontface struct dwrite_fontface
{ {
IDWriteFontFace5 IDWriteFontFace5_iface; IDWriteFontFace5 IDWriteFontFace5_iface;
@ -206,7 +214,7 @@ struct dwrite_fontface
unsigned int descent; unsigned int descent;
} typo_metrics; } typo_metrics;
INT charmap; INT charmap;
UINT16 flags; UINT32 flags;
struct dwrite_fonttable cmap; struct dwrite_fonttable cmap;
struct dwrite_fonttable vdmx; struct dwrite_fonttable vdmx;
@ -291,13 +299,15 @@ extern float fontface_get_scaled_design_advance(struct dwrite_fontface *fontface
extern struct dwrite_fontface *unsafe_impl_from_IDWriteFontFace(IDWriteFontFace *iface) DECLSPEC_HIDDEN; extern struct dwrite_fontface *unsafe_impl_from_IDWriteFontFace(IDWriteFontFace *iface) DECLSPEC_HIDDEN;
/* Opentype font table functions */ /* Opentype font table functions */
struct dwrite_font_props { struct dwrite_font_props
{
DWRITE_FONT_STYLE style; DWRITE_FONT_STYLE style;
DWRITE_FONT_STRETCH stretch; DWRITE_FONT_STRETCH stretch;
DWRITE_FONT_WEIGHT weight; DWRITE_FONT_WEIGHT weight;
DWRITE_PANOSE panose; DWRITE_PANOSE panose;
FONTSIGNATURE fontsig; FONTSIGNATURE fontsig;
LOGFONTW lf; LOGFONTW lf;
UINT32 flags;
}; };
struct file_stream_desc { struct file_stream_desc {
@ -392,7 +402,7 @@ extern BOOL freetype_has_kerning_pairs(IDWriteFontFace5 *fontface) DECLSPEC_HIDD
extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace5 *fontface, UINT16 left, UINT16 right) DECLSPEC_HIDDEN; extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace5 *fontface, UINT16 left, UINT16 right) DECLSPEC_HIDDEN;
extern void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap_desc) DECLSPEC_HIDDEN; extern void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap_desc) DECLSPEC_HIDDEN;
extern BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; extern BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN;
extern INT freetype_get_charmap_index(IDWriteFontFace5 *fontface, BOOL *is_symbol) DECLSPEC_HIDDEN; extern INT freetype_get_charmap_index(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
extern INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emsize, UINT16 index, extern INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emsize, UINT16 index,
DWRITE_MEASURING_MODE measuring_mode, BOOL *has_contours) DECLSPEC_HIDDEN; DWRITE_MEASURING_MODE measuring_mode, BOOL *has_contours) DECLSPEC_HIDDEN;
extern void freetype_get_design_glyph_bbox(IDWriteFontFace4*,UINT16,UINT16,RECT*) DECLSPEC_HIDDEN; extern void freetype_get_design_glyph_bbox(IDWriteFontFace4*,UINT16,UINT16,RECT*) DECLSPEC_HIDDEN;

View File

@ -69,7 +69,8 @@ struct dwrite_font_propvec {
FLOAT weight; FLOAT weight;
}; };
struct dwrite_font_data { struct dwrite_font_data
{
LONG ref; LONG ref;
DWRITE_FONT_STYLE style; DWRITE_FONT_STYLE style;
@ -77,6 +78,7 @@ struct dwrite_font_data {
DWRITE_FONT_WEIGHT weight; DWRITE_FONT_WEIGHT weight;
DWRITE_PANOSE panose; DWRITE_PANOSE panose;
FONTSIGNATURE fontsig; FONTSIGNATURE fontsig;
UINT32 flags; /* enum font_flags */
struct dwrite_font_propvec propvec; struct dwrite_font_propvec propvec;
DWRITE_FONT_METRICS1 metrics; DWRITE_FONT_METRICS1 metrics;
@ -206,13 +208,6 @@ struct dwrite_colorglyphenum
#define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1) #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
#define GLYPH_MAX 65536 #define GLYPH_MAX 65536
enum fontface_flags {
FONTFACE_IS_SYMBOL = 1 << 0,
FONTFACE_IS_MONOSPACED = 1 << 1,
FONTFACE_HAS_KERNING_PAIRS = 1 << 2,
FONTFACE_HAS_VERTICAL_VARIANTS = 1 << 3
};
struct dwrite_fontfile { struct dwrite_fontfile {
IDWriteFontFile IDWriteFontFile_iface; IDWriteFontFile IDWriteFontFile_iface;
LONG ref; LONG ref;
@ -621,7 +616,7 @@ static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace5 *iface)
TRACE("%p.\n", iface); TRACE("%p.\n", iface);
return !!(fontface->flags & FONTFACE_IS_SYMBOL); return !!(fontface->flags & FONT_IS_SYMBOL);
} }
static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace5 *iface, DWRITE_FONT_METRICS *metrics) static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace5 *iface, DWRITE_FONT_METRICS *metrics)
@ -1618,19 +1613,10 @@ static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont3 *iface)
static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont3 *iface) static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont3 *iface)
{ {
struct dwrite_font *font = impl_from_IDWriteFont3(iface); struct dwrite_font *font = impl_from_IDWriteFont3(iface);
IDWriteFontFace5 *fontface;
HRESULT hr;
BOOL ret;
TRACE("%p.\n", iface); TRACE("%p.\n", iface);
hr = get_fontface_from_font(font, &fontface); return !!(font->data->flags & FONT_IS_SYMBOL);
if (FAILED(hr))
return FALSE;
ret = IDWriteFontFace5_IsSymbolFont(fontface);
IDWriteFontFace5_Release(fontface);
return ret;
} }
static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont3 *iface, IDWriteLocalizedStrings **names) static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont3 *iface, IDWriteLocalizedStrings **names)
@ -3695,6 +3681,7 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized
data->panose = props.panose; data->panose = props.panose;
data->fontsig = props.fontsig; data->fontsig = props.fontsig;
data->lf = props.lf; data->lf = props.lf;
data->flags = props.flags;
fontstrings_get_en_string(*family_name, familyW, ARRAY_SIZE(familyW)); fontstrings_get_en_string(*family_name, familyW, ARRAY_SIZE(familyW));
fontstrings_get_en_string(data->names, faceW, ARRAY_SIZE(faceW)); fontstrings_get_en_string(data->names, faceW, ARRAY_SIZE(faceW));
@ -4651,8 +4638,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
{ {
struct file_stream_desc stream_desc; struct file_stream_desc stream_desc;
struct dwrite_fontface *fontface; struct dwrite_fontface *fontface;
HRESULT hr = S_OK; HRESULT hr;
BOOL is_symbol;
int i; int i;
*ret = NULL; *ret = NULL;
@ -4701,9 +4687,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
} }
} }
fontface->charmap = freetype_get_charmap_index(&fontface->IDWriteFontFace5_iface, &is_symbol); fontface->charmap = freetype_get_charmap_index(&fontface->IDWriteFontFace5_iface);
if (is_symbol)
fontface->flags |= FONTFACE_IS_SYMBOL;
if (freetype_has_kerning_pairs(&fontface->IDWriteFontFace5_iface)) if (freetype_has_kerning_pairs(&fontface->IDWriteFontFace5_iface))
fontface->flags |= FONTFACE_HAS_KERNING_PAIRS; fontface->flags |= FONTFACE_HAS_KERNING_PAIRS;
if (freetype_is_monospaced(&fontface->IDWriteFontFace5_iface)) if (freetype_is_monospaced(&fontface->IDWriteFontFace5_iface))
@ -4717,15 +4701,19 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
If face is created directly from factory we have to go through properties resolution. If face is created directly from factory we have to go through properties resolution.
*/ */
if (desc->font_data) { if (desc->font_data)
{
fontface->weight = desc->font_data->weight; fontface->weight = desc->font_data->weight;
fontface->style = desc->font_data->style; fontface->style = desc->font_data->style;
fontface->stretch = desc->font_data->stretch; fontface->stretch = desc->font_data->stretch;
fontface->panose = desc->font_data->panose; fontface->panose = desc->font_data->panose;
fontface->fontsig = desc->font_data->fontsig; fontface->fontsig = desc->font_data->fontsig;
fontface->lf = desc->font_data->lf; fontface->lf = desc->font_data->lf;
if (desc->font_data->flags & FONT_IS_SYMBOL)
fontface->flags |= FONT_IS_SYMBOL;
} }
else { else
{
IDWriteLocalizedStrings *names; IDWriteLocalizedStrings *names;
struct dwrite_font_data *data; struct dwrite_font_data *data;
@ -4742,6 +4730,8 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
fontface->panose = data->panose; fontface->panose = data->panose;
fontface->fontsig = data->fontsig; fontface->fontsig = data->fontsig;
fontface->lf = data->lf; fontface->lf = data->lf;
if (data->flags & FONT_IS_SYMBOL)
fontface->flags |= FONT_IS_SYMBOL;
IDWriteLocalizedStrings_Release(names); IDWriteLocalizedStrings_Release(names);
release_font_data(data); release_font_data(data);

View File

@ -855,29 +855,19 @@ BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
return ret; return ret;
} }
INT freetype_get_charmap_index(IDWriteFontFace5 *fontface, BOOL *is_symbol) INT freetype_get_charmap_index(IDWriteFontFace5 *fontface)
{ {
INT charmap_index = -1; INT charmap_index = -1;
FT_Face face; FT_Face face;
*is_symbol = FALSE;
EnterCriticalSection(&freetype_cs); EnterCriticalSection(&freetype_cs);
if (pFTC_Manager_LookupFace(cache_manager, fontface, &face) == 0) { if (pFTC_Manager_LookupFace(cache_manager, fontface, &face) == 0)
TT_OS2 *os2 = pFT_Get_Sfnt_Table(face, ft_sfnt_os2); {
FT_Int i; FT_Int i;
if (os2) {
FT_UInt dummy;
if (os2->version == 0)
*is_symbol = pFT_Get_First_Char(face, &dummy) >= 0x100;
else
*is_symbol = !!(os2->ulCodePageRange1 & FS_SYMBOL);
}
for (i = 0; i < face->num_charmaps; i++) for (i = 0; i < face->num_charmaps; i++)
if (face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL) { if (face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
*is_symbol = TRUE; {
charmap_index = i; charmap_index = i;
break; break;
} }
@ -978,9 +968,8 @@ BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
return FALSE; return FALSE;
} }
INT freetype_get_charmap_index(IDWriteFontFace5 *fontface, BOOL *is_symbol) INT freetype_get_charmap_index(IDWriteFontFace5 *fontface)
{ {
*is_symbol = FALSE;
return -1; return -1;
} }

View File

@ -44,6 +44,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
#define MS_SBIX_TAG DWRITE_MAKE_OPENTYPE_TAG('s','b','i','x') #define MS_SBIX_TAG DWRITE_MAKE_OPENTYPE_TAG('s','b','i','x')
#define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p') #define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p')
#define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C') #define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C')
#define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
/* 'sbix' formats */ /* 'sbix' formats */
#define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ') #define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ')
@ -131,6 +132,18 @@ enum OPENTYPE_CMAP_TABLE_FORMAT
OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE = 12 OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE = 12
}; };
enum opentype_cmap_table_platform
{
OPENTYPE_CMAP_TABLE_PLATFORM_WIN = 3,
};
enum opentype_cmap_table_encoding
{
OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL = 0,
OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_BMP = 1,
OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_FULL = 10,
};
/* PANOSE is 10 bytes in size, need to pack the structure properly */ /* PANOSE is 10 bytes in size, need to pack the structure properly */
#include "pshpack2.h" #include "pshpack2.h"
typedef struct typedef struct
@ -1705,6 +1718,7 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
struct dwrite_fonttable os2, head; struct dwrite_fonttable os2, head;
const TT_OS2_V2 *tt_os2; const TT_OS2_V2 *tt_os2;
const TT_HEAD *tt_head; const TT_HEAD *tt_head;
BOOL is_symbol;
opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2); opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2);
opentype_get_font_table(stream_desc, MS_HEAD_TAG, &head); opentype_get_font_table(stream_desc, MS_HEAD_TAG, &head);
@ -1721,7 +1735,8 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
memset(&props->lf, 0, sizeof(props->lf)); memset(&props->lf, 0, sizeof(props->lf));
/* DWRITE_FONT_STRETCH enumeration values directly match font data values */ /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
if (tt_os2) { if (tt_os2)
{
USHORT version = GET_BE_WORD(tt_os2->version); USHORT version = GET_BE_WORD(tt_os2->version);
USHORT fsSelection = GET_BE_WORD(tt_os2->fsSelection); USHORT fsSelection = GET_BE_WORD(tt_os2->fsSelection);
USHORT usWeightClass = GET_BE_WORD(tt_os2->usWeightClass); USHORT usWeightClass = GET_BE_WORD(tt_os2->usWeightClass);
@ -1752,11 +1767,8 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
props->fontsig.fsUsb[2] = GET_BE_DWORD(tt_os2->ulUnicodeRange3); props->fontsig.fsUsb[2] = GET_BE_DWORD(tt_os2->ulUnicodeRange3);
props->fontsig.fsUsb[3] = GET_BE_DWORD(tt_os2->ulUnicodeRange4); props->fontsig.fsUsb[3] = GET_BE_DWORD(tt_os2->ulUnicodeRange4);
if (GET_BE_WORD(tt_os2->version) == 0) { if (version)
props->fontsig.fsCsb[0] = 0; {
props->fontsig.fsCsb[1] = 0;
}
else {
props->fontsig.fsCsb[0] = GET_BE_DWORD(tt_os2->ulCodePageRange1); props->fontsig.fsCsb[0] = GET_BE_DWORD(tt_os2->ulCodePageRange1);
props->fontsig.fsCsb[1] = GET_BE_DWORD(tt_os2->ulCodePageRange2); props->fontsig.fsCsb[1] = GET_BE_DWORD(tt_os2->ulCodePageRange2);
} }
@ -1780,6 +1792,37 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
props->lf.lfWeight = props->weight; props->lf.lfWeight = props->weight;
if (!(is_symbol = props->panose.familyKind == DWRITE_PANOSE_FAMILY_SYMBOL))
{
struct dwrite_fonttable cmap;
int i, offset, num_tables;
opentype_get_font_table(stream_desc, MS_CMAP_TAG, &cmap);
if (cmap.data)
{
num_tables = table_read_be_word(&cmap, FIELD_OFFSET(struct cmap_header, num_tables));
offset = FIELD_OFFSET(struct cmap_header, tables);
for (i = 0; !is_symbol && i < num_tables; ++i)
{
WORD platform, encoding;
platform = table_read_be_word(&cmap, offset + i * sizeof(struct cmap_encoding_record) +
FIELD_OFFSET(struct cmap_encoding_record, platformID));
encoding = table_read_be_word(&cmap, offset + i * sizeof(struct cmap_encoding_record) +
FIELD_OFFSET(struct cmap_encoding_record, encodingID));
is_symbol = platform == OPENTYPE_CMAP_TABLE_PLATFORM_WIN &&
encoding == OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL;
}
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, cmap.context);
}
}
if (is_symbol)
props->flags |= FONT_IS_SYMBOL;
TRACE("stretch=%d, weight=%d, style %d\n", props->stretch, props->weight, props->style); TRACE("stretch=%d, weight=%d, style %d\n", props->stretch, props->weight, props->style);
if (os2.data) if (os2.data)

View File

@ -406,7 +406,7 @@ struct cmap_encoding_record
struct cmap_header struct cmap_header
{ {
WORD version; WORD version;
WORD numTables; WORD num_tables;
struct cmap_encoding_record tables[1]; struct cmap_encoding_record tables[1];
}; };
@ -3544,7 +3544,7 @@ static UINT32 opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *ta
*ranges = NULL; *ranges = NULL;
num_tables = table_read_be_word(table, 0, FIELD_OFFSET(struct cmap_header, numTables)); num_tables = table_read_be_word(table, 0, FIELD_OFFSET(struct cmap_header, num_tables));
tables = table->data + FIELD_OFFSET(struct cmap_header, tables); tables = table->data + FIELD_OFFSET(struct cmap_header, tables);
for (i = 0; i < num_tables; ++i) for (i = 0; i < num_tables; ++i)
@ -7260,9 +7260,6 @@ static BOOL get_expected_is_symbol(IDWriteFontFace *fontface)
if (tt_os2) if (tt_os2)
{ {
if (tt_os2->version)
is_symbol = !!(GET_BE_DWORD(tt_os2->ulCodePageRange1) & FS_SYMBOL);
if (!is_symbol)
is_symbol = tt_os2->panose.bFamilyType == PAN_FAMILY_PICTORIAL; is_symbol = tt_os2->panose.bFamilyType == PAN_FAMILY_PICTORIAL;
IDWriteFontFace_ReleaseFontTable(fontface, os2_context); IDWriteFontFace_ReleaseFontTable(fontface, os2_context);
} }
@ -7275,7 +7272,7 @@ static BOOL get_expected_is_symbol(IDWriteFontFace *fontface)
if (FAILED(hr) || !exists) if (FAILED(hr) || !exists)
return is_symbol; return is_symbol;
num_tables = table_read_be_word(&cmap, 0, FIELD_OFFSET(struct cmap_header, numTables)); num_tables = table_read_be_word(&cmap, 0, FIELD_OFFSET(struct cmap_header, num_tables));
tables = cmap.data + FIELD_OFFSET(struct cmap_header, tables); tables = cmap.data + FIELD_OFFSET(struct cmap_header, tables);
for (i = 0; i < num_tables; ++i) for (i = 0; i < num_tables; ++i)
@ -7345,9 +7342,7 @@ static void test_IsSymbolFont(void)
is_symbol_face = IDWriteFontFace_IsSymbolFont(fontface); is_symbol_face = IDWriteFontFace_IsSymbolFont(fontface);
ok(is_symbol_font == is_symbol_face, "Unexpected symbol flag.\n"); ok(is_symbol_font == is_symbol_face, "Unexpected symbol flag.\n");
/* FIXME: failures disabled on Wine for now */
is_symbol_expected = get_expected_is_symbol(fontface); is_symbol_expected = get_expected_is_symbol(fontface);
todo_wine_if(is_symbol_expected != is_symbol_face)
ok(is_symbol_expected == is_symbol_face, "Unexpected is_symbol flag %d for %s, font %d.\n", ok(is_symbol_expected == is_symbol_face, "Unexpected is_symbol flag %d for %s, font %d.\n",
is_symbol_face, wine_dbgstr_w(nameW), j); is_symbol_face, wine_dbgstr_w(nameW), j);