From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/d2d1_private.h | 1 + dlls/d2d1/effect.c | 111 ++++++++++++++++++++++++++++++++++++++- dlls/d2d1/tests/d2d1.c | 72 +++++++++++++++++++++++++ 3 files changed, 182 insertions(+), 2 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 46c486ab58a..6b6d51d4b3c 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -722,6 +722,7 @@ struct d2d_transform D2D1_EXTEND_MODE mode_x; D2D1_EXTEND_MODE mode_y; } border; + D2D1_RECT_L bounds; };
UINT32 input_count; diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c index 364539f87bf..42d2c589edc 100644 --- a/dlls/d2d1/effect.c +++ b/dlls/d2d1/effect.c @@ -35,6 +35,12 @@ static inline struct d2d_transform *impl_from_ID2D1BorderTransform(ID2D1BorderTr return CONTAINING_RECORD(iface, struct d2d_transform, ID2D1TransformNode_iface); }
+static inline struct d2d_transform *impl_from_ID2D1BoundsAdjustmentTransform( + ID2D1BoundsAdjustmentTransform *iface) +{ + return CONTAINING_RECORD(iface, struct d2d_transform, ID2D1TransformNode_iface); +} + static HRESULT STDMETHODCALLTYPE d2d_offset_transform_QueryInterface(ID2D1OffsetTransform *iface, REFIID iid, void **out) { @@ -408,6 +414,107 @@ static HRESULT d2d_border_transform_create(D2D1_EXTEND_MODE mode_x, D2D1_EXTEND_ return S_OK; }
+static HRESULT STDMETHODCALLTYPE d2d_bounds_adjustment_transform_QueryInterface( + ID2D1BoundsAdjustmentTransform *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_ID2D1BoundsAdjustmentTransform) + || IsEqualGUID(iid, &IID_ID2D1TransformNode) + || IsEqualGUID(iid, &IID_IUnknown)) + { + *out = iface; + ID2D1BoundsAdjustmentTransform_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE d2d_bounds_adjustment_transform_AddRef( + ID2D1BoundsAdjustmentTransform *iface) +{ + struct d2d_transform *transform = impl_from_ID2D1BoundsAdjustmentTransform(iface); + ULONG refcount = InterlockedIncrement(&transform->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE d2d_bounds_adjustment_transform_Release( + ID2D1BoundsAdjustmentTransform *iface) +{ + struct d2d_transform *transform = impl_from_ID2D1BoundsAdjustmentTransform(iface); + ULONG refcount = InterlockedDecrement(&transform->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + free(transform); + + return refcount; +} + +static UINT32 STDMETHODCALLTYPE d2d_bounds_adjustment_transform_GetInputCount( + ID2D1BoundsAdjustmentTransform *iface) +{ + TRACE("iface %p.\n", iface); + + return 1; +} + +static void STDMETHODCALLTYPE d2d_bounds_adjustment_transform_SetOutputBounds( + ID2D1BoundsAdjustmentTransform *iface, const D2D1_RECT_L *bounds) +{ + struct d2d_transform *transform = impl_from_ID2D1BoundsAdjustmentTransform(iface); + + TRACE("iface %p.\n", iface); + + transform->bounds = *bounds; +} + +static void STDMETHODCALLTYPE d2d_bounds_adjustment_transform_GetOutputBounds( + ID2D1BoundsAdjustmentTransform *iface, D2D1_RECT_L *bounds) +{ + struct d2d_transform *transform = impl_from_ID2D1BoundsAdjustmentTransform(iface); + + TRACE("iface %p.\n", iface); + + *bounds = transform->bounds; +} + +static const ID2D1BoundsAdjustmentTransformVtbl d2d_bounds_adjustment_transform_vtbl = +{ + d2d_bounds_adjustment_transform_QueryInterface, + d2d_bounds_adjustment_transform_AddRef, + d2d_bounds_adjustment_transform_Release, + d2d_bounds_adjustment_transform_GetInputCount, + d2d_bounds_adjustment_transform_SetOutputBounds, + d2d_bounds_adjustment_transform_GetOutputBounds, +}; + +static HRESULT d2d_bounds_adjustment_transform_create(const D2D1_RECT_L *rect, + ID2D1BoundsAdjustmentTransform **transform) +{ + struct d2d_transform *object; + + *transform = NULL; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + object->ID2D1TransformNode_iface.lpVtbl = (ID2D1TransformNodeVtbl *)&d2d_bounds_adjustment_transform_vtbl; + object->refcount = 1; + object->bounds = *rect; + + *transform = (ID2D1BoundsAdjustmentTransform *)&object->ID2D1TransformNode_iface; + + return S_OK; +} + static struct d2d_transform_node * d2d_transform_graph_get_node(const struct d2d_transform_graph *graph, ID2D1TransformNode *object) { @@ -1334,9 +1441,9 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_CreateOffsetTransform(ID2D1E static HRESULT STDMETHODCALLTYPE d2d_effect_context_CreateBoundsAdjustmentTransform(ID2D1EffectContext *iface, const D2D1_RECT_L *output_rect, ID2D1BoundsAdjustmentTransform **transform) { - FIXME("iface %p, output_rect %s, transform %p stub!\n", iface, debug_d2d_rect_l(output_rect), transform); + TRACE("iface %p, output_rect %s, transform %p.\n", iface, debug_d2d_rect_l(output_rect), transform);
- return E_NOTIMPL; + return d2d_bounds_adjustment_transform_create(output_rect, transform); }
static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadPixelShader(ID2D1EffectContext *iface, diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 96bea3fa4de..a26b6ca9a93 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -497,6 +497,14 @@ static void set_rect_u(D2D1_RECT_U *rect, UINT32 left, UINT32 top, UINT32 right, rect->bottom = bottom; }
+static void set_rect_l(D2D1_RECT_L *rect, LONG left, LONG top, LONG right, LONG bottom) +{ + rect->left = left; + rect->top = top; + rect->right = right; + rect->bottom = bottom; +} + static void set_ellipse(D2D1_ELLIPSE *ellipse, float x, float y, float rx, float ry) { set_point(&ellipse->point, x, y); @@ -13103,6 +13111,69 @@ static void test_border_transform(BOOL d3d11) release_test_context(&ctx); }
+static void test_bounds_adjustment_transform(BOOL d3d11) +{ + ID2D1BoundsAdjustmentTransform *transform = NULL; + ID2D1EffectContext *effect_context; + D2D1_PROPERTY_BINDING binding; + struct d2d1_test_context ctx; + ID2D1Factory1 *factory; + ID2D1Effect *effect; + UINT input_count; + D2D1_RECT_L rect; + HRESULT hr; + + if (!init_test_context(&ctx, d3d11)) + return; + + factory = ctx.factory1; + if (!factory) + { + win_skip("ID2D1Factory1 is not supported.\n"); + release_test_context(&ctx); + return; + } + + binding.propertyName = L"Context"; + binding.setFunction = NULL; + binding.getFunction = effect_impl_get_context; + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, + effect_xml_b, &binding, 1, effect_impl_create); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1DeviceContext_CreateEffect(ctx.context, &CLSID_TestEffect, &effect); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1Effect_GetValueByName(effect, L"Context", + D2D1_PROPERTY_TYPE_IUNKNOWN, (BYTE *)&effect_context, sizeof(effect_context)); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + set_rect_l(&rect, -1, 0, 25, -50); + hr = ID2D1EffectContext_CreateBoundsAdjustmentTransform(effect_context, &rect, &transform); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + memset(&rect, 0, sizeof(rect)); + ID2D1BoundsAdjustmentTransform_GetOutputBounds(transform, &rect); + ok(rect.left == -1 && rect.top == 0 && rect.right == 25 && rect.bottom == -50, + "Unexpected rectangle.\n"); + + set_rect_l(&rect, -50, 25, 0, -1); + ID2D1BoundsAdjustmentTransform_SetOutputBounds(transform, &rect); + memset(&rect, 0, sizeof(rect)); + ID2D1BoundsAdjustmentTransform_GetOutputBounds(transform, &rect); + ok(rect.left == -50 && rect.top == 25 && rect.right == 0 && rect.bottom == -1, + "Unexpected rectangle.\n"); + + /* Input count */ + input_count = ID2D1BoundsAdjustmentTransform_GetInputCount(transform); + ok(input_count == 1, "Got unexpected input count %u.\n", input_count); + + ID2D1BoundsAdjustmentTransform_Release(transform); + ID2D1Effect_Release(effect); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + release_test_context(&ctx); +} + static void test_stroke_contains_point(BOOL d3d11) { ID2D1TransformedGeometry *transformed_geometry; @@ -14640,6 +14711,7 @@ START_TEST(d2d1) queue_test(test_offset_transform); queue_test(test_blend_transform); queue_test(test_border_transform); + queue_test(test_bounds_adjustment_transform); queue_d3d10_test(test_stroke_contains_point); queue_test(test_image_bounds); queue_test(test_bitmap_map);