static inline GpStatus clone_element(const region_element* element, region_element** element2) { GpStatus stat; /* root node is allocated with GpRegion */ if(!*element2){ *element2 = GdipAlloc(sizeof(region_element)); if (!*element2) return OutOfMemory; } (*element2)->type = element->type; switch (element->type) { case RegionDataRect: (*element2)->elementdata.rect = element->elementdata.rect; break; case RegionDataEmptyRect: case RegionDataInfiniteRect: break; case RegionDataPath: (*element2)->elementdata.pathdata.pathheader = element->elementdata.pathdata.pathheader; stat = GdipClonePath(element->elementdata.pathdata.path, &(*element2)->elementdata.pathdata.path); if (stat != Ok) goto clone_out; break; default: (*element2)->elementdata.combine.left = NULL; (*element2)->elementdata.combine.right = NULL; 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) { region_element *element; TRACE("%p %p\n", region, clone); if (!(region && clone)) return InvalidParameter; *clone = heap_alloc_zero(sizeof(GpRegion)); if (!*clone) return OutOfMemory; element = &(*clone)->node; (*clone)->num_children = region->num_children; return clone_element(®ion->node, &element); }
/***************************************************************************** * GdipCombineRegionRect [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region, GDIPCONST GpRectF *rect, CombineMode mode) { GpRegion *rect_region; region_element *left, *right = NULL; GpStatus stat; TRACE("%p %s %d\n", region, debugstr_rectf(rect), mode); if (!(region && rect)) return InvalidParameter; stat = GdipCreateRegionRect(rect, &rect_region); if (stat != Ok) return stat; /* simply replace region data */ if(mode == CombineModeReplace){ delete_element(®ion->node); memcpy(region, rect_region, sizeof(GpRegion)); heap_free(rect_region); return Ok; } left = heap_alloc_zero(sizeof(region_element)); if (left) { memcpy(left, ®ion->node, sizeof(region_element)); stat = clone_element(&rect_region->node, &right); if (stat == Ok) { fuse_region(region, left, right, mode); GdipDeleteRegion(rect_region); return Ok; } } else stat = OutOfMemory; heap_free(left); GdipDeleteRegion(rect_region); return stat; }
/***************************************************************************** * GdipCombineRegionRect [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region, GDIPCONST GpRectF *rect, CombineMode mode) { GpRegion *rect_region; region_element *left, *right = NULL; GpStatus stat; TRACE("%p %p %d\n", region, rect, mode); if (!(region && rect)) return InvalidParameter; stat = GdipCreateRegionRect(rect, &rect_region); if (stat != Ok) return stat; /* simply replace region data */ if(mode == CombineModeReplace){ delete_element(®ion->node); memcpy(region, rect_region, sizeof(GpRegion)); GdipFree(rect_region); return Ok; } left = GdipAlloc(sizeof(region_element)); if (!left) goto out; memcpy(left, ®ion->node, sizeof(region_element)); stat = clone_element(&rect_region->node, &right); if (stat != Ok) goto out; fuse_region(region, left, right, mode); GdipDeleteRegion(rect_region); return Ok; out: GdipFree(left); GdipDeleteRegion(rect_region); return stat; }
/***************************************************************************** * GdipCombineRegionPath [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCombineRegionPath(GpRegion *region, GpPath *path, CombineMode mode) { GpRegion *path_region; region_element *left, *right = NULL; GpStatus stat; TRACE("%p %p %d\n", region, path, mode); if (!(region && path)) return InvalidParameter; stat = GdipCreateRegionPath(path, &path_region); if (stat != Ok) return stat; /* simply replace region data */ if(mode == CombineModeReplace){ delete_element(®ion->node); memcpy(region, path_region, sizeof(GpRegion)); heap_free(path_region); return Ok; } left = heap_alloc_zero(sizeof(region_element)); if (left) { *left = region->node; stat = clone_element(&path_region->node, &right); if (stat == Ok) { fuse_region(region, left, right, mode); GdipDeleteRegion(path_region); return Ok; } } else stat = OutOfMemory; heap_free(left); GdipDeleteRegion(path_region); return stat; }
/***************************************************************************** * GdipCombineRegionRegion [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCombineRegionRegion(GpRegion *region1, GpRegion *region2, CombineMode mode) { region_element *left, *right = NULL; GpStatus stat; GpRegion *reg2copy; TRACE("%p %p %d\n", region1, region2, mode); if(!(region1 && region2)) return InvalidParameter; /* simply replace region data */ if(mode == CombineModeReplace){ stat = GdipCloneRegion(region2, ®2copy); if(stat != Ok) return stat; delete_element(®ion1->node); memcpy(region1, reg2copy, sizeof(GpRegion)); heap_free(reg2copy); return Ok; } left = heap_alloc_zero(sizeof(region_element)); if (!left) return OutOfMemory; *left = region1->node; stat = clone_element(®ion2->node, &right); if (stat != Ok) { heap_free(left); return OutOfMemory; } fuse_region(region1, left, right, mode); region1->num_children += region2->num_children; return Ok; }