Leaked source code of windows server 2003
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.
 
 
 
 
 
 

673 lines
20 KiB

/*****************************************************************************
*
* conics - Entry points for Win32 to Win 16 converter
*
* Date: 7/1/91
* Author: Jeffrey Newman (c-jeffn)
*
* Copyright 1991 Microsoft Corp
*****************************************************************************/
#include "precomp.h"
#pragma hdrstop
FLOAT eRadsPerDegree = (FLOAT) (ePI / (FLOAT) 180.0) ;
BOOL bFindRadialEllipseIntersection(PLOCALDC pLocalDC,
INT x1, INT y1, INT x2, INT y2,
INT x3, INT y3, INT x4, INT y4,
PPOINT pptStart, PPOINT pptEnd) ;
BOOL bIncIncToIncExcXform (PLOCALDC pLocalDC, PRECTL prcl) ;
VOID vDoArcReflection(PLOCALDC pLocalDC, PPOINTL pptl) ;
/***************************************************************************
* DoSetArcDirection - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoSetArcDirection(PLOCALDC pLocalDC, INT iArcDirection)
{
pLocalDC->iArcDirection = iArcDirection ;
return(SetArcDirection(pLocalDC->hdcHelper, iArcDirection) != 0);
}
/***************************************************************************
* AngleArc - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoAngleArc
(
PLOCALDC pLocalDC,
int x,
int y,
DWORD ulRadius,
FLOAT eStartAngle,
FLOAT eSweepAngle
)
{
BOOL b ;
POINTL aptl[4] ;
FLOAT eEndAngle;
INT iArcDirection;
// If we're recording the drawing orders for a path
// then just pass the drawing order to the helper DC.
// Do not emit any Win16 drawing orders.
if (pLocalDC->flags & RECORDING_PATH)
{
if (pfnSetVirtualResolution == NULL)
{
POINTL p = {x, y};
bXformWorkhorse(&p, 1, &pLocalDC->xformRWorldToRDev);
b = AngleArc(pLocalDC->hdcHelper, p.x, p.y, ulRadius, eStartAngle, eSweepAngle) ;
}
else
{
b = AngleArc(pLocalDC->hdcHelper, x, y, ulRadius, eStartAngle, eSweepAngle) ;
}
ASSERTGDI(b, "MF3216: DoAngleArc, in path render failed\n") ;
return(b) ;
}
// Do the transformations.
// And emit the Win16 drawing orders.
if (pLocalDC->flags & STRANGE_XFORM
|| eSweepAngle > 360.0f // more than one revolution
|| eSweepAngle < -360.0f
)
{
b = bRenderCurveWithPath(pLocalDC, (LPPOINT) NULL, (PBYTE) NULL, 0,
x, y, 0, 0, 0, 0, 0, 0,
ulRadius, eStartAngle, eSweepAngle, EMR_ANGLEARC);
return(b);
}
// Calculate the ARC bounding box.
aptl[0].x = x - ulRadius ;
aptl[0].y = y - ulRadius ;
aptl[1].x = x + ulRadius ;
aptl[1].y = y + ulRadius ;
// Calculate the begin and end points for ARC from the
// eStartAngle and eSweepAngle.
aptl[2].x = x + (LONG) ((double) (ulRadius) * cos(eStartAngle * eRadsPerDegree) + 0.5f) ;
aptl[2].y = y - (LONG) ((double) (ulRadius) * sin(eStartAngle * eRadsPerDegree) + 0.5f) ;
eEndAngle = eStartAngle + eSweepAngle ;
aptl[3].x = x + (LONG) ((double) (ulRadius) * cos(eEndAngle * eRadsPerDegree) + 0.5f) ;
aptl[3].y = y - (LONG) ((double) (ulRadius) * sin(eEndAngle * eRadsPerDegree) + 0.5f) ;
// If the endpoints are identical, we cannot represent the AngleArc as
// an ArcTo. Use path to render it instead.
if (aptl[2].x == aptl[3].x && aptl[2].y == aptl[3].y)
{
b = bRenderCurveWithPath(pLocalDC, (LPPOINT) NULL, (PBYTE) NULL, 0,
x, y, 0, 0, 0, 0, 0, 0,
ulRadius, eStartAngle, eSweepAngle, EMR_ANGLEARC);
return(b);
}
// At this point we have the same parameters that would apply to
// a standard ArcTo. However, we still need to determine the arc
// direction to apply. If the sweep angle is positive, it is counter-
// clockwise. If the sweep angle is negative, it is clockwise.
// Save the current arc direction.
iArcDirection = pLocalDC->iArcDirection;
// Prepare the arc direction for the ArcTo.
(void) DoSetArcDirection
(pLocalDC, eSweepAngle < 0.0f ? AD_CLOCKWISE : AD_COUNTERCLOCKWISE);
// Do the ArcTo.
b = DoArcTo(pLocalDC, aptl[0].x, aptl[0].y, aptl[1].x, aptl[1].y,
aptl[2].x, aptl[2].y, aptl[3].x, aptl[3].y) ;
// Restore the current arc direction.
(void) DoSetArcDirection(pLocalDC, iArcDirection);
return (b) ;
}
/***************************************************************************
* Arc - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoArc
(
PLOCALDC pLocalDC,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
)
{
BOOL b ;
b = bConicCommon (pLocalDC, x1, y1, x2, y2, x3, y3, x4, y4, EMR_ARC) ;
return(b) ;
}
/***************************************************************************
* ArcTo - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoArcTo
(
PLOCALDC pLocalDC,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
)
{
BOOL b ;
POINT ptStart,
ptEnd ;
// If we're recording the drawing orders for a path
// then just pass the drawing order to the helper DC.
// Do not emit any Win16 drawing orders.
if (pLocalDC->flags & RECORDING_PATH)
{
if (pfnSetVirtualResolution == NULL)
{
POINTL p[4] = {x1, y1, x2, y2, x3, y3, x4, y4};
bXformWorkhorse(p, 4, &pLocalDC->xformRWorldToRDev);
b = ArcTo(pLocalDC->hdcHelper, p[0].x, p[0].y, p[1].x, p[1].y,
p[2].x, p[2].y, p[3].x, p[3].y) ;
}
else
{
b = ArcTo(pLocalDC->hdcHelper, x1, y1, x2, y2, x3, y3, x4, y4) ;
}
return(b) ;
}
b = bFindRadialEllipseIntersection(pLocalDC,
x1, y1, x2, y2,
x3, y3, x4, y4,
&ptStart, &ptEnd) ;
if (b == FALSE)
return(b) ;
b = DoLineTo(pLocalDC, ptStart.x, ptStart.y) ;
if (b == FALSE)
return(b) ;
b = DoArc(pLocalDC, x1, y1, x2, y2, x3, y3, x4, y4) ;
if (b == FALSE)
return(b) ;
b = DoMoveTo(pLocalDC, ptEnd.x, ptEnd.y) ;
return(b) ;
}
/***************************************************************************
* Chord - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoChord
(
PLOCALDC pLocalDC,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
)
{
BOOL b ;
b = bConicCommon (pLocalDC, x1, y1, x2, y2, x3, y3, x4, y4, EMR_CHORD) ;
return(b) ;
}
/***************************************************************************
* Ellipse - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoEllipse
(
PLOCALDC pLocalDC,
int x1,
int y1,
int x2,
int y2
)
{
BOOL b ;
b = bConicCommon (pLocalDC, x1, y1, x2, y2, 0, 0, 0, 0, EMR_ELLIPSE) ;
return(b) ;
}
/***************************************************************************
* Pie - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoPie
(
PLOCALDC pLocalDC,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
)
{
BOOL b ;
b = bConicCommon (pLocalDC, x1, y1, x2, y2, x3, y3, x4, y4, EMR_PIE) ;
return(b) ;
}
/***************************************************************************
* bConicCommon - The mother of all conic translations.
* They are Arc, Chord, Pie, Ellipse, Rectangle and RoundRect.
**************************************************************************/
BOOL bConicCommon (PLOCALDC pLocalDC, INT x1, INT y1, INT x2, INT y2,
INT x3, INT y3, INT x4, INT y4,
DWORD mrType)
{
SHORT sx1, sx2, sx3, sx4,
sy1, sy2, sy3, sy4 ;
LONG nPointls ;
POINTL aptl[4] ;
BOOL b ;
// If we're recording the drawing orders for a path
// then just pass the drawing order to the helper DC.
// Do not emit any Win16 drawing orders.
if (pLocalDC->flags & RECORDING_PATH)
{
POINTL ppts[4] = {x1, y1, x2, y2, x3, y3, x4, y4};
if (pfnSetVirtualResolution == NULL)
{
if (!bXformWorkhorse(ppts, 4, &pLocalDC->xformRWorldToRDev))
{
return(FALSE) ;
}
}
switch(mrType)
{
case EMR_ARC:
b = Arc(pLocalDC->hdcHelper, ppts[0].x, ppts[0].y, ppts[1].x, ppts[1].y,
ppts[2].x, ppts[2].y, ppts[3].x, ppts[3].y);
break ;
case EMR_CHORD:
b = Chord(pLocalDC->hdcHelper, ppts[0].x, ppts[0].y, ppts[1].x, ppts[1].y,
ppts[2].x, ppts[2].y, ppts[3].x, ppts[3].y);
break ;
case EMR_ELLIPSE:
b = Ellipse(pLocalDC->hdcHelper, ppts[0].x, ppts[0].y, ppts[1].x, ppts[1].y);
break ;
case EMR_PIE:
b = Pie(pLocalDC->hdcHelper, ppts[0].x, ppts[0].y, ppts[1].x, ppts[1].y,
ppts[2].x, ppts[2].y, ppts[3].x, ppts[3].y);
break ;
case EMR_RECTANGLE:
b = Rectangle(pLocalDC->hdcHelper, ppts[0].x, ppts[0].y, ppts[1].x, ppts[1].y);
break ;
case EMR_ROUNDRECT:
b = RoundRect(pLocalDC->hdcHelper, ppts[0].x, ppts[0].y, ppts[1].x, ppts[1].y,
ppts[2].x, ppts[2].y);
break ;
default:
b = FALSE;
RIPS("MF3216: bConicCommon, bad mrType");
break ;
}
ASSERTGDI(b, "MF3216: bConicCommon, in path render failed\n") ;
return(b) ;
}
// Do the transformations.
// And emit the Win16 drawing orders.
if (pLocalDC->flags & STRANGE_XFORM)
{
b = bRenderCurveWithPath(pLocalDC, (LPPOINT) NULL, (PBYTE) NULL, 0,
x1, y1, x2, y2, x3, y3, x4, y4, 0, 0.0f, 0.0f, mrType);
return(b);
}
// Do the simple transform case.
// Compute the number of points
nPointls = (LONG) (sizeof(aptl) / sizeof(POINTL)) ;
// Assign all the coordinates into an array for conversion.
aptl[0].x = x1 ;
aptl[0].y = y1 ;
aptl[1].x = x2 ;
aptl[1].y = y2 ;
aptl[2].x = x3 ;
aptl[2].y = y3 ;
aptl[3].x = x4 ;
aptl[3].y = y4 ;
// Take care of the arc direction.
switch (mrType)
{
case EMR_ARC:
case EMR_CHORD:
case EMR_PIE:
vDoArcReflection(pLocalDC, &aptl[2]) ;
break ;
default:
break ;
}
// Do the Record-time World to Play-time Page transformations.
// The radial definitions need only a world to page xform,
// and the ellipse definitions for roundrects only require
// a magnitude transformation.
if (mrType != EMR_ROUNDRECT)
{
b = bXformRWorldToPPage(pLocalDC, (PPOINTL) aptl, nPointls) ;
if (!b)
goto exit1 ;
}
else
{
/*
For roundrects do a Record-time-World to Play-time-Page
transform of the bounding box only. Then a magnatude only
transform of the corner ellipse definitions.
*/
b = bXformRWorldToPPage(pLocalDC, (PPOINTL) aptl, 2) ;
if (!b)
goto exit1 ;
aptl[2].x = iMagnitudeXform(pLocalDC, aptl[2].x, CX_MAG) ;
aptl[2].y = iMagnitudeXform(pLocalDC, aptl[2].y, CY_MAG) ;
aptl[3].x = iMagnitudeXform(pLocalDC, aptl[3].x, CX_MAG) ;
aptl[3].y = iMagnitudeXform(pLocalDC, aptl[3].y, CY_MAG) ;
}
// The bounding boxes for
// all the conics and rectangles that are handled by this
// common routine are inclusive-inclusive, and they must
// be transformed to the inclusive-exclusive Win16 form.
b = bIncIncToIncExcXform(pLocalDC, (PRECTL) &aptl[0]) ;
if (!b)
goto exit1 ;
// Assign the converted coordinates variables suited to
// the Win16 metafile.
sx1 = LOWORD(aptl[0].x) ;
sy1 = LOWORD(aptl[0].y) ;
sx2 = LOWORD(aptl[1].x) ;
sy2 = LOWORD(aptl[1].y) ;
sx3 = LOWORD(aptl[2].x) ;
sy3 = LOWORD(aptl[2].y) ;
sx4 = LOWORD(aptl[3].x) ;
sy4 = LOWORD(aptl[3].y) ;
// Emit the Win16 drawing orders to the Win16 metafile.
switch(mrType)
{
case EMR_ARC:
b = bEmitWin16Arc(pLocalDC, sx1, sy1, sx2, sy2,
sx3, sy3, sx4, sy4) ;
break ;
case EMR_CHORD:
b = bEmitWin16Chord(pLocalDC, sx1, sy1, sx2, sy2,
sx3, sy3, sx4, sy4) ;
break ;
case EMR_ELLIPSE:
b = bEmitWin16Ellipse(pLocalDC, sx1, sy1, sx2, sy2) ;
break ;
case EMR_PIE:
b = bEmitWin16Pie(pLocalDC, sx1, sy1, sx2, sy2,
sx3, sy3, sx4, sy4) ;
break ;
case EMR_RECTANGLE:
b = bEmitWin16Rectangle(pLocalDC, sx1, sy1, sx2, sy2) ;
break ;
case EMR_ROUNDRECT:
b = bEmitWin16RoundRect(pLocalDC, sx1, sy1, sx2, sy2, sx3, sy3) ;
break ;
default:
RIPS("MF3216: bConicCommon, bad mrType");
break ;
}
exit1:
return (b) ;
}
/*****************************************************************************
* vDoArcReflection - Test for an inversion in the RWorld to PPage matrix.
* If one and only one is found then swap the start
* and end position for the conics.
*****************************************************************************/
VOID vDoArcReflection(PLOCALDC pLocalDC, PPOINTL pptl)
{
FLOAT eM11,
eM22 ;
POINTL ptl ;
BOOL bFlip ;
// Win16 assumes the counter-clockwise arc direction in the
// device coordinates. Win32 defines the arc direction in the
// world coordinates.
// Assume no flipping of start and end points.
bFlip = FALSE ;
// Account for current arc direction.
if (pLocalDC->iArcDirection == AD_CLOCKWISE)
bFlip = !bFlip;
// If there is an inversion in the xform matrix then invert
// the arc direction.
eM11 = pLocalDC->xformRWorldToPPage.eM11 ;
eM22 = pLocalDC->xformRWorldToPPage.eM22 ;
if ( (eM11 < 0.0f && eM22 > 0.0f)
||(eM11 > 0.0f && eM22 < 0.0f)
)
bFlip = !bFlip;
// If the REQUESTED Win16 mapmode is fixed, then invert the
// arc direction.
switch(pLocalDC->iMapMode)
{
case MM_LOMETRIC:
case MM_HIMETRIC:
case MM_LOENGLISH:
case MM_HIENGLISH:
case MM_TWIPS:
bFlip = !bFlip;
break ;
}
if (bFlip)
SWAP(pptl[0], pptl[1], ptl);
return ;
}
/*****************************************************************************
* bIncIncToIncExcXform - Inclusize Inclusive To Inclusive Exclusize
* transform in play time coordinate space.
*****************************************************************************/
BOOL bIncIncToIncExcXform (PLOCALDC pLocalDC, PRECTL prcl)
{
LONG l;
// Convert the points from Playtime Page to Playtime Device space.
if (!bXformPPageToPDev(pLocalDC, (PPOINTL) prcl, 2))
return(FALSE);
// Reorder the rectangle
if (prcl->left > prcl->right)
SWAP(prcl->left, prcl->right, l);
if (prcl->top > prcl->bottom)
SWAP(prcl->top, prcl->bottom, l);
// Expand the right and bottom by one pixel.
prcl->right++ ;
prcl->bottom++ ;
// Convert the points back to Playtime Page space
return(bXformPDevToPPage(pLocalDC, (PPOINTL) prcl, 2));
}
/*****************************************************************************
* bFindRadialEllipseIntersection - Calculate the intersection of a radial
* and an Ellipse.
*
* Play the ArcTo into a path then query the path for the first and
* last points on the Arc.
*****************************************************************************/
BOOL bFindRadialEllipseIntersection(PLOCALDC pLocalDC,
INT x1, INT y1, INT x2, INT y2,
INT x3, INT y3, INT x4, INT y4,
LPPOINT pptStart, LPPOINT pptEnd)
{
BOOL b;
POINT ptCP;
POINTL ppts[4] = {x1, y1, x2, y2, x3, y3, x4, y4};
b = FALSE; // assume failure
// Save the current position in the helper DC.
if (!GetCurrentPositionEx(pLocalDC->hdcHelper, &ptCP))
return(FALSE);
if (pfnSetVirtualResolution == NULL)
{
if (!bXformWorkhorse(ppts, 4, &pLocalDC->xformRWorldToRDev))
{
goto exit_bFindRadialEllipseIntersection;
}
}
// Do an ArcTo with the same start radial line.
if (!ArcTo(pLocalDC->hdcHelper, ppts[0].x, ppts[0].y, ppts[1].x, ppts[1].y,
ppts[2].x, ppts[2].y, ppts[2].x, ppts[2].y))
goto exit_bFindRadialEllipseIntersection;
// Get the start point of the arc. It is the current position.
if (!GetCurrentPositionEx(pLocalDC->hdcHelper, pptStart))
goto exit_bFindRadialEllipseIntersection;
if (pfnSetVirtualResolution == NULL)
{
// On Win9x we need to convert from Device Units in the Helper DC
// to WorldUnits
if (!bXformWorkhorse((PPOINTL) pptStart, 1, &pLocalDC->xformRDevToRWorld))
goto exit_bFindRadialEllipseIntersection;
}
// Continue with the ArcTo with the same end radial line this time.
if (!ArcTo(pLocalDC->hdcHelper, ppts[0].x, ppts[0].y, ppts[1].x, ppts[1].y,
ppts[3].x, ppts[3].y, ppts[3].x, ppts[3].y))
goto exit_bFindRadialEllipseIntersection;
// Get the end point of the arc. It is the current position.
if (!GetCurrentPositionEx(pLocalDC->hdcHelper, pptEnd))
goto exit_bFindRadialEllipseIntersection;
if (pfnSetVirtualResolution == NULL)
{
// On Win9x we need to convert from Device Units in the Helper DC
// to WorldUnits
if (!bXformWorkhorse((PPOINTL) pptEnd, 1, &pLocalDC->xformRDevToRWorld))
goto exit_bFindRadialEllipseIntersection;
}
// Everything is golden.
b = TRUE;
exit_bFindRadialEllipseIntersection:
// Restore the current position in the helper DC.
if (!MoveToEx(pLocalDC->hdcHelper, ptCP.x, ptCP.y, (LPPOINT) NULL))
RIPS("MF3216: bFindRadialEllipseIntersection, MoveToEx failed");
return(b);
}