~D2DPathRendererState() { if (path) { path->Release(); path = NULL; } }
void VGraphicPath::Widen(const GReal inStrokeWidth, ID2D1StrokeStyle* inStrokeStyle) { xbox_assert(inStrokeStyle); End(); if (fPathD2D != NULL) { CComPtr<ID2D1StrokeStyle> strokeStyle = (ID2D1StrokeStyle *)inStrokeStyle; ID2D1Geometry *oldPath = fPathD2D; //create new path ID2D1PathGeometry *newPath = NULL; VWinD2DGraphicContext::GetMutexFactory().Lock(); HRESULT hr = VWinD2DGraphicContext::GetFactory()->CreatePathGeometry( &newPath); xbox_assert(SUCCEEDED(hr)); VWinD2DGraphicContext::GetMutexFactory().Unlock(); //widen current path CComPtr<ID2D1GeometrySink> thisGeomSink; if (SUCCEEDED(newPath->Open(&thisGeomSink))) { thisGeomSink->SetFillMode( fFillMode == FILLRULE_EVENODD ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING); if (!SUCCEEDED(oldPath->Widen( inStrokeWidth, strokeStyle, NULL, 0.0f, thisGeomSink))) { newPath->Release(); return; } thisGeomSink->Close(); } fPathD2D = newPath; oldPath->Release(); fCreateStorageForCrispEdges = false; fHasBezier = false; fDrawCmds.clear(); fCurTransform.MakeIdentity(); } }
void VGraphicPath::Begin() { #if ENABLE_D2D //start to populate geometry if (fGeomSink) return; if (fPathD2D == NULL) return; ID2D1PathGeometry *thisPath = NULL; if (FAILED(fPathD2D->QueryInterface( __uuidof(ID2D1PathGeometry), (void **)&thisPath))) return; //no more a ID2D1PathGeometry so skip ID2D1GeometrySink *thisGeomSink; if (SUCCEEDED(thisPath->Open(&thisGeomSink))) { fGeomSink = thisGeomSink; thisGeomSink->SetFillMode( fFillMode == FILLRULE_EVENODD ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING); fFigureIsClosed = true; } thisPath->Release(); #endif }
/** combine current path with the specified path @remarks does not update internal polygon used only by D2D impl for path clipping implementation */ void VGraphicPath::_Combine( const VGraphicPath& inPath, bool inIntersect) { End(); //ensure proper combination if current path or input path is empty if (inPath.GetBounds().GetWidth() == 0.0f || inPath.GetBounds().GetHeight() == 0.0f) { //input path is empty if (inIntersect) Clear(); return; } if (GetBounds().GetWidth() == 0.0f || GetBounds().GetHeight() == 0.0f) { //current path is empty if (inIntersect) return; else *this = inPath; return; } //combine D2D path if appropriate //TODO: make it work for Gdiplus::GraphicPath too ? if (fPathD2D != NULL && inPath.GetImplPathD2D()) { ID2D1Geometry *oldPath = fPathD2D; //create new path ID2D1PathGeometry *newPath = NULL; VWinD2DGraphicContext::GetMutexFactory().Lock(); HRESULT hr = VWinD2DGraphicContext::GetFactory()->CreatePathGeometry( &newPath); xbox_assert(SUCCEEDED(hr)); VWinD2DGraphicContext::GetMutexFactory().Unlock(); //combine current path with input path CComPtr<ID2D1GeometrySink> thisGeomSink; if (SUCCEEDED(newPath->Open(&thisGeomSink))) { thisGeomSink->SetFillMode( fFillMode == FILLRULE_EVENODD ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING); if (!SUCCEEDED(oldPath->CombineWithGeometry( inPath.GetImplPathD2D(), inIntersect ? D2D1_COMBINE_MODE_INTERSECT : D2D1_COMBINE_MODE_UNION, NULL, 0.0f, thisGeomSink ))) { newPath->Release(); return; } thisGeomSink->Close(); } fPathD2D = newPath; oldPath->Release(); if (inIntersect) fBounds.Intersect( inPath.GetBounds()); else fBounds.Union( inPath.GetBounds()); fCreateStorageForCrispEdges = false; fHasBezier = false; fDrawCmds.clear(); fCurTransform.MakeIdentity(); } }