[PATCH 4/5] d2d1/effect: Reimplement GetValue().
Ziqing Hui
zhui at codeweavers.com
Wed Jun 22 06:34:59 CDT 2022
Signed-off-by: Ziqing Hui <zhui at 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;
--
2.25.1
More information about the wine-devel
mailing list