Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/analyzer.c | 134 ++++++++++++++++-------------------
dlls/dwrite/dwrite_private.h | 36 ++++++++--
dlls/dwrite/font.c | 49 ++++++++++++-
dlls/dwrite/shape.c | 48 ++++++++-----
4 files changed, 172 insertions(+), 95 deletions(-)
diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index 7ee3675d2e..13d3d3216a 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -1157,16 +1157,14 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
UINT16* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* text_props, UINT16* glyph_indices,
DWRITE_SHAPING_GLYPH_PROPERTIES* glyph_props, UINT32* actual_glyph_count)
{
- const struct dwritescript_properties *scriptprops;
DWRITE_NUMBER_SUBSTITUTION_METHOD method;
struct scriptshaping_context context;
- struct scriptshaping_cache *cache = NULL;
+ struct dwrite_fontface *font_obj;
WCHAR digits[NATIVE_DIGITS_LEN];
BOOL update_cluster;
WCHAR *string;
UINT32 i, g;
HRESULT hr = S_OK;
- UINT16 script;
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,
@@ -1175,8 +1173,6 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
analyzer_dump_user_features(features, feature_range_lengths, feature_ranges);
- script = analysis->script > Script_LastId ? Script_Unknown : analysis->script;
-
if (max_glyph_count < length)
return E_NOT_SUFFICIENT_BUFFER;
@@ -1253,33 +1249,19 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
}
*actual_glyph_count = g;
- hr = create_scriptshaping_cache(fontface, &cache);
- if (FAILED(hr))
- goto done;
+ font_obj = unsafe_impl_from_IDWriteFontFace(fontface);
- context.cache = cache;
+ context.cache = fontface_get_shaping_cache(font_obj);
context.text = text;
context.length = length;
context.is_rtl = is_rtl;
- context.max_glyph_count = max_glyph_count;
context.language_tag = get_opentype_language(locale);
- scriptprops = &dwritescripts_properties[script];
- if (scriptprops->ops && scriptprops->ops->contextual_shaping) {
- hr = scriptprops->ops->contextual_shaping(&context, clustermap, glyph_indices, actual_glyph_count);
- if (FAILED(hr))
- goto done;
- }
-
/* FIXME: apply default features */
- if (scriptprops->ops && scriptprops->ops->set_text_glyphs_props)
- hr = scriptprops->ops->set_text_glyphs_props(&context, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props);
- else
- hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props);
+ hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props);
done:
- release_scriptshaping_cache(cache);
heap_free(string);
return hr;
@@ -1288,14 +1270,14 @@ done:
static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2 *iface,
WCHAR const* text, UINT16 const* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* props,
UINT32 text_len, UINT16 const* glyphs, DWRITE_SHAPING_GLYPH_PROPERTIES const* glyph_props,
- UINT32 glyph_count, IDWriteFontFace *fontface, FLOAT emSize, BOOL is_sideways, BOOL is_rtl,
+ UINT32 glyph_count, IDWriteFontFace *fontface, float emSize, BOOL is_sideways, BOOL is_rtl,
DWRITE_SCRIPT_ANALYSIS const* analysis, WCHAR const* locale, DWRITE_TYPOGRAPHIC_FEATURES const** features,
- UINT32 const* feature_range_lengths, UINT32 feature_ranges, FLOAT *advances, DWRITE_GLYPH_OFFSET *offsets)
+ UINT32 const* feature_range_lengths, UINT32 feature_ranges, float *advances, DWRITE_GLYPH_OFFSET *offsets)
{
- DWRITE_FONT_METRICS metrics;
- IDWriteFontFace1 *fontface1;
- HRESULT hr;
- UINT32 i;
+ const struct dwritescript_properties *scriptprops;
+ struct dwrite_fontface *font_obj;
+ unsigned int i, script;
+ HRESULT hr = S_OK;
TRACE("(%s %p %p %u %p %p %u %p %.2f %d %d %s %s %p %p %u %p %p)\n", debugstr_wn(text, text_len),
clustermap, props, text_len, glyphs, glyph_props, glyph_count, fontface, emSize, is_sideways,
@@ -1307,46 +1289,51 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2
if (glyph_count == 0)
return S_OK;
- hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
- if (FAILED(hr)) {
- WARN("failed to get IDWriteFontFace1.\n");
- return hr;
- }
+ font_obj = unsafe_impl_from_IDWriteFontFace(fontface);
- IDWriteFontFace_GetMetrics(fontface, &metrics);
- for (i = 0; i < glyph_count; i++) {
+ for (i = 0; i < glyph_count; ++i)
+ {
if (glyph_props[i].isZeroWidthSpace)
advances[i] = 0.0f;
- else {
- INT32 a;
-
- hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, &glyphs[i], &a, is_sideways);
- if (FAILED(hr))
- a = 0;
- advances[i] = get_scaled_advance_width(a, emSize, &metrics);
- }
+ else
+ advances[i] = fontface_get_scaled_design_advance(font_obj, DWRITE_MEASURING_MODE_NATURAL, emSize, 1.0f,
+ NULL, glyphs[i], is_sideways);
offsets[i].advanceOffset = 0.0f;
offsets[i].ascenderOffset = 0.0f;
}
- /* FIXME: actually apply features */
+ script = analysis->script > Script_LastId ? Script_Unknown : analysis->script;
- IDWriteFontFace1_Release(fontface1);
- return S_OK;
+ scriptprops = &dwritescripts_properties[script];
+ if (scriptprops->ops && scriptprops->ops->gpos_features)
+ {
+ struct scriptshaping_context context;
+
+ context.cache = fontface_get_shaping_cache(font_obj);
+ context.text = text;
+ context.length = text_len;
+ context.is_rtl = is_rtl;
+ context.language_tag = get_opentype_language(locale);
+
+ hr = shape_get_positions(&context, scriptprops->scripttags, scriptprops->ops->gpos_features);
+ }
+
+ return hr;
}
static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWriteTextAnalyzer2 *iface,
WCHAR const* text, UINT16 const* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* props,
UINT32 text_len, UINT16 const* glyphs, DWRITE_SHAPING_GLYPH_PROPERTIES const* glyph_props,
- UINT32 glyph_count, IDWriteFontFace *fontface, FLOAT emSize, FLOAT ppdip,
+ UINT32 glyph_count, IDWriteFontFace *fontface, float emSize, float ppdip,
DWRITE_MATRIX const* transform, BOOL use_gdi_natural, BOOL is_sideways, BOOL is_rtl,
DWRITE_SCRIPT_ANALYSIS const* analysis, WCHAR const* locale, DWRITE_TYPOGRAPHIC_FEATURES const** features,
- UINT32 const* feature_range_lengths, UINT32 feature_ranges, FLOAT *advances, DWRITE_GLYPH_OFFSET *offsets)
+ UINT32 const* feature_range_lengths, UINT32 feature_ranges, float *advances, DWRITE_GLYPH_OFFSET *offsets)
{
- DWRITE_FONT_METRICS metrics;
- IDWriteFontFace1 *fontface1;
- HRESULT hr;
- UINT32 i;
+ const struct dwritescript_properties *scriptprops;
+ DWRITE_MEASURING_MODE measuring_mode;
+ struct dwrite_fontface *font_obj;
+ unsigned int i, script;
+ HRESULT hr = S_OK;
TRACE("(%s %p %p %u %p %p %u %p %.2f %.2f %p %d %d %d %s %s %p %p %u %p %p)\n", debugstr_wn(text, text_len),
clustermap, props, text_len, glyphs, glyph_props, glyph_count, fontface, emSize, ppdip,
@@ -1358,35 +1345,38 @@ static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWrite
if (glyph_count == 0)
return S_OK;
- hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
- if (FAILED(hr)) {
- WARN("failed to get IDWriteFontFace1.\n");
- return hr;
- }
+ font_obj = unsafe_impl_from_IDWriteFontFace(fontface);
- hr = IDWriteFontFace_GetGdiCompatibleMetrics(fontface, emSize, ppdip, transform, &metrics);
- if (FAILED(hr)) {
- IDWriteFontFace1_Release(fontface1);
- WARN("failed to get compat metrics, 0x%08x\n", hr);
- return hr;
- }
- for (i = 0; i < glyph_count; i++) {
- INT32 a;
+ measuring_mode = use_gdi_natural ? DWRITE_MEASURING_MODE_GDI_NATURAL : DWRITE_MEASURING_MODE_GDI_CLASSIC;
- hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, emSize, ppdip,
- transform, use_gdi_natural, is_sideways, 1, &glyphs[i], &a);
- if (FAILED(hr))
+ for (i = 0; i < glyph_count; ++i)
+ {
+ if (glyph_props[i].isZeroWidthSpace)
advances[i] = 0.0f;
else
- advances[i] = floorf(a * emSize * ppdip / metrics.designUnitsPerEm + 0.5f) / ppdip;
+ advances[i] = fontface_get_scaled_design_advance(font_obj, measuring_mode, emSize, ppdip,
+ transform, glyphs[i], is_sideways);
offsets[i].advanceOffset = 0.0f;
offsets[i].ascenderOffset = 0.0f;
}
- /* FIXME: actually apply features */
+ script = analysis->script > Script_LastId ? Script_Unknown : analysis->script;
- IDWriteFontFace1_Release(fontface1);
- return S_OK;
+ scriptprops = &dwritescripts_properties[script];
+ if (scriptprops->ops && scriptprops->ops->gpos_features)
+ {
+ struct scriptshaping_context context;
+
+ context.cache = fontface_get_shaping_cache(font_obj);
+ context.text = text;
+ context.length = text_len;
+ context.is_rtl = is_rtl;
+ context.language_tag = get_opentype_language(locale);
+
+ hr = shape_get_positions(&context, scriptprops->scripttags, scriptprops->ops->gpos_features);
+ }
+
+ return hr;
}
static inline FLOAT get_cluster_advance(const FLOAT *advances, UINT32 start, UINT32 end)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 3595503f1e..2299a23cf1 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -192,6 +192,12 @@ extern void factory_lock(IDWriteFactory5*) DECLSPEC_HIDDEN;
extern void factory_unlock(IDWriteFactory5*) DECLSPEC_HIDDEN;
extern HRESULT create_inmemory_fileloader(IDWriteFontFileLoader**) DECLSPEC_HIDDEN;
+struct dwrite_fontface;
+
+extern float fontface_get_scaled_design_advance(struct dwrite_fontface *fontface, DWRITE_MEASURING_MODE measuring_mode,
+ float emsize, float ppdip, const DWRITE_MATRIX *transform, UINT16 glyph, BOOL is_sideways) DECLSPEC_HIDDEN;
+extern struct dwrite_fontface *unsafe_impl_from_IDWriteFontFace(IDWriteFontFace *iface) DECLSPEC_HIDDEN;
+
/* Opentype font table functions */
struct dwrite_font_props {
DWRITE_FONT_STYLE style;
@@ -320,7 +326,12 @@ enum SCRIPT_JUSTIFY
SCRIPT_JUSTIFY_ARABIC_SEEN_M
};
-struct scriptshaping_cache;
+struct scriptshaping_cache
+{
+ const struct shaping_font_ops *font;
+ void *context;
+ UINT16 upem;
+};
struct scriptshaping_context
{
@@ -328,21 +339,38 @@ struct scriptshaping_context
UINT32 language_tag;
const WCHAR *text;
- UINT32 length;
+ unsigned int length;
BOOL is_rtl;
+};
- UINT32 max_glyph_count;
+struct shaping_font_ops
+{
+ 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);
+ UINT16 (*get_font_upem)(void *context);
};
-extern HRESULT create_scriptshaping_cache(IDWriteFontFace*,struct scriptshaping_cache**) DECLSPEC_HIDDEN;
+extern struct scriptshaping_cache *create_scriptshaping_cache(void *context,
+ const struct shaping_font_ops *font_ops) 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;
+
+struct shaping_features
+{
+ const DWORD *tags;
+ unsigned int count;
+};
struct scriptshaping_ops
{
HRESULT (*contextual_shaping)(struct scriptshaping_context *context, UINT16 *clustermap, UINT16 *glyph_indices, UINT32* actual_glyph_count);
HRESULT (*set_text_glyphs_props)(struct scriptshaping_context *context, UINT16 *clustermap, UINT16 *glyph_indices,
UINT32 glyphcount, DWRITE_SHAPING_TEXT_PROPERTIES *text_props, DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props);
+ const struct shaping_features *gpos_features;
};
extern const struct scriptshaping_ops default_shaping_ops DECLSPEC_HIDDEN;
extern const struct scriptshaping_ops latn_shaping_ops DECLSPEC_HIDDEN;
+
+extern HRESULT shape_get_positions(struct scriptshaping_context *context, const DWORD *scripts,
+ const struct shaping_features *features) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index d1e4fb9725..f50133d18c 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -240,6 +240,8 @@ struct dwrite_fontface {
FONTSIGNATURE fontsig;
UINT32 glyph_image_formats;
+ struct scriptshaping_cache *shaping_cache;
+
LOGFONTW lf;
};
@@ -263,6 +265,47 @@ struct dwrite_fontfacereference {
IDWriteFactory5 *factory;
};
+static void dwrite_grab_font_table(void *context, UINT32 table, const BYTE **data, UINT32 *size, void **data_context)
+{
+ struct dwrite_fontface *fontface = context;
+ BOOL exists = FALSE;
+
+ if (FAILED(IDWriteFontFace4_TryGetFontTable(&fontface->IDWriteFontFace4_iface, table, (const void **)data,
+ size, data_context, &exists)) || !exists)
+ {
+ *data = NULL;
+ *size = 0;
+ *data_context = NULL;
+ }
+}
+
+static void dwrite_release_font_table(void *context, void *data_context)
+{
+ struct dwrite_fontface *fontface = context;
+ IDWriteFontFace4_ReleaseFontTable(&fontface->IDWriteFontFace4_iface, data_context);
+}
+
+static UINT16 dwrite_get_font_upem(void *context)
+{
+ struct dwrite_fontface *fontface = context;
+ return fontface->metrics.designUnitsPerEm;
+}
+
+static const struct shaping_font_ops dwrite_font_ops =
+{
+ dwrite_grab_font_table,
+ dwrite_release_font_table,
+ dwrite_get_font_upem,
+};
+
+struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface)
+{
+ if (fontface->shaping_cache)
+ return fontface->shaping_cache;
+
+ return fontface->shaping_cache = create_scriptshaping_cache(fontface, &dwrite_font_ops);
+}
+
static inline struct dwrite_fontface *impl_from_IDWriteFontFace4(IDWriteFontFace4 *iface)
{
return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace4_iface);
@@ -493,7 +536,7 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace4 *iface)
factory_unlock(This->factory);
heap_free(This->cached);
}
-
+ release_scriptshaping_cache(This->shaping_cache);
if (This->cmap.context)
IDWriteFontFace4_ReleaseFontTable(iface, This->cmap.context);
if (This->vdmx.context)
@@ -1775,7 +1818,7 @@ static struct dwrite_font *unsafe_impl_from_IDWriteFont(IDWriteFont *iface)
return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont3_iface);
}
-static struct dwrite_fontface *unsafe_impl_from_IDWriteFontFace(IDWriteFontFace *iface)
+struct dwrite_fontface *unsafe_impl_from_IDWriteFontFace(IDWriteFontFace *iface)
{
if (!iface)
return NULL;
@@ -5363,7 +5406,7 @@ static inline void transform_point(D2D_POINT_2F *point, const DWRITE_MATRIX *m)
*point = ret;
}
-static float fontface_get_scaled_design_advance(struct dwrite_fontface *fontface, DWRITE_MEASURING_MODE measuring_mode,
+float fontface_get_scaled_design_advance(struct dwrite_fontface *fontface, DWRITE_MEASURING_MODE measuring_mode,
float emsize, float ppdip, const DWRITE_MATRIX *transform, UINT16 glyph, BOOL is_sideways)
{
unsigned int upem = fontface->metrics.designUnitsPerEm;
diff --git a/dlls/dwrite/shape.c b/dlls/dwrite/shape.c
index a6039323ea..69780450e9 100644
--- a/dlls/dwrite/shape.c
+++ b/dlls/dwrite/shape.c
@@ -23,32 +23,26 @@
#include "dwrite_private.h"
-struct scriptshaping_cache
+struct scriptshaping_cache *create_scriptshaping_cache(void *context, const struct shaping_font_ops *font_ops)
{
- IDWriteFontFace *fontface;
-};
-
-HRESULT create_scriptshaping_cache(IDWriteFontFace *fontface, struct scriptshaping_cache **cache)
-{
- struct scriptshaping_cache *ret;
+ struct scriptshaping_cache *cache;
- ret = heap_alloc(sizeof(*ret));
- if (!ret)
- return E_OUTOFMEMORY;
+ cache = heap_alloc_zero(sizeof(*cache));
+ if (!cache)
+ return NULL;
- ret->fontface = fontface;
- IDWriteFontFace_AddRef(fontface);
+ cache->font = font_ops;
+ cache->context = context;
- *cache = ret;
+ cache->upem = cache->font->get_font_upem(cache->context);
- return S_OK;
+ return cache;
}
void release_scriptshaping_cache(struct scriptshaping_cache *cache)
{
if (!cache)
return;
- IDWriteFontFace_Release(cache->fontface);
heap_free(cache);
}
@@ -160,10 +154,24 @@ static HRESULT latn_set_text_glyphs_props(struct scriptshaping_context *context,
return hr;
}
+static const DWORD std_gpos_tags[] =
+{
+ DWRITE_FONT_FEATURE_TAG_KERNING,
+ DWRITE_FONT_FEATURE_TAG_MARK_POSITIONING,
+ DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING,
+};
+
+static const struct shaping_features std_gpos_features =
+{
+ std_gpos_tags,
+ ARRAY_SIZE(std_gpos_tags),
+};
+
const struct scriptshaping_ops latn_shaping_ops =
{
NULL,
- latn_set_text_glyphs_props
+ latn_set_text_glyphs_props,
+ &std_gpos_features,
};
const struct scriptshaping_ops default_shaping_ops =
@@ -171,3 +179,11 @@ const struct scriptshaping_ops default_shaping_ops =
NULL,
default_set_text_glyphs_props
};
+
+HRESULT shape_get_positions(struct scriptshaping_context *context, const DWORD *scripts,
+ const struct shaping_features *features)
+{
+ /* FIXME: stub */
+
+ return S_OK;
+}
--
2.20.1