//-----------------------------------------------------------------------------
void D2DDrawContext::fillLinearGradient (CGraphicsPath* _path, const CGradient& gradient, const CPoint& startPoint, const CPoint& endPoint, bool evenOdd, CGraphicsTransform* t)
{
    if (renderTarget == 0)
        return;

    D2DGraphicsPath* d2dPath = dynamic_cast<D2DGraphicsPath*> (_path);
    if (d2dPath == 0)
        return;

    ID2D1PathGeometry* path = d2dPath->getPath (evenOdd ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING);
    if (path)
    {
        D2DApplyClip ac (this);

        ID2D1Geometry* geometry = 0;
        if (t)
        {
            ID2D1TransformedGeometry* tg = 0;
            D2D1_MATRIX_3X2_F matrix;
            matrix._11 = (FLOAT)t->m11;
            matrix._12 = (FLOAT)t->m12;
            matrix._21 = (FLOAT)t->m21;
            matrix._22 = (FLOAT)t->m22;
            matrix._31 = (FLOAT)t->dx;
            matrix._32 = (FLOAT)t->dy;
            getD2DFactory ()->CreateTransformedGeometry (path, matrix, &tg);
            geometry = tg;
        }
        else
        {
            geometry = path;
            geometry->AddRef ();
        }

        ID2D1GradientStopCollection* collection = 0;
        D2D1_GRADIENT_STOP gradientStops[2];
        gradientStops[0].position = (FLOAT)gradient.getColor1Start ();
        gradientStops[1].position = (FLOAT)gradient.getColor2Start ();
        gradientStops[0].color = D2D1::ColorF (gradient.getColor1 ().red/255.f, gradient.getColor1 ().green/255.f, gradient.getColor1 ().blue/255.f, gradient.getColor1 ().alpha/255.f * currentState.globalAlpha);
        gradientStops[1].color = D2D1::ColorF (gradient.getColor2 ().red/255.f, gradient.getColor2 ().green/255.f, gradient.getColor2 ().blue/255.f, gradient.getColor2 ().alpha/255.f * currentState.globalAlpha);

        if (SUCCEEDED (getRenderTarget ()->CreateGradientStopCollection (gradientStops, 2, &collection)))
        {
            ID2D1LinearGradientBrush* brush = 0;
            D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES properties;
            properties.startPoint = makeD2DPoint (startPoint);
            properties.endPoint = makeD2DPoint (endPoint);
            if (SUCCEEDED (getRenderTarget ()->CreateLinearGradientBrush (properties, collection, &brush)))
            {
                getRenderTarget ()->SetTransform (D2D1::Matrix3x2F::Translation ((FLOAT)getOffset ().x, (FLOAT)getOffset ().y));
                getRenderTarget ()->FillGeometry (geometry, brush);
                getRenderTarget ()->SetTransform (D2D1::Matrix3x2F::Identity ());
                brush->Release ();
            }
            collection->Release ();
        }

        geometry->Release ();
    }
}
//-----------------------------------------------------------------------------
void D2DDrawContext::fillRadialGradient (CGraphicsPath* _path, const CGradient& gradient, const CPoint& center, CCoord radius, const CPoint& originOffset, bool evenOdd, CGraphicsTransform* t)
{
	if (renderTarget == 0)
		return;

	D2DApplyClip ac (this);
	if (ac.isEmpty ())
		return;
	
	D2DGraphicsPath* d2dPath = dynamic_cast<D2DGraphicsPath*> (_path);
	if (d2dPath == 0)
		return;

	ID2D1Geometry* path = d2dPath->createPath (evenOdd ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING);
	if (path)
	{
		ID2D1Geometry* geometry = 0;
		if (t)
		{
			ID2D1TransformedGeometry* tg = 0;
			getD2DFactory ()->CreateTransformedGeometry (path, convert (*t), &tg);
			geometry = tg;
		}
		else
		{
			geometry = path;
			geometry->AddRef ();
		}
		ID2D1GradientStopCollection* collection = createGradientStopCollection (gradient);
		if (collection)
		{
			// brush properties
			ID2D1RadialGradientBrush* brush = 0;
			D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES properties;
			properties.center = makeD2DPoint (center);
			properties.gradientOriginOffset = makeD2DPoint (originOffset);
			properties.radiusX = (FLOAT)radius;
			properties.radiusY = (FLOAT)radius;

			if (SUCCEEDED (getRenderTarget ()->CreateRadialGradientBrush (properties, collection, &brush)))
			{
				getRenderTarget ()->FillGeometry (geometry, brush);
				brush->Release ();
			}
			collection->Release ();
		}
		geometry->Release ();
		path->Release ();
	}
}
//-----------------------------------------------------------------------------
void D2DDrawContext::drawGraphicsPath (CGraphicsPath* _path, PathDrawMode mode, CGraphicsTransform* t)
{
    if (renderTarget == 0)
        return;

    D2DGraphicsPath* d2dPath = dynamic_cast<D2DGraphicsPath*> (_path);
    if (d2dPath == 0)
        return;

    ID2D1PathGeometry* path = d2dPath->getPath (mode == kPathFilledEvenOdd ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING);
    if (path)
    {
        D2DApplyClip ac (this);

        ID2D1Geometry* geometry = 0;
        if (t)
        {
            ID2D1TransformedGeometry* tg = 0;
            D2D1_MATRIX_3X2_F matrix;
            matrix._11 = (FLOAT)t->m11;
            matrix._12 = (FLOAT)t->m12;
            matrix._21 = (FLOAT)t->m21;
            matrix._22 = (FLOAT)t->m22;
            matrix._31 = (FLOAT)t->dx;
            matrix._32 = (FLOAT)t->dy;
            getD2DFactory ()->CreateTransformedGeometry (path, matrix, &tg);
            geometry = tg;
        }
        else
        {
            geometry = path;
            geometry->AddRef ();
        }

        getRenderTarget ()->SetTransform (D2D1::Matrix3x2F::Translation ((FLOAT)getOffset ().x, (FLOAT)getOffset ().y));

        if (mode == kPathFilled || mode == kPathFilledEvenOdd)
            getRenderTarget ()->FillGeometry (geometry, getFillBrush ());
        else if (mode == kPathStroked)
            getRenderTarget ()->DrawGeometry (geometry, getStrokeBrush (), (FLOAT)getLineWidth (), getStrokeStyle ());

        getRenderTarget ()->SetTransform (D2D1::Matrix3x2F::Identity ());

        geometry->Release ();
    }
}
VGraphicPath& VGraphicPath::operator = (const VGraphicPath& inOriginal)
{	
	End();

	fBounds = inOriginal.fBounds;
	fPolygon = inOriginal.fPolygon;

#if !GRAPHIC_MIXED_GDIPLUS_D2D
	if (VWinD2DGraphicContext::IsAvailable())
		fPath = NULL;
	else
#endif
		fPath = inOriginal.fPath->Clone();

	fComputeBoundsAccurate = inOriginal.fComputeBoundsAccurate;
	if (fComputeBoundsAccurate)
	{
		fPathMin		= inOriginal.fPathMin;		
		fPathMax		= inOriginal.fPathMax;		
	}

	fCreateStorageForCrispEdges = inOriginal.fCreateStorageForCrispEdges;
	if (fCreateStorageForCrispEdges)
	{
		fDrawCmds = inOriginal.fDrawCmds;
		fCurTransform = inOriginal.fCurTransform;
	}
	fHasBezier = inOriginal.fHasBezier;

	fFillMode = inOriginal.GetFillMode();

#if ENABLE_D2D
	if (fGeomSink != NULL)
	{
		fGeomSink->Release();
		fGeomSink = NULL;
	}
	if (fPathD2D != NULL)
	{
		fPathD2D->Release();
		fPathD2D = NULL;
	}

	fFigureIsClosed = true;

	if (VWinD2DGraphicContext::IsAvailable() && inOriginal.IsBuilded())
	{
		//copy from source path
		//(just retain source path because D2D paths are immutable)
		ID2D1Geometry *pathSource = inOriginal.GetImplPathD2D();
		xbox_assert(pathSource);
#if !D2D_FACTORY_MULTI_THREADED
#if VERSIONDEBUG
		{
		VWinD2DGraphicContext::GetMutexFactory().Lock();
		CComPtr<ID2D1Factory> factorySource;
		pathSource->GetFactory(&factorySource);
		xbox_assert(factorySource == VWinD2DGraphicContext::GetFactory());
		VWinD2DGraphicContext::GetMutexFactory().Unlock();
		}
#endif
#endif
		pathSource->AddRef();
		fPathD2D = pathSource;
	}
#endif
	return *this;
}