dwrite: Add helper functions to collect default GSUB features.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Nikolay Sivov 2020-05-04 11:29:32 +03:00 committed by Alexandre Julliard
parent 7208bc40dc
commit bd6a500ab0
4 changed files with 108 additions and 18 deletions

View File

@ -1149,21 +1149,22 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
BOOL is_rtl, DWRITE_SCRIPT_ANALYSIS const* analysis, WCHAR const* locale, BOOL is_rtl, DWRITE_SCRIPT_ANALYSIS const* analysis, WCHAR const* locale,
IDWriteNumberSubstitution* substitution, DWRITE_TYPOGRAPHIC_FEATURES const** features, IDWriteNumberSubstitution* substitution, DWRITE_TYPOGRAPHIC_FEATURES const** features,
UINT32 const* feature_range_lengths, UINT32 feature_ranges, UINT32 max_glyph_count, UINT32 const* feature_range_lengths, UINT32 feature_ranges, UINT32 max_glyph_count,
UINT16* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* text_props, UINT16* glyph_indices, UINT16* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* text_props, UINT16 *glyphs,
DWRITE_SHAPING_GLYPH_PROPERTIES* glyph_props, UINT32* actual_glyph_count) DWRITE_SHAPING_GLYPH_PROPERTIES* glyph_props, UINT32* actual_glyph_count)
{ {
const struct dwritescript_properties *scriptprops;
DWRITE_NUMBER_SUBSTITUTION_METHOD method; DWRITE_NUMBER_SUBSTITUTION_METHOD method;
struct scriptshaping_context context; struct scriptshaping_context context;
struct dwrite_fontface *font_obj; struct dwrite_fontface *font_obj;
WCHAR digits[NATIVE_DIGITS_LEN]; WCHAR digits[NATIVE_DIGITS_LEN];
unsigned int i, g, script;
BOOL update_cluster; BOOL update_cluster;
WCHAR *string; WCHAR *string;
UINT32 i, g;
HRESULT hr = S_OK; HRESULT hr = S_OK;
TRACE("(%s:%u %p %d %d %s %s %p %p %p %u %u %p %p %p %p %p)\n", debugstr_wn(text, length), TRACE("(%s:%u %p %d %d %s %s %p %p %p %u %u %p %p %p %p %p)\n", debugstr_wn(text, length),
length, fontface, is_sideways, is_rtl, debugstr_sa_script(analysis->script), debugstr_w(locale), substitution, length, fontface, is_sideways, is_rtl, debugstr_sa_script(analysis->script), debugstr_w(locale), substitution,
features, feature_range_lengths, feature_ranges, max_glyph_count, clustermap, text_props, glyph_indices, features, feature_range_lengths, feature_ranges, max_glyph_count, clustermap, text_props, glyphs,
glyph_props, actual_glyph_count); glyph_props, actual_glyph_count);
analyzer_dump_user_features(features, feature_range_lengths, feature_ranges); analyzer_dump_user_features(features, feature_range_lengths, feature_ranges);
@ -1225,7 +1226,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
else else
update_cluster = TRUE; update_cluster = TRUE;
hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &glyph_indices[g]); hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &glyphs[g]);
if (FAILED(hr)) if (FAILED(hr))
goto done; goto done;
@ -1250,11 +1251,15 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
context.text = text; context.text = text;
context.length = length; context.length = length;
context.is_rtl = is_rtl; context.is_rtl = is_rtl;
context.is_sideways = is_sideways;
context.language_tag = get_opentype_language(locale); context.language_tag = get_opentype_language(locale);
/* FIXME: apply default features */ script = analysis->script > Script_LastId ? Script_Unknown : analysis->script;
scriptprops = &dwritescripts_properties[script];
hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props); hr = shape_get_glyphs(&context, scriptprops->scripttags);
if (SUCCEEDED(hr))
hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyphs, *actual_glyph_count,
text_props, glyph_props);
done: done:
heap_free(string); heap_free(string);

View File

@ -24,6 +24,9 @@
#include "wine/list.h" #include "wine/list.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B')
#define MS_GPOS_TAG DWRITE_MAKE_OPENTYPE_TAG('G','P','O','S')
static const DWRITE_MATRIX identity = static const DWRITE_MATRIX identity =
{ {
1.0f, 0.0f, 1.0f, 0.0f,
@ -466,6 +469,7 @@ struct scriptshaping_context
const WCHAR *text; const WCHAR *text;
unsigned int length; unsigned int length;
BOOL is_rtl; BOOL is_rtl;
BOOL is_sideways;
union union
{ {
@ -495,10 +499,16 @@ extern struct scriptshaping_cache *create_scriptshaping_cache(void *context,
extern void release_scriptshaping_cache(struct scriptshaping_cache*) DECLSPEC_HIDDEN; extern void release_scriptshaping_cache(struct scriptshaping_cache*) DECLSPEC_HIDDEN;
extern struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface) DECLSPEC_HIDDEN; extern struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface) DECLSPEC_HIDDEN;
struct shaping_feature
{
unsigned int tag;
};
struct shaping_features struct shaping_features
{ {
const DWORD *tags; struct shaping_feature *features;
unsigned int count; size_t count;
size_t capacity;
}; };
extern void opentype_layout_scriptshaping_cache_init(struct scriptshaping_cache *cache) DECLSPEC_HIDDEN; extern void opentype_layout_scriptshaping_cache_init(struct scriptshaping_cache *cache) DECLSPEC_HIDDEN;
@ -506,6 +516,8 @@ extern DWORD opentype_layout_find_script(const struct scriptshaping_cache *cache
unsigned int *script_index) DECLSPEC_HIDDEN; unsigned int *script_index) DECLSPEC_HIDDEN;
extern DWORD opentype_layout_find_language(const struct scriptshaping_cache *cache, DWORD kind, DWORD tag, extern DWORD opentype_layout_find_language(const struct scriptshaping_cache *cache, DWORD kind, DWORD tag,
unsigned int script_index, unsigned int *language_index) DECLSPEC_HIDDEN; unsigned int script_index, unsigned int *language_index) DECLSPEC_HIDDEN;
extern HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index,
unsigned int language_index, const struct shaping_features *features) DECLSPEC_HIDDEN;
extern void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index, extern void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index,
unsigned int language_index, const struct shaping_features *features) DECLSPEC_HIDDEN; unsigned int language_index, const struct shaping_features *features) DECLSPEC_HIDDEN;
@ -520,5 +532,6 @@ struct scriptshaping_ops
extern const struct scriptshaping_ops default_shaping_ops DECLSPEC_HIDDEN; extern const struct scriptshaping_ops default_shaping_ops DECLSPEC_HIDDEN;
extern const struct scriptshaping_ops latn_shaping_ops DECLSPEC_HIDDEN; extern const struct scriptshaping_ops latn_shaping_ops DECLSPEC_HIDDEN;
extern HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned int *scripts) DECLSPEC_HIDDEN;
extern HRESULT shape_get_positions(struct scriptshaping_context *context, const DWORD *scripts, extern HRESULT shape_get_positions(struct scriptshaping_context *context, const DWORD *scripts,
const struct shaping_features *features) DECLSPEC_HIDDEN; const struct shaping_features *features) DECLSPEC_HIDDEN;

View File

@ -34,8 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
#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_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f') #define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f')
#define MS_GDEF_TAG DWRITE_MAKE_OPENTYPE_TAG('G','D','E','F') #define MS_GDEF_TAG DWRITE_MAKE_OPENTYPE_TAG('G','D','E','F')
#define MS_GPOS_TAG DWRITE_MAKE_OPENTYPE_TAG('G','P','O','S')
#define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B')
#define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e') #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
#define MS_GLYF_TAG DWRITE_MAKE_OPENTYPE_TAG('g','l','y','f') #define MS_GLYF_TAG DWRITE_MAKE_OPENTYPE_TAG('g','l','y','f')
#define MS_CFF__TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F',' ') #define MS_CFF__TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F',' ')
@ -4107,7 +4105,7 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context,
if (feature_index >= total_feature_count) if (feature_index >= total_feature_count)
continue; continue;
if (feature_list->features[feature_index].tag == features->tags[i]) if (feature_list->features[feature_index].tag == features->features[i].tag)
{ {
WORD feature_offset = GET_BE_WORD(feature_list->features[feature_index].offset); WORD feature_offset = GET_BE_WORD(feature_list->features[feature_index].offset);
WORD lookup_count; WORD lookup_count;
@ -4152,3 +4150,9 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context,
heap_free(lookups.indexes); heap_free(lookups.indexes);
} }
HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index,
unsigned int language_index, const struct shaping_features *features)
{
return S_OK;
}

View File

@ -27,8 +27,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(dwrite); WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
#define MS_GPOS_TAG DWRITE_MAKE_OPENTYPE_TAG('G','P','O','S')
struct scriptshaping_cache *create_scriptshaping_cache(void *context, const struct shaping_font_ops *font_ops) struct scriptshaping_cache *create_scriptshaping_cache(void *context, const struct shaping_font_ops *font_ops)
{ {
struct scriptshaping_cache *cache; struct scriptshaping_cache *cache;
@ -165,11 +163,11 @@ static HRESULT latn_set_text_glyphs_props(struct scriptshaping_context *context,
return hr; return hr;
} }
static const DWORD std_gpos_tags[] = static struct shaping_feature std_gpos_tags[] =
{ {
DWRITE_FONT_FEATURE_TAG_KERNING, { DWRITE_FONT_FEATURE_TAG_KERNING },
DWRITE_FONT_FEATURE_TAG_MARK_POSITIONING, { DWRITE_FONT_FEATURE_TAG_MARK_POSITIONING },
DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING, { DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING },
}; };
static const struct shaping_features std_gpos_features = static const struct shaping_features std_gpos_features =
@ -268,3 +266,73 @@ HRESULT shape_get_positions(struct scriptshaping_context *context, const DWORD *
return S_OK; return S_OK;
} }
static void shape_add_feature(struct shaping_features *features, unsigned int tag)
{
if (!dwrite_array_reserve((void **)&features->features, &features->capacity, features->count + 1,
sizeof(*features->features)))
return;
features->features[features->count++].tag = tag;
}
static unsigned int shape_get_script_lang_index(struct scriptshaping_context *context, const unsigned int *scripts,
unsigned int table, unsigned int *script_index, unsigned int *language_index)
{
unsigned int script;
/* Resolve script tag to actually supported script. */
if ((script = shape_select_script(context->cache, table, scripts, script_index)))
{
unsigned int language = context->language_tag;
if ((language = shape_select_language(context->cache, table, *script_index, language, language_index)))
return script;
}
return 0;
}
HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned int *scripts)
{
static const unsigned int common_features[] =
{
DWRITE_FONT_FEATURE_TAG_GLYPH_COMPOSITION_DECOMPOSITION,
DWRITE_FONT_FEATURE_TAG_LOCALIZED_FORMS,
DWRITE_FONT_FEATURE_TAG_REQUIRED_LIGATURES,
};
static const unsigned int horizontal_features[] =
{
DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_ALTERNATES,
DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_LIGATURES,
DWRITE_FONT_FEATURE_TAG_STANDARD_LIGATURES,
DWRITE_MAKE_OPENTYPE_TAG('r','c','l','t'),
};
struct scriptshaping_cache *cache = context->cache;
unsigned int script_index, language_index, script;
struct shaping_features features = { 0 };
unsigned int i;
for (i = 0; i < ARRAY_SIZE(common_features); ++i)
shape_add_feature(&features, common_features[i]);
/* Horizontal features */
if (!context->is_sideways)
{
for (i = 0; i < ARRAY_SIZE(horizontal_features); ++i)
shape_add_feature(&features, horizontal_features[i]);
}
/* Resolve script tag to actually supported script. */
if (cache->gsub.table.data)
{
if ((script = shape_get_script_lang_index(context, scripts, MS_GSUB_TAG, &script_index, &language_index)))
{
opentype_layout_apply_gsub_features(context, script_index, language_index, &features);
}
}
heap_free(features.features);
return S_OK;
}