#include "stdafx.h" #include "SelectedItemMotionGraphDrawer.h" #include "SigmaDoc.h" void PathTool_GetPath(POSITION pos, Gdiplus::GraphicsPath & pathOut, CSigmaDoc * pDoc); class PathItemDrawer { public: PathItemDrawer(); ~PathItemDrawer(); bool Init(Gdiplus::GraphicsPath & path); void Draw(CDC* pDC); Gdiplus::Status TransformPoints(Gdiplus::Matrix * transform); private: void Clear(); private: Gdiplus::GraphicsPath * m_pGraphicsPath; LPPOINT m_pPathPoints; LPBYTE m_pPathTypes; }; PathItemDrawer::PathItemDrawer() : m_pGraphicsPath(NULL), m_pPathPoints(NULL), m_pPathTypes(NULL) { return; } PathItemDrawer::~PathItemDrawer() { Clear(); } bool PathItemDrawer::Init(Gdiplus::GraphicsPath & path) { Clear(); m_pGraphicsPath = path.Clone(); if (!m_pGraphicsPath) return false; int n = path.GetPointCount(); if (n > 0) { // Reserve space for path points... m_pPathPoints = new POINT[n]; // ... and for point types m_pPathTypes = new BYTE[n]; // Get the point types. We'll retrieve the points in OnUpdate(). if (m_pPathTypes) path.GetPathTypes(m_pPathTypes, n); if (m_pPathPoints == NULL || m_pPathTypes == NULL) { Clear(); return false; } } return true; } void PathItemDrawer::Draw(CDC* pDC) { if (m_pGraphicsPath == NULL) return; // Next is a variation of code in the MFC documentation // for CDC::BeginPath(). Draw a GDI+ GraphicsPath in gdi. // We could have used CDC::PolyDraw(), but it isn't supported on Win98 and WinME. int nPathPoints = m_pGraphicsPath->GetPointCount(); if (nPathPoints <= 0) return; int i; LPPOINT pLastMoveTo = NULL; for (i = 0; i < nPathPoints; i++) { BYTE type = m_pPathTypes[i]; type &= ~(Gdiplus::PathPointTypeDashMode | Gdiplus::PathPointTypePathMarker); switch (type) { case Gdiplus::PathPointTypeStart: if (pLastMoveTo && i > 0) pDC->LineTo(*pLastMoveTo); pDC->MoveTo(m_pPathPoints[i]); //pLastMoveTo = & m_pPathPoints[i]; break; case Gdiplus::PathPointTypeLine | Gdiplus::PathPointTypeCloseSubpath: pDC->LineTo(m_pPathPoints[i]); if (pLastMoveTo) pDC->LineTo(*pLastMoveTo); pLastMoveTo = NULL; break; case Gdiplus::PathPointTypeLine: pDC->LineTo(m_pPathPoints[i]); break; case Gdiplus::PathPointTypeBezier | Gdiplus::PathPointTypeCloseSubpath: pDC->PolyBezierTo(&m_pPathPoints[i], 3); i += 2; if (pLastMoveTo) pDC->LineTo(*pLastMoveTo); pLastMoveTo = NULL; break; case Gdiplus::PathPointTypeBezier: pDC->PolyBezierTo(&m_pPathPoints[i], 3); i += 2; break; default: break; } } //if (pLastMoveTo && i > 1) pDC->LineTo(* pLastMoveTo); } Gdiplus::Status PathItemDrawer::TransformPoints(Gdiplus::Matrix * transform) { if (transform == NULL) return Gdiplus::GenericError; if (m_pGraphicsPath == NULL) return Gdiplus::GenericError; int nPathPoints = m_pGraphicsPath->GetPointCount(); if (nPathPoints <= 0) return Gdiplus::GenericError; // ...refresh the points... m_pGraphicsPath->GetPathPoints((Gdiplus::Point*)m_pPathPoints, nPathPoints); // ... and transform them too. return transform->TransformPoints((Gdiplus::Point*)m_pPathPoints, nPathPoints); } void PathItemDrawer::Clear() { if (m_pGraphicsPath) delete m_pGraphicsPath; m_pGraphicsPath = NULL; if (m_pPathPoints) delete[] m_pPathPoints; m_pPathPoints = NULL; if (m_pPathTypes) delete[] m_pPathTypes; m_pPathTypes = NULL; } SelectedItemMotionGraphDrawer::SelectedItemMotionGraphDrawer() { m_colorPath = RGB(0, 153, 255); } bool SelectedItemMotionGraphDrawer::Init(CSigmaDoc * pDoc, CPositionList * selectionSet) { Reset(); if (selectionSet->IsEmpty()) return false; POSITION pos = selectionSet->GetHeadPosition(); POSITION pt; Gdiplus::GraphicsPath path; while (pos != NULL) { path.Reset(); pt = selectionSet->GetNext(pos); PathTool_GetPath(pt, path, pDoc); PathItemDrawer * drawer = new PathItemDrawer(); drawer->Init(path); m_paths.Add(drawer); } return true; } void SelectedItemMotionGraphDrawer::Reset() { int count = m_paths.GetCount(); for (int i = 0; i < count; i++) delete m_paths[i]; m_paths.RemoveAll(); } void SelectedItemMotionGraphDrawer::Translate(Gdiplus::Matrix * matrix) { if (!m_paths.IsEmpty()) { int count = m_paths.GetCount(); for (int i = 0; i < count; i++) m_paths[i]->TransformPoints(matrix); } } void SelectedItemMotionGraphDrawer::Draw(CDC * pDC) { int nOldRop = pDC->SetROP2(R2_NOTXORPEN); CPen pen(PS_SOLID, 0, m_colorPath); //CGdiObject * pOldPen = pDC->SelectObject(&pen); int count = m_paths.GetCount(); for (int i = 0; i < count; i++) m_paths[i]->Draw(pDC); //pDC->SelectObject(pOldPen); pDC->SetROP2(nOldRop); }