[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 = &reg->info->display_name;
+    else if(!wcscmp(name, L"Author"))
+        ptr = &reg->info->author;
+    else if(!wcscmp(name, L"Category"))
+        ptr = &reg->info->category;
+    else if(!wcscmp(name, L"Description"))
+        ptr = &reg->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 **)&reg->properties, &reg->property_size, reg->property_count + 1, sizeof(*reg->properties)))
+    {
+        ERR("Failed to resize properties array.\n");
+        goto done;
+    }
+    entry = &reg->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