/** * @file XTPMarkupGdiPlusTransformationMatrix.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "GraphicLibrary/GdiPlus/XTPGdiPlus.h" using namespace Gdiplus; using namespace Gdiplus::DllExports; #include "Markup/DeviceContext/XTPGdiPlus.h" #include "Markup/Transform/XTPMarkupTransformationMatrix.h" #include "Markup/Transform/XTPMarkupGdiPlusTransformationMatrix.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # undef THIS_FILE static char THIS_FILE[] = __FILE__; # define new DEBUG_NEW #endif IMPLEMENT_DYNAMIC(CXTPMarkupGdiPlusTransformationMatrix, CObject); CXTPMarkupGdiPlusTransformationMatrix::CXTPMarkupGdiPlusTransformationMatrix(CXTPGdiPlus* pReserved, GpMatrix* pMatrix) : m_pMatrix(pMatrix) { UNREFERENCED_PARAMETER(pReserved); _ASSERTE(NULL != m_pMatrix); } CXTPMarkupGdiPlusTransformationMatrix::~CXTPMarkupGdiPlusTransformationMatrix() { GdipDeleteMatrix(m_pMatrix); } CXTPMarkupTransformationMatrix* CXTPMarkupGdiPlusTransformationMatrix::Clone() const { CXTPMarkupTransformationMatrix* pClonedInstance = NULL; GpMatrix* pClonedMatrix = NULL; if (Gdiplus::Ok == GdipCloneMatrix(m_pMatrix, &pClonedMatrix)) { pClonedInstance = new CXTPMarkupGdiPlusTransformationMatrix(NULL, pClonedMatrix); } return pClonedInstance; } void CXTPMarkupGdiPlusTransformationMatrix::Offset(const POINT& offset) { GdipTranslateMatrix(m_pMatrix, static_cast(offset.x), static_cast(offset.y), Gdiplus::MatrixOrderPrepend); } inline BOOL PointInTriangle(PointF p, PointF a, PointF b, PointF c) { if (a.Equals(b) && a.Equals(c)) return a.Equals(p); #define PLANESIGN(p1, p2, p3) \ ((p1).X - (p3).X) * ((p2).Y - (p3).Y) - ((p2).X - (p3).X) * ((p1).Y - (p3).Y) float d1 = PLANESIGN(p, a, b); float d2 = PLANESIGN(p, b, c); float d3 = PLANESIGN(p, c, a); #undef PLANESIGN BOOL bHasNeg = (d1 < 0) || (d2 < 0) || (d3 < 0); BOOL bHasPos = (d1 > 0) || (d2 > 0) || (d3 > 0); return !(bHasNeg && bHasPos); } BOOL CXTPMarkupGdiPlusTransformationMatrix::TransformRect(const RECT& rect, const POINT& absoluteOffset, PointF (&transformedRectPoints)[4]) const { BOOL bSuccess = FALSE; transformedRectPoints[0].X = static_cast(rect.left); transformedRectPoints[0].Y = static_cast(rect.top); transformedRectPoints[1].X = static_cast(rect.right); transformedRectPoints[1].Y = transformedRectPoints[0].Y; transformedRectPoints[2].X = transformedRectPoints[1].X; transformedRectPoints[2].Y = static_cast(rect.bottom); transformedRectPoints[3].X = transformedRectPoints[0].X; transformedRectPoints[3].Y = transformedRectPoints[2].Y; if (Ok == GdipTransformMatrixPoints(m_pMatrix, transformedRectPoints, _countof(transformedRectPoints))) { PointF offset(static_cast(absoluteOffset.x), static_cast(absoluteOffset.y)); transformedRectPoints[0].X -= offset.X; transformedRectPoints[0].Y -= offset.Y; transformedRectPoints[1].X -= offset.X; transformedRectPoints[1].Y -= offset.Y; transformedRectPoints[2].X -= offset.X; transformedRectPoints[2].Y -= offset.Y; transformedRectPoints[3].X -= offset.X; transformedRectPoints[3].Y -= offset.Y; bSuccess = TRUE; } return bSuccess; } BOOL CXTPMarkupGdiPlusTransformationMatrix::PtInRect(const RECT& rect, const POINT& absoluteOffset, const POINT& point) const { BOOL bHit = FALSE; PointF transformedRectPoints[4]; if (!TransformRect(rect, absoluteOffset, transformedRectPoints)) return FALSE; PointF pointf(static_cast(point.x), static_cast(point.y)); bHit = PointInTriangle(pointf, transformedRectPoints[0], transformedRectPoints[1], transformedRectPoints[2]); if (!bHit) { bHit = PointInTriangle(pointf, transformedRectPoints[2], transformedRectPoints[3], transformedRectPoints[0]); } return bHit; } CRect CXTPMarkupGdiPlusTransformationMatrix::GetBoundRect(const RECT& rect, const POINT& absoluteOffset) const { CRect rcBound; rcBound.SetRectEmpty(); PointF transformedRectPoints[4]; if (TransformRect(rect, absoluteOffset, transformedRectPoints)) { rcBound.SetRect(INT_MAX, INT_MAX, INT_MIN, INT_MIN); for (int i = 0; i < _countof(transformedRectPoints); ++i) { int x = static_cast(transformedRectPoints[i].X); int y = static_cast(transformedRectPoints[i].Y); if (x < rcBound.left) { rcBound.left = x; } if (y < rcBound.top) { rcBound.top = y; } if (rcBound.right < x) { rcBound.right = x; } if (rcBound.bottom < y) { rcBound.bottom = y; } } } return rcBound; }