dwrite: Implement HasVerticalGlyphVariants().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
90bcff0eae
commit
e30607fdb0
@ -229,6 +229,7 @@ extern UINT32 opentype_get_cpal_palettecount(const void*) DECLSPEC_HIDDEN;
|
|||||||
extern UINT32 opentype_get_cpal_paletteentrycount(const void*) DECLSPEC_HIDDEN;
|
extern UINT32 opentype_get_cpal_paletteentrycount(const void*) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT opentype_get_cpal_entries(const void*,UINT32,UINT32,UINT32,DWRITE_COLOR_F*) DECLSPEC_HIDDEN;
|
extern HRESULT opentype_get_cpal_entries(const void*,UINT32,UINT32,UINT32,DWRITE_COLOR_F*) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT opentype_get_font_signature(struct file_stream_desc*,FONTSIGNATURE*) DECLSPEC_HIDDEN;
|
extern HRESULT opentype_get_font_signature(struct file_stream_desc*,FONTSIGNATURE*) DECLSPEC_HIDDEN;
|
||||||
|
extern BOOL opentype_has_vertical_variants(IDWriteFontFace3*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
struct dwrite_colorglyph {
|
struct dwrite_colorglyph {
|
||||||
USHORT layer; /* [0, num_layers) index indicating current layer */
|
USHORT layer; /* [0, num_layers) index indicating current layer */
|
||||||
|
@ -205,6 +205,13 @@ 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_KERN_PAIRS = 1 << 2,
|
||||||
|
FONTFACE_HAS_VERTICAL_VARIANTS = 1 << 3
|
||||||
|
};
|
||||||
|
|
||||||
struct dwrite_fontface {
|
struct dwrite_fontface {
|
||||||
IDWriteFontFace3 IDWriteFontFace3_iface;
|
IDWriteFontFace3 IDWriteFontFace3_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
@ -219,9 +226,7 @@ struct dwrite_fontface {
|
|||||||
DWRITE_FONT_METRICS1 metrics;
|
DWRITE_FONT_METRICS1 metrics;
|
||||||
DWRITE_CARET_METRICS caret;
|
DWRITE_CARET_METRICS caret;
|
||||||
INT charmap;
|
INT charmap;
|
||||||
BOOL is_symbol;
|
UINT16 flags;
|
||||||
BOOL has_kerning_pairs : 1;
|
|
||||||
BOOL is_monospaced : 1;
|
|
||||||
|
|
||||||
struct dwrite_fonttable cmap;
|
struct dwrite_fonttable cmap;
|
||||||
struct dwrite_fonttable vdmx;
|
struct dwrite_fonttable vdmx;
|
||||||
@ -545,7 +550,7 @@ static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace3 *iface)
|
|||||||
{
|
{
|
||||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
|
struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
return This->is_symbol;
|
return !!(This->flags & FONTFACE_IS_SYMBOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace3 *iface, DWRITE_FONT_METRICS *metrics)
|
static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace3 *iface, DWRITE_FONT_METRICS *metrics)
|
||||||
@ -859,7 +864,7 @@ static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace3 *iface)
|
|||||||
{
|
{
|
||||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
|
struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
return This->is_monospaced;
|
return !!(This->flags & FONTFACE_IS_MONOSPACED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace3 *iface,
|
static HRESULT WINAPI dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace3 *iface,
|
||||||
@ -929,7 +934,7 @@ static HRESULT WINAPI dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace3
|
|||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!This->has_kerning_pairs) {
|
if (This->flags & FONTFACE_HAS_KERN_PAIRS) {
|
||||||
memset(adjustments, 0, count*sizeof(INT32));
|
memset(adjustments, 0, count*sizeof(INT32));
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -945,7 +950,7 @@ static BOOL WINAPI dwritefontface1_HasKerningPairs(IDWriteFontFace3 *iface)
|
|||||||
{
|
{
|
||||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
|
struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
return This->has_kerning_pairs;
|
return !!(This->flags & FONTFACE_HAS_KERN_PAIRS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace3 *iface,
|
static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace3 *iface,
|
||||||
@ -968,8 +973,8 @@ static HRESULT WINAPI dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace3
|
|||||||
static BOOL WINAPI dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace3 *iface)
|
static BOOL WINAPI dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace3 *iface)
|
||||||
{
|
{
|
||||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
|
struct dwrite_fontface *This = impl_from_IDWriteFontFace3(iface);
|
||||||
FIXME("(%p): stub\n", This);
|
TRACE("(%p)\n", This);
|
||||||
return FALSE;
|
return !!(This->flags & FONTFACE_HAS_VERTICAL_VARIANTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL WINAPI dwritefontface2_IsColorFont(IDWriteFontFace3 *iface)
|
static BOOL WINAPI dwritefontface2_IsColorFont(IDWriteFontFace3 *iface)
|
||||||
@ -4130,6 +4135,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace3 **ret
|
|||||||
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 = S_OK;
|
||||||
|
BOOL is_symbol;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
*ret = NULL;
|
*ret = NULL;
|
||||||
@ -4188,9 +4194,17 @@ HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace3 **ret
|
|||||||
fontface->caret.slopeRun = fontface->caret.slopeRise / 3;
|
fontface->caret.slopeRun = fontface->caret.slopeRise / 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fontface->charmap = freetype_get_charmap_index(&fontface->IDWriteFontFace3_iface, &fontface->is_symbol);
|
|
||||||
fontface->has_kerning_pairs = freetype_has_kerning_pairs(&fontface->IDWriteFontFace3_iface);
|
fontface->flags = 0;
|
||||||
fontface->is_monospaced = freetype_is_monospaced(&fontface->IDWriteFontFace3_iface);
|
fontface->charmap = freetype_get_charmap_index(&fontface->IDWriteFontFace3_iface, &is_symbol);
|
||||||
|
if (is_symbol)
|
||||||
|
fontface->flags |= FONTFACE_IS_SYMBOL;
|
||||||
|
if (freetype_has_kerning_pairs(&fontface->IDWriteFontFace3_iface))
|
||||||
|
fontface->flags |= FONTFACE_HAS_KERN_PAIRS;
|
||||||
|
if (freetype_is_monospaced(&fontface->IDWriteFontFace3_iface))
|
||||||
|
fontface->flags |= FONTFACE_IS_MONOSPACED;
|
||||||
|
if (opentype_has_vertical_variants(&fontface->IDWriteFontFace3_iface))
|
||||||
|
fontface->flags |= FONTFACE_HAS_VERTICAL_VARIANTS;
|
||||||
|
|
||||||
/* Font properties are reused from font object when 'normal' face creation path is used:
|
/* Font properties are reused from font object when 'normal' face creation path is used:
|
||||||
collection -> family -> matching font -> fontface.
|
collection -> family -> matching font -> fontface.
|
||||||
|
@ -334,6 +334,49 @@ enum OPENTYPE_PLATFORM_ID
|
|||||||
OPENTYPE_PLATFORM_CUSTOM
|
OPENTYPE_PLATFORM_CUSTOM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD FeatureParams;
|
||||||
|
WORD LookupCount;
|
||||||
|
WORD LookupListIndex[1];
|
||||||
|
} OT_Feature;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD LookupCount;
|
||||||
|
WORD Lookup[1];
|
||||||
|
} OT_LookupList;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD LookupType;
|
||||||
|
WORD LookupFlag;
|
||||||
|
WORD SubTableCount;
|
||||||
|
WORD SubTable[1];
|
||||||
|
} OT_LookupTable;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD SubstFormat;
|
||||||
|
WORD Coverage;
|
||||||
|
WORD DeltaGlyphID;
|
||||||
|
} GSUB_SingleSubstFormat1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD SubstFormat;
|
||||||
|
WORD Coverage;
|
||||||
|
WORD GlyphCount;
|
||||||
|
WORD Substitute[1];
|
||||||
|
} GSUB_SingleSubstFormat2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD SubstFormat;
|
||||||
|
WORD ExtensionLookupType;
|
||||||
|
DWORD ExtensionOffset;
|
||||||
|
} GSUB_ExtensionPosFormat1;
|
||||||
|
|
||||||
|
enum OPENTYPE_GPOS_LOOKUPS
|
||||||
|
{
|
||||||
|
OPENTYPE_GPOS_SINGLE_SUBST = 1,
|
||||||
|
OPENTYPE_GPOS_EXTENSION_SUBST = 7
|
||||||
|
};
|
||||||
|
|
||||||
enum TT_NAME_WINDOWS_ENCODING_ID
|
enum TT_NAME_WINDOWS_ENCODING_ID
|
||||||
{
|
{
|
||||||
TT_NAME_WINDOWS_ENCODING_SYMBOL = 0,
|
TT_NAME_WINDOWS_ENCODING_SYMBOL = 0,
|
||||||
@ -1887,3 +1930,76 @@ HRESULT opentype_get_font_signature(struct file_stream_desc *stream_desc, FONTSI
|
|||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL opentype_has_vertical_variants(IDWriteFontFace3 *fontface)
|
||||||
|
{
|
||||||
|
const OT_FeatureList *featurelist;
|
||||||
|
const OT_LookupList *lookup_list;
|
||||||
|
BOOL exists = FALSE, ret = FALSE;
|
||||||
|
const GPOS_GSUB_Header *header;
|
||||||
|
const void *data;
|
||||||
|
void *context;
|
||||||
|
UINT32 size;
|
||||||
|
HRESULT hr;
|
||||||
|
UINT16 i;
|
||||||
|
|
||||||
|
hr = IDWriteFontFace3_TryGetFontTable(fontface, MS_GSUB_TAG, &data, &size, &context, &exists);
|
||||||
|
if (FAILED(hr) || !exists)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
header = data;
|
||||||
|
featurelist = (OT_FeatureList*)((BYTE*)header + GET_BE_WORD(header->FeatureList));
|
||||||
|
lookup_list = (const OT_LookupList*)((BYTE*)header + GET_BE_WORD(header->LookupList));
|
||||||
|
|
||||||
|
for (i = 0; i < GET_BE_WORD(featurelist->FeatureCount); i++) {
|
||||||
|
if (*(UINT32*)featurelist->FeatureRecord[i].FeatureTag == DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING) {
|
||||||
|
const OT_Feature *feature = (const OT_Feature*)((BYTE*)featurelist + GET_BE_WORD(featurelist->FeatureRecord[i].Feature));
|
||||||
|
UINT16 lookup_count = GET_BE_WORD(feature->LookupCount), index, count, type;
|
||||||
|
const GSUB_SingleSubstFormat2 *subst2;
|
||||||
|
const OT_LookupTable *lookup_table;
|
||||||
|
UINT32 offset;
|
||||||
|
|
||||||
|
if (lookup_count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* check if lookup is empty */
|
||||||
|
index = GET_BE_WORD(feature->LookupListIndex[0]);
|
||||||
|
lookup_table = (const OT_LookupTable*)((BYTE*)lookup_list + GET_BE_WORD(lookup_list->Lookup[index]));
|
||||||
|
|
||||||
|
type = GET_BE_WORD(lookup_table->LookupType);
|
||||||
|
if (type != OPENTYPE_GPOS_SINGLE_SUBST && type != OPENTYPE_GPOS_EXTENSION_SUBST)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
count = GET_BE_WORD(lookup_table->SubTableCount);
|
||||||
|
if (count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
offset = GET_BE_WORD(lookup_table->SubTable[0]);
|
||||||
|
if (type == OPENTYPE_GPOS_EXTENSION_SUBST) {
|
||||||
|
const GSUB_ExtensionPosFormat1 *ext = (const GSUB_ExtensionPosFormat1 *)((const BYTE *)lookup_table + offset);
|
||||||
|
if (GET_BE_WORD(ext->SubstFormat) == 1)
|
||||||
|
offset += GET_BE_DWORD(ext->ExtensionOffset);
|
||||||
|
else
|
||||||
|
FIXME("Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext->SubstFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
subst2 = (const GSUB_SingleSubstFormat2*)((BYTE*)lookup_table + offset);
|
||||||
|
index = GET_BE_WORD(subst2->SubstFormat);
|
||||||
|
if (index == 1)
|
||||||
|
FIXME("Validate Single Substitution Format 1\n");
|
||||||
|
else if (index == 2) {
|
||||||
|
/* SimSun-ExtB has 0 glyph count for this substitution */
|
||||||
|
if (GET_BE_WORD(subst2->GlyphCount) > 0) {
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WARN("Unknown Single Substitution Format, %u\n", index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IDWriteFontFace3_ReleaseFontTable(fontface, context);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
|
#define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
|
||||||
#define MS_HHEA_TAG DWRITE_MAKE_OPENTYPE_TAG('h','h','e','a')
|
#define MS_HHEA_TAG DWRITE_MAKE_OPENTYPE_TAG('h','h','e','a')
|
||||||
#define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
|
#define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
|
||||||
|
#define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B')
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
#define GET_BE_WORD(x) (x)
|
#define GET_BE_WORD(x) (x)
|
||||||
@ -220,6 +221,60 @@ typedef struct {
|
|||||||
USHORT numberOfHMetrics;
|
USHORT numberOfHMetrics;
|
||||||
} TT_HHEA;
|
} TT_HHEA;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD version;
|
||||||
|
WORD ScriptList;
|
||||||
|
WORD FeatureList;
|
||||||
|
WORD LookupList;
|
||||||
|
} GSUB_Header;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CHAR FeatureTag[4];
|
||||||
|
WORD Feature;
|
||||||
|
} OT_FeatureRecord;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD FeatureCount;
|
||||||
|
OT_FeatureRecord FeatureRecord[1];
|
||||||
|
} OT_FeatureList;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD FeatureParams;
|
||||||
|
WORD LookupCount;
|
||||||
|
WORD LookupListIndex[1];
|
||||||
|
} OT_Feature;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD LookupCount;
|
||||||
|
WORD Lookup[1];
|
||||||
|
} OT_LookupList;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD LookupType;
|
||||||
|
WORD LookupFlag;
|
||||||
|
WORD SubTableCount;
|
||||||
|
WORD SubTable[1];
|
||||||
|
} OT_LookupTable;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD SubstFormat;
|
||||||
|
WORD Coverage;
|
||||||
|
WORD DeltaGlyphID;
|
||||||
|
} GSUB_SingleSubstFormat1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD SubstFormat;
|
||||||
|
WORD Coverage;
|
||||||
|
WORD GlyphCount;
|
||||||
|
WORD Substitute[1];
|
||||||
|
} GSUB_SingleSubstFormat2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD SubstFormat;
|
||||||
|
WORD ExtensionLookupType;
|
||||||
|
DWORD ExtensionOffset;
|
||||||
|
} GSUB_ExtensionPosFormat1;
|
||||||
|
|
||||||
#include "poppack.h"
|
#include "poppack.h"
|
||||||
|
|
||||||
static IDWriteFactory *create_factory(void)
|
static IDWriteFactory *create_factory(void)
|
||||||
@ -6300,6 +6355,153 @@ static void test_font_properties(void)
|
|||||||
IDWriteFactory_Release(factory);
|
IDWriteFactory_Release(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL has_vertical_glyph_variants(IDWriteFontFace1 *fontface)
|
||||||
|
{
|
||||||
|
const OT_FeatureList *featurelist;
|
||||||
|
const OT_LookupList *lookup_list;
|
||||||
|
BOOL exists = FALSE, ret = FALSE;
|
||||||
|
const GSUB_Header *header;
|
||||||
|
const void *data;
|
||||||
|
void *context;
|
||||||
|
UINT32 size;
|
||||||
|
HRESULT hr;
|
||||||
|
UINT16 i;
|
||||||
|
|
||||||
|
hr = IDWriteFontFace1_TryGetFontTable(fontface, MS_GSUB_TAG, &data, &size, &context, &exists);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
if (!exists)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
header = data;
|
||||||
|
featurelist = (OT_FeatureList*)((BYTE*)header + GET_BE_WORD(header->FeatureList));
|
||||||
|
lookup_list = (const OT_LookupList*)((BYTE*)header + GET_BE_WORD(header->LookupList));
|
||||||
|
|
||||||
|
for (i = 0; i < GET_BE_WORD(featurelist->FeatureCount); i++) {
|
||||||
|
if (*(UINT32*)featurelist->FeatureRecord[i].FeatureTag == DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING) {
|
||||||
|
const OT_Feature *feature = (const OT_Feature*)((BYTE*)featurelist + GET_BE_WORD(featurelist->FeatureRecord[i].Feature));
|
||||||
|
UINT16 lookup_count = GET_BE_WORD(feature->LookupCount), index, count, type;
|
||||||
|
const GSUB_SingleSubstFormat2 *subst2;
|
||||||
|
const OT_LookupTable *lookup_table;
|
||||||
|
UINT32 offset;
|
||||||
|
|
||||||
|
if (lookup_count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ok(lookup_count == 1, "got lookup count %u\n", lookup_count);
|
||||||
|
|
||||||
|
/* check if lookup is empty */
|
||||||
|
index = GET_BE_WORD(feature->LookupListIndex[0]);
|
||||||
|
lookup_table = (const OT_LookupTable*)((BYTE*)lookup_list + GET_BE_WORD(lookup_list->Lookup[index]));
|
||||||
|
|
||||||
|
type = GET_BE_WORD(lookup_table->LookupType);
|
||||||
|
ok(type == 1 || type == 7, "got unexpected lookup type %u\n", type);
|
||||||
|
|
||||||
|
|
||||||
|
count = GET_BE_WORD(lookup_table->SubTableCount);
|
||||||
|
if (count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ok(count > 0, "got unexpected subtable count %u\n", count);
|
||||||
|
|
||||||
|
offset = GET_BE_WORD(lookup_table->SubTable[0]);
|
||||||
|
if (type == 7) {
|
||||||
|
const GSUB_ExtensionPosFormat1 *ext = (const GSUB_ExtensionPosFormat1 *)((const BYTE *)lookup_table + offset);
|
||||||
|
if (GET_BE_WORD(ext->SubstFormat) == 1)
|
||||||
|
offset += GET_BE_DWORD(ext->ExtensionOffset);
|
||||||
|
else
|
||||||
|
ok(0, "Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext->SubstFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
subst2 = (const GSUB_SingleSubstFormat2*)((BYTE*)lookup_table + offset);
|
||||||
|
index = GET_BE_WORD(subst2->SubstFormat);
|
||||||
|
if (index == 1)
|
||||||
|
ok(0, "validate Single Substitution Format 1\n");
|
||||||
|
else if (index == 2) {
|
||||||
|
/* SimSun-ExtB has 0 glyph count for this substitution */
|
||||||
|
if (GET_BE_WORD(subst2->GlyphCount) > 0) {
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ok(0, "unknown Single Substitution Format, %u\n", index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IDWriteFontFace1_ReleaseFontTable(fontface, context);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_HasVerticalGlyphVariants(void)
|
||||||
|
{
|
||||||
|
IDWriteFontCollection *syscollection;
|
||||||
|
IDWriteFontFace1 *fontface1;
|
||||||
|
IDWriteFontFace *fontface;
|
||||||
|
IDWriteFactory *factory;
|
||||||
|
UINT32 count, i;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
factory = create_factory();
|
||||||
|
fontface = create_fontface(factory);
|
||||||
|
|
||||||
|
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
|
||||||
|
IDWriteFontFace_Release(fontface);
|
||||||
|
if (hr != S_OK) {
|
||||||
|
win_skip("HasVerticalGlyphVariants() is not supported.\n");
|
||||||
|
IDWriteFactory_Release(factory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IDWriteFontFace1_Release(fontface1);
|
||||||
|
|
||||||
|
hr = IDWriteFactory_GetSystemFontCollection(factory, &syscollection, FALSE);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
count = IDWriteFontCollection_GetFontFamilyCount(syscollection);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
IDWriteLocalizedStrings *names;
|
||||||
|
BOOL expected_vert, has_vert;
|
||||||
|
IDWriteFontFamily *family;
|
||||||
|
IDWriteFont *font;
|
||||||
|
WCHAR nameW[256];
|
||||||
|
|
||||||
|
hr = IDWriteFontCollection_GetFontFamily(syscollection, i, &family);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
|
||||||
|
DWRITE_FONT_STYLE_NORMAL, &font);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
hr = IDWriteFont_CreateFontFace(font, &fontface);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
hr = IDWriteFontFamily_GetFamilyNames(family, &names);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
get_enus_string(names, nameW, sizeof(nameW)/sizeof(nameW[0]));
|
||||||
|
|
||||||
|
expected_vert = has_vertical_glyph_variants(fontface1);
|
||||||
|
has_vert = IDWriteFontFace1_HasVerticalGlyphVariants(fontface1);
|
||||||
|
|
||||||
|
ok(expected_vert == has_vert, "%s: expected vertical feature %d, got %d\n",
|
||||||
|
wine_dbgstr_w(nameW), expected_vert, has_vert);
|
||||||
|
|
||||||
|
IDWriteLocalizedStrings_Release(names);
|
||||||
|
IDWriteFont_Release(font);
|
||||||
|
|
||||||
|
IDWriteFontFace1_Release(fontface1);
|
||||||
|
IDWriteFontFace_Release(fontface);
|
||||||
|
IDWriteFontFamily_Release(family);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDWriteFontCollection_Release(syscollection);
|
||||||
|
IDWriteFactory_Release(factory);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(font)
|
START_TEST(font)
|
||||||
{
|
{
|
||||||
IDWriteFactory *factory;
|
IDWriteFactory *factory;
|
||||||
@ -6357,6 +6559,7 @@ START_TEST(font)
|
|||||||
test_CreateFontFaceReference();
|
test_CreateFontFaceReference();
|
||||||
test_GetFontSignature();
|
test_GetFontSignature();
|
||||||
test_font_properties();
|
test_font_properties();
|
||||||
|
test_HasVerticalGlyphVariants();
|
||||||
|
|
||||||
IDWriteFactory_Release(factory);
|
IDWriteFactory_Release(factory);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user