242 lines
6.4 KiB
C++
242 lines
6.4 KiB
C++
|
|
extern "C"
|
|
{
|
|
#include "precomp.h"
|
|
}
|
|
#include "wtypes.h"
|
|
#include "objbase.h"
|
|
#include "gdiplus.h"
|
|
|
|
|
|
extern "C" BOOL bInvertxform(PXFORM pxformSrc, PXFORM pxformDest);
|
|
extern "C" BOOL bXformWorkhorse(PPOINTL aptl, DWORD nCount, PXFORM pXform);
|
|
|
|
using namespace Gdiplus;
|
|
|
|
inline REAL
|
|
GetDistance(
|
|
GpPointF & p1,
|
|
GpPointF & p2
|
|
)
|
|
{
|
|
double dx = (double)p2.X - p1.X;
|
|
double dy = (double)p2.Y - p1.Y;
|
|
|
|
return (REAL)sqrt((dx * dx) + (dy * dy));
|
|
}
|
|
|
|
// Flatten a path using GDI+ and transform the points before hand so we flatten
|
|
// the points that will go in the metafile. We allocate one buffer that will
|
|
// contain the points and types. The caller has to free that buffer
|
|
extern "C" BOOL GdipFlattenGdiPath(PLOCALDC pLocalDC,
|
|
LPVOID *buffer,
|
|
INT *count)
|
|
{
|
|
BOOL b = FALSE;
|
|
INT i ;
|
|
INT cpt;
|
|
PBYTE pb = NULL;
|
|
PointF* pptf;
|
|
LPPOINT ppt;
|
|
PBYTE pjType;
|
|
INT flattenCount;
|
|
PBYTE flattenpb = NULL;
|
|
PointF* flattenPoints;
|
|
PBYTE flattenTypes;
|
|
PBYTE returnpb = NULL;
|
|
|
|
ASSERT(buffer != NULL && *buffer == NULL && count != NULL);
|
|
|
|
// Get the path data.
|
|
|
|
// First get a count of the number of points.
|
|
|
|
cpt = GetPath(pLocalDC->hdcHelper, (LPPOINT) NULL, (LPBYTE) NULL, 0);
|
|
if (cpt == -1)
|
|
{
|
|
RIPS("MF3216: DoFlattenPath, GetPath failed\n");
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
|
|
// Check for empty path.
|
|
|
|
if (cpt == 0)
|
|
{
|
|
b = TRUE;
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
|
|
// Allocate memory for the path data.
|
|
|
|
if (!(pb = (PBYTE) LocalAlloc
|
|
(
|
|
LMEM_FIXED,
|
|
cpt * (sizeof(PointF) + sizeof(POINT) + sizeof(BYTE))
|
|
)
|
|
)
|
|
)
|
|
{
|
|
RIPS("MF3216: DoFlattenPath, LocalAlloc failed\n");
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
|
|
// Order of assignment is important for dword alignment.
|
|
|
|
pptf = (PointF*) pb;
|
|
ppt = (LPPOINT) (pptf + cpt);
|
|
pjType = (LPBYTE) (ppt + cpt);
|
|
|
|
// Finally, get the path data.
|
|
|
|
if (GetPath(pLocalDC->hdcHelper, ppt, pjType, cpt) != cpt)
|
|
{
|
|
RIPS("MF3216: DoFlattenPath, GetPath failed\n");
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
|
|
if (pfnSetVirtualResolution == NULL)
|
|
{
|
|
if (!bXformWorkhorse((PPOINTL) ppt, cpt, &pLocalDC->xformRDevToRWorld))
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
|
|
BYTE tempType;
|
|
for (i = 0; i < cpt; i++)
|
|
{
|
|
pptf[i] = PointF((REAL) ppt[i].x, (REAL) ppt[i].y);
|
|
switch (pjType[i] & ~PT_CLOSEFIGURE)
|
|
{
|
|
case PT_LINETO:
|
|
tempType = PathPointTypeLine;
|
|
break;
|
|
|
|
case PT_MOVETO:
|
|
tempType = PathPointTypeStart;
|
|
break;
|
|
|
|
case PT_BEZIERTO:
|
|
tempType = PathPointTypeBezier;
|
|
break;
|
|
|
|
default:
|
|
WARNING(("MF3216: There's something wrong with this path"));
|
|
tempType = PathPointTypeLine;
|
|
break;
|
|
}
|
|
if (pjType[i] & PT_CLOSEFIGURE)
|
|
{
|
|
tempType |= PathPointTypeCloseSubpath;
|
|
}
|
|
pjType[i] = tempType;
|
|
}
|
|
{
|
|
|
|
XFORM* xform = &(pLocalDC->xformRWorldToPPage);
|
|
Matrix matrix((REAL)xform->eM11, (REAL)xform->eM12, (REAL)xform->eM21,
|
|
(REAL)xform->eM22, (REAL)xform->eDx, (REAL)xform->eDy);
|
|
GraphicsPath gdipPath (pptf,
|
|
pjType,
|
|
cpt);
|
|
// This will transform the flattened point into the resolution of the
|
|
// metafile, giving us the best resolution for playtime
|
|
gdipPath.Flatten(&matrix, 1.0f/6.0f);
|
|
flattenCount = gdipPath.GetPointCount();
|
|
|
|
if (flattenCount < 0)
|
|
{
|
|
RIPS("MF3216: GDIP failed in flatting the path\n");
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
|
|
if (!(flattenpb = (PBYTE) LocalAlloc
|
|
(
|
|
LMEM_FIXED,
|
|
flattenCount * (sizeof(PointF) + sizeof(BYTE))
|
|
)
|
|
)
|
|
)
|
|
{
|
|
RIPS("MF3216: DoFlattenPath, LocalAlloc failed\n");
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
flattenPoints = (PointF*) flattenpb;
|
|
flattenTypes = (PBYTE) (flattenPoints + flattenCount);
|
|
|
|
if (!(returnpb = (PBYTE) LocalAlloc
|
|
(
|
|
LMEM_FIXED,
|
|
flattenCount * (sizeof(POINT) + sizeof(BYTE))
|
|
)
|
|
)
|
|
)
|
|
{
|
|
RIPS("MF3216: DoFlattenPath, LocalAlloc failed\n");
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
ppt = (LPPOINT) returnpb;
|
|
pjType = (PBYTE) (ppt + flattenCount);
|
|
|
|
if (gdipPath.GetPathTypes(flattenTypes, flattenCount) != Ok)
|
|
{
|
|
RIPS("MF3216: DoFlattenPath, GetPathTypes failed\n");
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
|
|
if (gdipPath.GetPathPoints(flattenPoints, flattenCount) != Ok)
|
|
{
|
|
RIPS("MF3216: DoFlattenPath, GetPathPoints failed\n");
|
|
goto exit_DoFlattenPath;
|
|
}
|
|
|
|
for (i = 0; i < flattenCount; i++)
|
|
{
|
|
ppt[i].x = (INT)(flattenPoints[i].X + 0.5f);
|
|
ppt[i].y = (INT)(flattenPoints[i].Y + 0.5f);
|
|
switch (flattenTypes[i] & ~PathPointTypeCloseSubpath)
|
|
{
|
|
case PathPointTypeLine:
|
|
tempType = PT_LINETO;
|
|
break;
|
|
|
|
case PathPointTypeStart:
|
|
tempType = PT_MOVETO;
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
WARNING(("MF3216: There's something wrong with this path"));
|
|
break;
|
|
}
|
|
if (flattenTypes[i] & PathPointTypeCloseSubpath)
|
|
{
|
|
tempType |= PT_CLOSEFIGURE;
|
|
}
|
|
pjType[i] = tempType;
|
|
}
|
|
}
|
|
*buffer = returnpb;
|
|
*count = flattenCount;
|
|
returnpb = NULL;
|
|
b = TRUE;
|
|
|
|
exit_DoFlattenPath:
|
|
|
|
// Cleanup any allocations
|
|
if (pb != NULL)
|
|
{
|
|
LocalFree((HANDLE)pb);
|
|
}
|
|
if (flattenpb != NULL)
|
|
{
|
|
LocalFree((HANDLE)flattenpb);
|
|
}
|
|
// This should only happen if we failed
|
|
if (returnpb != NULL)
|
|
{
|
|
LocalFree((HANDLE)returnpb);
|
|
}
|
|
|
|
return b;
|
|
}
|