// 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;
}
Example #2
0
/*****************************************************************************
 * 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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
/*
 * 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;
}
Example #6
0
/*****************************************************************************
 * 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;
}
Example #7
0
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;
}