Signed-off-by: Ziqing Hui zhui@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;