[PATCH 3/5] d2d1: Implement property parsing for RegisterEffectFromStream().
Ziqing Hui
zhui at codeweavers.com
Mon Jun 6 02:35:23 CDT 2022
Signed-off-by: Ziqing Hui <zhui at codeweavers.com>
---
dlls/d2d1/d2d1_private.h | 12 +++
dlls/d2d1/factory.c | 155 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 164 insertions(+), 3 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index cc625ff5719..07f07c3a087 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -603,12 +603,24 @@ struct d2d_effect_context
void d2d_effect_context_init(struct d2d_effect_context *effect_context,
struct d2d_device_context *device_context) DECLSPEC_HIDDEN;
+struct d2d_effect_property
+{
+ WCHAR *name;
+ D2D1_PROPERTY_TYPE type;
+ PD2D1_PROPERTY_SET_FUNCTION set_function;
+ PD2D1_PROPERTY_GET_FUNCTION get_function;
+};
+
struct d2d_effect_info
{
const CLSID *clsid;
UINT32 default_input_count;
UINT32 min_inputs;
UINT32 max_inputs;
+ WCHAR *display_name;
+ WCHAR *author;
+ WCHAR *category;
+ WCHAR *description;
};
struct d2d_effect
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index e8aa1fab012..b3b65b0cb92 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -36,6 +36,10 @@ struct d2d_effect_reg
struct d2d_effect_info *info;
+ struct d2d_effect_property *properties;
+ size_t property_size;
+ size_t property_count;
+
struct list entry;
};
@@ -67,10 +71,24 @@ static inline struct d2d_factory *impl_from_ID2D1Multithread(ID2D1Multithread *i
static void d2d_effect_reg_cleanup(struct d2d_effect_reg *reg)
{
+ size_t i;
+
if (!reg)
return;
- heap_free(reg->info);
+ if (reg->info)
+ {
+ heap_free(reg->info->display_name);
+ heap_free(reg->info->author);
+ heap_free(reg->info->category);
+ heap_free(reg->info->description);
+ heap_free(reg->info);
+ }
+
+ for (i = 0; i < reg->property_count; ++i)
+ heap_free(reg->properties[i].name);
+ heap_free(reg->properties);
+
heap_free(reg);
}
@@ -590,6 +608,110 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateGdiMetafile(ID2D1Factory3 *if
return E_NOTIMPL;
}
+static HRESULT heap_get_attribute(IXmlReader *xml_reader, const WCHAR *name, WCHAR **ptr)
+{
+ const WCHAR *value;
+
+ if (IXmlReader_MoveToAttributeByName(xml_reader, name, NULL) != S_OK)
+ return E_INVALIDARG;
+ if (IXmlReader_GetValue(xml_reader, &value, NULL) != S_OK)
+ return E_INVALIDARG;
+ if (!(*ptr = heap_strdupW(value)))
+ return E_OUTOFMEMORY;
+ return S_OK;
+}
+
+static D2D1_PROPERTY_TYPE str_to_property_type(const WCHAR *str)
+{
+ unsigned int i;
+
+ static const WCHAR *type_str[] =
+ {
+ L"", L"string", L"bool", L"uint32", L"int32", L"float", L"vector2", L"vector3",
+ L"vector4", L"blob", L"iunknown", L"enum", L"array", L"clsid", L"matrix3x2",
+ L"matrix4x3", L"matrix4x4", L"matrix5x4", L"colorcontext",
+ };
+
+ for (i = 1; i < ARRAY_SIZE(type_str); ++i)
+ {
+ if (!wcscmp(str, type_str[i]))
+ return i;
+ }
+
+ return D2D1_PROPERTY_TYPE_UNKNOWN;
+}
+
+static HRESULT parse_property(IXmlReader *xml_reader, struct d2d_effect_reg *reg)
+{
+ struct d2d_effect_property *entry;
+ D2D1_PROPERTY_TYPE property_type;
+ WCHAR **ptr = NULL, *name = NULL;
+ const WCHAR *type;
+ unsigned int i;
+ HRESULT hr;
+
+ /* get property name and type */
+ if (FAILED(hr = heap_get_attribute(xml_reader, L"name", &name)))
+ goto done;
+ if ((hr = IXmlReader_MoveToAttributeByName(xml_reader, L"type", NULL)) != S_OK)
+ goto done;
+ if ((hr = IXmlReader_GetValue(xml_reader, &type, NULL)) != S_OK)
+ goto done;
+ property_type = str_to_property_type(type);
+ if (property_type == D2D1_PROPERTY_TYPE_UNKNOWN)
+ {
+ hr = E_INVALIDARG;
+ goto done;
+ }
+
+ /* is system property */
+ if (!wcscmp(name, L"DisplayName"))
+ ptr = ®->info->display_name;
+ else if(!wcscmp(name, L"Author"))
+ ptr = ®->info->author;
+ else if(!wcscmp(name, L"Category"))
+ ptr = ®->info->category;
+ else if(!wcscmp(name, L"Description"))
+ ptr = ®->info->description;
+ if (ptr)
+ {
+ heap_free(name);
+ if (*ptr || property_type != D2D1_PROPERTY_TYPE_STRING)
+ return E_INVALIDARG;
+ if (FAILED(heap_get_attribute(xml_reader, L"value", ptr)))
+ {
+ if (!(*ptr = heap_strdupW(L"")))
+ hr = E_OUTOFMEMORY;
+ }
+ return hr;
+ }
+
+ /* is custom property */
+ for (i = 0; i < reg->property_count; ++i)
+ {
+ if (!wcscmp(name, reg->properties[i].name))
+ {
+ hr = E_INVALIDARG;
+ goto done;
+ }
+ }
+ if (!d2d_array_reserve((void **)®->properties, ®->property_size, reg->property_count + 1, sizeof(*reg->properties)))
+ {
+ ERR("Failed to resize properties array.\n");
+ goto done;
+ }
+ entry = ®->properties[reg->property_count++];
+ entry->name = name;
+ entry->type = property_type;
+ entry->get_function = NULL;
+ entry->set_function = NULL;
+
+done:
+ if (hr != S_OK)
+ heap_free(name);
+ return hr;
+}
+
static HRESULT parse_effect_xml(IStream *property_xml, struct d2d_effect_reg *reg)
{
unsigned int i, len, depth, input_count = 0;
@@ -632,7 +754,8 @@ static HRESULT parse_effect_xml(IStream *property_xml, struct d2d_effect_reg *re
if (!wcscmp(node_name[depth - 1], L"Effect")
&& !wcscmp(node_name[depth], L"Property"))
{
- FIXME("Property is ignored.\n");
+ if (FAILED(hr = parse_property(xml_reader, reg)))
+ goto done;
}
break;
case 2:
@@ -644,7 +767,7 @@ static HRESULT parse_effect_xml(IStream *property_xml, struct d2d_effect_reg *re
else if (!wcscmp(node_name[depth - 1], L"Property")
&& !wcscmp(node_name[depth], L"Property"))
{
- FIXME("Sub property is ignored.\n");
+ FIXME("SubProperty is ignored.\n");
}
break;
default:
@@ -652,6 +775,12 @@ static HRESULT parse_effect_xml(IStream *property_xml, struct d2d_effect_reg *re
}
}
+ if (!reg->info->display_name || !reg->info->author || !reg->info->category || !reg->info->description)
+ {
+ hr = E_INVALIDARG;
+ goto done;
+ }
+
reg->info->default_input_count = input_count;
reg->info->min_inputs = input_count;
reg->info->max_inputs = input_count;
@@ -669,6 +798,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
{
struct d2d_factory *factory = impl_from_ID2D1Factory3(iface);
struct d2d_effect_reg *iter, *entry = NULL;
+ unsigned int i, j;
HRESULT hr;
TRACE("iface %p, effect_id %s, property_xml %p, bindings %p, binding_count %u, effect_factory %p.\n",
@@ -692,6 +822,25 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
if (FAILED(hr = parse_effect_xml(property_xml, entry)))
goto done;
+ /* bind getter and setter to properties */
+ for (i = 0; i < binding_count; ++i)
+ {
+ for (j = 0; j < entry->property_count; ++j)
+ {
+ if (!wcscmp(bindings[i].propertyName, entry->properties[j].name))
+ {
+ entry->properties[j].get_function = bindings[i].getFunction;
+ entry->properties[j].set_function = bindings[i].setFunction;
+ break;
+ }
+ }
+ if (j > entry->property_count)
+ {
+ hr = D2DERR_INVALID_PROPERTY;
+ goto done;
+ }
+ }
+
entry->count = 1;
entry->info->clsid = effect_id;
entry->factory = effect_factory;
--
2.25.1
More information about the wine-devel
mailing list