[PATCH 3/9] d2d1: Implement property parsing for RegisterEffectFromStream().
Ziqing Hui
wine at gitlab.winehq.org
Sun Jun 19 13:43:36 CDT 2022
From: Ziqing Hui <zhui at codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/d2d1/factory.c | 199 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 193 insertions(+), 6 deletions(-)
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 4a08a0cf76d..b3875f28209 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -30,6 +30,15 @@ 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;
@@ -38,10 +47,22 @@ struct d2d_effect_registration
CLSID id;
UINT32 input_count;
+
+ struct d2d_effect_property *properties;
+ size_t property_size;
+ size_t property_count;
};
static void d2d_effect_registration_cleanup(struct d2d_effect_registration *reg)
{
+ size_t i;
+
+ for (i = 0; i < reg->property_count; ++i)
+ {
+ free(reg->properties[i].name);
+ free(reg->properties[i].value);
+ }
+ free(reg->properties);
free(reg);
}
@@ -643,7 +664,146 @@ static HRESULT parse_effect_skip_element(IXmlReader *reader, unsigned int elemen
return hr;
}
-static HRESULT parse_effect_xml(IXmlReader *reader)
+static HRESULT parse_effect_get_attribute(IXmlReader *reader, const WCHAR *name, WCHAR **ret)
+{
+ const WCHAR *value;
+
+ *ret = NULL;
+
+ if (IXmlReader_MoveToAttributeByName(reader, name, NULL) != S_OK)
+ return E_INVALIDARG;
+ if (IXmlReader_GetValue(reader, &value, NULL) != S_OK)
+ return E_INVALIDARG;
+ if (!(*ret = wcsdup(value)))
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+static HRESULT parse_effect_get_property_type(IXmlReader *reader, D2D1_PROPERTY_TYPE *type)
+{
+ static const WCHAR *types[] =
+ {
+ L"", /* D2D1_PROPERTY_TYPE_UNKNOWN */
+ L"string", /* D2D1_PROPERTY_TYPE_STRING */
+ L"bool", /* D2D1_PROPERTY_TYPE_BOOL */
+ L"uint32", /* D2D1_PROPERTY_TYPE_UINT32 */
+ L"int32", /* D2D1_PROPERTY_TYPE_INT32 */
+ L"float", /* D2D1_PROPERTY_TYPE_FLOAT */
+ L"vector2", /* D2D1_PROPERTY_TYPE_VECTOR2 */
+ L"vector3", /* D2D1_PROPERTY_TYPE_VECTOR3 */
+ L"vector4", /* D2D1_PROPERTY_TYPE_VECTOR4 */
+ L"blob", /* D2D1_PROPERTY_TYPE_BLOB */
+ L"iunknown", /* D2D1_PROPERTY_TYPE_IUNKNOWN */
+ L"enum", /* D2D1_PROPERTY_TYPE_ENUM */
+ L"array", /* D2D1_PROPERTY_TYPE_ARRAY */
+ L"clsid", /* D2D1_PROPERTY_TYPE_CLSID */
+ L"matrix3x2", /* D2D1_PROPERTY_TYPE_MATRIX_3X2 */
+ L"matrix4x3", /* D2D1_PROPERTY_TYPE_MATRIX_4X3 */
+ L"matrix4x4", /* D2D1_PROPERTY_TYPE_MATRIX_4X4 */
+ L"matrix5x4", /* D2D1_PROPERTY_TYPE_MATRIX_5X4 */
+ L"colorcontext", /* D2D1_PROPERTY_TYPE_COLOR_CONTEXT */
+ };
+ unsigned int i;
+ WCHAR *value;
+ HRESULT hr;
+
+ if (FAILED(hr = parse_effect_get_attribute(reader, L"type", &value))) return hr;
+
+ *type = D2D1_PROPERTY_TYPE_UNKNOWN;
+
+ for (i = 0; i < ARRAY_SIZE(types); ++i)
+ {
+ if (!wcscmp(value, types[i]))
+ {
+ *type = i;
+ break;
+ }
+ }
+
+ free(value);
+
+ return *type == D2D1_PROPERTY_TYPE_UNKNOWN ? E_INVALIDARG : S_OK;
+}
+
+static struct d2d_effect_property * parse_effect_get_property(const struct d2d_effect_registration *effect,
+ const WCHAR *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < effect->property_count; ++i)
+ {
+ if (!wcscmp(name, effect->properties[i].name))
+ return &effect->properties[i];
+ }
+
+ return NULL;
+}
+
+static HRESULT parse_effect_add_property(struct d2d_effect_registration *effect, WCHAR *name,
+ D2D1_PROPERTY_TYPE type, BYTE *value)
+{
+ struct d2d_effect_property *property;
+
+ if (!d2d_array_reserve((void **)&effect->properties, &effect->property_size,
+ effect->property_count + 1, sizeof(*effect->properties)))
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ property = &effect->properties[effect->property_count++];
+ property->name = name;
+ property->type = type;
+ property->value = value;
+ property->set_function = NULL;
+ property->get_function = NULL;
+
+ return S_OK;
+}
+
+static HRESULT parse_effect_property(IXmlReader *reader, struct d2d_effect_registration *effect)
+{
+ WCHAR *name = NULL, *value = NULL;
+ D2D1_PROPERTY_TYPE type;
+ unsigned int depth;
+ HRESULT hr;
+
+ if (FAILED(hr = parse_effect_get_attribute(reader, L"name", &name)))
+ return hr;
+
+ if (FAILED(hr = parse_effect_get_property_type(reader, &type)))
+ {
+ free(name);
+ return hr;
+ }
+
+ /* Check for duplicates. */
+ if (parse_effect_get_property(effect, name))
+ hr = E_INVALIDARG;
+
+ parse_effect_get_attribute(reader, L"value", &value);
+
+ if (SUCCEEDED(hr))
+ {
+ /* FIXME: sub properties are ignored */
+ IXmlReader_MoveToElement(reader);
+ IXmlReader_GetDepth(reader, &depth);
+ hr = parse_effect_skip_element(reader, depth);
+ }
+
+ if (SUCCEEDED(hr))
+ hr = parse_effect_add_property(effect, name, type, (BYTE *)value);
+
+ if (FAILED(hr))
+ {
+ free(value);
+ free(name);
+ }
+
+ return hr;
+}
+
+static HRESULT parse_effect_xml(IXmlReader *reader, struct d2d_effect_registration *effect)
{
const WCHAR *node_name;
XmlNodeType node_type;
@@ -666,11 +826,10 @@ static HRESULT parse_effect_xml(IXmlReader *reader)
if (FAILED(hr = IXmlReader_GetLocalName(reader, &node_name, NULL))) return hr;
if (node_type == XmlNodeType_EndElement) break;
- if (!wcscmp(node_name, L"Property")
- || !wcscmp(node_name, L"Inputs"))
- {
+ 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);
- }
else
{
WARN("Unexpected element %s.\n", debugstr_w(node_name));
@@ -691,6 +850,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
struct d2d_factory *factory = impl_from_ID2D1Factory3(iface);
struct d2d_effect_registration *effect;
IXmlReader *reader;
+ unsigned int i;
HRESULT hr;
TRACE("iface %p, effect_id %s, property_xml %p, bindings %p, binding_count %u, effect_factory %p.\n",
@@ -720,7 +880,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
return E_OUTOFMEMORY;
}
- hr = parse_effect_xml(reader);
+ hr = parse_effect_xml(reader, effect);
IXmlReader_Release(reader);
if (FAILED(hr))
{
@@ -729,6 +889,33 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
return hr;
}
+ /* Check required properties. */
+ if (!parse_effect_get_property(effect, L"DisplayName")
+ || !parse_effect_get_property(effect, L"Author")
+ || !parse_effect_get_property(effect, L"Category")
+ || !parse_effect_get_property(effect, L"Description"))
+ {
+ WARN("Missing required properties.\n");
+ d2d_effect_registration_cleanup(effect);
+ return E_INVALIDARG;
+ }
+
+ /* Bind getter and setter. */
+ for (i = 0; i < binding_count; ++i)
+ {
+ struct d2d_effect_property *property;
+
+ if (!(property = parse_effect_get_property(effect, bindings[i].propertyName)))
+ {
+ WARN("Failed to bind to missing property.\n");
+ d2d_effect_registration_cleanup(effect);
+ return D2DERR_INVALID_PROPERTY;
+ }
+
+ property->get_function = bindings[i].getFunction;
+ property->set_function = bindings[i].setFunction;
+ }
+
effect->registration_count = 1;
effect->id = *effect_id;
effect->factory = effect_factory;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/278
More information about the wine-devel
mailing list