gdiplus: Implement GdipBeginContainer2 and GdipEndContainer.
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 @@
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 @@
(*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 GdipDeleteGraphics(GpGraphics *graphics)
{
+ GraphicsContainerItem *cont, *next;
TRACE("(%p)\n", graphics);
if(!graphics) return InvalidParameter;
@@ -1163,6 +1265,11 @@
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 @@
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 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,