>From 555a6ab28fdbdd35ec4cec4c312ea963ffd757de Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Tue, 17 Jan 2012 14:38:15 +1100
Subject: [PATCH] Add EnhMetafile PolyBezier,PolyBezierTo support
To: wine-patches <wine-patches@winehq.org>

---
 dlls/gdi32/enhmfdrv/enhmetafiledrv.h |    3 +-
 dlls/gdi32/enhmfdrv/graphics.c       |   15 ++++
 dlls/gdi32/enhmfdrv/init.c           |    4 +-
 dlls/gdi32/tests/metafile.c          |  145 +++++++++++++++++++++++++++++++++-
 4 files changed, 163 insertions(+), 4 deletions(-)

diff --git a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
index a1cead5..5ead69a 100644
--- a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
+++ b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
@@ -94,6 +94,8 @@ extern BOOL     EMFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN;
 extern BOOL     EMFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) DECLSPEC_HIDDEN;
 extern BOOL     EMFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
                             INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN;
+extern BOOL     EMFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count );
+extern BOOL     EMFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count );
 extern BOOL     EMFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys) DECLSPEC_HIDDEN;
 extern BOOL     EMFDRV_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWORD polys) DECLSPEC_HIDDEN;
 extern BOOL     EMFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count ) DECLSPEC_HIDDEN;
@@ -145,5 +147,4 @@ extern BOOL     EMFDRV_StrokeAndFillPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
 extern BOOL     EMFDRV_StrokePath( PHYSDEV dev ) DECLSPEC_HIDDEN;
 extern BOOL     EMFDRV_WidenPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
 
-
 #endif  /* __WINE_METAFILEDRV_H */
diff --git a/dlls/gdi32/enhmfdrv/graphics.c b/dlls/gdi32/enhmfdrv/graphics.c
index 71fd118..299ec4f 100644
--- a/dlls/gdi32/enhmfdrv/graphics.c
+++ b/dlls/gdi32/enhmfdrv/graphics.c
@@ -795,3 +795,18 @@ no_bounds:
     HeapFree( GetProcessHeap(), 0, pemr );
     return ret;
 }
+
+BOOL EMFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count )
+{
+    if(EMFDRV_Polylinegon16( dev, pts, count, EMR_POLYBEZIER16 ))
+        return TRUE;
+    return EMFDRV_Polylinegon( dev, pts, count, EMR_POLYBEZIER );
+}
+
+
+BOOL EMFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count )
+{
+    if(EMFDRV_Polylinegon16( dev, pts, count, EMR_POLYBEZIERTO16 ))
+        return TRUE;
+    return EMFDRV_Polylinegon( dev, pts, count, EMR_POLYBEZIERTO );
+}
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index f988ebd..d254cba 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -109,8 +109,8 @@ static const struct gdi_dc_funcs EMFDRV_Funcs =
     EMFDRV_PaintRgn,                 /* pPaintRgn */
     EMFDRV_PatBlt,                   /* pPatBlt */
     EMFDRV_Pie,                      /* pPie */
-    NULL,                            /* pPolyBezier */
-    NULL,                            /* pPolyBezierTo */
+    EMFDRV_PolyBezier,               /* pPolyBezier */
+    EMFDRV_PolyBezierTo,             /* pPolyBezierTo */
     NULL,                            /* pPolyDraw */
     EMFDRV_PolyPolygon,              /* pPolyPolygon */
     EMFDRV_PolyPolyline,             /* pPolyPolyline */
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index 206e15a..e9e28df 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -2245,12 +2245,105 @@ static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
            abs(rc1->bottom - rc2->bottom) <= 1;
 }
 
+static BOOL PolyBezier16Called = FALSE;
+static BOOL PolyBezierCalled = FALSE;
+static BOOL PolyBezierTo16Called = FALSE;
+static BOOL PolyBezierToCalled = FALSE;
+static int CALLBACK poly_bezier_enum_proc(HDC hdc, HANDLETABLE *handle_table,
+                                       const ENHMETARECORD *emr, int n_objs, LPARAM param)
+{
+    if (emr->iType == EMR_POLYBEZIER16)
+    {
+        const EMRPOLYBEZIER16 *bezier = (const EMRPOLYBEZIER16 *)emr;
+
+        PolyBezier16Called = TRUE;
+
+        ok(bezier->cpts == 4, "expected 3 got %d\n", bezier->cpts);
+        if(bezier->cpts == 4)
+        {
+            ok(bezier->apts[0].x == 10, "expected 10 got %d\n", bezier->apts[0].x);
+            ok(bezier->apts[0].y == 10, "expected 10 got %d\n", bezier->apts[0].y);
+
+            ok(bezier->apts[1].x == 20, "expected 20 got %d\n", bezier->apts[1].x);
+            ok(bezier->apts[1].y == 20, "expected 20 got %d\n", bezier->apts[1].y);
+
+            ok(bezier->apts[2].x == 15, "expected 15 got %d\n", bezier->apts[2].x);
+            ok(bezier->apts[2].y == 15, "expected 15 got %d\n", bezier->apts[2].y);
+
+            ok(bezier->apts[3].x == 25, "expected 25 got %d\n", bezier->apts[3].x);
+            ok(bezier->apts[3].y == 25, "expected 25 got %d\n", bezier->apts[3].y);
+        }
+    }
+    else if (emr->iType == EMR_POLYBEZIER)
+    {
+        const EMRPOLYBEZIER *bezier = (const EMRPOLYBEZIER *)emr;
+
+        PolyBezierCalled = TRUE;
+
+        ok(bezier->cptl == 4, "expected 3 got %d\n", bezier->cptl);
+        if(bezier->cptl == 4)
+        {
+            ok(bezier->aptl[0].x == 32769, "expected 32769 got %d\n", bezier->aptl[0].x);
+            ok(bezier->aptl[0].y == 32769, "expected 32769 got %d\n", bezier->aptl[0].y);
+
+            ok(bezier->aptl[1].x == 20, "expected 20 got %d\n", bezier->aptl[1].x);
+            ok(bezier->aptl[1].y == 20, "expected 20 got %d\n", bezier->aptl[1].y);
+
+            ok(bezier->aptl[2].x == 15, "expected 15 got %d\n", bezier->aptl[2].x);
+            ok(bezier->aptl[2].y == 15, "expected 15 got %d\n", bezier->aptl[2].y);
+
+            ok(bezier->aptl[3].x == 25, "expected 25 got %d\n", bezier->aptl[3].x);
+            ok(bezier->aptl[3].y == 25, "expected 25 got %d\n", bezier->aptl[3].y);
+        }
+    }
+    else if (emr->iType == EMR_POLYBEZIERTO16)
+    {
+        const EMRPOLYBEZIERTO16 *bezier = (const EMRPOLYBEZIERTO16 *)emr;
+
+        PolyBezierTo16Called = TRUE;
+
+        ok(bezier->cpts == 3, "expected 3 got %d\n", bezier->cpts);
+        if(bezier->cpts == 3)
+        {
+            ok(bezier->apts[0].x == 10, "expected 10 got %d\n", bezier->apts[0].x);
+            ok(bezier->apts[0].y == 10, "expected 10 got %d\n", bezier->apts[0].y);
+
+            ok(bezier->apts[1].x == 20, "expected 20 got %d\n", bezier->apts[1].x);
+            ok(bezier->apts[1].y == 20, "expected 20 got %d\n", bezier->apts[1].y);
+
+            ok(bezier->apts[2].x == 15, "expected 15 got %d\n", bezier->apts[2].x);
+            ok(bezier->apts[2].y == 15, "expected 15 got %d\n", bezier->apts[2].y);
+        }
+    }
+    else if (emr->iType == EMR_POLYBEZIERTO)
+    {
+        const EMRPOLYBEZIERTO *bezier = (const EMRPOLYBEZIERTO *)emr;
+
+        PolyBezierToCalled = TRUE;
+
+        ok(bezier->cptl == 3, "expected 3 got %d\n", bezier->cptl);
+        if(bezier->cptl == 3)
+        {
+            ok(bezier->aptl[0].x == 32769, "expected 32769 got %d\n", bezier->aptl[0].x);
+            ok(bezier->aptl[0].y == 32769, "expected 32769 got %d\n", bezier->aptl[0].y);
+
+            ok(bezier->aptl[1].x == 20, "expected 20 got %d\n", bezier->aptl[1].x);
+            ok(bezier->aptl[1].y == 20, "expected 20 got %d\n", bezier->aptl[1].y);
+
+            ok(bezier->aptl[2].x == 15, "expected 15 got %d\n", bezier->aptl[2].x);
+            ok(bezier->aptl[2].y == 15, "expected 15 got %d\n", bezier->aptl[2].y);
+        }
+    }
+
+    return 1;
+}
+
 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
 {
     if (emr->iType == EMR_EXTSELECTCLIPRGN)
     {
-	const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
+        const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
         union _rgn
         {
             RGNDATA data;
@@ -3089,6 +3182,55 @@ static void test_SetEnhMetaFileBits(void)
     DeleteEnhMetaFile(hemf);
 }
 
+static void test_emf_polybezier(void)
+{
+    HDC hdc, hdcMetafile;
+    HWND hwnd;
+    HENHMETAFILE hemf;
+    INT ret;
+    POINT pts[4];
+    static const RECT rc = { 0, 0, 100, 100 };
+
+    SetLastError(0xdeadbeef);
+    hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
+    ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
+
+    pts[0].x = pts[0].y = 10;
+    pts[1].x = pts[1].y = 20;
+    pts[2].x = pts[2].y = 15;
+    pts[3].x = pts[3].y = 25;
+    PolyBezier(hdcMetafile, pts, 4);    /* EMR_POLYBEZIER16   */
+    PolyBezierTo(hdcMetafile, pts, 3);  /* EMR_POLYBEZIERTO16 */
+
+    pts[0].x = pts[0].y = 32769;
+    pts[1].x = pts[1].y = 20;
+    pts[2].x = pts[2].y = 15;
+    pts[3].x = pts[3].y = 25;
+    PolyBezier(hdcMetafile, pts, 4);    /* EMR_POLYBEZIER   */
+    PolyBezierTo(hdcMetafile, pts, 3);  /* EMR_POLYBEZIERTO */
+
+    hemf = CloseEnhMetaFile(hdcMetafile);
+    ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
+
+    hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
+                           0, 0, 200, 200, 0, 0, 0, NULL);
+    ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
+
+    hdc = GetDC(hwnd);
+
+    ret = EnumEnhMetaFile(hdc, hemf, poly_bezier_enum_proc, NULL, &rc);
+    ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
+
+    ok(PolyBezier16Called,   "PolyBezier16 not called\n");
+    ok(PolyBezierCalled,     "PolyBezier not called\n");
+    ok(PolyBezierTo16Called, "PolyBezierTo16 not called\n");
+    ok(PolyBezierToCalled,   "PolyBezierTo not called\n");
+
+    DeleteEnhMetaFile(hemf);
+    ReleaseDC(hwnd, hdc);
+    DestroyWindow(hwnd);
+}
+
 START_TEST(metafile)
 {
     init_function_pointers();
@@ -3111,6 +3253,7 @@ START_TEST(metafile)
     test_mf_ExtTextOut_on_path();
     test_emf_ExtTextOut_on_path();
     test_emf_clipping();
+    test_emf_polybezier();
 
     /* For metafile conversions */
     test_mf_conversions();
-- 
1.7.5.4

