dwrite: Use mirrored character only if font supports it.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
bb91e877b3
commit
da55f010df
|
@ -280,16 +280,6 @@ static inline struct dwrite_fontfallback_builder *impl_from_IDWriteFontFallbackB
|
||||||
return CONTAINING_RECORD(iface, struct dwrite_fontfallback_builder, IDWriteFontFallbackBuilder_iface);
|
return CONTAINING_RECORD(iface, struct dwrite_fontfallback_builder, IDWriteFontFallbackBuilder_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline UINT32 decode_surrogate_pair(const WCHAR *str, UINT32 index, UINT32 end)
|
|
||||||
{
|
|
||||||
if (index < end-1 && IS_SURROGATE_PAIR(str[index], str[index+1])) {
|
|
||||||
UINT32 ch = 0x10000 + ((str[index] - 0xd800) << 10) + (str[index+1] - 0xdc00);
|
|
||||||
TRACE("surrogate pair (%x %x) => %x\n", str[index], str[index+1], ch);
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline UINT16 get_char_script(WCHAR c)
|
static inline UINT16 get_char_script(WCHAR c)
|
||||||
{
|
{
|
||||||
UINT16 script = get_table_entry(wine_scripts_table, c);
|
UINT16 script = get_table_entry(wine_scripts_table, c);
|
||||||
|
@ -1059,15 +1049,17 @@ static UINT32 get_opentype_language(const WCHAR *locale)
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWRITE_NUMBER_SUBSTITUTION_METHOD get_number_substitutes(IDWriteNumberSubstitution *substitution, WCHAR *digits)
|
static void get_number_substitutes(IDWriteNumberSubstitution *substitution, BOOL is_rtl, WCHAR *digits)
|
||||||
{
|
{
|
||||||
struct dwrite_numbersubstitution *numbersubst = unsafe_impl_from_IDWriteNumberSubstitution(substitution);
|
struct dwrite_numbersubstitution *numbersubst = unsafe_impl_from_IDWriteNumberSubstitution(substitution);
|
||||||
DWRITE_NUMBER_SUBSTITUTION_METHOD method;
|
DWRITE_NUMBER_SUBSTITUTION_METHOD method;
|
||||||
WCHAR isolang[9];
|
WCHAR isolang[9];
|
||||||
DWORD lctype;
|
DWORD lctype;
|
||||||
|
|
||||||
|
digits[0] = 0;
|
||||||
|
|
||||||
if (!numbersubst)
|
if (!numbersubst)
|
||||||
return DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE;
|
return;
|
||||||
|
|
||||||
lctype = numbersubst->ignore_user_override ? LOCALE_NOUSEROVERRIDE : 0;
|
lctype = numbersubst->ignore_user_override ? LOCALE_NOUSEROVERRIDE : 0;
|
||||||
|
|
||||||
|
@ -1096,7 +1088,6 @@ static DWRITE_NUMBER_SUBSTITUTION_METHOD get_number_substitutes(IDWriteNumberSub
|
||||||
else
|
else
|
||||||
method = numbersubst->method;
|
method = numbersubst->method;
|
||||||
|
|
||||||
digits[0] = 0;
|
|
||||||
switch (method)
|
switch (method)
|
||||||
{
|
{
|
||||||
case DWRITE_NUMBER_SUBSTITUTION_METHOD_NATIONAL:
|
case DWRITE_NUMBER_SUBSTITUTION_METHOD_NATIONAL:
|
||||||
|
@ -1125,7 +1116,8 @@ static DWRITE_NUMBER_SUBSTITUTION_METHOD get_number_substitutes(IDWriteNumberSub
|
||||||
method = DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE;
|
method = DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return method;
|
if ((method == DWRITE_NUMBER_SUBSTITUTION_METHOD_CONTEXTUAL && !is_rtl) || method == DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE)
|
||||||
|
digits[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void analyzer_dump_user_features(DWRITE_TYPOGRAPHIC_FEATURES const **features,
|
static void analyzer_dump_user_features(DWRITE_TYPOGRAPHIC_FEATURES const **features,
|
||||||
|
@ -1153,14 +1145,11 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
|
||||||
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;
|
const struct dwritescript_properties *scriptprops;
|
||||||
DWRITE_NUMBER_SUBSTITUTION_METHOD method;
|
struct scriptshaping_context context = { 0 };
|
||||||
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;
|
unsigned int script;
|
||||||
BOOL update_cluster;
|
HRESULT hr;
|
||||||
WCHAR *string;
|
|
||||||
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,
|
||||||
|
@ -1172,78 +1161,11 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
|
||||||
if (max_glyph_count < length)
|
if (max_glyph_count < length)
|
||||||
return E_NOT_SUFFICIENT_BUFFER;
|
return E_NOT_SUFFICIENT_BUFFER;
|
||||||
|
|
||||||
string = heap_calloc(length, sizeof(*string));
|
get_number_substitutes(substitution, is_rtl, digits);
|
||||||
if (!string)
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
|
|
||||||
method = get_number_substitutes(substitution, digits);
|
|
||||||
|
|
||||||
/* FIXME: have the shaping engine set this */
|
/* FIXME: have the shaping engine set this */
|
||||||
memset(text_props, 0, length * sizeof(*text_props));
|
memset(text_props, 0, length * sizeof(*text_props));
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
/* FIXME: set to better values */
|
|
||||||
glyph_props[i].justification = text[i] == ' ' ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER;
|
|
||||||
glyph_props[i].isClusterStart = 1;
|
|
||||||
glyph_props[i].isDiacritic = 0;
|
|
||||||
glyph_props[i].isZeroWidthSpace = 0;
|
|
||||||
glyph_props[i].reserved = 0;
|
|
||||||
|
|
||||||
clustermap[i] = i;
|
|
||||||
|
|
||||||
string[i] = text[i];
|
|
||||||
switch (method)
|
|
||||||
{
|
|
||||||
case DWRITE_NUMBER_SUBSTITUTION_METHOD_CONTEXTUAL:
|
|
||||||
if (!is_rtl)
|
|
||||||
break;
|
|
||||||
/* fallthrough */
|
|
||||||
default:
|
|
||||||
if (string[i] >= '0' && string[i] <= '9')
|
|
||||||
string[i] = digits[string[i] - '0'];
|
|
||||||
break;
|
|
||||||
case DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i < max_glyph_count; i++) {
|
|
||||||
glyph_props[i].justification = SCRIPT_JUSTIFY_NONE;
|
|
||||||
glyph_props[i].isClusterStart = 0;
|
|
||||||
glyph_props[i].isDiacritic = 0;
|
|
||||||
glyph_props[i].isZeroWidthSpace = 0;
|
|
||||||
glyph_props[i].reserved = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, g = 0, update_cluster = FALSE; i < length; i++) {
|
|
||||||
UINT32 codepoint;
|
|
||||||
|
|
||||||
if (!update_cluster) {
|
|
||||||
codepoint = decode_surrogate_pair(string, i, length);
|
|
||||||
if (!codepoint)
|
|
||||||
codepoint = is_rtl ? bidi_get_mirrored_char(string[i]) : string[i];
|
|
||||||
else
|
|
||||||
update_cluster = TRUE;
|
|
||||||
|
|
||||||
hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &glyphs[g]);
|
|
||||||
if (FAILED(hr))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
g++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
INT32 k;
|
|
||||||
|
|
||||||
update_cluster = FALSE;
|
|
||||||
/* mark surrogate halves with same cluster */
|
|
||||||
clustermap[i] = clustermap[i-1];
|
|
||||||
/* update following clusters */
|
|
||||||
for (k = i + 1; k >= 0 && k < length; k++)
|
|
||||||
clustermap[k]--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*actual_glyph_count = g;
|
|
||||||
|
|
||||||
font_obj = unsafe_impl_from_IDWriteFontFace(fontface);
|
font_obj = unsafe_impl_from_IDWriteFontFace(fontface);
|
||||||
|
|
||||||
context.cache = fontface_get_shaping_cache(font_obj);
|
context.cache = fontface_get_shaping_cache(font_obj);
|
||||||
|
@ -1253,8 +1175,9 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
|
||||||
context.is_sideways = is_sideways;
|
context.is_sideways = is_sideways;
|
||||||
context.u.subst.glyphs = glyphs;
|
context.u.subst.glyphs = glyphs;
|
||||||
context.u.subst.glyph_props = glyph_props;
|
context.u.subst.glyph_props = glyph_props;
|
||||||
|
context.u.subst.clustermap = clustermap;
|
||||||
context.u.subst.max_glyph_count = max_glyph_count;
|
context.u.subst.max_glyph_count = max_glyph_count;
|
||||||
context.glyph_count = g;
|
context.u.subst.digits = digits;
|
||||||
context.language_tag = get_opentype_language(locale);
|
context.language_tag = get_opentype_language(locale);
|
||||||
context.user_features.features = features;
|
context.user_features.features = features;
|
||||||
context.user_features.range_lengths = feature_range_lengths;
|
context.user_features.range_lengths = feature_range_lengths;
|
||||||
|
@ -1265,12 +1188,13 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
|
||||||
scriptprops = &dwritescripts_properties[script];
|
scriptprops = &dwritescripts_properties[script];
|
||||||
hr = shape_get_glyphs(&context, scriptprops->scripttags);
|
hr = shape_get_glyphs(&context, scriptprops->scripttags);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
*actual_glyph_count = context.glyph_count;
|
||||||
hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyphs, *actual_glyph_count,
|
hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyphs, *actual_glyph_count,
|
||||||
text_props, glyph_props);
|
text_props, glyph_props);
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
heap_free(context.glyph_infos);
|
heap_free(context.glyph_infos);
|
||||||
heap_free(string);
|
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,13 +158,6 @@ static void bidi_classify(const WCHAR *string, UINT8 *chartype, UINT32 count)
|
||||||
chartype[i] = get_table_entry( bidi_direction_table, string[i] );
|
chartype[i] = get_table_entry( bidi_direction_table, string[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
WCHAR bidi_get_mirrored_char(WCHAR ch)
|
|
||||||
{
|
|
||||||
extern const WCHAR wine_mirror_map[] DECLSPEC_HIDDEN;
|
|
||||||
WCHAR mirror = get_table_entry( wine_mirror_map, ch );
|
|
||||||
return mirror ? mirror : ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RESOLVE EXPLICIT */
|
/* RESOLVE EXPLICIT */
|
||||||
|
|
||||||
static inline UINT8 get_greater_even_level(UINT8 level)
|
static inline UINT8 get_greater_even_level(UINT8 level)
|
||||||
|
|
|
@ -300,6 +300,8 @@ extern void factory_unlock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT create_inmemory_fileloader(IDWriteFontFileLoader**) DECLSPEC_HIDDEN;
|
extern HRESULT create_inmemory_fileloader(IDWriteFontFileLoader**) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index,
|
extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index,
|
||||||
IDWriteFontResource **resource) DECLSPEC_HIDDEN;
|
IDWriteFontResource **resource) DECLSPEC_HIDDEN;
|
||||||
|
extern HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints,
|
||||||
|
UINT32 count, UINT16 *glyphs);
|
||||||
|
|
||||||
struct dwrite_fontface;
|
struct dwrite_fontface;
|
||||||
|
|
||||||
|
@ -378,7 +380,6 @@ extern unsigned int opentype_get_gasp_flags(const struct dwrite_fonttable *gasp,
|
||||||
|
|
||||||
/* BiDi helpers */
|
/* BiDi helpers */
|
||||||
extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN;
|
extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN;
|
||||||
extern WCHAR bidi_get_mirrored_char(WCHAR) DECLSPEC_HIDDEN;
|
|
||||||
|
|
||||||
/* FreeType integration */
|
/* FreeType integration */
|
||||||
struct dwrite_glyphbitmap
|
struct dwrite_glyphbitmap
|
||||||
|
@ -487,7 +488,9 @@ struct scriptshaping_context
|
||||||
{
|
{
|
||||||
UINT16 *glyphs;
|
UINT16 *glyphs;
|
||||||
DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props;
|
DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props;
|
||||||
|
UINT16 *clustermap;
|
||||||
unsigned int max_glyph_count;
|
unsigned int max_glyph_count;
|
||||||
|
const WCHAR *digits;
|
||||||
} subst;
|
} subst;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
|
@ -512,6 +515,8 @@ struct shaping_font_ops
|
||||||
void (*grab_font_table)(void *context, UINT32 table, const BYTE **data, UINT32 *size, void **data_context);
|
void (*grab_font_table)(void *context, UINT32 table, const BYTE **data, UINT32 *size, void **data_context);
|
||||||
void (*release_font_table)(void *context, void *data_context);
|
void (*release_font_table)(void *context, void *data_context);
|
||||||
UINT16 (*get_font_upem)(void *context);
|
UINT16 (*get_font_upem)(void *context);
|
||||||
|
BOOL (*has_glyph)(void *context, unsigned int codepoint);
|
||||||
|
UINT16 (*get_glyph)(void *context, unsigned int codepoint);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct scriptshaping_cache *create_scriptshaping_cache(void *context,
|
extern struct scriptshaping_cache *create_scriptshaping_cache(void *context,
|
||||||
|
|
|
@ -272,11 +272,29 @@ static UINT16 dwrite_get_font_upem(void *context)
|
||||||
return fontface->metrics.designUnitsPerEm;
|
return fontface->metrics.designUnitsPerEm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL dwrite_has_glyph(void *context, unsigned int codepoint)
|
||||||
|
{
|
||||||
|
struct dwrite_fontface *fontface = context;
|
||||||
|
UINT16 index = 0;
|
||||||
|
fontface_get_glyphs(fontface, &codepoint, 1, &index);
|
||||||
|
return !!index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT16 dwrite_get_glyph(void *context, unsigned int codepoint)
|
||||||
|
{
|
||||||
|
struct dwrite_fontface *fontface = context;
|
||||||
|
UINT16 index = 0;
|
||||||
|
fontface_get_glyphs(fontface, &codepoint, 1, &index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct shaping_font_ops dwrite_font_ops =
|
static const struct shaping_font_ops dwrite_font_ops =
|
||||||
{
|
{
|
||||||
dwrite_grab_font_table,
|
dwrite_grab_font_table,
|
||||||
dwrite_release_font_table,
|
dwrite_release_font_table,
|
||||||
dwrite_get_font_upem,
|
dwrite_get_font_upem,
|
||||||
|
dwrite_has_glyph,
|
||||||
|
dwrite_get_glyph,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface)
|
struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface)
|
||||||
|
@ -714,17 +732,9 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *ifa
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints,
|
HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints,
|
||||||
UINT32 count, UINT16 *glyphs)
|
UINT32 count, UINT16 *glyphs)
|
||||||
{
|
{
|
||||||
if (!glyphs)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
if (!codepoints) {
|
|
||||||
memset(glyphs, 0, count * sizeof(*glyphs));
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
freetype_get_glyphs(&fontface->IDWriteFontFace5_iface, fontface->charmap, codepoints, count, glyphs);
|
freetype_get_glyphs(&fontface->IDWriteFontFace5_iface, fontface->charmap, codepoints, count, glyphs);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -736,6 +746,15 @@ static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace5 *iface, UI
|
||||||
|
|
||||||
TRACE("%p, %p, %u, %p.\n", iface, codepoints, count, glyphs);
|
TRACE("%p, %p, %u, %p.\n", iface, codepoints, count, glyphs);
|
||||||
|
|
||||||
|
if (!glyphs)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
if (!codepoints)
|
||||||
|
{
|
||||||
|
memset(glyphs, 0, count * sizeof(*glyphs));
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
return fontface_get_glyphs(fontface, codepoints, count, glyphs);
|
return fontface_get_glyphs(fontface, codepoints, count, glyphs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1390,8 +1409,7 @@ static BOOL WINAPI dwritefontface3_HasCharacter(IDWriteFontFace5 *iface, UINT32
|
||||||
TRACE("%p, %#x.\n", iface, ch);
|
TRACE("%p, %#x.\n", iface, ch);
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
if (FAILED(fontface_get_glyphs(fontface, &ch, 1, &index)))
|
fontface_get_glyphs(fontface, &ch, 1, &index);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return index != 0;
|
return index != 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4187,6 +4187,9 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex
|
||||||
unsigned int global_bit_mask = 1;
|
unsigned int global_bit_mask = 1;
|
||||||
UINT16 feature_index;
|
UINT16 feature_index;
|
||||||
|
|
||||||
|
if (!table->table.data)
|
||||||
|
return;
|
||||||
|
|
||||||
/* ScriptTable offset. */
|
/* ScriptTable offset. */
|
||||||
table_offset = table_read_be_word(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) +
|
table_offset = table_read_be_word(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) +
|
||||||
script_index * sizeof(struct ot_script_record) + FIELD_OFFSET(struct ot_script_record, script));
|
script_index * sizeof(struct ot_script_record) + FIELD_OFFSET(struct ot_script_record, script));
|
||||||
|
@ -4329,7 +4332,7 @@ static unsigned int shaping_features_get_mask(const struct shaping_features *fea
|
||||||
if (!feature || feature->index == 0xffff)
|
if (!feature || feature->index == 0xffff)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*shift = feature->shift;
|
if (shift) *shift = feature->shift;
|
||||||
return feature->mask;
|
return feature->mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4671,6 +4674,67 @@ static void opentype_layout_apply_gsub_lookup(struct scriptshaping_context *cont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int unicode_get_mirrored_char(unsigned int codepoint)
|
||||||
|
{
|
||||||
|
extern const WCHAR wine_mirror_map[] DECLSPEC_HIDDEN;
|
||||||
|
WCHAR mirror;
|
||||||
|
/* TODO: check if mirroring for higher planes makes sense at all */
|
||||||
|
if (codepoint > 0xffff) return codepoint;
|
||||||
|
mirror = get_table_entry(wine_mirror_map, codepoint);
|
||||||
|
return mirror ? mirror : codepoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void opentype_get_nominal_glyphs(struct scriptshaping_context *context, const struct shaping_features *features)
|
||||||
|
{
|
||||||
|
unsigned int rtlm_mask = shaping_features_get_mask(features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','m'), NULL);
|
||||||
|
const struct shaping_font_ops *font = context->cache->font;
|
||||||
|
UINT16 *clustermap = context->u.subst.clustermap;
|
||||||
|
const WCHAR *text = context->text;
|
||||||
|
unsigned int i, g, c, codepoint;
|
||||||
|
BOOL bmp;
|
||||||
|
|
||||||
|
memset(context->u.subst.glyph_props, 0, context->u.subst.max_glyph_count * sizeof(*context->u.subst.glyph_props));
|
||||||
|
|
||||||
|
for (i = 0; i < context->length; ++i)
|
||||||
|
{
|
||||||
|
g = context->glyph_count;
|
||||||
|
|
||||||
|
if ((bmp = !(IS_HIGH_SURROGATE(text[i]) && (i < context->length - 1) && IS_LOW_SURROGATE(text[i + 1]))))
|
||||||
|
{
|
||||||
|
codepoint = text[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codepoint = 0x10000 + ((text[i] - 0xd800) << 10) + (text[i + 1] - 0xdc00);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->is_rtl)
|
||||||
|
{
|
||||||
|
c = unicode_get_mirrored_char(codepoint);
|
||||||
|
if (c != codepoint && font->has_glyph(context->cache->context, c))
|
||||||
|
codepoint = c;
|
||||||
|
else
|
||||||
|
context->glyph_infos[i].mask |= rtlm_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: should this check for glyph availability? */
|
||||||
|
if (*context->u.subst.digits && codepoint >= '0' && codepoint <= '9')
|
||||||
|
codepoint = context->u.subst.digits[codepoint - '0'];
|
||||||
|
|
||||||
|
context->u.subst.glyphs[g] = font->get_glyph(context->cache->context, codepoint);
|
||||||
|
context->u.subst.glyph_props[g].justification = SCRIPT_JUSTIFY_CHARACTER;
|
||||||
|
context->u.subst.glyph_props[g].isClusterStart = 1;
|
||||||
|
context->glyph_count++;
|
||||||
|
|
||||||
|
clustermap[i] = i;
|
||||||
|
if (!bmp)
|
||||||
|
{
|
||||||
|
clustermap[i + 1] = i;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index,
|
HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index,
|
||||||
unsigned int language_index, const struct shaping_features *features)
|
unsigned int language_index, const struct shaping_features *features)
|
||||||
{
|
{
|
||||||
|
@ -4679,6 +4743,7 @@ HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *contex
|
||||||
|
|
||||||
opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gsub, &lookups);
|
opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gsub, &lookups);
|
||||||
|
|
||||||
|
opentype_get_nominal_glyphs(context, features);
|
||||||
opentype_layout_set_glyph_masks(context, features);
|
opentype_layout_set_glyph_masks(context, features);
|
||||||
|
|
||||||
for (i = 0; i < lookups.count; ++i)
|
for (i = 0; i < lookups.count; ++i)
|
||||||
|
|
|
@ -362,8 +362,7 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i
|
||||||
DWRITE_MAKE_OPENTYPE_TAG('l','i','g','a'),
|
DWRITE_MAKE_OPENTYPE_TAG('l','i','g','a'),
|
||||||
DWRITE_MAKE_OPENTYPE_TAG('r','c','l','t'),
|
DWRITE_MAKE_OPENTYPE_TAG('r','c','l','t'),
|
||||||
};
|
};
|
||||||
struct scriptshaping_cache *cache = context->cache;
|
unsigned int script_index, language_index;
|
||||||
unsigned int script_index, language_index, script;
|
|
||||||
struct shaping_features features = { 0 };
|
struct shaping_features features = { 0 };
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
@ -396,13 +395,8 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i
|
||||||
shape_merge_features(context, &features);
|
shape_merge_features(context, &features);
|
||||||
|
|
||||||
/* Resolve script tag to actually supported script. */
|
/* Resolve script tag to actually supported script. */
|
||||||
if (cache->gsub.table.data)
|
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);
|
||||||
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);
|
heap_free(features.features);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue