[PATCH 4/5] d2d1/effect: Reimplement GetValue().

Ziqing Hui zhui at codeweavers.com
Wed Jun 22 06:34:59 CDT 2022


Signed-off-by: Ziqing Hui <zhui at codeweavers.com>
---
 dlls/d2d1/d2d1_private.h |  17 ++++-
 dlls/d2d1/effect.c       | 144 ++++++++++++++++++++++++++++++---------
 dlls/d2d1/factory.c      |   9 ---
 3 files changed, 125 insertions(+), 45 deletions(-)

diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 9be553c72d8..27606e78a42 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -35,6 +35,8 @@
 #endif
 #include "dwrite_2.h"
 
+#define D2D1_SYSTEM_PROPERTY_COUNT (D2D1_PROPERTY_MAX_INPUTS - D2D1_PROPERTY_CLSID + 1)
+
 enum d2d_brush_type
 {
     D2D_BRUSH_TYPE_SOLID,
@@ -610,18 +612,29 @@ struct d2d_effect_info
     UINT32 max_inputs;
 };
 
+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
 {
     ID2D1Effect ID2D1Effect_iface;
     ID2D1Image ID2D1Image_iface;
     LONG refcount;
 
-    const struct d2d_effect_info *info;
-
     struct d2d_effect_context *effect_context;
     ID2D1Image **inputs;
     size_t inputs_size;
     size_t input_count;
+
+    struct d2d_effect_property system_properties[D2D1_SYSTEM_PROPERTY_COUNT];
+    struct d2d_effect_property *custom_properties;
+    size_t custom_property_count;
 };
 
 HRESULT d2d_effect_init(struct d2d_effect *effect,
diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c
index f5d5494c67a..e0c028664d7 100644
--- a/dlls/d2d1/effect.c
+++ b/dlls/d2d1/effect.c
@@ -30,6 +30,14 @@ static const struct d2d_effect_info builtin_effects[] =
     {&CLSID_D2D1Grayscale,              1, 1, 1},
 };
 
+static void *memdup(const void *ptr, size_t size)
+{
+    void *ret = malloc(size);
+    if (ret)
+        memcpy(ret, ptr, size);
+    return ret;
+}
+
 static inline struct d2d_effect_context *impl_from_ID2D1EffectContext(ID2D1EffectContext *iface)
 {
     return CONTAINING_RECORD(iface, struct d2d_effect_context, ID2D1EffectContext_iface);
@@ -413,10 +421,53 @@ static inline struct d2d_effect *impl_from_ID2D1Effect(ID2D1Effect *iface)
     return CONTAINING_RECORD(iface, struct d2d_effect, ID2D1Effect_iface);
 }
 
+static UINT32 d2d_effect_property_get_value_size(struct d2d_effect_property *property)
+{
+    static const UINT32 value_size[] =
+    {
+        0,                           /* D2D1_PROPERTY_TYPE_UNKNOWN */
+        0,                           /* D2D1_PROPERTY_TYPE_STRING */
+        sizeof(BOOL),                /* D2D1_PROPERTY_TYPE_BOOL */
+        sizeof(UINT32),              /* D2D1_PROPERTY_TYPE_UINT32 */
+        sizeof(INT32),               /* D2D1_PROPERTY_TYPE_INT32 */
+        sizeof(FLOAT),               /* D2D1_PROPERTY_TYPE_FLOAT */
+        sizeof(D2D_VECTOR_2F),       /* D2D1_PROPERTY_TYPE_VECTOR2 */
+        sizeof(D2D_VECTOR_3F),       /* D2D1_PROPERTY_TYPE_VECTOR3 */
+        sizeof(D2D_VECTOR_4F),       /* D2D1_PROPERTY_TYPE_VECTOR4 */
+        0,                           /* D2D1_PROPERTY_TYPE_BLOB */
+        sizeof(IUnknown *),          /* D2D1_PROPERTY_TYPE_IUNKNOWN */
+        sizeof(UINT32),              /* D2D1_PROPERTY_TYPE_ENUM */
+        sizeof(UINT32),              /* D2D1_PROPERTY_TYPE_ARRAY */
+        sizeof(CLSID),               /* D2D1_PROPERTY_TYPE_CLSID */
+        sizeof(D2D_MATRIX_3X2_F),    /* D2D1_PROPERTY_TYPE_MATRIX_3X2 */
+        sizeof(D2D_MATRIX_4X3_F),    /* D2D1_PROPERTY_TYPE_MATRIX_4X3 */
+        sizeof(D2D_MATRIX_4X4_F),    /* D2D1_PROPERTY_TYPE_MATRIX_4X4 */
+        sizeof(D2D_MATRIX_5X4_F),    /* D2D1_PROPERTY_TYPE_MATRIX_5X4 */
+        sizeof(ID2D1ColorContext *), /* D2D1_PROPERTY_TYPE_COLOR_CONTEXT */
+    };
+
+    if (property->type == D2D1_PROPERTY_TYPE_STRING)
+        return sizeof(WCHAR) * (wcslen((WCHAR *)property->value) + 1);
+
+    return value_size[property->type];
+}
+
 static void d2d_effect_cleanup(struct d2d_effect *effect)
 {
     unsigned int i;
 
+    for (i = 0; i < ARRAY_SIZE(effect->system_properties); ++i)
+    {
+        free(effect->system_properties[i].name);
+        free(effect->system_properties[i].value);
+    }
+
+    for (i = 0; i < effect->custom_property_count; ++i)
+    {
+        free(effect->custom_properties[i].name);
+        free(effect->custom_properties[i].value);
+    }
+
     for (i = 0; i < effect->input_count; ++i)
     {
         if (effect->inputs[i])
@@ -426,6 +477,16 @@ static void d2d_effect_cleanup(struct d2d_effect *effect)
     ID2D1EffectContext_Release(&effect->effect_context->ID2D1EffectContext_iface);
 }
 
+static struct d2d_effect_property *d2d_effect_get_property(struct d2d_effect *effect, UINT32 index)
+{
+    if (index < effect->custom_property_count)
+        return &effect->custom_properties[index];
+    else if (D2D1_PROPERTY_CLSID <= index && index <= D2D1_PROPERTY_MAX_INPUTS)
+        return &effect->system_properties[index - D2D1_PROPERTY_CLSID];
+    else
+        return NULL;
+}
+
 static HRESULT STDMETHODCALLTYPE d2d_effect_QueryInterface(ID2D1Effect *iface, REFIID iid, void **out)
 {
     struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
@@ -546,41 +607,34 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_GetValue(ID2D1Effect *iface, UINT32
         BYTE *value, UINT32 value_size)
 {
     struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
-    const void *src;
+    struct d2d_effect_property *property;
+    UINT32 actual_size;
 
     TRACE("iface %p, index %u, type %#x, value %p, value_size %u.\n", iface, index, type, value, value_size);
 
-    switch (index)
-    {
-        case D2D1_PROPERTY_CLSID:
-            if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_CLSID)
-                    || value_size != sizeof(*effect->info->clsid))
-                return E_INVALIDARG;
-            src = effect->info->clsid;
-            break;
-        case D2D1_PROPERTY_MIN_INPUTS:
-            if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_UINT32)
-                    || value_size != sizeof(effect->info->min_inputs))
-                return E_INVALIDARG;
-            src = &effect->info->min_inputs;
-            break;
-        case D2D1_PROPERTY_MAX_INPUTS:
-            if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != D2D1_PROPERTY_TYPE_UINT32)
-                    || value_size != sizeof(effect->info->max_inputs))
-                return E_INVALIDARG;
-            src = &effect->info->max_inputs;
-            break;
-        default:
-            if (index < D2D1_PROPERTY_CLSID)
-                FIXME("Custom properties are not supported.\n");
-            else if (index <= D2D1_PROPERTY_MAX_INPUTS)
-                FIXME("Standard property %#x is not supported.\n", index);
-            return D2DERR_INVALID_PROPERTY;
-    }
+    if (!(property = d2d_effect_get_property(effect, index)))
+        return D2DERR_INVALID_PROPERTY;
 
-    memcpy(value, src, value_size);
+    actual_size = d2d_effect_property_get_value_size(property);
+    if ((type != D2D1_PROPERTY_TYPE_UNKNOWN && type != property->type)
+            || (type != D2D1_PROPERTY_TYPE_STRING && value_size != actual_size)
+            || (type == D2D1_PROPERTY_TYPE_STRING && value_size < actual_size))
+        return E_INVALIDARG;
 
-    return S_OK;
+    if (property->get_function)
+    {
+        return property->get_function((IUnknown *)iface, value, value_size, NULL);
+    }
+    else if (property->value)
+    {
+        memcpy(value, property->value, actual_size);
+        return S_OK;
+    }
+    else
+    {
+        WARN("Unable to get property value.\n");
+        return D2DERR_INVALID_PROPERTY;
+    }
 }
 
 static UINT32 STDMETHODCALLTYPE d2d_effect_GetValueSize(ID2D1Effect *iface, UINT32 index)
@@ -614,12 +668,18 @@ static void STDMETHODCALLTYPE d2d_effect_SetInput(ID2D1Effect *iface, UINT32 ind
 
 static HRESULT STDMETHODCALLTYPE d2d_effect_SetInputCount(ID2D1Effect *iface, UINT32 count)
 {
+    struct d2d_effect_property *min_inputs_property, *max_inputs_property;
     struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
-    unsigned int i;
+    UINT32 min_inputs, max_inputs, i;
 
     TRACE("iface %p, count %u.\n", iface, count);
 
-    if (count < effect->info->min_inputs || count > effect->info->max_inputs)
+    min_inputs_property = d2d_effect_get_property(effect, D2D1_PROPERTY_MIN_INPUTS);
+    max_inputs_property = d2d_effect_get_property(effect, D2D1_PROPERTY_MAX_INPUTS);
+    min_inputs = *((UINT32 *)min_inputs_property->value);
+    max_inputs = *((UINT32 *)max_inputs_property->value);
+
+    if (count < min_inputs || count > max_inputs)
         return E_INVALIDARG;
     if (count == effect->input_count)
         return S_OK;
@@ -752,6 +812,7 @@ static const ID2D1ImageVtbl d2d_effect_image_vtbl =
 
 HRESULT d2d_effect_init(struct d2d_effect *effect, struct d2d_effect_context *effect_context, const CLSID *effect_id)
 {
+    struct d2d_effect_property *property;
     unsigned int i;
 
     effect->ID2D1Effect_iface.lpVtbl = &d2d_effect_vtbl;
@@ -762,10 +823,25 @@ HRESULT d2d_effect_init(struct d2d_effect *effect, struct d2d_effect_context *ef
     {
         if (IsEqualGUID(effect_id, builtin_effects[i].clsid))
         {
-            effect->info = &builtin_effects[i];
-            d2d_effect_SetInputCount(&effect->ID2D1Effect_iface, effect->info->default_input_count);
+            property = d2d_effect_get_property(effect, D2D1_PROPERTY_CLSID);
+            property->name  = wcsdup(L"ClSID");
+            property->type  = D2D1_PROPERTY_TYPE_CLSID;
+            property->value = memdup(effect_id, sizeof(*effect_id));
+
+            property = d2d_effect_get_property(effect, D2D1_PROPERTY_MIN_INPUTS);
+            property->name  = wcsdup(L"MinInputs");
+            property->type  = D2D1_PROPERTY_TYPE_UINT32;
+            property->value = memdup(&builtin_effects[i].min_inputs, sizeof(builtin_effects[i].min_inputs));
+
+            property = d2d_effect_get_property(effect, D2D1_PROPERTY_MAX_INPUTS);
+            property->name  = wcsdup(L"MaxInputs");
+            property->type  = D2D1_PROPERTY_TYPE_UINT32;
+            property->value = memdup(&builtin_effects[i].max_inputs, sizeof(builtin_effects[i].max_inputs));
+
+            d2d_effect_SetInputCount(&effect->ID2D1Effect_iface, builtin_effects[i].default_input_count);
             effect->effect_context = effect_context;
             ID2D1EffectContext_AddRef(&effect_context->ID2D1EffectContext_iface);
+
             return S_OK;
         }
     }
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 5c79d1791ff..36feaeb6f29 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -30,15 +30,6 @@ 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;
-- 
2.25.1




More information about the wine-devel mailing list