[PATCH 1/4] d2d1/effect: Initial implementation of subproperties.
Nikolay Sivov
wine at gitlab.winehq.org
Thu Jun 30 03:23:39 CDT 2022
From: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/d2d1/d2d1_private.h | 8 +
dlls/d2d1/effect.c | 359 +++++++++++++++++++++++++++++++--------
dlls/d2d1/factory.c | 51 +++++-
dlls/d2d1/tests/d2d1.c | 61 ++++++-
4 files changed, 409 insertions(+), 70 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 7e74f5dd959..db6787c2f86 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -617,10 +617,14 @@ struct d2d_effect_property
UINT32 size;
PD2D1_PROPERTY_SET_FUNCTION set_function;
PD2D1_PROPERTY_GET_FUNCTION get_function;
+ struct d2d_effect_properties *subproperties;
};
struct d2d_effect_properties
{
+ ID2D1Properties ID2D1Properties_iface;
+ struct d2d_effect *effect;
+
struct d2d_effect_property *properties;
size_t offset;
size_t size;
@@ -673,6 +677,10 @@ HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effec
ID2D1Effect **effect) DECLSPEC_HIDDEN;
HRESULT d2d_effect_properties_add(struct d2d_effect_properties *props, const WCHAR *name,
UINT32 index, D2D1_PROPERTY_TYPE type, const WCHAR *value) DECLSPEC_HIDDEN;
+HRESULT d2d_effect_subproperties_add(struct d2d_effect_properties *props, const WCHAR *name,
+ UINT32 index, D2D1_PROPERTY_TYPE type, const WCHAR *value) DECLSPEC_HIDDEN;
+struct d2d_effect_property * d2d_effect_properties_get_property_by_name(
+ const struct d2d_effect_properties *properties, const WCHAR *name) DECLSPEC_HIDDEN;
void d2d_effect_properties_cleanup(struct d2d_effect_properties *props) DECLSPEC_HIDDEN;
static inline BOOL d2d_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c
index 7abee71e6d9..5daf16fd838 100644
--- a/dlls/d2d1/effect.c
+++ b/dlls/d2d1/effect.c
@@ -229,8 +229,8 @@ static const struct d2d_effect_info builtin_effects[] =
{&CLSID_D2D1Grayscale, 1, 1, 1},
};
-HRESULT d2d_effect_properties_add(struct d2d_effect_properties *props, const WCHAR *name,
- UINT32 index, D2D1_PROPERTY_TYPE type, const WCHAR *value)
+static HRESULT d2d_effect_properties_internal_add(struct d2d_effect_properties *props,
+ const WCHAR *name, UINT32 index, BOOL subprop, D2D1_PROPERTY_TYPE type, const WCHAR *value)
{
static const UINT32 sizes[] =
{
@@ -246,7 +246,7 @@ HRESULT d2d_effect_properties_add(struct d2d_effect_properties *props, const WCH
0, /* FIXME: D2D1_PROPERTY_TYPE_BLOB */
sizeof(void *), /* D2D1_PROPERTY_TYPE_IUNKNOWN */
sizeof(UINT32), /* D2D1_PROPERTY_TYPE_ENUM */
- 0, /* FIXME: D2D1_PROPERTY_TYPE_ARRAY */
+ sizeof(UINT32), /* D2D1_PROPERTY_TYPE_ARRAY */
sizeof(CLSID), /* D2D1_PROPERTY_TYPE_CLSID */
6 * sizeof(float), /* D2D1_PROPERTY_TYPE_MATRIX_3X2 */
12 * sizeof(float), /* D2D1_PROPERTY_TYPE_MATRIX_4X3 */
@@ -258,7 +258,7 @@ HRESULT d2d_effect_properties_add(struct d2d_effect_properties *props, const WCH
assert(type >= D2D1_PROPERTY_TYPE_STRING && type <= D2D1_PROPERTY_TYPE_COLOR_CONTEXT);
- if (type == D2D1_PROPERTY_TYPE_BLOB || type == D2D1_PROPERTY_TYPE_ARRAY)
+ if (type == D2D1_PROPERTY_TYPE_BLOB)
{
FIXME("Ignoring property %s of type %u.\n", wine_dbgstr_w(name), type);
return S_OK;
@@ -279,21 +279,24 @@ HRESULT d2d_effect_properties_add(struct d2d_effect_properties *props, const WCH
props->data.count += sizes[type];
p = &props->properties[props->count++];
+ memset(p, 0, sizeof(*p));
p->index = index;
if (p->index < 0x80000000)
{
props->custom_count++;
- /* FIXME: this should probably be controller by subproperty */
+ /* FIXME: this should probably be controlled by subproperty */
p->readonly = FALSE;
}
+ else if (subprop)
+ p->readonly = TRUE;
else
p->readonly = index != D2D1_PROPERTY_CACHED && index != D2D1_PROPERTY_PRECISION;
p->name = wcsdup(name);
p->type = type;
- if (p->type == D2D1_PROPERTY_TYPE_STRING)
+ if (p->type == D2D1_PROPERTY_TYPE_STRING && value)
{
- p->data.ptr = value ? wcsdup(value) : NULL;
- p->size = value ? (wcslen(value) + 1) * sizeof(WCHAR) : 0;
+ p->data.ptr = wcsdup(value);
+ p->size = (wcslen(value) + 1) * sizeof(WCHAR);
}
else
{
@@ -337,15 +340,26 @@ HRESULT d2d_effect_properties_add(struct d2d_effect_properties *props, const WCH
else if (p->size)
memset(props->data.ptr + p->data.offset, 0, p->size);
}
- p->set_function = NULL;
- p->get_function = NULL;
return S_OK;
}
+HRESULT d2d_effect_properties_add(struct d2d_effect_properties *props, const WCHAR *name,
+ UINT32 index, D2D1_PROPERTY_TYPE type, const WCHAR *value)
+{
+ return d2d_effect_properties_internal_add(props, name, index, FALSE, type, value);
+}
+
+HRESULT d2d_effect_subproperties_add(struct d2d_effect_properties *props, const WCHAR *name,
+ UINT32 index, D2D1_PROPERTY_TYPE type, const WCHAR *value)
+{
+ return d2d_effect_properties_internal_add(props, name, index, TRUE, type, value);
+}
+
static HRESULT d2d_effect_duplicate_properties(struct d2d_effect_properties *dst,
const struct d2d_effect_properties *src)
{
+ HRESULT hr;
size_t i;
memset(dst, 0, sizeof(*dst));
@@ -372,6 +386,14 @@ static HRESULT d2d_effect_duplicate_properties(struct d2d_effect_properties *dst
d->name = wcsdup(s->name);
if (d->type == D2D1_PROPERTY_TYPE_STRING)
d->data.ptr = wcsdup((WCHAR *)s->data.ptr);
+
+ if (s->subproperties)
+ {
+ if (!(d->subproperties = calloc(1, sizeof(*d->subproperties))))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = d2d_effect_duplicate_properties(d->subproperties, s->subproperties)))
+ return hr;
+ }
}
return S_OK;
@@ -391,7 +413,7 @@ static struct d2d_effect_property * d2d_effect_properties_get_property_by_index(
return NULL;
}
-static struct d2d_effect_property * d2d_effect_properties_get_property_by_name(
+struct d2d_effect_property * d2d_effect_properties_get_property_by_name(
const struct d2d_effect_properties *properties, const WCHAR *name)
{
unsigned int i;
@@ -405,9 +427,10 @@ static struct d2d_effect_property * d2d_effect_properties_get_property_by_name(
return NULL;
}
-static UINT32 d2d_effect_properties_get_value_size(const struct d2d_effect *effect,
- const struct d2d_effect_properties *properties, UINT32 index)
+static UINT32 d2d_effect_properties_get_value_size(const struct d2d_effect_properties *properties,
+ UINT32 index)
{
+ struct d2d_effect *effect = properties->effect;
struct d2d_effect_property *prop;
UINT32 size;
@@ -432,10 +455,10 @@ static HRESULT d2d_effect_return_string(const WCHAR *str, WCHAR *buffer, UINT32
return S_OK;
}
-static HRESULT d2d_effect_property_get_value(const struct d2d_effect *effect,
- const struct d2d_effect_properties *properties, const struct d2d_effect_property *prop,
- D2D1_PROPERTY_TYPE type, BYTE *value, UINT32 size)
+static HRESULT d2d_effect_property_get_value(const struct d2d_effect_properties *properties,
+ const struct d2d_effect_property *prop, D2D1_PROPERTY_TYPE type, BYTE *value, UINT32 size)
{
+ struct d2d_effect *effect = properties->effect;
UINT32 actual_size;
if (type != D2D1_PROPERTY_TYPE_UNKNOWN && prop->type != type) return E_INVALIDARG;
@@ -446,7 +469,6 @@ static HRESULT d2d_effect_property_get_value(const struct d2d_effect *effect,
switch (prop->type)
{
- case D2D1_PROPERTY_TYPE_ARRAY:
case D2D1_PROPERTY_TYPE_BLOB:
FIXME("Unimplemented for type %u.\n", prop->type);
return E_NOTIMPL;
@@ -460,10 +482,10 @@ static HRESULT d2d_effect_property_get_value(const struct d2d_effect *effect,
return S_OK;
}
-static HRESULT d2d_effect_property_set_value(const struct d2d_effect *effect,
- struct d2d_effect_properties *properties, struct d2d_effect_property *prop,
- D2D1_PROPERTY_TYPE type, const BYTE *value, UINT32 size)
+static HRESULT d2d_effect_property_set_value(struct d2d_effect_properties *properties,
+ struct d2d_effect_property *prop, D2D1_PROPERTY_TYPE type, const BYTE *value, UINT32 size)
{
+ struct d2d_effect *effect = properties->effect;
if (prop->readonly) return E_INVALIDARG;
if (type != D2D1_PROPERTY_TYPE_UNKNOWN && prop->type != type) return E_INVALIDARG;
if (prop->get_function && !prop->set_function) return E_INVALIDARG;
@@ -499,6 +521,11 @@ void d2d_effect_properties_cleanup(struct d2d_effect_properties *props)
free(p->name);
if (p->type == D2D1_PROPERTY_TYPE_STRING)
free(p->data.ptr);
+ if (p->subproperties)
+ {
+ d2d_effect_properties_cleanup(p->subproperties);
+ free(p->subproperties);
+ }
}
free(props->properties);
free(props->data.ptr);
@@ -967,118 +994,91 @@ static UINT32 STDMETHODCALLTYPE d2d_effect_GetPropertyCount(ID2D1Effect *iface)
TRACE("iface %p.\n", iface);
- return effect->properties.custom_count;
+ return ID2D1Properties_GetPropertyCount(&effect->properties.ID2D1Properties_iface);
}
static HRESULT STDMETHODCALLTYPE d2d_effect_GetPropertyName(ID2D1Effect *iface, UINT32 index,
WCHAR *name, UINT32 name_count)
{
struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- struct d2d_effect_property *prop;
TRACE("iface %p, index %u, name %p, name_count %u.\n", iface, index, name, name_count);
- if (!(prop = d2d_effect_properties_get_property_by_index(&effect->properties, index)))
- return D2DERR_INVALID_PROPERTY;
-
- return d2d_effect_return_string(prop->name, name, name_count);
+ return ID2D1Properties_GetPropertyName(&effect->properties.ID2D1Properties_iface,
+ index, name, name_count);
}
static UINT32 STDMETHODCALLTYPE d2d_effect_GetPropertyNameLength(ID2D1Effect *iface, UINT32 index)
{
struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- struct d2d_effect_property *prop;
TRACE("iface %p, index %u.\n", iface, index);
- if (!(prop = d2d_effect_properties_get_property_by_index(&effect->properties, index)))
- return D2DERR_INVALID_PROPERTY;
-
- return wcslen(prop->name) + 1;
+ return ID2D1Properties_GetPropertyNameLength(&effect->properties.ID2D1Properties_iface, index);
}
static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE d2d_effect_GetType(ID2D1Effect *iface, UINT32 index)
{
struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- struct d2d_effect_property *prop;
TRACE("iface %p, index %#x.\n", iface, index);
- if (!(prop = d2d_effect_properties_get_property_by_index(&effect->properties, index)))
- return D2D1_PROPERTY_TYPE_UNKNOWN;
-
- return prop->type;
+ return ID2D1Properties_GetType(&effect->properties.ID2D1Properties_iface, index);
}
static UINT32 STDMETHODCALLTYPE d2d_effect_GetPropertyIndex(ID2D1Effect *iface, const WCHAR *name)
{
struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- struct d2d_effect_property *prop;
TRACE("iface %p, name %s.\n", iface, debugstr_w(name));
- if (!(prop = d2d_effect_properties_get_property_by_name(&effect->properties, name)))
- return D2D1_INVALID_PROPERTY_INDEX;
-
- return prop->index;
+ return ID2D1Properties_GetPropertyIndex(&effect->properties.ID2D1Properties_iface, name);
}
static HRESULT STDMETHODCALLTYPE d2d_effect_SetValueByName(ID2D1Effect *iface, const WCHAR *name,
D2D1_PROPERTY_TYPE type, const BYTE *value, UINT32 value_size)
{
struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- struct d2d_effect_property *prop;
TRACE("iface %p, name %s, type %u, value %p, value_size %u.\n", iface, debugstr_w(name),
type, value, value_size);
- if (!(prop = d2d_effect_properties_get_property_by_name(&effect->properties, name)))
- return D2DERR_INVALID_PROPERTY;
-
- return d2d_effect_property_set_value(effect, &effect->properties, prop, type, value, value_size);
+ return ID2D1Properties_SetValueByName(&effect->properties.ID2D1Properties_iface, name,
+ type, value, value_size);
}
static HRESULT STDMETHODCALLTYPE d2d_effect_SetValue(ID2D1Effect *iface, UINT32 index, D2D1_PROPERTY_TYPE type,
const BYTE *value, UINT32 value_size)
{
struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- struct d2d_effect_property *prop;
TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface, index, type, value, value_size);
- if (!(prop = d2d_effect_properties_get_property_by_index(&effect->properties, index)))
- return D2DERR_INVALID_PROPERTY;
-
- return d2d_effect_property_set_value(effect, &effect->properties, prop, type, value, value_size);
+ return ID2D1Properties_SetValue(&effect->properties.ID2D1Properties_iface, index, type,
+ value, value_size);
}
static HRESULT STDMETHODCALLTYPE d2d_effect_GetValueByName(ID2D1Effect *iface, const WCHAR *name,
D2D1_PROPERTY_TYPE type, BYTE *value, UINT32 value_size)
{
struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- struct d2d_effect_property *prop;
TRACE("iface %p, name %s, type %#x, value %p, value_size %u.\n", iface, debugstr_w(name), type,
value, value_size);
- if (!(prop = d2d_effect_properties_get_property_by_name(&effect->properties, name)))
- return D2DERR_INVALID_PROPERTY;
-
- return d2d_effect_property_get_value(effect, &effect->properties, prop, type, value, value_size);
+ return ID2D1Properties_GetValueByName(&effect->properties.ID2D1Properties_iface, name, type,
+ value, value_size);
}
static HRESULT STDMETHODCALLTYPE d2d_effect_GetValue(ID2D1Effect *iface, UINT32 index, D2D1_PROPERTY_TYPE type,
BYTE *value, UINT32 value_size)
{
struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- struct d2d_effect_property *prop;
TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface, index, type, value, value_size);
- if (!(prop = d2d_effect_properties_get_property_by_index(&effect->properties, index)))
- return D2DERR_INVALID_PROPERTY;
-
- return d2d_effect_property_get_value(effect, &effect->properties, prop, type, value, value_size);
+ return ID2D1Properties_GetValue(&effect->properties.ID2D1Properties_iface, index, type,
+ value, value_size);
}
static UINT32 STDMETHODCALLTYPE d2d_effect_GetValueSize(ID2D1Effect *iface, UINT32 index)
@@ -1087,14 +1087,17 @@ static UINT32 STDMETHODCALLTYPE d2d_effect_GetValueSize(ID2D1Effect *iface, UINT
TRACE("iface %p, index %#x.\n", iface, index);
- return d2d_effect_properties_get_value_size(effect, &effect->properties, index);
+ return ID2D1Properties_GetValueSize(&effect->properties.ID2D1Properties_iface, index);
}
-static HRESULT STDMETHODCALLTYPE d2d_effect_GetSubProperties(ID2D1Effect *iface, UINT32 index, ID2D1Properties **props)
+static HRESULT STDMETHODCALLTYPE d2d_effect_GetSubProperties(ID2D1Effect *iface, UINT32 index,
+ ID2D1Properties **props)
{
- FIXME("iface %p, index %u, props %p stub!\n", iface, index, props);
+ struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
- return E_NOTIMPL;
+ TRACE("iface %p, index %u, props %p.\n", iface, index, props);
+
+ return ID2D1Properties_GetSubProperties(&effect->properties.ID2D1Properties_iface, index, props);
}
static void STDMETHODCALLTYPE d2d_effect_SetInput(ID2D1Effect *iface, UINT32 index, ID2D1Image *input, BOOL invalidate)
@@ -1255,17 +1258,234 @@ static const ID2D1ImageVtbl d2d_effect_image_vtbl =
d2d_effect_image_GetFactory,
};
+static inline struct d2d_effect_properties *impl_from_ID2D1Properties(ID2D1Properties *iface)
+{
+ return CONTAINING_RECORD(iface, struct d2d_effect_properties, ID2D1Properties_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_properties_QueryInterface(ID2D1Properties *iface,
+ REFIID riid, void **obj)
+{
+ if (IsEqualGUID(riid, &IID_ID2D1Properties) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ ID2D1Properties_AddRef(iface);
+ return S_OK;
+ }
+
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d2d_effect_properties_AddRef(ID2D1Properties *iface)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ return ID2D1Effect_AddRef(&properties->effect->ID2D1Effect_iface);
+}
+
+static ULONG STDMETHODCALLTYPE d2d_effect_properties_Release(ID2D1Properties *iface)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ return ID2D1Effect_Release(&properties->effect->ID2D1Effect_iface);
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_properties_GetPropertyCount(ID2D1Properties *iface)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+
+ TRACE("iface %p.\n", iface);
+
+ return properties->custom_count;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_properties_GetPropertyName(ID2D1Properties *iface,
+ UINT32 index, WCHAR *name, UINT32 name_count)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, index %u, name %p, name_count %u.\n", iface, index, name, name_count);
+
+ if (!(prop = d2d_effect_properties_get_property_by_index(properties, index)))
+ return D2DERR_INVALID_PROPERTY;
+
+ return d2d_effect_return_string(prop->name, name, name_count);
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_properties_GetPropertyNameLength(ID2D1Properties *iface,
+ UINT32 index)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, index %u.\n", iface, index);
+
+ if (!(prop = d2d_effect_properties_get_property_by_index(properties, index)))
+ return D2DERR_INVALID_PROPERTY;
+
+ return wcslen(prop->name) + 1;
+}
+
+static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE d2d_effect_properties_GetType(ID2D1Properties *iface,
+ UINT32 index)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, index %#x.\n", iface, index);
+
+ if (!(prop = d2d_effect_properties_get_property_by_index(properties, index)))
+ return D2D1_PROPERTY_TYPE_UNKNOWN;
+
+ return prop->type;
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_properties_GetPropertyIndex(ID2D1Properties *iface,
+ const WCHAR *name)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name));
+
+ if (!(prop = d2d_effect_properties_get_property_by_name(properties, name)))
+ return D2D1_INVALID_PROPERTY_INDEX;
+
+ return prop->index;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_properties_SetValueByName(ID2D1Properties *iface,
+ const WCHAR *name, D2D1_PROPERTY_TYPE type, const BYTE *value, UINT32 value_size)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, name %s, type %u, value %p, value_size %u.\n", iface, debugstr_w(name),
+ type, value, value_size);
+
+ if (!(prop = d2d_effect_properties_get_property_by_name(properties, name)))
+ return D2DERR_INVALID_PROPERTY;
+
+ return d2d_effect_property_set_value(properties, prop, type, value, value_size);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_properties_SetValue(ID2D1Properties *iface,
+ UINT32 index, D2D1_PROPERTY_TYPE type, const BYTE *value, UINT32 value_size)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface, index, type, value, value_size);
+
+ if (!(prop = d2d_effect_properties_get_property_by_index(properties, index)))
+ return D2DERR_INVALID_PROPERTY;
+
+ return d2d_effect_property_set_value(properties, prop, type, value, value_size);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_properties_GetValueByName(ID2D1Properties *iface,
+ const WCHAR *name, D2D1_PROPERTY_TYPE type, BYTE *value, UINT32 value_size)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, name %s, type %#x, value %p, value_size %u.\n", iface, debugstr_w(name), type,
+ value, value_size);
+
+ if (!(prop = d2d_effect_properties_get_property_by_name(properties, name)))
+ return D2DERR_INVALID_PROPERTY;
+
+ return d2d_effect_property_get_value(properties, prop, type, value, value_size);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_properties_GetValue(ID2D1Properties *iface,
+ UINT32 index, D2D1_PROPERTY_TYPE type, BYTE *value, UINT32 value_size)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface, index, type, value, value_size);
+
+ if (!(prop = d2d_effect_properties_get_property_by_index(properties, index)))
+ return D2DERR_INVALID_PROPERTY;
+
+ return d2d_effect_property_get_value(properties, prop, type, value, value_size);
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_properties_GetValueSize(ID2D1Properties *iface,
+ UINT32 index)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+
+ TRACE("iface %p, index %#x.\n", iface, index);
+
+ return d2d_effect_properties_get_value_size(properties, index);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_properties_GetSubProperties(ID2D1Properties *iface,
+ UINT32 index, ID2D1Properties **props)
+{
+ struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
+ struct d2d_effect_property *prop;
+
+ TRACE("iface %p, index %u, props %p.\n", iface, index, props);
+
+ if (!(prop = d2d_effect_properties_get_property_by_index(properties, index)))
+ return D2DERR_INVALID_PROPERTY;
+
+ if (!prop->subproperties) return D2DERR_NO_SUBPROPERTIES;
+
+ *props = &prop->subproperties->ID2D1Properties_iface;
+ ID2D1Properties_AddRef(*props);
+ return S_OK;
+}
+
+static const ID2D1PropertiesVtbl d2d_effect_properties_vtbl =
+{
+ d2d_effect_properties_QueryInterface,
+ d2d_effect_properties_AddRef,
+ d2d_effect_properties_Release,
+ d2d_effect_properties_GetPropertyCount,
+ d2d_effect_properties_GetPropertyName,
+ d2d_effect_properties_GetPropertyNameLength,
+ d2d_effect_properties_GetType,
+ d2d_effect_properties_GetPropertyIndex,
+ d2d_effect_properties_SetValueByName,
+ d2d_effect_properties_SetValue,
+ d2d_effect_properties_GetValueByName,
+ d2d_effect_properties_GetValue,
+ d2d_effect_properties_GetValueSize,
+ d2d_effect_properties_GetSubProperties,
+};
+
+static void d2d_effect_init_properties_vtbls(struct d2d_effect *effect)
+{
+ unsigned int i;
+
+ effect->properties.ID2D1Properties_iface.lpVtbl = &d2d_effect_properties_vtbl;
+ effect->properties.effect = effect;
+
+ for (i = 0; i < effect->properties.count; ++i)
+ {
+ struct d2d_effect_property *prop = &effect->properties.properties[i];
+ if (!prop->subproperties) continue;
+ prop->subproperties->ID2D1Properties_iface.lpVtbl = &d2d_effect_properties_vtbl;
+ prop->subproperties->effect = effect;
+ }
+}
+
HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effect_id,
ID2D1Effect **effect)
{
const struct d2d_effect_info *builtin = NULL;
struct d2d_effect_context *effect_context;
const struct d2d_effect_registration *reg;
+ unsigned int i, default_input_count;
struct d2d_transform_graph *graph;
PD2D1_EFFECT_FACTORY factory;
struct d2d_effect *object;
WCHAR clsidW[39];
- unsigned int i;
HRESULT hr;
if (!(reg = d2d_factory_get_registered_effect(context->factory, effect_id)))
@@ -1323,7 +1543,7 @@ HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effec
d2d_effect_properties_add(&object->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS,
D2D1_PROPERTY_TYPE_UINT32, max_inputs);
- d2d_effect_SetInputCount(&object->ID2D1Effect_iface, builtin->default_input_count);
+ default_input_count = builtin->default_input_count;
factory = builtin_factory_stub;
}
@@ -1335,7 +1555,7 @@ HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effec
d2d_effect_properties_add(&object->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS,
D2D1_PROPERTY_TYPE_UINT32, L"1" /* FIXME */);
- d2d_effect_SetInputCount(&object->ID2D1Effect_iface, 1);
+ default_input_count = 1;
factory = reg->factory;
}
@@ -1343,6 +1563,9 @@ HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effec
d2d_effect_properties_add(&object->properties, L"CLSID", D2D1_PROPERTY_CLSID, D2D1_PROPERTY_TYPE_CLSID, clsidW);
d2d_effect_properties_add(&object->properties, L"Cached", D2D1_PROPERTY_CACHED, D2D1_PROPERTY_TYPE_BOOL, L"false");
d2d_effect_properties_add(&object->properties, L"Precision", D2D1_PROPERTY_PRECISION, D2D1_PROPERTY_TYPE_ENUM, L"0");
+ d2d_effect_init_properties_vtbls(object);
+
+ d2d_effect_SetInputCount(&object->ID2D1Effect_iface, default_input_count);
if (FAILED(hr = factory((IUnknown **)&object->impl)))
{
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 911d809b58b..699b8c05669 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -782,6 +782,55 @@ static HRESULT parse_effect_property(IXmlReader *reader, struct d2d_effect_regis
return hr;
}
+static HRESULT parse_effect_inputs(IXmlReader *reader, struct d2d_effect_registration *effect)
+{
+ struct d2d_effect_properties *subproperties;
+ unsigned int depth, input_count = 0;
+ struct d2d_effect_property *inputs;
+ XmlNodeType node_type;
+ WCHAR nameW[16];
+ WCHAR *name;
+ HRESULT hr;
+
+ if (FAILED(hr = d2d_effect_properties_add(&effect->properties, L"Inputs",
+ D2D1_PROPERTY_INPUTS, D2D1_PROPERTY_TYPE_ARRAY, NULL)))
+ return hr;
+
+ if (!(inputs = d2d_effect_properties_get_property_by_name(&effect->properties, L"Inputs")))
+ return E_FAIL;
+ if (!(inputs->subproperties = calloc(1, sizeof(*inputs->subproperties))))
+ return E_OUTOFMEMORY;
+ subproperties = inputs->subproperties;
+
+ d2d_effect_subproperties_add(subproperties, L"IsReadOnly", D2D1_SUBPROPERTY_ISREADONLY,
+ D2D1_PROPERTY_TYPE_BOOL, L"true");
+ d2d_effect_subproperties_add(subproperties, L"DisplayName", D2D1_SUBPROPERTY_DISPLAYNAME,
+ D2D1_PROPERTY_TYPE_STRING, L"Inputs");
+
+ if (IXmlReader_IsEmptyElement(reader)) return S_OK;
+
+ while (parse_effect_get_next_xml_node(reader, XmlNodeType_None, L"Input", &depth) == S_OK)
+ {
+ if (FAILED(hr = IXmlReader_GetNodeType(reader, &node_type))) return hr;
+ if (node_type == XmlNodeType_EndElement) continue;
+ if (node_type != XmlNodeType_Element) return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+
+ if (FAILED(hr = parse_effect_get_attribute(reader, L"name", &name))) return hr;
+
+ swprintf(nameW, ARRAY_SIZE(nameW), L"%lu", input_count);
+ d2d_effect_subproperties_add(subproperties, nameW, input_count, D2D1_PROPERTY_TYPE_STRING, name);
+ input_count++;
+
+ free(name);
+ }
+ *(UINT32 *)(effect->properties.data.ptr + inputs->data.offset) = input_count;
+
+ if (FAILED(hr = IXmlReader_GetNodeType(reader, &node_type))) return hr;
+ if (node_type != XmlNodeType_EndElement) return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+
+ return S_OK;
+}
+
static HRESULT parse_effect_xml(IXmlReader *reader, struct d2d_effect_registration *effect)
{
const WCHAR *node_name;
@@ -808,7 +857,7 @@ static HRESULT parse_effect_xml(IXmlReader *reader, struct d2d_effect_registrati
if (!wcscmp(node_name, L"Property"))
hr = parse_effect_property(reader, effect);
else if (!wcscmp(node_name, L"Inputs"))
- hr = parse_effect_skip_element(reader, depth);
+ hr = parse_effect_inputs(reader, effect);
else
{
WARN("Unexpected element %s.\n", debugstr_w(node_name));
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 6ba4d8cec59..fe7bfa38753 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -10926,12 +10926,15 @@ static void test_effect_context(BOOL d3d11)
static void test_effect_properties(BOOL d3d11)
{
- UINT32 i, min_inputs, max_inputs, integer, index;
+ UINT32 i, min_inputs, max_inputs, integer, index, size;
ID2D1EffectContext *effect_context;
D2D1_BUFFER_PRECISION precision;
+ ID2D1Properties *subproperties;
+ D2D1_PROPERTY_TYPE prop_type;
struct d2d1_test_context ctx;
ID2D1Factory1 *factory;
ID2D1Effect *effect;
+ UINT32 count, data;
WCHAR buffer[128];
CLSID clsid;
BOOL cached;
@@ -10976,6 +10979,62 @@ static void test_effect_properties(BOOL d3d11)
return;
}
+ /* Inputs array */
+ hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, effect_xml_a,
+ NULL, 0, effect_impl_create);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ hr = ID2D1DeviceContext_CreateEffect(ctx.context, &CLSID_TestEffect, &effect);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ size = ID2D1Effect_GetValueSize(effect, D2D1_PROPERTY_INPUTS);
+ ok(size == 4, "Unexpected size %u.\n", size);
+ prop_type = ID2D1Effect_GetType(effect, D2D1_PROPERTY_INPUTS);
+ ok(prop_type == D2D1_PROPERTY_TYPE_ARRAY, "Unexpected type %u.\n", prop_type);
+ hr = ID2D1Effect_GetPropertyName(effect, D2D1_PROPERTY_INPUTS, buffer, ARRAY_SIZE(buffer));
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(!wcscmp(buffer, L"Inputs"), "Unexpected name %s.\n", wine_dbgstr_w(buffer));
+
+ /* Value is the number of elements. */
+ data = 123;
+ hr = ID2D1Effect_GetValue(effect, D2D1_PROPERTY_INPUTS, D2D1_PROPERTY_TYPE_ARRAY,
+ (BYTE *)&data, sizeof(data));
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(data == 1, "Unexpected data %u.\n", data);
+
+ hr = ID2D1Effect_GetSubProperties(effect, D2D1_PROPERTY_INPUTS, &subproperties);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ count = ID2D1Properties_GetPropertyCount(subproperties);
+ ok(count == 1, "Unexpected count %u.\n", count);
+
+ hr = ID2D1Properties_GetPropertyName(subproperties, 0, buffer, ARRAY_SIZE(buffer));
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(!wcscmp(buffer, L"0"), "Unexpected name %s.\n", wine_dbgstr_w(buffer));
+ hr = ID2D1Properties_GetValue(subproperties, 0, D2D1_PROPERTY_TYPE_STRING,
+ (BYTE *)buffer, sizeof(buffer));
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(!wcscmp(buffer, L"Source"), "Unexpected value %s.\n", wine_dbgstr_w(buffer));
+
+ hr = ID2D1Properties_GetValue(subproperties, D2D1_SUBPROPERTY_ISREADONLY, D2D1_PROPERTY_TYPE_BOOL,
+ (BYTE *)&data, sizeof(data));
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(data == TRUE, "Unexpected value %u.\n", data);
+ hr = ID2D1Properties_GetPropertyName(subproperties, D2D1_SUBPROPERTY_ISREADONLY,
+ buffer, ARRAY_SIZE(buffer));
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(!wcscmp(buffer, L"IsReadOnly"), "Unexpected name %s.\n", wine_dbgstr_w(buffer));
+ hr = ID2D1Properties_GetValue(subproperties, D2D1_SUBPROPERTY_DISPLAYNAME,
+ D2D1_PROPERTY_TYPE_STRING, (BYTE *)buffer, ARRAY_SIZE(buffer));
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ok(!wcscmp(buffer, L"Inputs"), "Unexpected name %s.\n", wine_dbgstr_w(buffer));
+
+ ID2D1Properties_Release(subproperties);
+ ID2D1Effect_Release(effect);
+
+ hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
/* Test system properties */
for (i = 0; i < ARRAY_SIZE(system_property_tests); ++i)
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/347
More information about the wine-devel
mailing list