[v2 PATCH] d2d1: Implement retrieving dash pattern data for stroke styles

Nikolay Sivov nsivov at codeweavers.com
Thu Nov 24 05:29:37 CST 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

v2: fixed GetDashes() when requested dash count exceeds actual dash count

 dlls/d2d1/d2d1_private.h |  4 ++-
 dlls/d2d1/factory.c      |  8 ++++-
 dlls/d2d1/stroke.c       | 59 +++++++++++++++++++++++++++++----
 dlls/d2d1/tests/d2d1.c   | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 148 insertions(+), 8 deletions(-)

diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index bfe60ee..29823cc 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -224,9 +224,11 @@ struct d2d_stroke_style
 
     ID2D1Factory *factory;
     D2D1_STROKE_STYLE_PROPERTIES desc;
+    float *dashes;
+    UINT32 dash_count;
 };
 
-void d2d_stroke_style_init(struct d2d_stroke_style *style, ID2D1Factory *factory,
+HRESULT d2d_stroke_style_init(struct d2d_stroke_style *style, ID2D1Factory *factory,
         const D2D1_STROKE_STYLE_PROPERTIES *desc, const float *dashes, UINT32 dash_count) DECLSPEC_HIDDEN;
 
 struct d2d_mesh
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 6de0271..3bb240f 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -213,6 +213,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateStrokeStyle(ID2D1Factory *ifa
         ID2D1StrokeStyle **stroke_style)
 {
     struct d2d_stroke_style *object;
+    HRESULT hr;
 
     TRACE("iface %p, desc %p, dashes %p, dash_count %u, stroke_style %p.\n",
             iface, desc, dashes, dash_count, stroke_style);
@@ -220,7 +221,12 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateStrokeStyle(ID2D1Factory *ifa
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
 
-    d2d_stroke_style_init(object, iface, desc, dashes, dash_count);
+    if (FAILED(hr = d2d_stroke_style_init(object, iface, desc, dashes, dash_count)))
+    {
+        WARN("Failed to initialize stroke style, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
+    }
 
     TRACE("Created stroke style %p.\n", object);
     *stroke_style = &object->ID2D1StrokeStyle_iface;
diff --git a/dlls/d2d1/stroke.c b/dlls/d2d1/stroke.c
index 3b5dbfd..c5a1d50 100644
--- a/dlls/d2d1/stroke.c
+++ b/dlls/d2d1/stroke.c
@@ -67,6 +67,8 @@ static ULONG STDMETHODCALLTYPE d2d_stroke_style_Release(ID2D1StrokeStyle *iface)
     if (!refcount)
     {
         ID2D1Factory_Release(style->factory);
+        if (style->desc.dashStyle == D2D1_DASH_STYLE_CUSTOM)
+            HeapFree(GetProcessHeap(), 0, style->dashes);
         HeapFree(GetProcessHeap(), 0, style);
     }
 
@@ -147,14 +149,22 @@ static D2D1_DASH_STYLE STDMETHODCALLTYPE d2d_stroke_style_GetDashStyle(ID2D1Stro
 
 static UINT32 STDMETHODCALLTYPE d2d_stroke_style_GetDashesCount(ID2D1StrokeStyle *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d2d_stroke_style *style = impl_from_ID2D1StrokeStyle(iface);
+
+    TRACE("iface %p.\n", iface);
 
-    return 0;
+    return style->dash_count;
 }
 
-static void STDMETHODCALLTYPE d2d_stroke_style_GetDashes(ID2D1StrokeStyle *iface, float *dashes, UINT32 count)
+static void STDMETHODCALLTYPE d2d_stroke_style_GetDashes(ID2D1StrokeStyle *iface, float *dashes, UINT32 dash_count)
 {
-    FIXME("iface %p, dashes %p, count %u stub!\n", iface, dashes, count);
+    struct d2d_stroke_style *style = impl_from_ID2D1StrokeStyle(iface);
+
+    TRACE("iface %p, dashes %p, count %u.\n", iface, dashes, dash_count);
+
+    memcpy(dashes, style->dashes, min(style->dash_count, dash_count) * sizeof(*dashes));
+    if (dash_count > style->dash_count)
+        memset(dashes + style->dash_count, 0, (dash_count - style->dash_count) * sizeof(*dashes));
 }
 
 static const struct ID2D1StrokeStyleVtbl d2d_stroke_style_vtbl =
@@ -174,13 +184,50 @@ static const struct ID2D1StrokeStyleVtbl d2d_stroke_style_vtbl =
     d2d_stroke_style_GetDashes,
 };
 
-void d2d_stroke_style_init(struct d2d_stroke_style *style, ID2D1Factory *factory,
+HRESULT d2d_stroke_style_init(struct d2d_stroke_style *style, ID2D1Factory *factory,
         const D2D1_STROKE_STYLE_PROPERTIES *desc, const float *dashes, UINT32 dash_count)
 {
-    FIXME("Ignoring stroke style properties.\n");
+    static const struct
+    {
+        UINT32 dash_count;
+        float dashes[6];
+    }
+    builtin_dash_styles[] =
+    {
+        /* D2D1_DASH_STYLE_SOLID */        { 0 },
+        /* D2D1_DASH_STYLE_DASH */         { 2, {2.0f, 2.0f}},
+        /* D2D1_DASH_STYLE_DOT */          { 2, {0.0f, 2.0f}},
+        /* D2D1_DASH_STYLE_DASH_DOT */     { 4, {2.0f, 2.0f, 0.0f, 2.0f}},
+        /* D2D1_DASH_STYLE_DASH_DOT_DOT */ { 6, {2.0f, 2.0f, 0.0f, 2.0f, 0.0f, 2.0f}},
+    };
+
+    if (desc->dashStyle > D2D1_DASH_STYLE_CUSTOM)
+        return E_INVALIDARG;
 
     style->ID2D1StrokeStyle_iface.lpVtbl = &d2d_stroke_style_vtbl;
     style->refcount = 1;
+
+    if (desc->dashStyle == D2D1_DASH_STYLE_CUSTOM)
+    {
+        if (!dashes || !dash_count)
+            return E_INVALIDARG;
+
+        if (!(style->dashes = HeapAlloc(GetProcessHeap(), 0, dash_count * sizeof(*style->dashes))))
+            return E_OUTOFMEMORY;
+        memcpy(style->dashes, dashes, dash_count * sizeof(*style->dashes));
+        style->dash_count = dash_count;
+    }
+    else
+    {
+        if (dashes)
+            return E_INVALIDARG;
+
+        style->dashes = (float *)builtin_dash_styles[desc->dashStyle].dashes;
+        style->dash_count = builtin_dash_styles[desc->dashStyle].dash_count;
+    }
+
     ID2D1Factory_AddRef(style->factory = factory);
     style->desc = *desc;
+
+    return S_OK;
 }
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 857cba2..7fcda64 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -3335,6 +3335,20 @@ static void test_desktop_dpi(void)
 
 static void test_stroke_style(void)
 {
+    static const struct
+    {
+        D2D1_DASH_STYLE dash_style;
+        UINT32 dash_count;
+        float dashes[6];
+    }
+    dash_style_tests[] =
+    {
+        {D2D1_DASH_STYLE_SOLID,        0},
+        {D2D1_DASH_STYLE_DASH,         2, {2.0f, 2.0f}},
+        {D2D1_DASH_STYLE_DOT,          2, {0.0f, 2.0f}},
+        {D2D1_DASH_STYLE_DASH_DOT,     4, {2.0f, 2.0f, 0.0f, 2.0f}},
+        {D2D1_DASH_STYLE_DASH_DOT_DOT, 6, {2.0f, 2.0f, 0.0f, 2.0f, 0.0f, 2.0f}},
+    };
     D2D1_STROKE_STYLE_PROPERTIES desc;
     ID2D1StrokeStyle *style;
     ID2D1Factory *factory;
@@ -3344,6 +3358,8 @@ static void test_stroke_style(void)
     D2D1_LINE_JOIN line_join;
     float miter_limit, dash_offset;
     D2D1_DASH_STYLE dash_style;
+    unsigned int i;
+    float dashes[2];
 
     hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory);
     ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr);
@@ -3374,9 +3390,78 @@ static void test_stroke_style(void)
     dash_offset = ID2D1StrokeStyle_GetDashOffset(style);
     ok(dash_offset == -1.0f, "Unexpected dash offset %f.\n", dash_offset);
 
+    /* Custom dash pattern, no dashes data specified. */
+    desc.startCap = D2D1_CAP_STYLE_SQUARE;
+    desc.endCap = D2D1_CAP_STYLE_ROUND;
+    desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
+    desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
+    desc.miterLimit = 1.5f;
+    desc.dashStyle = D2D1_DASH_STYLE_CUSTOM;
+    desc.dashOffset = 0.0f;
+
+    hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
+    ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
+
+    hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 0, &style);
+    ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
 
+    hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
+    ok(hr == S_OK, "Unexpected return value, %#x.\n", hr);
     ID2D1StrokeStyle_Release(style);
 
+    /* Builtin style, dashes are specified. */
+    desc.dashStyle = D2D1_DASH_STYLE_DOT;
+    hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, dashes, 1, &style);
+    ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
+
+    /* Invalid style. */
+    desc.dashStyle = 100;
+    hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
+    ok(hr == E_INVALIDARG, "Unexpected return value, %#x.\n", hr);
+
+    /* Test returned dash pattern for builtin styles. */
+    desc.startCap = D2D1_CAP_STYLE_SQUARE;
+    desc.endCap = D2D1_CAP_STYLE_ROUND;
+    desc.dashCap = D2D1_CAP_STYLE_TRIANGLE;
+    desc.lineJoin = D2D1_LINE_JOIN_BEVEL;
+    desc.miterLimit = 1.5f;
+    desc.dashOffset = 0.0f;
+
+    for (i = 0; i < sizeof(dash_style_tests)/sizeof(dash_style_tests[0]); i++)
+    {
+        float dashes[10];
+        UINT dash_count;
+
+        desc.dashStyle = dash_style_tests[i].dash_style;
+
+        hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 0, &style);
+        ok(SUCCEEDED(hr), "Failed to create stroke style, %#x.\n", hr);
+
+        dash_count = ID2D1StrokeStyle_GetDashesCount(style);
+        ok(dash_count == dash_style_tests[i].dash_count, "%u: unexpected dash count %u, expected %u.\n",
+                i, dash_count, dash_style_tests[i].dash_count);
+        ok(dash_count < sizeof(dashes)/sizeof(dashes[0]), "%u: unexpectedly large dash count %u.\n", i, dash_count);
+        if (dash_count == dash_style_tests[i].dash_count)
+        {
+            unsigned int j;
+
+            ID2D1StrokeStyle_GetDashes(style, dashes, dash_count);
+            ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
+                    "%u: unexpected dash array.\n", i);
+
+            /* Ask for more dashes than style actually has. */
+            memset(dashes, 0xcc, sizeof(dashes));
+            ID2D1StrokeStyle_GetDashes(style, dashes, sizeof(dashes)/sizeof(dashes[0]));
+            ok(!memcmp(dashes, dash_style_tests[i].dashes, sizeof(*dashes) * dash_count),
+                    "%u: unexpected dash array.\n", i);
+
+            for (j = dash_count; j < sizeof(dashes)/sizeof(dashes[0]); j++)
+                ok(dashes[j] == 0.0f, "%u: unexpected dash value at %u.\n", i, j);
+        }
+
+        ID2D1StrokeStyle_Release(style);
+    }
+
     /* NULL dashes array, non-zero length. */
     memset(&desc, 0, sizeof(desc));
     hr = ID2D1Factory_CreateStrokeStyle(factory, &desc, NULL, 1, &style);
-- 
2.10.2




More information about the wine-patches mailing list