Andrew Eikum : gdiplus: Implement GdipBeginContainer2 and GdipEndContainer.

Alexandre Julliard julliard at winehq.org
Tue Jul 7 08:08:21 CDT 2009


Module: wine
Branch: master
Commit: 632aef3d8b3bc4baa0d673980552df288550c72c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=632aef3d8b3bc4baa0d673980552df288550c72c

Author: Andrew Eikum <andrew at brightnightgames.com>
Date:   Sun Jul  5 17:04:20 2009 -0500

gdiplus: Implement GdipBeginContainer2 and GdipEndContainer.

---

 dlls/gdiplus/gdiplus_private.h |    3 +
 dlls/gdiplus/graphics.c        |  153 ++++++++++++++++++++++++++++++++++++++--
 include/gdiplusflat.h          |    1 +
 3 files changed, 151 insertions(+), 6 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 95133ca..be881c7 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -29,6 +29,7 @@
 
 #include "objbase.h"
 #include "ocidl.h"
+#include "wine/list.h"
 
 #include "gdiplus.h"
 
@@ -109,6 +110,8 @@ struct GpGraphics{
     BOOL busy;      /* hdc handle obtained by GdipGetDC */
     GpRegion *clip;
     UINT textcontrast; /* not used yet. get/set only */
+    struct list containers;
+    GraphicsContainer contid; /* last-issued container ID */
 };
 
 struct GpBrush{
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 3525743..b81a984 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -38,6 +38,7 @@
 #include "gdiplus.h"
 #include "gdiplus_private.h"
 #include "wine/debug.h"
+#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
 
@@ -941,6 +942,104 @@ GpStatus trace_path(GpGraphics *graphics, GpPath *path)
     return result;
 }
 
+typedef struct _GraphicsContainerItem {
+    struct list entry;
+    GraphicsContainer contid;
+
+    SmoothingMode smoothing;
+    CompositingQuality compqual;
+    InterpolationMode interpolation;
+    CompositingMode compmode;
+    TextRenderingHint texthint;
+    REAL scale;
+    GpUnit unit;
+    PixelOffsetMode pixeloffset;
+    UINT textcontrast;
+    GpMatrix* worldtrans;
+    GpRegion* clip;
+} GraphicsContainerItem;
+
+static GpStatus init_container(GraphicsContainerItem** container,
+        GDIPCONST GpGraphics* graphics){
+    GpStatus sts;
+
+    *container = GdipAlloc(sizeof(GraphicsContainerItem));
+    if(!(*container))
+        return OutOfMemory;
+
+    (*container)->contid = graphics->contid + 1;
+
+    (*container)->smoothing = graphics->smoothing;
+    (*container)->compqual = graphics->compqual;
+    (*container)->interpolation = graphics->interpolation;
+    (*container)->compmode = graphics->compmode;
+    (*container)->texthint = graphics->texthint;
+    (*container)->scale = graphics->scale;
+    (*container)->unit = graphics->unit;
+    (*container)->textcontrast = graphics->textcontrast;
+    (*container)->pixeloffset = graphics->pixeloffset;
+
+    sts = GdipCloneMatrix(graphics->worldtrans, &(*container)->worldtrans);
+    if(sts != Ok){
+        GdipFree(*container);
+        *container = NULL;
+        return sts;
+    }
+
+    sts = GdipCloneRegion(graphics->clip, &(*container)->clip);
+    if(sts != Ok){
+        GdipDeleteMatrix((*container)->worldtrans);
+        GdipFree(*container);
+        *container = NULL;
+        return sts;
+    }
+
+    return Ok;
+}
+
+static void delete_container(GraphicsContainerItem* container){
+    GdipDeleteMatrix(container->worldtrans);
+    GdipDeleteRegion(container->clip);
+    GdipFree(container);
+}
+
+static GpStatus restore_container(GpGraphics* graphics,
+        GDIPCONST GraphicsContainerItem* container){
+    GpStatus sts;
+    GpMatrix *newTrans;
+    GpRegion *newClip;
+
+    sts = GdipCloneMatrix(container->worldtrans, &newTrans);
+    if(sts != Ok)
+        return sts;
+
+    sts = GdipCloneRegion(container->clip, &newClip);
+    if(sts != Ok){
+        GdipDeleteMatrix(newTrans);
+        return sts;
+    }
+
+    GdipDeleteMatrix(graphics->worldtrans);
+    graphics->worldtrans = newTrans;
+
+    GdipDeleteRegion(graphics->clip);
+    graphics->clip = newClip;
+
+    graphics->contid = container->contid - 1;
+
+    graphics->smoothing = container->smoothing;
+    graphics->compqual = container->compqual;
+    graphics->interpolation = container->interpolation;
+    graphics->compmode = container->compmode;
+    graphics->texthint = container->texthint;
+    graphics->scale = container->scale;
+    graphics->unit = container->unit;
+    graphics->textcontrast = container->textcontrast;
+    graphics->pixeloffset = container->pixeloffset;
+
+    return Ok;
+}
+
 GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
 {
     TRACE("(%p, %p)\n", hdc, graphics);
@@ -991,6 +1090,8 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra
     (*graphics)->scale = 1.0;
     (*graphics)->busy = FALSE;
     (*graphics)->textcontrast = 4;
+    list_init(&(*graphics)->containers);
+    (*graphics)->contid = 0;
 
     return Ok;
 }
@@ -1155,6 +1256,7 @@ GpStatus WINGDIPAPI GdipCreateStreamOnFile(GDIPCONST WCHAR * filename,
 
 GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
 {
+    GraphicsContainerItem *cont, *next;
     TRACE("(%p)\n", graphics);
 
     if(!graphics) return InvalidParameter;
@@ -1163,6 +1265,11 @@ GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
     if(graphics->owndc)
         ReleaseDC(graphics->hwnd, graphics->hdc);
 
+    LIST_FOR_EACH_ENTRY_SAFE(cont, next, &graphics->containers, GraphicsContainerItem, entry){
+        list_remove(&cont->entry);
+        delete_container(cont);
+    }
+
     GdipDeleteRegion(graphics->clip);
     GdipDeleteMatrix(graphics->worldtrans);
     GdipFree(graphics);
@@ -3254,14 +3361,24 @@ GpStatus WINGDIPAPI GdipSaveGraphics(GpGraphics *graphics, GraphicsState *state)
     return Ok;
 }
 
-GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics, GraphicsContainer *state)
+GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics,
+        GraphicsContainer *state)
 {
-    FIXME("(%p, %p)\n", graphics, state);
+    GraphicsContainerItem *container;
+    GpStatus sts;
+
+    TRACE("(%p, %p)\n", graphics, state);
 
     if(!graphics || !state)
         return InvalidParameter;
 
-    *state = 0xdeadbeef;
+    sts = init_container(&container, graphics);
+    if(sts != Ok)
+        return sts;
+
+    list_add_head(&graphics->containers, &container->entry);
+    *state = graphics->contid = container->contid;
+
     return Ok;
 }
 
@@ -3285,12 +3402,36 @@ GpStatus WINGDIPAPI GdipComment(GpGraphics *graphics, UINT sizeData, GDIPCONST B
 
 GpStatus WINGDIPAPI GdipEndContainer(GpGraphics *graphics, GraphicsState state)
 {
-    FIXME("(%p, 0x%x)\n", graphics, state);
+    GpStatus sts;
+    GraphicsContainerItem *container, *container2;
 
-    if(!graphics || !state)
+    TRACE("(%p, %x)\n", graphics, state);
+
+    if(!graphics)
         return InvalidParameter;
 
-    return Ok;
+    LIST_FOR_EACH_ENTRY(container, &graphics->containers, GraphicsContainerItem, entry){
+        if(container->contid == state)
+            break;
+    }
+
+    /* did not find a matching container */
+    if(&container->entry == &graphics->containers)
+        return Ok;
+
+    /* remove all of the containers on top of the found container */
+    LIST_FOR_EACH_ENTRY_SAFE(container, container2, &graphics->containers, GraphicsContainerItem, entry){
+        if(container->contid == state)
+            break;
+        list_remove(&container->entry);
+        delete_container(container);
+    }
+
+    list_remove(&container->entry);
+    sts = restore_container(graphics, container);
+    delete_container(container);
+
+    return sts;
 }
 
 GpStatus WINGDIPAPI GdipScaleWorldTransform(GpGraphics *graphics, REAL sx,
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 48c188b..0c1e54f 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -127,6 +127,7 @@ GpStatus WINGDIPAPI GdipFlush(GpGraphics*, GpFlushIntention);
 GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics*,GDIPCONST GpRectF*,GDIPCONST GpRectF*,GpUnit,GraphicsContainer*);
 GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics*,GraphicsContainer*);
 GpStatus WINGDIPAPI GdipBeginContainerI(GpGraphics*,GDIPCONST GpRect*,GDIPCONST GpRect*,GpUnit,GraphicsContainer*);
+GpStatus WINGDIPAPI GdipEndContainer(GpGraphics*,GraphicsContainer);
 GpStatus WINGDIPAPI GdipComment(GpGraphics*,UINT,GDIPCONST BYTE*);
 GpStatus WINGDIPAPI GdipCreateFromHDC(HDC,GpGraphics**);
 GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC,HANDLE,GpGraphics**);




More information about the wine-cvs mailing list