gdiplus: Implement GdipBeginContainer2 and GdipEndContainer
Andrew Eikum
andrew at brightnightgames.com
Thu Jul 2 18:43:58 CDT 2009
---
dlls/gdiplus/gdiplus_private.h | 2 +
dlls/gdiplus/graphics.c | 189 ++++++++++++++++++++++++++++++++++++++--
include/gdiplusflat.h | 1 +
3 files changed, 186 insertions(+), 6 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 95133ca..b6ed8fe 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,7 @@ struct GpGraphics{
BOOL busy; /* hdc handle obtained by GdipGetDC */
GpRegion *clip;
UINT textcontrast; /* not used yet. get/set only */
+ struct list containers;
};
struct GpBrush{
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 3525743..78c68be 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,141 @@ 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;
+
+typedef struct _GraphicsContainerID {
+ struct list entry;
+
+ GraphicsContainer id;
+} GraphicsContainerID;
+
+static struct list availableGCIDs = LIST_INIT(availableGCIDs);
+static GraphicsContainer lowest_unallocated_GCID = 0;
+
+static void make_available_gcid(GraphicsContainer id){
+ GraphicsContainerID *gcid;
+
+ gcid = GdipAlloc(sizeof(GraphicsContainerID));
+ gcid->id = id;
+ list_add_head(&availableGCIDs, &gcid->entry);
+}
+
+static void allocate_gcids(){
+ const GraphicsContainer num_new_ids = 20;
+ GraphicsContainer i;
+
+ for(i = 0; i < num_new_ids; i++){
+ make_available_gcid(i + lowest_unallocated_GCID);
+ }
+
+ lowest_unallocated_GCID += num_new_ids;
+}
+
+static void get_available_gcid(GraphicsContainer* id){
+ GraphicsContainerID *gcid;
+
+ if(list_empty(&availableGCIDs))
+ allocate_gcids();
+
+ gcid = LIST_ENTRY(list_head(&availableGCIDs), GraphicsContainerID, entry);
+ *id = gcid->id;
+ list_remove(&gcid->entry);
+ GdipFree(gcid);
+}
+
+static GpStatus init_container(GraphicsContainerItem** container,
+ GDIPCONST GpGraphics* graphics){
+ GpStatus sts;
+
+ *container = GdipAlloc(sizeof(GraphicsContainerItem));
+ if(!(*container))
+ return OutOfMemory;
+
+ get_available_gcid(&(*container)->contid);
+
+ (*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){
+ make_available_gcid(container->contid);
+ 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)
+ return sts;
+
+ GdipDeleteMatrix(graphics->worldtrans);
+ graphics->worldtrans = newTrans;
+
+ GdipDeleteRegion(graphics->clip);
+ graphics->clip = newClip;
+
+ 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 +1127,7 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra
(*graphics)->scale = 1.0;
(*graphics)->busy = FALSE;
(*graphics)->textcontrast = 4;
+ list_init(&(*graphics)->containers);
return Ok;
}
@@ -1155,6 +1292,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 +1301,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 +3397,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 = container->contid;
+
return Ok;
}
@@ -3285,12 +3438,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**);
--
1.6.3.3
--------------080901000402010706010406--
More information about the wine-devel
mailing list