|
|
/******************************Module*Header*******************************\
* Module Name: draweng.hxx * * Internal helper functions for GDI draw calls. * * Created: 19-Nov-1990 * Author: J. Andrew Goossen [andrewgo] * * Copyright (c) 1990-1999 Microsoft Corporation * \**************************************************************************/
// This constant defines how many fractional device units to expand
// an ellipse if it will be filled, so that it looks better according
// to our fill conventions:
#define GROW_ELLIPSE_SIZE 4
// Some internal DrawEng structures:
enum PARTIALARC { PARTIALARCTYPE_CONTINUE, PARTIALARCTYPE_MOVETO, PARTIALARCTYPE_LINETO };
// Arctan constants:
#define NEGATE_X 0x01
#define NEGATE_Y 0x02
#define SWITCH_X_AND_Y 0x04
#define OCTANT_0 0
#define OCTANT_1 (SWITCH_X_AND_Y)
#define OCTANT_2 (NEGATE_X | SWITCH_X_AND_Y)
#define OCTANT_3 (NEGATE_X)
#define OCTANT_4 (NEGATE_X | NEGATE_Y)
#define OCTANT_5 (NEGATE_X | NEGATE_Y | SWITCH_X_AND_Y)
#define OCTANT_6 (NEGATE_Y | SWITCH_X_AND_Y)
#define OCTANT_7 (NEGATE_Y)
// The following fraction is for determing the control point
// placements for approximating a quarter-ellipse by a Bezier curve,
// given the vector that describes the side of the bounding box.
//
// It is is the fraction over 2^32 which for the vector of the bound box
// pointing towards the origin, describes the placement of the corresponding
// control point on that vector. This value is equal to
// (4 cos(45)) / (3 cos(45) + 1):
#define QUADRANT_TAU 1922922357L
/******************************Public*Routine******************************\
* VOID vEllipseControlsOut(pvec, pvecResult, peq) * * For a quarter portion of an ellipse, this function, given a vector * pointing away from the origin of the ellipse that describes the * boundbox, returns the vector that describes the placement of the * corresponding control point on that vector. * * History: * 4-Apr-1992 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
inline VOID vEllipseControlsOut( VECTORFX* pvec, // Input vector
VECTORFX* pvecResult, // Output vector
LONGLONG* peq) // Temporary EQUAD. If it's declared here,
// compiler pops function out-line
{ *peq = Int32x32To64(pvec->x, QUADRANT_TAU); pvecResult->x = pvec->x - (LONG) (*peq >> 32);
*peq = Int32x32To64(pvec->y, QUADRANT_TAU); pvecResult->y = pvec->y - (LONG) (*peq >> 32); }
/******************************Public*Routine******************************\
* VOID vEllipseControlsIn(pvec, pvecResult, peq) * * For a quarter portion of an ellipse, this function, given a vector * pointing towards the origin of the ellipse that describes the * boundbox, returns the vector that describes the placement of the * corresponding control point on that vector. * * History: * 4-Apr-1992 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
inline VOID vEllipseControlsIn( VECTORFX* pvec, // Input vector
VECTORFX* pvecResult, // Output vector
LONGLONG* peq) // Temporary EQUAD. If it's declared here,
// compiler pops function out-line
{ *peq = Int32x32To64(pvec->x, QUADRANT_TAU); pvecResult->x = (LONG) (*peq>>32);
*peq = Int32x32To64(pvec->y, QUADRANT_TAU); pvecResult->y = (LONG) (*peq >> 32); }
/************************************Class*********************************\
* class EAPOINTL * * EPOINTL class without any constructors, so that it can be used in * an array. (Compiler mucks up with static constructors.) * * History: * 9-Oct-1991 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
class EAPOINTL : public _POINTL { public: VOID operator=(POINTL& ptl) { x = ptl.x; y = ptl.y; } VOID operator+=(POINTL& ptl) { x += ptl.x; y += ptl.y; } VOID operator-=(POINTL& ptl) { x -= ptl.x; y -= ptl.y; } };
/************************************Class*********************************\
* class EBOX * * Object defining the bounding box for figures requiring one. Useful * for providing a consistent object defining the bound box for the * various uses of the APIs requiring it. * * Arcs must be constructed in device coordinates because the 'snapping' * of the control points to the grid can only be done in device space. * As such, the bounding box goes through the World-to-Device linear * transform and will become a parallelogram. * * Figures requiring a bounding box must be drawn in the same direction * and starting at the same part of the figure, independent of the current * Page-to-Device transform and the ordering of the rectangle given by * the User. When the World-to-Page transform is identity, figures must * be drawn in a counter-clockwise direction for compatiblity with Old * Windows. * * As such, the 'rcl' describing the bound box must be well-ordered so * that (yTop, xLeft) is the upper-left corner of the box in device * coordinates when the World-to-Page transform is indentity (i.e., the * ordering is depedent of the Page-to-Device transform). * * 'rcl' doesn't have to be well-ordered for the Create-region APIs * because it doesn't matter where the figure starts and in what direction * it is drawn when it is converted to a region. * * Public interface: * * EBOX(dco, rcl, pla, bFillEllipse) * // Constructor when PS_INSIDEFRAME and lower-right
* // exclusion has to be done (uses WORLD_TO_DEVICE
* // DC transform on the 'rcl')
* EBOX(xfo, rcl) // Constructor when PS_INSIDEFRAME and lower-right
* // exclusion don't have to be done
* EBOX(ercl, bFillEllipse) * // Constructor for Create-region APIs
* ptlXform(ptef) // Transforms a point constructed on the unit circle
* // centered at the origin to the ellipse described
* // by the bounding box
* bEmpty() // TRUE when no figure will be drawn
* * Public members: * * rclWorld // Original rectangle expressed in world
* // coordinates that defines the box.
* ptlA // Half the vector defining the "horizontal" axis
* // of the ellipse (in device coordinates)
* ptlB // Half the vector defining the "vertical" axis
* // of the ellipse (in device coordinates)
* eptlOrigin // Center of box (in device coordinates). Note that
* // it is rounded and so the figure may be 1/16th of
* // a pel off.
* aptl // Points defining corners of the box (in device
* // coordinates)
* * 1-------------0 * | | * | | * ^ | o <- eptlOrigin * | | | * B | | * | 2-------------3 * * ---A---> * * History: * 19-Nov-1990 -by- J. Andrew Goossen [andrewgo] * Wrote it. \**************************************************************************/
class EBOX /* ebox */ { private: BOOL bIsEmpty; BOOL bIsFillInsideFrame; public: EAPOINTL aeptl[4]; EAPOINTL eptlOrigin; EAPOINTL eptlA; EAPOINTL eptlB; RECTL rclWorld;
EBOX(ERECTL& ercl, BOOL bFillEllipse = FALSE); EBOX(EXFORMOBJ& xfo, RECTL& rcl); EBOX(DCOBJ& dco, RECTL& rcl, PLINEATTRS pla, BOOL bFillEllipse = FALSE); POINTL ptlXform(EPOINTFL& ptef); BOOL bEmpty() { return(bIsEmpty); } BOOL bFillInsideFrame() { return(bIsFillInsideFrame); } };
// Prototypes:
BOOL bPartialArc ( PARTIALARC paType, EPATHOBJ& epo, EBOX& ebox, EPOINTFL& eptefStart, LONG lStartQuadrant, EFLOAT& efStartAngle, EPOINTFL& eptefEnd, LONG lEndQuadrant, EFLOAT& efEndAngle, LONG lQuadrants );
BOOL bEllipse ( EPATHOBJ& epo, EBOX& ebox );
BOOL bRoundRect ( EPATHOBJ& epo, EBOX& ebox, LONG dx, LONG dy );
BOOL bPolyPolygon ( EPATHOBJ& epo, EXFORMOBJ& xfo, PPOINTL pptl, PLONG pcptl, ULONG ccptl, LONG cMaxPoints );
BOOL GreRectBlt ( DCOBJ& dco, ERECTL* percl );
VOID vArctan ( EFLOAT x, EFLOAT y, EFLOAT& efTheta, LONG& lQuadrant );
|