// coverity[+alloc : arg-*0] GpStatus GdipCreatePathIter (GpPathIterator **iterator, GpPath *path) { GpPath *clone = NULL; GpPathIterator *iter; GpStatus status; if (!iterator) return InvalidParameter; iter = (GpPathIterator *) GdipAlloc (sizeof (GpPathIterator)); if (iter == NULL) return OutOfMemory; /* supplying a path isn't required */ if (path) { status = GdipClonePath (path, &clone); if (status != Ok) { GdipFree (iter); if (clone) GdipDeletePath (clone); return status; } } iter->path = clone; iter->markerPosition = 0; iter->subpathPosition = 0; iter->pathTypePosition = 0; *iterator = iter; return Ok; }
/***************************************************************************** * GdipCreateRegionPath [GDIPLUS.@] * * Creates a GpRegion from a GpPath * * PARAMS * path [I] path to base the region on * region [O] pointer to the newly allocated region * * RETURNS * SUCCESS: Ok * FAILURE: InvalidParameter * * NOTES * If a path has no floating point points, its points will be stored as shorts * (INTPATH) * * If a path is empty, it is considered to be an INTPATH */ GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region) { region_element* element; GpStatus stat; TRACE("%p, %p\n", path, region); if (!(path && region)) return InvalidParameter; *region = heap_alloc_zero(sizeof(GpRegion)); if(!*region) return OutOfMemory; stat = init_region(*region, RegionDataPath); if (stat != Ok) { GdipDeleteRegion(*region); return stat; } element = &(*region)->node; stat = GdipClonePath(path, &element->elementdata.path); if (stat != Ok) { GdipDeleteRegion(*region); return stat; } return Ok; }
GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath *path, REAL x, REAL y, REAL width, REAL height) { GpPath *backup; GpPointF ptf[2]; GpStatus retstat; BOOL old_new; if(!path || width < 0.0 || height < 0.0) return InvalidParameter; /* make a backup copy of path data */ if((retstat = GdipClonePath(path, &backup)) != Ok) return retstat; /* rectangle should start as new path */ old_new = path->newfigure; path->newfigure = TRUE; if((retstat = GdipAddPathLine(path,x,y,x+width,y)) != Ok){ path->newfigure = old_new; goto fail; } ptf[0].X = x+width; ptf[0].Y = y+height; ptf[1].X = x; ptf[1].Y = y+height; if((retstat = GdipAddPathLine2(path,(GDIPCONST GpPointF*)&ptf,2)) != Ok) goto fail; path->pathdata.Types[path->pathdata.Count-1] |= PathPointTypeCloseSubpath; /* free backup */ GdipDeletePath(backup); return Ok; fail: /* reverting */ GdipDeletePath(path); GdipClonePath(backup, &path); GdipDeletePath(backup); return retstat; }
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; }
/* * gdip_region_copy_tree: * @source: the GpPathTree to copy * @dest: the GpPathTree copy * * Recursively copy (and allocate) the @source path tree into @dest. * If @source is present then we must have a valid @dest. */ GpStatus gdip_region_copy_tree (GpPathTree *source, GpPathTree *dest) { GpStatus status; if (!source) return Ok; g_assert (dest); if (source->path) { status = GdipClonePath (source->path, &dest->path); if (status != Ok) return status; dest->branch1 = NULL; dest->branch2 = NULL; } else { dest->path = NULL; dest->mode = source->mode; dest->branch1 = (GpPathTree *) GdipAlloc (sizeof (GpPathTree)); if (!dest->branch1) return OutOfMemory; status = gdip_region_copy_tree (source->branch1, dest->branch1); if (status != Ok) return status; dest->branch2 = (GpPathTree *) GdipAlloc (sizeof (GpPathTree)); if (!dest->branch2) return OutOfMemory; status = gdip_region_copy_tree (source->branch2, dest->branch2); if (status != Ok) return status; } return Ok; }
/***************************************************************************** * GdipCreateRegionPath [GDIPLUS.@] * * Creates a GpRegion from a GpPath * * PARAMS * path [I] path to base the region on * region [O] pointer to the newly allocated region * * RETURNS * SUCCESS: Ok * FAILURE: InvalidParameter * * NOTES * If a path has no floating point points, its points will be stored as shorts * (INTPATH) * * If a path is empty, it is considered to be an INTPATH */ GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region) { region_element* element; GpPoint *pointsi; GpPointF *pointsf; GpStatus stat; DWORD flags = FLAGS_INTPATH; INT count, i; TRACE("%p, %p\n", path, region); if (!(path && region)) return InvalidParameter; *region = GdipAlloc(sizeof(GpRegion)); if(!*region) return OutOfMemory; stat = init_region(*region, RegionDataPath); if (stat != Ok) { GdipDeleteRegion(*region); return stat; } element = &(*region)->node; count = path->pathdata.Count; /* Test to see if the path is an Integer path */ if (count) { pointsi = GdipAlloc(sizeof(GpPoint) * count); pointsf = GdipAlloc(sizeof(GpPointF) * count); if (!(pointsi && pointsf)) { GdipFree(pointsi); GdipFree(pointsf); GdipDeleteRegion(*region); return OutOfMemory; } stat = GdipGetPathPointsI(path, pointsi, count); if (stat != Ok) { GdipDeleteRegion(*region); return stat; } stat = GdipGetPathPoints(path, pointsf, count); if (stat != Ok) { GdipDeleteRegion(*region); return stat; } for (i = 0; i < count; i++) { if (!(pointsi[i].X == pointsf[i].X && pointsi[i].Y == pointsf[i].Y )) { flags = FLAGS_NOFLAGS; break; } } GdipFree(pointsi); GdipFree(pointsf); } stat = GdipClonePath(path, &element->elementdata.pathdata.path); if (stat != Ok) { GdipDeleteRegion(*region); return stat; } /* 3 for headers, once again size doesn't count itself */ element->elementdata.pathdata.pathheader.size = ((sizeof(DWORD) * 3)); switch(flags) { /* Floats, sent out as floats */ case FLAGS_NOFLAGS: element->elementdata.pathdata.pathheader.size += (sizeof(DWORD) * count * 2); break; /* INTs, sent out as packed shorts */ case FLAGS_INTPATH: element->elementdata.pathdata.pathheader.size += (sizeof(DWORD) * count); break; default: FIXME("Unhandled flags (%08x). Expect wrong results.\n", flags); } element->elementdata.pathdata.pathheader.size += get_pathtypes_size(path); element->elementdata.pathdata.pathheader.magic = VERSION_MAGIC; element->elementdata.pathdata.pathheader.count = count; element->elementdata.pathdata.pathheader.flags = flags; (*region)->header.size = sizeheader_size + get_element_size(element); return Ok; }
static GF_Err gdip_surface_fill(GF_SURFACE _this, GF_STENCIL stencil) { GpStatus ret; GpMatrix *newmat; struct _stencil *_sten; GPGRAPH(); if (!_this) return GF_BAD_PARAM; if (!_graph->current) return GF_OK; _sten = (struct _stencil *)stencil; assert(_sten); #ifdef NODRAW return GF_OK; #endif if (_graph->clip) GdipSetClipPath(_graph->graph, _graph->clip, CombineModeReplace); switch (_sten->type) { case GF_STENCIL_SOLID: assert(_sten->pSolid); GdipFillPath(_graph->graph, _sten->pSolid, _graph->current); break; case GF_STENCIL_LINEAR_GRADIENT: if (_sten->pMat) { /*rebuild gradient*/ gdip_recompute_line_gradient(_sten); GdipResetTextureTransform((GpTexture*)_sten->pLinear); if (_sten->pMat) { GdipCloneMatrix(_sten->pMat, &newmat); } else { GdipCreateMatrix(&newmat); } GdipMultiplyMatrix(newmat, _sten->pLinearMat, MatrixOrderPrepend); GdipSetTextureTransform((GpTexture*)_sten->pLinear, newmat); GdipDeleteMatrix(newmat); } GdipFillPath(_graph->graph, _sten->pLinear, _graph->current); break; case GF_STENCIL_RADIAL_GRADIENT: /*build gradient*/ gdip_recompute_radial_gradient(_sten); GdipSetCompositingQuality(_graph->graph, CompositingQualityHighSpeed); GdipSetInterpolationMode(_graph->graph, InterpolationModeLowQuality); GdipSetSmoothingMode(_graph->graph, SmoothingModeHighSpeed); /*check if we need to draw solid background (GDIplus doesn't implement padded mode on path gradients)*/ if (_sten->pSolid) { GpPath *tr; GdipClonePath(_sten->circle, &tr); GdipTransformPath(tr, _sten->pMat); GdipSetClipPath(_graph->graph, tr, CombineModeExclude); GdipFillPath(_graph->graph, _sten->pSolid, _graph->current); GdipDeletePath(tr); GdipResetClip(_graph->graph); if (_graph->clip) GdipSetClipPath(_graph->graph, _graph->clip, CombineModeReplace); } GdipFillPath(_graph->graph, _sten->pRadial, _graph->current); break; case GF_STENCIL_VERTEX_GRADIENT: assert(_sten->pRadial); if (_sten->pMat) GdipSetTextureTransform((GpTexture*)_sten->pRadial, _sten->pMat); ret = GdipFillPath(_graph->graph, _sten->pRadial, _graph->current); break; case GF_STENCIL_TEXTURE: gdip_load_texture(_sten); if (_sten->pTexture) { GpMatrix *newmat; GdipResetTextureTransform((GpTexture*)_sten->pTexture); if (_sten->pMat) { GdipCloneMatrix(_sten->pMat, &newmat); } else { GdipCreateMatrix(&newmat); } /*gdip flip*/ if (_graph->center_coords && !(_sten->tiling&GF_TEXTURE_FLIP) ) GdipScaleMatrix(newmat, 1, -1, MatrixOrderPrepend); else if (!_graph->center_coords && (_sten->tiling&GF_TEXTURE_FLIP) ) GdipScaleMatrix(newmat, 1, -1, MatrixOrderPrepend); GdipSetTextureTransform((GpTexture*)_sten->pTexture, newmat); GdipDeleteMatrix(newmat); GdipSetInterpolationMode(_graph->graph, (_sten->tFilter==GF_TEXTURE_FILTER_HIGH_QUALITY) ? InterpolationModeHighQuality : InterpolationModeLowQuality); GdipFillPath(_graph->graph, _sten->pTexture, _graph->current); } break; } return GF_OK; }