[try7][Gdiplus 05/10] Implement GdipCloneRegion

Adam Petaccia adam at tpetaccia.com
Mon Aug 4 12:56:45 CDT 2008


Changelog:
(try4):
    Move further up the patch series, others will depend on this now.
    Deal with the fact that region->node isn't a pointer
    Update to new naming scheme
    Apply const qualifier
(try2):
    Check *element2 for not NULL; clean up better in case of failure.
---
 dlls/gdiplus/region.c |   71 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index 43a4cf7..43efc77 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -162,15 +162,80 @@ static inline void delete_element(region_element* element)
     }
 }
 
+static inline GpStatus clone_element(const region_element* element,
+        region_element** element2)
+{
+    GpStatus stat;
+
+    *element2 = GdipAlloc(sizeof(region_element));
+    if (!*element2)
+        return OutOfMemory;
+
+    (*element2)->type = element->type;
+
+    switch (element->type)
+    {
+        case RegionDataRect:
+            memcpy(&(*element2)->elementdata.rect,
+                    &element->elementdata.rect, sizeof(GpRectF));
+            break;
+        case RegionDataEmptyRect:
+        case RegionDataInfiniteRect:
+            break;
+        case RegionDataPath:
+            memcpy(&(*element2)->elementdata.pathdata.pathheader,
+                    &element->elementdata.pathdata.pathheader, sizeof(DWORD)*4);
+            stat = GdipClonePath(element->elementdata.pathdata.path,
+                    &(*element2)->elementdata.pathdata.path);
+            if (stat != Ok) goto clone_out;
+            break;
+        default:
+            stat = clone_element(element->elementdata.combine.left,
+                    &(*element2)->elementdata.combine.left);
+            if (stat != Ok) goto clone_out;
+            stat = clone_element(element->elementdata.combine.right,
+                    &(*element2)->elementdata.combine.right);
+            if (stat != Ok) goto clone_out;
+            break;
+    }
+
+    return Ok;
+
+clone_out:
+    delete_element(*element2);
+    *element2 = NULL;
+    return stat;
+}
+
 /*****************************************************************************
  * GdipCloneRegion [GDIPLUS.@]
+ *
+ * Creates a deep copy of the region
+ *
+ * PARAMS
+ *  region  [I] source region
+ *  clone   [O] resulting clone
+ *
+ * RETURNS
+ *  SUCCESS: Ok
+ *  FAILURE: InvalidParameter or OutOfMemory
  */
 GpStatus WINGDIPAPI GdipCloneRegion(GpRegion *region, GpRegion **clone)
 {
-    FIXME("(%p %p): stub\n", region, clone);
+    region_element *element;
 
-    *clone = NULL;
-    return NotImplemented;
+    TRACE("%p %p\n", region, clone);
+
+    if (!(region && clone))
+        return InvalidParameter;
+
+    *clone = GdipAlloc(sizeof(GpRegion));
+    if (!*clone)
+        return OutOfMemory;
+    element = &(*clone)->node;
+
+    memcpy(&(*clone)->header, &region->header, sizeof(DWORD) * 4);
+    return clone_element(&region->node, &element);
 }
 
 GpStatus WINGDIPAPI GdipCombineRegionPath(GpRegion *region, GpPath *path, CombineMode mode)
-- 
1.5.4.3




More information about the wine-patches mailing list