Signed-off-by: Ziqing Hui zhui@codeweavers.com --- dlls/d2d1/d2d1_private.h | 17 ++++- dlls/d2d1/effect.c | 144 ++++++++++++++++++++++++++++++--------- dlls/d2d1/factory.c | 9 --- 3 files changed, 125 insertions(+), 45 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 9be553c72d8..27606e78a42 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -35,6 +35,8 @@ #endif #include "dwrite_2.h"
+#define D2D1_SYSTEM_PROPERTY_COUNT (D2D1_PROPERTY_MAX_INPUTS - D2D1_PROPERTY_CLSID + 1) + enum d2d_brush_type { D2D_BRUSH_TYPE_SOLID, @@ -610,18 +612,29 @@ struct d2d_effect_info UINT32 max_inputs; };
+struct d2d_effect_property +{ + WCHAR *name; + D2D1_PROPERTY_TYPE type; + BYTE *value; + PD2D1_PROPERTY_SET_FUNCTION set_function; + PD2D1_PROPERTY_GET_FUNCTION get_function; +}; + struct d2d_effect { ID2D1Effect ID2D1Effect_iface; ID2D1Image ID2D1Image_iface; LONG refcount;
- const struct d2d_effect_info *info; - struct d2d_effect_context *effect_context; ID2D1Image **inputs; size_t inputs_size; size_t input_count; + + struct d2d_effect_property system_properties[D2D1_SYSTEM_PROPERTY_COUNT]; + struct d2d_effect_property *custom_properties; + size_t custom_property_count; };
HRESULT d2d_effect_init(struct d2d_effect *effect, diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c index f5d5494c67a..e0c028664d7 100644 --- a/dlls/d2d1/effect.c +++ b/dlls/d2d1/effect.c @@ -30,6 +30,14 @@ static const struct d2d_effect_info builtin_effects[] = {&CLSID_D2D1Grayscale, 1, 1, 1}, };
+static void *memdup(const void *ptr, size_t size) +{ + void *ret = malloc(size); + if (ret) + memcpy(ret, ptr, size); + return ret; +} + static inline struct d2d_effect_context *impl_from_ID2D1EffectContext(ID2D1EffectContext *iface) { return CONTAINING_RECORD(iface, struct d2d_effect_context, ID2D1EffectContext_iface); @@ -413,10 +421,53 @@ static inline struct d2d_effect *impl_from_ID2D1Effect(ID2D1Effect *iface) return CONTAINING_RECORD(iface, struct d2d_effect, ID2D1Effect_iface); }
+static UINT32 d2d_effect_property_get_value_size(struct d2d_effect_property *property) +{ + static const UINT32 value_size[] = + { + 0, /* D2D1_PROPERTY_TYPE_UNKNOWN */ + 0, /* D2D1_PROPERTY_TYPE_STRING */ + sizeof(BOOL), /* D2D1_PROPERTY_TYPE_BOOL */ + sizeof(UINT32), /* D2D1_PROPERTY_TYPE_UINT32 */ + sizeof(INT32), /* D2D1_PROPERTY_TYPE_INT32 */ + sizeof(FLOAT), /* D2D1_PROPERTY_TYPE_FLOAT */ + sizeof(D2D_VECTOR_2F), /* D2D1_PROPERTY_TYPE_VECTOR2 */ + sizeof(D2D_VECTOR_3F), /* D2D1_PROPERTY_TYPE_VECTOR3 */ + sizeof(D2D_VECTOR_4F), /* D2D1_PROPERTY_TYPE_VECTOR4 */ + 0, /* D2D1_PROPERTY_TYPE_BLOB */ + sizeof(IUnknown *), /* D2D1_PROPERTY_TYPE_IUNKNOWN */ + sizeof(UINT32), /* D2D1_PROPERTY_TYPE_ENUM */ + sizeof(UINT32), /* D2D1_PROPERTY_TYPE_ARRAY */ + sizeof(CLSID), /* D2D1_PROPERTY_TYPE_CLSID */ + sizeof(D2D_MATRIX_3X2_F), /* D2D1_PROPERTY_TYPE_MATRIX_3X2 */ + sizeof(D2D_MATRIX_4X3_F), /* D2D1_PROPERTY_TYPE_MATRIX_4X3 */ + sizeof(D2D_MATRIX_4X4_F), /* D2D1_PROPERTY_TYPE_MATRIX_4X4 */ + sizeof(D2D_MATRIX_5X4_F), /* D2D1_PROPERTY_TYPE_MATRIX_5X4 */ + sizeof(ID2D1ColorContext *), /* D2D1_PROPERTY_TYPE_COLOR_CONTEXT */ + }; + + if (property->type == D2D1_PROPERTY_TYPE_STRING) + return sizeof(WCHAR) * (wcslen((WCHAR *)property->value) + 1); + + return value_size[property->type]; +} + static void d2d_effect_cleanup(struct d2d_effect *effect) { unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(effect->system_properties); ++i) + { + free(effect->system_properties[i].name); + free(effect->system_properties[i].value); + } + + for (i = 0; i < effect->custom_property_count; ++i) + { + free(effect->custom_properties[i].name); + free(effect->custom_properties[i].value); + } + for (i = 0; i < effect->input_count; ++i) { if (effect->inputs[i]) @@ -426,6 +477,16 @@ static void d2d_effect_cleanup(struct d2d_effect *effect) ID2D1EffectContext_Release(&effect->effect_context->ID2D1EffectContext_iface); }
+static struct d2d_effect_property *d2d_effect_get_property(struct d2d_effect *effect, UINT32 index) +{ + if (index < effect->custom_property_count) + return &effect->custom_properties[index]; + else if (D2D1_PROPERTY_CLSID <= index && index <= D2D1_PROPERTY_MAX_INPUTS) + return &effect->system_properties[index - D2D1_PROPERTY_CLSID]; + else + return NULL; +} + static HRESULT STDMETHODCALLTYPE d2d_effect_QueryInterface(ID2D1Effect *iface, REFIID iid, void **out) { struct d2d_effect *effect = impl_from_ID2D1Effect(iface); @@ -546,41 +607,34 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_GetValue(ID2D1Effect *iface, UINT32 BYTE *value, UINT32 value_size) { struct d2d_effect *effect = impl_from_ID2D1Effect(iface); - const void *src; + struct d2d_effect_property *property; + UINT32 actual_size;
TRACE("iface %p, index %u, type %#x, value %p, value_size %u.\n", iface, index, type, value, value_size);
- switch (index) - { - case D2D1_PROPERTY_CLSID: - if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_CLSID) - || value_size != sizeof(*effect->info->clsid)) - return E_INVALIDARG; - src = effect->info->clsid; - break; - case D2D1_PROPERTY_MIN_INPUTS: - if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_UINT32) - || value_size != sizeof(effect->info->min_inputs)) - return E_INVALIDARG; - src = &effect->info->min_inputs; - break; - case D2D1_PROPERTY_MAX_INPUTS: - if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_UINT32) - || value_size != sizeof(effect->info->max_inputs)) - return E_INVALIDARG; - src = &effect->info->max_inputs; - break; - default: - if (index < D2D1_PROPERTY_CLSID) - FIXME("Custom properties are not supported.\n"); - else if (index <= D2D1_PROPERTY_MAX_INPUTS) - FIXME("Standard property %#x is not supported.\n", index); - return D2DERR_INVALID_PROPERTY; - } + if (!(property = d2d_effect_get_property(effect, index))) + return D2DERR_INVALID_PROPERTY;
- memcpy(value, src, value_size); + actual_size = d2d_effect_property_get_value_size(property); + if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != property->type) + || (type != D2D1_PROPERTY_TYPE_STRING && value_size != actual_size) + || (type == D2D1_PROPERTY_TYPE_STRING && value_size < actual_size)) + return E_INVALIDARG;
- return S_OK; + if (property->get_function) + { + return property->get_function((IUnknown *)iface, value, value_size, NULL); + } + else if (property->value) + { + memcpy(value, property->value, actual_size); + return S_OK; + } + else + { + WARN("Unable to get property value.\n"); + return D2DERR_INVALID_PROPERTY; + } }
static UINT32 STDMETHODCALLTYPE d2d_effect_GetValueSize(ID2D1Effect *iface, UINT32 index) @@ -614,12 +668,18 @@ static void STDMETHODCALLTYPE d2d_effect_SetInput(ID2D1Effect *iface, UINT32 ind
static HRESULT STDMETHODCALLTYPE d2d_effect_SetInputCount(ID2D1Effect *iface, UINT32 count) { + struct d2d_effect_property *min_inputs_property, *max_inputs_property; struct d2d_effect *effect = impl_from_ID2D1Effect(iface); - unsigned int i; + UINT32 min_inputs, max_inputs, i;
TRACE("iface %p, count %u.\n", iface, count);
- if (count < effect->info->min_inputs || count > effect->info->max_inputs) + min_inputs_property = d2d_effect_get_property(effect, D2D1_PROPERTY_MIN_INPUTS); + max_inputs_property = d2d_effect_get_property(effect, D2D1_PROPERTY_MAX_INPUTS); + min_inputs = *((UINT32 *)min_inputs_property->value); + max_inputs = *((UINT32 *)max_inputs_property->value); + + if (count < min_inputs || count > max_inputs) return E_INVALIDARG; if (count == effect->input_count) return S_OK; @@ -752,6 +812,7 @@ static const ID2D1ImageVtbl d2d_effect_image_vtbl =
HRESULT d2d_effect_init(struct d2d_effect *effect, struct d2d_effect_context *effect_context, const CLSID *effect_id) { + struct d2d_effect_property *property; unsigned int i;
effect->ID2D1Effect_iface.lpVtbl = &d2d_effect_vtbl; @@ -762,10 +823,25 @@ HRESULT d2d_effect_init(struct d2d_effect *effect, struct d2d_effect_context *ef { if (IsEqualGUID(effect_id, builtin_effects[i].clsid)) { - effect->info = &builtin_effects[i]; - d2d_effect_SetInputCount(&effect->ID2D1Effect_iface, effect->info->default_input_count); + property = d2d_effect_get_property(effect, D2D1_PROPERTY_CLSID); + property->name = wcsdup(L"ClSID"); + property->type = D2D1_PROPERTY_TYPE_CLSID; + property->value = memdup(effect_id, sizeof(*effect_id)); + + property = d2d_effect_get_property(effect, D2D1_PROPERTY_MIN_INPUTS); + property->name = wcsdup(L"MinInputs"); + property->type = D2D1_PROPERTY_TYPE_UINT32; + property->value = memdup(&builtin_effects[i].min_inputs, sizeof(builtin_effects[i].min_inputs)); + + property = d2d_effect_get_property(effect, D2D1_PROPERTY_MAX_INPUTS); + property->name = wcsdup(L"MaxInputs"); + property->type = D2D1_PROPERTY_TYPE_UINT32; + property->value = memdup(&builtin_effects[i].max_inputs, sizeof(builtin_effects[i].max_inputs)); + + d2d_effect_SetInputCount(&effect->ID2D1Effect_iface, builtin_effects[i].default_input_count); effect->effect_context = effect_context; ID2D1EffectContext_AddRef(&effect_context->ID2D1EffectContext_iface); + return S_OK; } } diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c index 5c79d1791ff..36feaeb6f29 100644 --- a/dlls/d2d1/factory.c +++ b/dlls/d2d1/factory.c @@ -30,15 +30,6 @@ struct d2d_settings d2d_settings = ~0u, /* No ID2D1Factory version limit by default. */ };
-struct d2d_effect_property -{ - WCHAR *name; - D2D1_PROPERTY_TYPE type; - BYTE *value; - PD2D1_PROPERTY_SET_FUNCTION set_function; - PD2D1_PROPERTY_GET_FUNCTION get_function; -}; - struct d2d_effect_registration { struct list entry;