|
|
/*****************************************************************************
* * 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); }
|