You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
955 lines
32 KiB
955 lines
32 KiB
/*****************************************************************************
|
|
*
|
|
* xforms - Entry points for Win32 to Win 16 converter
|
|
*
|
|
* Date: 7/1/91
|
|
* Author: Jeffrey Newman (c-jeffn)
|
|
*
|
|
* Copyright 1991 Microsoft Corp
|
|
*----------------------------------------------------------------------------
|
|
*
|
|
* September 21, 1991
|
|
* Updated [20-Dec-1991]
|
|
*
|
|
* Transformations in the Win32 to Win16 translator.
|
|
*
|
|
* We are now supporting coordinate transformations from any
|
|
* map mode to any map mode.
|
|
*
|
|
* Where:
|
|
* W is the record-time-world to record-time-device xform.
|
|
* (aka metafile-world to metafile-device.)
|
|
* D is the record-time device to play-time-device xform.
|
|
* (aka metafile-device to reference-device.)
|
|
* P is the play-time-device to play-time-page xform.
|
|
* (aka reference-device to reference-logical (or page).)
|
|
*
|
|
* W is the transformation defined by the world xform, map mode, window org,
|
|
* window extent, viewport org, and viewport extent in the
|
|
* Win32 metafile. This transform is also known as the world to
|
|
* device xform.
|
|
*
|
|
* The normal composite xform is:
|
|
*
|
|
* W D P
|
|
* ^ ^ ^ ^
|
|
* | | | +- coordinate recorded in the win16 metafile.
|
|
* | | | play-time-page coordinates (aka reference-logical)
|
|
* | | +---- play-time-device (reference-device) coordinates.
|
|
* | +------ record-time device (metafile-device) coordinates.
|
|
* +-------- world coordinates, recorded in Win32 metafile
|
|
*
|
|
* The following comment is from Hockl's mail about transforms.
|
|
*
|
|
* Message 11:
|
|
* From hockl Thu Dec 19 11:50:54 1991
|
|
* To: c-jeffn
|
|
* Cc: johnc
|
|
* Subject: Transform hints for the 32-16 converter
|
|
* Date: Thu Dec 19 11:46:40 1991
|
|
*
|
|
* Here are some transform hints for the converter:
|
|
*
|
|
* A. Issue the following records immediately following the 16-bit header
|
|
* record:
|
|
*
|
|
* 1. SetMapMode - use the given mapping mode, it is MM_ANISOTROPIC
|
|
* in most cases.
|
|
*
|
|
* 2. SetWindowOrg - use the upper left coordinates of the rclFrame.
|
|
* The coordinates are in the logical units of the reference DC. So
|
|
* you have to convert .01mm to the reference device coordinates, then
|
|
* to the logical coordinates. You can use the third transform
|
|
* defined in B.4 below to convert device coordinates to the logical
|
|
* coordinates of the reference device. (Note the conversion formula
|
|
* for LPtoDP is defined as Dx = (Lx - xWO) * xVE/xWE + xVO and so on).
|
|
* This record is required to translate the converted picture to the
|
|
* origin (see comments in GetMetaFileBitsEx).
|
|
*
|
|
* 3. SetWindowExt - use the extents of the rclFrame.
|
|
* xExt = rclFrame.right - rclFrame.left;
|
|
* yExt = rclFrame.bottom - rclFrame.top;
|
|
* The extents are in the device units of the reference DC. So
|
|
* you have to convert .01mm to the reference device units.
|
|
*
|
|
* These three records should always be generated. Note that
|
|
* SetWindowExt has no effect in all fixed mapping modes (e.g.
|
|
* MM_LOENGLISH and MM_TEXT) and will have no effect when the converted
|
|
* metafile is played.
|
|
*
|
|
* B. Once you have issued the records, you need to use a xform helper DC
|
|
* to convert the coordinates of all drawing orders. To do this, you
|
|
* need to do the following:
|
|
*
|
|
* 1. Create a xform helper DC. This is a display info DC.
|
|
*
|
|
* 2. Call SetVirtualResolution to set the xform helper DC to that of
|
|
* the metafile. Use the metafile header's szlDevice and
|
|
* szlMillimeters values to set the resolution. This is to ensure
|
|
* that the help DC maps the logical coordinates to the device
|
|
* coordinates of the original metafile device. If you reuse this
|
|
* helper DC in conversion, make sure you initialize the transforms
|
|
* using SetMapMode, ModifyWorldTransform, SetWindowOrgEx and
|
|
* SetViewportOrgEx. You can use the same code in the
|
|
* CreateMetaFileEx function.
|
|
*
|
|
* 3. Once you have set up the xform helper DC, you should play all
|
|
* 32-bit xform calls into the helper DC. But never emit any
|
|
* xform records in the converter. Everytime the xform is changed
|
|
* in the helper DC, you need to get the world to device xform
|
|
* (xformWDHelper) from the helper DC. The xformWDHelper is used to
|
|
* convert the coordinates of the drawing orders subsequently.
|
|
* You can get it using the GetTransform(hdcHelper,XFORM_WORLD_TO_DEVICE)
|
|
* private API.
|
|
*
|
|
* 4. To convert drawing order coordinates, you pass them through three
|
|
* transforms. The first is the xformWDHelper as computed above. It
|
|
* converts all logical coordiates into the device coordinates of
|
|
* the original metafile device. Note that this coordinates may
|
|
* be different from the conversion's reference device. For example,
|
|
* the metafile may be created for a printer but the conversion is
|
|
* requested for the display. The second transform therefore scales
|
|
* the coordinates from the metafile device to the reference device.
|
|
* The scaled coordinates are in MM_TEXT units. So we need the third
|
|
* transform to convert the coordinates into the requested mapmode
|
|
* units. For MM_TEXT, MM_ANISOTROPIC and MM_ISOTROPIC mapmode, this
|
|
* is the identity transform. For the other mapmodes, this is a scale
|
|
* transform. The scale transform maps the device units of the
|
|
* reference device to the logical units and can be computed using
|
|
* szlDevice, szlMillimeters of the reference device (not the metafile
|
|
* device!) and some predefined constants (to map millimeter to
|
|
* english, for example). Note that in these fixed mapping modes, the
|
|
* y-axis goes in the opposite direction. So make sure that the eM22
|
|
* component of the third transform is negative. As you can see, the
|
|
* second and third transform never change in the duration of the
|
|
* conversion. So you can combine them into one to optimize computation
|
|
* of the composite transform. The composite transfom makes up of the
|
|
* three transforms and is used to convert drawing order coordinates
|
|
* into coordinates for the converted metafile.
|
|
*
|
|
* C. To display a converted metafile in Windows 3.0, do the following before
|
|
* calling PlayMetaFile:
|
|
*
|
|
* 1. If the mapmode is MM_ANISOTROPIC, which is 99.9% of the time, call
|
|
* SetMapMode(MM_ANISOTROPIC), SetViewportOrigin and SetViewportExt.
|
|
* The viewport origin defines the upper left corner of the display area
|
|
* and the viewport origin defines the extent of the display area. Both
|
|
* are in device units.
|
|
*
|
|
* 2. If the mapmode is MM_ISOTROPIC, which is strange, call
|
|
* SetMapMode(MM_ISOTROPIC), SetViewportOrigin and SetViewportExt.
|
|
* This is almost the same as C.1 above.
|
|
*
|
|
* 3. If the mapmode is others, the metafile has a fixed physical size
|
|
* and cannot be scaled easily without a lot of heck in the application.
|
|
* Call SetViewportOrigin to define the upper left corner of the display
|
|
* area. The origin is in device coordinates.
|
|
*
|
|
* I hope these steps are clear. If you have any questions, feel free to
|
|
* give me a call.
|
|
*
|
|
* HockL
|
|
*
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI GetTransform(HDC hdc,DWORD iXform,LPXFORM pxform);
|
|
BOOL WINAPI SetVirtualResolution(HDC hdc,
|
|
int cxDevice,
|
|
int cyDevice,
|
|
int cxMillimeters,
|
|
int cyMillimeters);
|
|
|
|
|
|
BOOL bComputeCompositeXform(PLOCALDC pLocalDC) ;
|
|
VOID vInitRecDevToPlayDevXform(PLOCALDC pLocalDC, PENHMETAHEADER pmf32header) ;
|
|
|
|
|
|
/*
|
|
[19-Dec-1991]
|
|
A note about transformations.
|
|
|
|
We will map into any map mode (when the converter is complete).
|
|
|
|
We will use a helper DC to compute our transformation matrices.
|
|
|
|
All the Win32 APIs that effect transformations or map modes
|
|
will be sent to a helper DC. The helper DC will return a transform
|
|
matrix that converts from World Coordinates to Device Coordinates.
|
|
This transformation matrix is: xformRWorldToRDev.
|
|
|
|
xformRWorldToRDev is combined with the xformRDevToPPage matrix to produce
|
|
the xformRWorldToPPage matrix. All coordinates are mapped through the
|
|
xformRWorldToPPage matrix.
|
|
*/
|
|
|
|
|
|
XFORM xformIdentity = {(FLOAT) 1.0,
|
|
(FLOAT) 0.0,
|
|
(FLOAT) 0.0,
|
|
(FLOAT) 1.0,
|
|
(FLOAT) 0.0,
|
|
(FLOAT) 0.0 } ;
|
|
|
|
|
|
/****************************************************************************
|
|
* Initialize all the matrices.
|
|
****************************************************************************/
|
|
|
|
// Units per millimeter array. It must be in the order of MM_LOMETRIC,
|
|
// MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, MM_TWIPS.
|
|
|
|
FLOAT aeUnitsPerMM[5] = { 10.0f, 100.0f, 3.937f, 39.37f, 56.6928f };
|
|
|
|
BOOL bInitXformMatrices(PLOCALDC pLocalDC, PENHMETAHEADER pmf32header)
|
|
{
|
|
// Init xformRDevToPDev.
|
|
|
|
vInitRecDevToPlayDevXform(pLocalDC, pmf32header) ;
|
|
|
|
// Init xformPDevToPPage and xformPPageToPDev.
|
|
// (aka reference-device to reference-logical) transform.
|
|
|
|
switch(pLocalDC->iMapMode)
|
|
{
|
|
case MM_TEXT:
|
|
case MM_ANISOTROPIC:
|
|
case MM_ISOTROPIC:
|
|
pLocalDC->xformPDevToPPage = xformIdentity ;
|
|
pLocalDC->xformPPageToPDev = xformIdentity ;
|
|
break ;
|
|
|
|
case MM_LOMETRIC:
|
|
case MM_HIMETRIC:
|
|
case MM_LOENGLISH:
|
|
case MM_HIENGLISH:
|
|
case MM_TWIPS:
|
|
{
|
|
FLOAT exUnitsPerPel;
|
|
FLOAT eyUnitsPerPel;
|
|
|
|
// Compute units per pixel.
|
|
|
|
exUnitsPerPel = (FLOAT) pLocalDC->cxPlayDevMM
|
|
/ (FLOAT) pLocalDC->cxPlayDevPels
|
|
* aeUnitsPerMM[pLocalDC->iMapMode - MM_LOMETRIC];
|
|
|
|
eyUnitsPerPel = (FLOAT) pLocalDC->cyPlayDevMM
|
|
/ (FLOAT) pLocalDC->cyPlayDevPels
|
|
* aeUnitsPerMM[pLocalDC->iMapMode - MM_LOMETRIC];
|
|
|
|
pLocalDC->xformPDevToPPage.eM11 = exUnitsPerPel;
|
|
pLocalDC->xformPDevToPPage.eM12 = 0.0f;
|
|
pLocalDC->xformPDevToPPage.eM21 = 0.0f;
|
|
pLocalDC->xformPDevToPPage.eM22 = -eyUnitsPerPel;
|
|
pLocalDC->xformPDevToPPage.eDx = 0.0f;
|
|
pLocalDC->xformPDevToPPage.eDy = 0.0f;
|
|
|
|
pLocalDC->xformPPageToPDev.eM11 = 1.0f / exUnitsPerPel;
|
|
pLocalDC->xformPPageToPDev.eM12 = 0.0f;
|
|
pLocalDC->xformPPageToPDev.eM21 = 0.0f;
|
|
pLocalDC->xformPPageToPDev.eM22 = -1.0f / eyUnitsPerPel;
|
|
pLocalDC->xformPPageToPDev.eDx = 0.0f;
|
|
pLocalDC->xformPPageToPDev.eDy = 0.0f;
|
|
}
|
|
break ;
|
|
}
|
|
|
|
// Init xformRDevToPPage.
|
|
// This xform is used in the SelectClipRegion code.
|
|
|
|
if (!CombineTransform(&pLocalDC->xformRDevToPPage,
|
|
&pLocalDC->xformRDevToPDev,
|
|
&pLocalDC->xformPDevToPPage))
|
|
{
|
|
RIP("MF3216: InitXformMatrices, CombineTransform failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
// We are going to use the helper DC to compute the
|
|
// Record-time-World to Record-time-Device transform.
|
|
|
|
// Set the Helper DC virtual resolution to the Metafiles
|
|
// resolution.
|
|
|
|
if (!SetVirtualResolution(pLocalDC->hdcHelper,
|
|
(INT) pmf32header->szlDevice.cx,
|
|
(INT) pmf32header->szlDevice.cy,
|
|
(INT) pmf32header->szlMillimeters.cx,
|
|
(INT) pmf32header->szlMillimeters.cy))
|
|
{
|
|
RIP("MF3216: InitXformMatrices, SetVirtualResolution failed \n") ;
|
|
return(FALSE);
|
|
}
|
|
|
|
// Init other matrices.
|
|
|
|
return(bComputeCompositeXform(pLocalDC));
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Initialize the Record-time to Play-time scalers. (xformRDevToPDev)
|
|
****************************************************************************/
|
|
VOID vInitRecDevToPlayDevXform(PLOCALDC pLocalDC, PENHMETAHEADER pmf32header)
|
|
{
|
|
FLOAT ecxRecDevPels,
|
|
ecyRecDevPels,
|
|
ecxRecDevMM,
|
|
ecyRecDevMM,
|
|
ecxPlayDevPels,
|
|
ecyPlayDevPels,
|
|
ecxPlayDevMM,
|
|
ecyPlayDevMM,
|
|
exMillsPerPelRec,
|
|
eyMillsPerPelRec,
|
|
exMillsPerPelPlay,
|
|
eyMillsPerPelPlay ;
|
|
|
|
|
|
// Pickup the physical dimensions of the record-time
|
|
// device, both in pels and millimeters.
|
|
// Converts them to floats
|
|
|
|
ecxRecDevPels = (FLOAT) pmf32header->szlDevice.cx ;
|
|
ecyRecDevPels = (FLOAT) pmf32header->szlDevice.cy ;
|
|
ecxRecDevMM = (FLOAT) pmf32header->szlMillimeters.cx ;
|
|
ecyRecDevMM = (FLOAT) pmf32header->szlMillimeters.cy ;
|
|
|
|
// convert the Play-time device dimensions to floats.
|
|
|
|
ecxPlayDevPels = (FLOAT) pLocalDC->cxPlayDevPels ;
|
|
ecyPlayDevPels = (FLOAT) pLocalDC->cyPlayDevPels ;
|
|
ecxPlayDevMM = (FLOAT) pLocalDC->cxPlayDevMM ;
|
|
ecyPlayDevMM = (FLOAT) pLocalDC->cyPlayDevMM ;
|
|
|
|
// Calucalte the pels per millimeter for both the record-time
|
|
// and play-time devices.
|
|
|
|
exMillsPerPelRec = ecxRecDevMM / ecxRecDevPels ;
|
|
eyMillsPerPelRec = ecyRecDevMM / ecyRecDevPels ;
|
|
|
|
exMillsPerPelPlay = ecxPlayDevMM / ecxPlayDevPels ;
|
|
eyMillsPerPelPlay = ecyPlayDevMM / ecyPlayDevPels ;
|
|
|
|
// Init the Record-time-device to the Play-time-device transform.
|
|
// aka the Metafile-device to the Reference-device transform.
|
|
|
|
pLocalDC->xformRDevToPDev.eM11 = exMillsPerPelRec / exMillsPerPelPlay ;
|
|
pLocalDC->xformRDevToPDev.eM12 = (FLOAT) 0.0 ;
|
|
pLocalDC->xformRDevToPDev.eDx = (FLOAT) 0.0 ;
|
|
pLocalDC->xformRDevToPDev.eM21 = (FLOAT) 0.0 ;
|
|
pLocalDC->xformRDevToPDev.eM22 = eyMillsPerPelRec / eyMillsPerPelPlay ;
|
|
pLocalDC->xformRDevToPDev.eDy = (FLOAT) 0.0 ;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
#if 0
|
|
/***************************************************************************
|
|
* vInvertMatrix - Invert a matrix
|
|
**************************************************************************/
|
|
VOID vInvertMatrix(PXFORM pxformSrc, PINVERSMATRIX pinvxfm)
|
|
{
|
|
FLOAT eM11, eM12, eM21, eM22, eDx, eDy,
|
|
detA ;
|
|
|
|
// dereference the matrix elements, just to make the rest of this
|
|
// routine more readable.
|
|
|
|
eM11 = pxformSrc->eM11 ;
|
|
eM12 = pxformSrc->eM12 ;
|
|
eM21 = pxformSrc->eM21 ;
|
|
eM22 = pxformSrc->eM22 ;
|
|
eDx = pxformSrc->eDx ;
|
|
eDy = pxformSrc->eDy ;
|
|
|
|
// First determine the determinant of the source matrix.
|
|
|
|
detA = (eM11 * eM22) - (eM11 * eDy) ;
|
|
|
|
pinvxfm->a1 = eM22 / detA ;
|
|
pinvxfm->a2 = -(eM21 / detA) ;
|
|
pinvxfm->a3 = ((eM21 * eDy) - (eDx * eM22)) / detA ;
|
|
pinvxfm->b1 = -(eM12 / detA) ;
|
|
pinvxfm->b2 = eM11 / detA ;
|
|
pinvxfm->b3 = -(((eM11 * eDy) - (eDx * eM12)) / detA) ;
|
|
pinvxfm->c1 = (FLOAT) 0.0 ;
|
|
pinvxfm->c2 = (FLOAT) 0.0 ;
|
|
pinvxfm->c3 = ((eM11 * eM22) - (eM21 * eM12)) / detA ;
|
|
|
|
// This is just for testing.
|
|
|
|
pinvxfm->a1 = pxformSrc->eM11 ;
|
|
pinvxfm->a2 = pxformSrc->eM12 ;
|
|
pinvxfm->a3 = (FLOAT) 0.0 ;
|
|
pinvxfm->b1 = pxformSrc->eM21 ;
|
|
pinvxfm->b2 = pxformSrc->eM22 ;
|
|
pinvxfm->b3 = (FLOAT) 0.0 ;
|
|
pinvxfm->c1 = pxformSrc->eDx ;
|
|
pinvxfm->c2 = pxformSrc->eDy ;
|
|
pinvxfm->c3 = (FLOAT) 1.0 ;
|
|
|
|
return ;
|
|
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
/***************************************************************************
|
|
* XformPDevToPPage - Do a transform on the array of points passed in.
|
|
*
|
|
* This does the play-time (reference) device to
|
|
* play-time (reference) page (logical) transformation.
|
|
**************************************************************************/
|
|
BOOL bXformPDevToPPage(PLOCALDC pLocalDC, PPOINTL aptl, INT nCount)
|
|
{
|
|
BOOL b ;
|
|
|
|
b = bXformWorkhorse(aptl, nCount, &pLocalDC->xformPDevToPPage) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* XformPPageToPDev - Do a transform on the array of points passed in.
|
|
*
|
|
* This does the play-time (reference) page (logical) to
|
|
* play-time (reference) device transformation.
|
|
**************************************************************************/
|
|
BOOL bXformPPageToPDev(PLOCALDC pLocalDC, PPOINTL aptl, INT nCount)
|
|
{
|
|
BOOL b ;
|
|
|
|
b = bXformWorkhorse(aptl, nCount, &pLocalDC->xformPPageToPDev) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* XformRWorldToRDev - Do a transform on the array of points passed in.
|
|
*
|
|
* This does the Record-time (metafile) world to
|
|
* record-time device translation.
|
|
**************************************************************************/
|
|
BOOL bXformRWorldToRDev(PLOCALDC pLocalDC, PPOINTL aptl, INT nCount)
|
|
{
|
|
BOOL b ;
|
|
|
|
b = bXformWorkhorse(aptl, nCount, &pLocalDC->xformRWorldToRDev) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* XformRDevToRWorld - Do a transform on the array of points passed in.
|
|
*
|
|
* This does the Record-device (metafile) world to
|
|
* record-time world translation.
|
|
**************************************************************************/
|
|
BOOL bXformRDevToRWorld(PLOCALDC pLocalDC, PPOINTL aptl, INT nCount)
|
|
{
|
|
BOOL b ;
|
|
|
|
b = bXformWorkhorse(aptl, nCount, &pLocalDC->xformRDevToRWorld) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* XformRWorldToPPage - Do a transform on the array of points passed in.
|
|
*
|
|
* This is the workhorse translation routine.
|
|
* This translates from record-time-world (aka metafile-world)
|
|
* to record-time-device (aka metafile-device) then from
|
|
* record-time-device (aka metafile-device) to play-time-device
|
|
* (aka reference-device) then from play-time-device
|
|
* (aka reference-device) to play-time-page (reference-logical)
|
|
* space.
|
|
**************************************************************************/
|
|
BOOL bXformRWorldToPPage(PLOCALDC pLocalDC, PPOINTL aptl, DWORD nCount)
|
|
{
|
|
BOOL b ;
|
|
|
|
b = bXformWorkhorse(aptl, nCount, &pLocalDC->xformRWorldToPPage) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* bXformWorkhorse - Transformation Workhorse.
|
|
**************************************************************************/
|
|
BOOL bXformWorkhorse(PPOINTL aptl, DWORD nCount, PXFORM pXform)
|
|
{
|
|
INT i ;
|
|
FLOAT x, y ;
|
|
BOOL b ;
|
|
FLOAT fx, fy;
|
|
|
|
for (i = 0 ; i < (INT) nCount ; i++)
|
|
{
|
|
x = (FLOAT) aptl[i].x ;
|
|
y = (FLOAT) aptl[i].y ;
|
|
fx = (x * pXform->eM11 + y * pXform->eM21 + pXform->eDx) ;
|
|
fy = (x * pXform->eM12 + y * pXform->eM22 + pXform->eDy) ;
|
|
aptl[i].x = (LONG) (fx + ((fx < 0.0) ? -0.5f : 0.5f)) ;
|
|
aptl[i].y = (LONG) (fy + ((fy < 0.0) ? -0.5f : 0.5f)) ;
|
|
}
|
|
|
|
// Do the coordinate overflow detection.
|
|
|
|
b = bCoordinateOverflowTest((PLONG) aptl, nCount * 2) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* vXformWorkhorseFloat - Transformation Workhorse.
|
|
**************************************************************************/
|
|
VOID vXformWorkhorseFloat(PPOINTFL aptfl, UINT nCount, PXFORM pXform)
|
|
{
|
|
UINT i ;
|
|
FLOAT x, y ;
|
|
|
|
for (i = 0 ; i < nCount ; i++)
|
|
{
|
|
x = aptfl[i].x ;
|
|
y = aptfl[i].y ;
|
|
aptfl[i].x = x * pXform->eM11 + y * pXform->eM21 + pXform->eDx;
|
|
aptfl[i].y = x * pXform->eM12 + y * pXform->eM22 + pXform->eDy;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* iMagnitudeXform - Transform the magnitude of a number from
|
|
* Record-time-World to Play-time-Page coordinate space.
|
|
*****************************************************************************/
|
|
INT iMagnitudeXform (PLOCALDC pLocalDC, INT value, INT iType)
|
|
{
|
|
PXFORM pxform ;
|
|
INT iRet ;
|
|
|
|
pxform = &(pLocalDC->xformRWorldToPPage) ;
|
|
|
|
iRet = iMagXformWorkhorse (value, pxform, iType) ;
|
|
|
|
return (iRet) ;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* iMagXformWorkhorse - get the magnitude component of a translated vector
|
|
*****************************************************************************/
|
|
INT iMagXformWorkhorse (INT value, PXFORM pxform, INT iType)
|
|
{
|
|
POINTFL aptfl[2] ;
|
|
FLOAT x1, y1, x2, y2;
|
|
double emag ;
|
|
|
|
// Create a vector, from (0,0) to the point.
|
|
|
|
aptfl[0].x = 0.0f ;
|
|
aptfl[0].y = 0.0f ;
|
|
|
|
if (iType == CX_MAG)
|
|
{
|
|
aptfl[1].x = (FLOAT) value ;
|
|
aptfl[1].y = 0.0f ;
|
|
}
|
|
else
|
|
{
|
|
aptfl[1].x = 0.0f ;
|
|
aptfl[1].y = (FLOAT) value ;
|
|
}
|
|
|
|
vXformWorkhorseFloat(aptfl, 2, pxform);
|
|
|
|
// Now get the magnitude
|
|
|
|
x1 = aptfl[0].x ;
|
|
y1 = aptfl[0].y ;
|
|
x2 = aptfl[1].x ;
|
|
y2 = aptfl[1].y ;
|
|
|
|
emag = sqrt((double) ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))) ;
|
|
|
|
return((INT) (emag + (double) 0.5f));
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* bRotationTest -
|
|
* return - TRUE if there is a rotation or shear in this xform
|
|
* FALSE if there is none.
|
|
*****************************************************************************/
|
|
BOOL bRotationTest(PXFORM pxform)
|
|
{
|
|
BOOL b ;
|
|
|
|
if ( (pxform->eM12 != (FLOAT) 0.0)
|
|
|| (pxform->eM21 != (FLOAT) 0.0)
|
|
)
|
|
{
|
|
b = TRUE ;
|
|
}
|
|
else
|
|
{
|
|
b = FALSE ;
|
|
}
|
|
|
|
return(b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* SetMapMode - Win32 to Win16 Metafile Converter Entry Point
|
|
*
|
|
* All the map mode translations are done by the helper DC.
|
|
* The Helper DC always transforms to device, then we combine the
|
|
* MetafileWorldToDevice with the DeviceToPage transform.
|
|
* This becomes the Win32 to Win16 transform.
|
|
*
|
|
* Some of the metafiles converted from Win16 to Win32 do not
|
|
* define a Viewport extent. Since the Isotropic and AnIsotropic
|
|
* map modes are undefined if either the Viewport Extent or the Window
|
|
* Extent are undefined we will default the Viewport extent to the
|
|
* device extent in the Win32 metafile header.
|
|
**************************************************************************/
|
|
BOOL WINAPI DoSetMapMode
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
DWORD ulMapMode
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
|
|
if (!SetMapMode(pLocalDC->hdcHelper, ulMapMode))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoSetMapMode failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* ScaleWindowsExtEx - Win32 to Win16 Metafile Converter Entry Point
|
|
**************************************************************************/
|
|
BOOL WINAPI DoScaleWindowExt
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
INT Xnum,
|
|
INT Xdenom,
|
|
INT Ynum,
|
|
INT Ydenom
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
// Set the Windows extent
|
|
|
|
if (!ScaleWindowExtEx(pLocalDC->hdcHelper,
|
|
Xnum, Xdenom,
|
|
Ynum, Ydenom,
|
|
(LPSIZE) 0))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoScaleWindowExt failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* ScaleViewportExtEx - Win32 to Win16 Metafile Converter Entry Point
|
|
**************************************************************************/
|
|
BOOL WINAPI DoScaleViewportExt
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
INT Xnum,
|
|
INT Xdenom,
|
|
INT Ynum,
|
|
INT Ydenom
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
// Set the viewport extent
|
|
|
|
if (!ScaleViewportExtEx(pLocalDC->hdcHelper,
|
|
Xnum, Xdenom,
|
|
Ynum, Ydenom,
|
|
(LPSIZE) 0))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoScaleViewportExt failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* SetViewportExtEx - Win32 to Win16 Metafile Converter Entry Point
|
|
**************************************************************************/
|
|
BOOL WINAPI DoSetViewportExt
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
int x,
|
|
int y
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
// Set the viewport extent
|
|
|
|
if (!SetViewportExtEx(pLocalDC->hdcHelper, x, y, (LPSIZE) 0))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoSetViewportExt failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* SetViewportOrgEx - Win32 to Win16 Metafile Converter Entry Point
|
|
**************************************************************************/
|
|
BOOL WINAPI DoSetViewportOrg
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
int x,
|
|
int y
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
// Set the viewport origin
|
|
|
|
if (!SetViewportOrgEx(pLocalDC->hdcHelper, x, y, (LPPOINT) 0))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoSetViewportOrg failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* SetWindowExtEx - Win32 to Win16 Metafile Converter Entry Point
|
|
**************************************************************************/
|
|
BOOL WINAPI DoSetWindowExt
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
int x,
|
|
int y
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
// Set the window extent
|
|
|
|
if (!SetWindowExtEx(pLocalDC->hdcHelper, x, y, (LPSIZE) 0))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoSetWindowExt failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* SetWindowOrgEx - Win32 to Win16 Metafile Converter Entry Point
|
|
*
|
|
* Since we will always record TWIPS in the Win16 metafile,
|
|
* we will transform the WindowOrg from the current MapMode to
|
|
* TWIPS. Then we will set the Dx and Dy elements of the Viewport
|
|
* transformation matrix.
|
|
*
|
|
**************************************************************************/
|
|
BOOL WINAPI DoSetWindowOrg
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
int x,
|
|
int y
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
// Set the window origin
|
|
|
|
if (!SetWindowOrgEx(pLocalDC->hdcHelper, x, y, (LPPOINT) 0))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoSetWindowOrg failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* SetWorldTransform - Win32 to Win16 Metafile Converter Entry Point
|
|
**************************************************************************/
|
|
BOOL WINAPI DoSetWorldTransform
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
PXFORM pxf
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
|
|
// Set the world xform in the helper DC.
|
|
|
|
if (!SetWorldTransform(pLocalDC->hdcHelper, pxf))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoSetWorldTransform failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* ModifyWorldTransform - Win32 to Win16 Metafile Converter Entry Point
|
|
**************************************************************************/
|
|
BOOL WINAPI DoModifyWorldTransform
|
|
(
|
|
PLOCALDC pLocalDC,
|
|
PXFORM pxf,
|
|
DWORD imode
|
|
)
|
|
{
|
|
BOOL b ;
|
|
|
|
// Set the world xform in the helper DC.
|
|
|
|
if (!ModifyWorldTransform(pLocalDC->hdcHelper, pxf, imode))
|
|
{
|
|
ASSERTGDI(FALSE, "MF3216: DoModifyWorldTransform failed\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
b = bComputeCompositeXform(pLocalDC) ;
|
|
|
|
return (b) ;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* bComputeCompositeXform - Compute the composite Xforms.
|
|
*
|
|
* The following transforms are re-computed:
|
|
*
|
|
* xformRWorldToRDev
|
|
* xformRDevToRWorld
|
|
* xformRWorldToPPage
|
|
*
|
|
****************************************************************************/
|
|
BOOL bComputeCompositeXform(PLOCALDC pLocalDC)
|
|
{
|
|
BOOL b ;
|
|
|
|
// Recompute xformRWorldToRDev.
|
|
// Get the record-time world to record-time device xform
|
|
// from the helper DC
|
|
|
|
b = GetTransform(pLocalDC->hdcHelper,
|
|
XFORM_WORLD_TO_DEVICE,
|
|
&pLocalDC->xformRWorldToRDev) ;
|
|
if (b == FALSE)
|
|
{
|
|
RIP("MF3216: bComputeCompositeXform - GetTransform (RWorld to RDev) failed \n") ;
|
|
goto error_exit ;
|
|
}
|
|
|
|
// Recompute xformRDevToRWorld.
|
|
// Get the record-time-device to record-time-world xform
|
|
|
|
b = GetTransform(pLocalDC->hdcHelper,
|
|
XFORM_DEVICE_TO_WORLD,
|
|
&pLocalDC->xformRDevToRWorld) ;
|
|
if (b == FALSE)
|
|
{
|
|
RIP("MF3216: bComputeCompositeXform - GetTransform (RDev To RWorld) failed \n") ;
|
|
goto error_exit ;
|
|
}
|
|
|
|
// Recompute xformRWorldToPPage.
|
|
|
|
b = CombineTransform(&pLocalDC->xformRWorldToPPage,
|
|
&pLocalDC->xformRWorldToRDev,
|
|
&pLocalDC->xformRDevToPPage);
|
|
if (b == FALSE)
|
|
{
|
|
RIP("MF3216: bComputeCompositeXform - CombineTransform failed\n");
|
|
goto error_exit ;
|
|
}
|
|
|
|
// Recompute transform flags.
|
|
|
|
if (pLocalDC->xformRWorldToRDev.eM12 != (FLOAT) 0.0
|
|
|| pLocalDC->xformRWorldToRDev.eM21 != (FLOAT) 0.0)
|
|
pLocalDC->flags |= STRANGE_XFORM ;
|
|
else
|
|
pLocalDC->flags &= ~STRANGE_XFORM ;
|
|
|
|
error_exit:
|
|
return(b) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
* bCoordinateOverflowTest - Test for 1 16 bit coordinate overflow
|
|
*
|
|
* RETURNS: FALSE if there is a coordinate overflow
|
|
* TRUE if there is no overflow.
|
|
**************************************************************************/
|
|
BOOL bCoordinateOverflowTest(PLONG pCoordinates, INT nCount)
|
|
{
|
|
BOOL b ;
|
|
INT i, j ;
|
|
|
|
b = TRUE ;
|
|
for (i = 0 ; i < nCount ; i++)
|
|
{
|
|
|
|
j = pCoordinates[i] ;
|
|
if (j < -32768 || j > 32767)
|
|
{
|
|
b = FALSE ;
|
|
SetLastError(ERROR_ARITHMETIC_OVERFLOW);
|
|
RIP("MF3216: bCoordinateOverflowTest, coordinate overflow\n") ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
return(b) ;
|
|
}
|