>From 15d7e1b157391736170995f6a1f89bb7e702b0c5 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          |  119 ++++++++++++++++++++++++++++++++--
 4 files changed, 132 insertions(+), 9 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..f59e7af 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -1321,6 +1321,51 @@ static const unsigned char EMF_DCBRUSH_BITS[] =
     0x14, 0x00, 0x00, 0x00
 };
 
+static const unsigned char EMF_BEZIER_BITS[] =
+{
+    0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
+    0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
+    0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+    0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
+    0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
+    0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+    0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+    0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
+    0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
+    0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+    0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+    0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+    0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
+    0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
+    0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+    0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+    0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
+    0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
+    0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+    0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+    0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+    0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+    0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+    0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
+    0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+    0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
+    0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+    0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+    0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+    0x14, 0x00, 0x00, 0x00
+};
+
 /* For debugging or dumping the raw metafiles produced by
  * new test functions.
  */
@@ -1588,6 +1633,28 @@ static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr
             HeapFree(GetProcessHeap(), 0, emr_nt4);
         }
     }
+    else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
+    {
+        EMRPOLYBEZIER16 *eto1, *eto2;
+        
+        eto1 = (EMRPOLYBEZIER16*)emr1;
+        eto2 = (EMRPOLYBEZIER16*)emr2;
+        
+        diff = eto1->cpts != eto1->cpts;
+        if(!diff)
+            diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
+    }
+    else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
+    {
+        EMRPOLYBEZIER *eto1, *eto2;
+        
+        eto1 = (EMRPOLYBEZIER*)emr1;
+        eto2 = (EMRPOLYBEZIER*)emr2;
+        
+        diff = eto1->cptl != eto1->cptl;
+        if(!diff)
+            diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
+    }
     else
         diff = memcmp(emr1, emr2, emr1->nSize);
 
@@ -1658,17 +1725,17 @@ static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
     offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
     while (offset1 < emh1->nBytes)
     {
-	const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
-	const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
+        const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
+        const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
 
-	trace("%s: EMF record %u, size %u/record %u, size %u\n",
+        trace("%s: EMF record %u, size %u/record %u, size %u\n",
               desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
 
         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
 
         /* We have already bailed out if iType or nSize don't match */
-	offset1 += emr1->nSize;
-	offset2 += emr2->nSize;
+        offset1 += emr1->nSize;
+        offset2 += emr2->nSize;
     }
     return 0;
 }
@@ -2250,7 +2317,7 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
 {
     if (emr->iType == EMR_EXTSELECTCLIPRGN)
     {
-	const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
+        const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
         union _rgn
         {
             RGNDATA data;
@@ -3089,6 +3156,45 @@ static void test_SetEnhMetaFileBits(void)
     DeleteEnhMetaFile(hemf);
 }
 
+static void test_emf_polybezier(void)
+{
+    HDC hdcMetafile;
+    HENHMETAFILE hemf;
+    POINT pts[4];
+    BOOL ret;
+
+    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;
+    ret = PolyBezierTo(hdcMetafile, pts, 3);  /* EMR_POLYBEZIERTO16 */
+    ok( ret, "PolyBezierTo failed\n" );
+    ret = PolyBezier(hdcMetafile, pts, 4);    /* EMR_POLYBEZIER16   */
+    ok( ret, "PolyBezier failed\n" );
+
+    pts[0].x = pts[0].y = 32769;
+    ret = PolyBezier(hdcMetafile, pts, 4);    /* EMR_POLYBEZIER   */
+    ok( ret, "PolyBezier failed\n" );
+    ret = PolyBezierTo(hdcMetafile, pts, 3);  /* EMR_POLYBEZIERTO */
+    ok( ret, "PolyBezierTo failed\n" );
+
+    hemf = CloseEnhMetaFile(hdcMetafile);
+    ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
+
+    if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
+        "emf_Bezier", FALSE) != 0)
+    {
+        dump_emf_bits(hemf, "emf_Bezier");
+        dump_emf_records(hemf, "emf_Bezier");
+    }
+
+    DeleteEnhMetaFile(hemf);
+}
+
 START_TEST(metafile)
 {
     init_function_pointers();
@@ -3111,6 +3217,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

