Attached to this email is a rough implementation of the main GDI+
containers functions.  It performs correctly in a few simple tests I
ran on it, but it's not quite ready to send off to wine-patches.  I'd
like to get some feedback here, since I'm certain that I'm doing some
things wrong.  I'm wondering about two things specifically.  Since the
vast majority of my programming experience has been with object
oriented languages, I'm not used to how to do things in C.

First, where should the utility functions and variables go?  Right
now, they're just thrown in above the functions I'm working on.  It
seems messy to me to have, for example, low and high (which need to be
renamed) declared where they are.  Do they belong there (or, rather,
near the top of graphics.c like some other utility functions), or
should they be placed elsewhere?

Second, I implemented a simple linked list to manage the stack of
GpGraphics objects.  I would imagine that there's some standard way of
doing stacks, rather than creating a simple one with utility functions
as I have here.  Can someone point me in the direction of the proper
way to do stacks like this in C?

Finally, while the code's still rough and needs cleaning up,
correctness checking, using Windows types and const properly, etc., am
I doing anything glaringly wrong?  As I mentioned, it works as
expected in the tests I've done, so I can't be too far off the mark :)

Thanks for taking a look,
Andrew

Patch attached.
Also available at:
http://www.brightnightgames.com/wine/gdipcontainers.patch

---
 dlls/gdiplus/graphics.c |  125 ++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 119 insertions(+), 6 deletions(-)
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 2be64c7..bef36c8 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -3254,24 +3254,133 @@ GpStatus WINGDIPAPI GdipSaveGraphics(GpGraphics *graphics, GraphicsState *state)
     return Ok;
 }
 
-GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics, GraphicsContainer *state)
+short high = 0xFDBB;
+short low = 0x0DBC;
+
+typedef struct _GraphicsNode {
+    GraphicsContainer container;
+    GpGraphics graphics;
+    struct _GraphicsNode* next;
+} GraphicsNode;
+
+GraphicsNode* first_graphics_node = NULL;
+
+GraphicsNode* get_last_graphics_node(){
+    GraphicsNode* cur;
+
+    if(!first_graphics_node)
+        return NULL;
+
+    cur = first_graphics_node;
+    while(cur->next != NULL){
+        cur = cur->next;
+    }
+    return cur;
+}
+
+void push_graphics_node(GraphicsNode* node){
+    GraphicsNode* last = get_last_graphics_node();
+
+    if(!last){
+        first_graphics_node = node;
+    }else{
+        last->next = node;
+    }
+}
+
+GpStatus copy_graphics(GpGraphics* dst, GpGraphics* src){
+    memcpy(dst, src, sizeof(GpGraphics));
+
+    dst->worldtrans = GdipAlloc(sizeof(GpMatrix));
+    if(!dst->worldtrans)
+        return OutOfMemory;
+    memcpy(dst->worldtrans, src->worldtrans, sizeof(GpMatrix));
+
+    dst->clip = GdipAlloc(sizeof(GpRegion));
+    if(!dst->clip)
+        return OutOfMemory;
+    memcpy(dst->clip, src->clip, sizeof(GpRegion));
+
+    return Ok;
+}
+
+void delete_graphics(GpGraphics* graphics){
+    GdipFree(graphics->worldtrans);
+    GdipFree(graphics->clip);
+    GdipFree(graphics);
+}
+
+void delete_graphics_node_and_children(GraphicsNode* node){
+    GraphicsNode* next;
+
+    while(node != NULL){
+        next = node->next;
+        delete_graphics(&node->graphics);
+        GdipFree(node);
+        node = next;
+    }
+}
+
+BOOL pop_graphics_node(GraphicsContainer container, GpGraphics* graphics){
+    GraphicsNode* cur = first_graphics_node;
+    GraphicsNode* prev = NULL;
+    while(cur != NULL){
+        if(cur->container == container){
+            copy_graphics(graphics, &cur->graphics);
+            delete_graphics_node_and_children(cur);
+            if(prev != NULL)
+                prev->next = NULL;
+            return TRUE;
+        }
+        prev = cur;
+        cur = cur->next;
+    }
+    return FALSE;
+}
+
+GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics,
+        GraphicsContainer *state)
 {
-    FIXME("(%p, %p)\n", graphics, state);
+    GraphicsNode* node;
+    GpStatus sts;
+
+    TRACE("(%p, %p)\n", graphics, state);
 
     if(!graphics || !state)
         return InvalidParameter;
 
-    *state = 0xdeadbeef;
+    node = GdipAlloc(sizeof(GraphicsNode));
+    if(!node)
+        return OutOfMemory;
+    node->next = NULL;
+
+    sts = copy_graphics(&(node->graphics), graphics);
+    if(sts != Ok)
+        return sts;
+
+    high -= 1;
+    low += 1;
+    *state = (high << 16) + low;
+
+    node->container = *state;
+
+    push_graphics_node(node);
+
+    FIXME("%x\n", *state);
     return Ok;
 }
 
-GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics, GDIPCONST GpRectF *dstrect, GDIPCONST GpRectF *srcrect, GpUnit unit, GraphicsContainer *state)
+GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics,
+        GDIPCONST GpRectF *dstrect, GDIPCONST GpRectF *srcrect, GpUnit unit,
+        GraphicsContainer *state)
 {
     FIXME("(%p, %p, %p, %d, %p): stub\n", graphics, dstrect, srcrect, unit, state);
     return NotImplemented;
 }
 
-GpStatus WINGDIPAPI GdipBeginContainerI(GpGraphics *graphics, GDIPCONST GpRect *dstrect, GDIPCONST GpRect *srcrect, GpUnit unit, GraphicsContainer *state)
+GpStatus WINGDIPAPI GdipBeginContainerI(GpGraphics *graphics,
+        GDIPCONST GpRect *dstrect, GDIPCONST GpRect *srcrect, GpUnit unit,
+        GraphicsContainer *state)
 {
     FIXME("(%p, %p, %p, %d, %p): stub\n", graphics, dstrect, srcrect, unit, state);
     return NotImplemented;
@@ -3287,9 +3396,13 @@ GpStatus WINGDIPAPI GdipEndContainer(GpGraphics *graphics, GraphicsState state)
 {
     FIXME("(%p, 0x%x)\n", graphics, state);
 
-    if(!graphics || !state)
+    if(!graphics)
         return InvalidParameter;
 
+    pop_graphics_node(state, graphics);
+
+    low -= 1;
+
     return Ok;
 }
 


Reply via email to