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.
645 lines
20 KiB
645 lines
20 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: pathwide.hxx
|
|
*
|
|
* Path widening defines.
|
|
*
|
|
* CLASS HIERARCHY
|
|
*
|
|
* In constructing the wide-line, we keep track of 4 paths:
|
|
*
|
|
* 1) The original path.
|
|
* 2) The path holding the vertices of the polygonized pen.
|
|
* 3) The 'left' side of the wide-line outline.
|
|
* 4) The 'right' side of the wide-line outline.
|
|
*
|
|
* To keep track of the latter 3 paths, we use:
|
|
*
|
|
* PATHMEMOBJ // Regular path
|
|
* |
|
|
* v
|
|
* WIDEPATHOBJ // Path object to keep track of one side of the
|
|
* | // wide-line. Adds methods for easily adding
|
|
* | // one point at a time.
|
|
* v
|
|
* WIDEPENOBJ // Path object to keep the pen shape. A pen is
|
|
* // composed of an arbitrary number of points,
|
|
* // like a path, so we make it a path. Plus we
|
|
* // add some pen functionality.
|
|
*
|
|
* It was useful to compartmentalize the task of the widener into separate
|
|
* base classes:
|
|
*
|
|
* READER // Reads the original path a point at a time
|
|
* |
|
|
* v
|
|
* LINER // Reads the path a line at a time (flattening
|
|
* | // Beziers and generating close-figure lines as
|
|
* | // it goes).
|
|
* v
|
|
* STYLER // Handles styling by hacking the lines into
|
|
* | // itty bitty pieces.
|
|
* v
|
|
* WIDENER // Widens the path by generating the points at
|
|
* // every line-join and end-cap.
|
|
*
|
|
* Created: 9-Oct-1991
|
|
* Author: J. Andrew Goossen [andrewgo]
|
|
*
|
|
* Copyright (c) 1991-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#if DBG
|
|
// #define DEBUG_WIDE
|
|
#endif
|
|
|
|
class WIDENER;
|
|
|
|
#define SQUARE(x) ((x) * (x))
|
|
#define LPLUSHALFTOFX(x) (LTOFX(x) + (LTOFX(1) >> 1))
|
|
|
|
/***********************************Struct*********************************\
|
|
* struct HOBBY
|
|
*
|
|
* Structure used for containing half a Hobby pen.
|
|
*
|
|
* History:
|
|
* 9-Oct-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
typedef struct _HOBBY
|
|
{
|
|
PPOINTFIX pptfx;
|
|
COUNT cptfx;
|
|
} HOBBY, *PHOBBY; /* hob, phob */
|
|
|
|
/*********************************class************************************\
|
|
* class EVECTORFLEXT
|
|
*
|
|
* Can use VECTORFX's.
|
|
*
|
|
* History:
|
|
* 22-Oct-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
class EVECTORFLEXT : public EVECTORFL /* evecfl */
|
|
{
|
|
public:
|
|
EVECTORFLEXT(VECTORFX& vec)
|
|
{
|
|
x.vFxToEf(vec.x);
|
|
y.vFxToEf(vec.y);
|
|
}
|
|
BOOL bToVECTORFX(VECTORFX& vec)
|
|
{
|
|
return(x.bEfToFx(vec.x) && y.bEfToFx(vec.y));
|
|
}
|
|
};
|
|
|
|
/*********************************class************************************\
|
|
* class LINEDATA
|
|
*
|
|
* Keeps track of useful stuff about the current line in the original
|
|
* path that we're processing.
|
|
*
|
|
* History:
|
|
* 22-Oct-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
// LINEDATA flags:
|
|
|
|
#define LDF_INVERT 0x0001L
|
|
#define LDF_VECSQUARECOMPUTED 0x0002L
|
|
#define LDF_VECPERPCOMPUTED 0x0004L
|
|
#define LDF_VECDRAWCOMPUTED 0x0008L
|
|
#define LDF_NORMALIZEDCOMPUTED 0x0010L
|
|
|
|
class LINEDATA /* ld */
|
|
{
|
|
public:
|
|
FLONG fl; // LINEDATA flags, as above
|
|
|
|
PPATHREC ppr; // Pathrecord containing point
|
|
PPOINTFIX pptfx; // *pptfx == -ptfx if bInvert is TRUE
|
|
LONGLONG fxCrossStart;
|
|
LONGLONG fxCrossEnd;
|
|
|
|
EVECTORFX vecLine; // Actual line vector
|
|
EVECTORFX vecTangent; // True tangent to current point. Direction
|
|
// only -- to be used for calculating perps
|
|
|
|
// Cached values:
|
|
|
|
EVECTORFX vecSquare; // Vector to offset to square cap start
|
|
EVECTORFX vecPerp; // Perpendicular vector to line
|
|
EVECTORFX vecDraw; // Drawing vector for line
|
|
POINTFL ptflNormalized; // Normalized version of line vector
|
|
|
|
BOOL bInvert() { return(fl & LDF_INVERT); }
|
|
VOID vSetInvert() { fl |= LDF_INVERT; }
|
|
VOID vClearInvert() { fl &= ~LDF_INVERT; }
|
|
|
|
VOID vSetVecSquareComputed() { fl |= LDF_VECSQUARECOMPUTED; }
|
|
VOID vSetVecPerpComputed() { fl |= LDF_VECPERPCOMPUTED; }
|
|
VOID vSetVecDrawComputed() { fl |= LDF_VECDRAWCOMPUTED; }
|
|
VOID vSetNormalizedComputed() { fl |= LDF_NORMALIZEDCOMPUTED; }
|
|
|
|
BOOL bVecSquareComputed() { return(fl & LDF_VECSQUARECOMPUTED); }
|
|
BOOL bVecPerpComputed() { return(fl & LDF_VECPERPCOMPUTED); }
|
|
BOOL bVecDrawComputed() { return(fl & LDF_VECDRAWCOMPUTED); }
|
|
BOOL bNormalizedComputed() { return(fl & LDF_NORMALIZEDCOMPUTED); }
|
|
|
|
VOID vInit() { fl = 0; }
|
|
|
|
VOID vInit(POINTFIX& ptfxEnd, POINTFIX& ptfxStart)
|
|
{ fl = 0;
|
|
vecLine = ptfxEnd;
|
|
vecLine -= ptfxStart;
|
|
vecTangent = vecLine; }
|
|
|
|
// bToLeftSide() returns true if the perpendicular for the line
|
|
// falls to the left of the draw vector:
|
|
|
|
BOOL bToLeftSide() { return(fxCrossStart > fxCrossEnd); }
|
|
|
|
// bSamePenSection() returns true if the two lines have perpendicular
|
|
// vectors in the same area:
|
|
|
|
BOOL bSamePenSection(LINEDATA& ld)
|
|
{
|
|
return((pptfx == ld.pptfx) && (bToLeftSide() == ld.bToLeftSide()));
|
|
}
|
|
};
|
|
|
|
typedef LINEDATA *PLINEDATA;
|
|
|
|
/*********************************Class************************************\
|
|
* class WIDEPATHOBJ
|
|
*
|
|
* History:
|
|
* 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
class WIDEPATHOBJ : public PATHMEMOBJ /* wpath */
|
|
{
|
|
private:
|
|
#ifdef DEBUG_WIDE
|
|
BOOL bOpenPath;
|
|
#endif
|
|
|
|
protected:
|
|
BOOL bOutOfMemory;
|
|
|
|
PPOINTFIX pptfxPathRecCurrent;
|
|
PPOINTFIX pptfxPathRecEnd;
|
|
PPATHREC pprFigureStart;
|
|
|
|
BOOL bGrowPath();
|
|
VOID vGrowPathAndAddPoint(
|
|
PPOINTFIX, PEVECTORFX = (PEVECTORFX) NULL, BOOL = FALSE);
|
|
|
|
public:
|
|
WIDEPATHOBJ()
|
|
{
|
|
bOutOfMemory = FALSE;
|
|
|
|
#ifdef DEBUG_WIDE
|
|
bOpenPath = FALSE;
|
|
#endif
|
|
}
|
|
|
|
~WIDEPATHOBJ() {}
|
|
|
|
VOID vAddPoint(PPOINTFIX pptfx, BOOL bAddRecordIfNeeded = TRUE)
|
|
{
|
|
#ifdef DEBUG_WIDE
|
|
ASSERTGDI(bOpenPath, "vAddPoint path not open!");
|
|
#endif
|
|
|
|
if (pptfxPathRecCurrent >= pptfxPathRecEnd)
|
|
{
|
|
#ifdef DEBUG_WIDE
|
|
ASSERTGDI(pptfxPathRecCurrent == pptfxPathRecEnd,
|
|
"vAddPoint out of bounds!");
|
|
#endif
|
|
|
|
if (bAddRecordIfNeeded)
|
|
vGrowPathAndAddPoint(pptfx);
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_WIDE
|
|
ASSERTGDI((PBYTE) pptfxPathRecCurrent - (PBYTE) ppath->ppachain
|
|
< (LONG) ppath->ppachain->siztPathAlloc, "vAddPoint out of bounds.");
|
|
#endif
|
|
|
|
*pptfxPathRecCurrent++ = *pptfx;
|
|
}
|
|
}
|
|
|
|
VOID vAddPoint(PPOINTFIX pptfx, PEVECTORFX pvec, BOOL bInvert)
|
|
{
|
|
#ifdef DEBUG_WIDE
|
|
ASSERTGDI(bOpenPath, "vAddPoint2 path not open!");
|
|
#endif
|
|
|
|
if (pptfxPathRecCurrent >= pptfxPathRecEnd)
|
|
{
|
|
#ifdef DEBUG_WIDE
|
|
ASSERTGDI(pptfxPathRecCurrent == pptfxPathRecEnd,
|
|
"vAddPoint2 out of bounds!");
|
|
#endif
|
|
|
|
vGrowPathAndAddPoint(pptfx, pvec, bInvert);
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_WIDE
|
|
ASSERTGDI((PBYTE) pptfxPathRecCurrent - (PBYTE) ppath->ppachain
|
|
< (LONG) ppath->ppachain->siztPathAlloc, "vAddPoint2 out of bounds.");
|
|
#endif
|
|
|
|
// 'bInvert' will usually be constant, and so one of these code
|
|
// paths will optimize away:
|
|
|
|
if (bInvert)
|
|
{
|
|
pptfxPathRecCurrent->x = pptfx->x - pvec->x;
|
|
pptfxPathRecCurrent->y = pptfx->y - pvec->y;
|
|
}
|
|
else
|
|
{
|
|
pptfxPathRecCurrent->x = pptfx->x + pvec->x;
|
|
pptfxPathRecCurrent->y = pptfx->y + pvec->y;
|
|
}
|
|
|
|
pptfxPathRecCurrent++;
|
|
}
|
|
}
|
|
|
|
VOID vReverseConcatenate(WIDEPATHOBJ&);
|
|
VOID vPrependBeforeFigure();
|
|
VOID vPrependBeforeSubpath();
|
|
|
|
VOID vMarkFigureStart() { pprFigureStart = ppath->pprlast; }
|
|
|
|
BOOL bBeginFigure();
|
|
VOID vEndFigure();
|
|
VOID vCloseFigure() { ppath->pprlast->flags |= PD_CLOSEFIGURE; }
|
|
|
|
BOOL bValid() { return(PATHMEMOBJ::bValid() && !bOutOfMemory); }
|
|
VOID vSetError() { bOutOfMemory = TRUE; }
|
|
};
|
|
|
|
/******************************Public*Routine******************************\
|
|
* WIDEPATHOBJ::vAddPoint(pptfx, pvec, bInvert)
|
|
*
|
|
* Adds a single point to the path. The added point is the given point
|
|
* plus the specified vector (minus the vector if bInvert is TRUE).
|
|
*
|
|
* History:
|
|
* 1-Oct-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
/*********************************Class************************************\
|
|
* class WIDEPENOBJ
|
|
*
|
|
* History:
|
|
* 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
class WIDEPENOBJ : public WIDEPATHOBJ /* wpen */
|
|
{
|
|
private:
|
|
|
|
// Pre-computed look-up tables containing points of circular Hobby pens
|
|
// for widths 1 through 6:
|
|
|
|
#define HOBBY_TABLE_SIZE 6L
|
|
|
|
static POINTFIX aptfxHobby1[4];
|
|
static POINTFIX aptfxHobby2[5];
|
|
static POINTFIX aptfxHobby3[6];
|
|
static POINTFIX aptfxHobby4[8];
|
|
static POINTFIX aptfxHobby5[10];
|
|
static POINTFIX aptfxHobby6[10];
|
|
|
|
static HOBBY ahob[HOBBY_TABLE_SIZE];
|
|
|
|
BOOL bHobby; // TRUE if this is a Hobby pen
|
|
BOOL bThicken(PPOINTFIX pptfx); // Thickens pen if need-be
|
|
BOOL bHobbyize(EVECTORFX avec[]);// Makes a Hobby pen if need-be
|
|
BOOL bPenFlatten(PPOINTFIX); // Converts Beziers to lines
|
|
VOID vAddPenPoint(PPOINTFIX); // Adds a point to the end of our path
|
|
|
|
public:
|
|
WIDEPENOBJ() { bHobby = FALSE; }
|
|
|
|
BOOL bIsHobby() { return(bHobby); }
|
|
BOOL bIsHobby(BOOL b) { return(bHobby = b); }
|
|
|
|
BOOL bPolygonizePen(EXFORMOBJ&, LONG);
|
|
VOID vDetermineDrawVertex(EVECTORFX&, LINEDATA&);
|
|
COUNT cptAddRound(WIDENER&, LINEDATA&, LINEDATA&,
|
|
BOOL, BOOL, BOOL);
|
|
VOID vAddRoundEndCap(WIDENER&, LINEDATA&, BOOL, BOOL);
|
|
};
|
|
|
|
|
|
/*********************************class************************************\
|
|
* class READER
|
|
*
|
|
* Reads the path.
|
|
*
|
|
* History:
|
|
* 22-Oct-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
// Path widening flags:
|
|
|
|
#define FW_MORETOENUM 0x00000001L
|
|
#define FW_DOINGSTYLES 0x00000002L
|
|
#define FW_STYLENEXT 0x00000004L
|
|
#define FW_FIGURESTYLED 0x00000008L
|
|
#define FW_ALLROUND 0x00000010L
|
|
|
|
class READER
|
|
{
|
|
private:
|
|
EPATHOBJ* pepoSpine;
|
|
PATHDATA pd;
|
|
|
|
VOID vMoreToEnum(BOOL b) { vSetFlag(b, FW_MORETOENUM); }
|
|
BOOL bMoreToEnum() { return(fl & FW_MORETOENUM); }
|
|
|
|
PPOINTFIX pptfxRead;
|
|
PPOINTFIX pptfxEnd;
|
|
|
|
protected:
|
|
FLONG fl; // For widening flags, as above
|
|
|
|
VOID vSetFlag(BOOL b, FLONG flBit)
|
|
{
|
|
if (b)
|
|
fl |= flBit;
|
|
else
|
|
fl &= ~flBit;
|
|
}
|
|
|
|
READER(EPATHOBJ& epo) { pepoSpine = &epo;
|
|
pepoSpine->vEnumStart();
|
|
vMoreToEnum(TRUE); }
|
|
|
|
BOOL bIsBezier() { return(pd.flags & PD_BEZIERS); }
|
|
|
|
BOOL bNextFigure();
|
|
BOOL bNextPoint(POINTFIX& ptfx);
|
|
|
|
// Only valid when !bNextPoint():
|
|
|
|
BOOL bIsClosedFigure() { return(pd.flags & PD_CLOSEFIGURE); }
|
|
};
|
|
|
|
|
|
/*********************************class************************************\
|
|
* class LINER
|
|
*
|
|
* Cracks Beziers and handles CloseFigures.
|
|
*
|
|
* History:
|
|
* 22-Oct-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
enum WIDENEVENT { WE_STARTFIGURE, // Figure starts at 'ptfxThis'
|
|
WE_ENDFIGURE, // Figure ends at 'ptfxThis'
|
|
WE_CLOSEFIGURE, // Do a close figure join at 'ptfxThis'
|
|
WE_JOIN, // Do a join at 'ptfxThis'
|
|
WE_BEZIERJOIN, // Do a Bezier join at 'ptfxThis'
|
|
WE_STOPDASH, // Stop a styling dash at 'ptfxThis'
|
|
WE_STARTDASH, // Start a styling dash at 'ptfxThis'
|
|
WE_ZEROFIGURE, // Figure has zero length at 'ptfxThis'
|
|
WE_FINISHFIGURE, // Do start-cap of figure at 'ptfxThis'
|
|
WE_DONEPATH };
|
|
|
|
enum LINESTATE { LS_READPATH, // Next point in figure comes from path
|
|
LS_STARTFIGURE, // Next point in path is the start of
|
|
// a figure
|
|
LS_FINISHFIGURE, // Go back to first point in figure
|
|
LS_READBEZIER, // Next point comes from current Bezier
|
|
LS_DONEPATH };
|
|
|
|
class LINER : public READER
|
|
{
|
|
private:
|
|
BEZIER bez;
|
|
|
|
BOOL bReadLine(LINEDATA& ld);
|
|
|
|
POINTFIX ptfxNext; // Next point in path after 'ptfxThis' (see below)
|
|
POINTFIX ptfxStartFigure; // Keep around for later
|
|
|
|
LINEDATA ldStartFigure; // Start point for current figure
|
|
LINEDATA ldBuf[2]; // Line vector data buffer for current lines
|
|
|
|
LINESTATE ls; // Reading path state
|
|
|
|
VOID vNextPoint();
|
|
VOID vZeroFigure(); // Sets up for a zero-length figure
|
|
|
|
protected:
|
|
LINEDATA ldEndTangent; // Line vector data for last line in figure
|
|
LINEDATA ldStartTangent; // Line vector data for first line in figure
|
|
|
|
public:
|
|
|
|
LINER(EPATHOBJ& epo) : READER(epo)
|
|
{
|
|
if (!bNextFigure())
|
|
ls = LS_DONEPATH;
|
|
else
|
|
{
|
|
bNextPoint(ptfxNext);
|
|
ptfxStartFigure = ptfxNext;
|
|
ls = LS_STARTFIGURE;
|
|
}
|
|
}
|
|
|
|
VOID vNextEvent();
|
|
|
|
// Keeps track of all the info needed to add a join, start-cap or end-cap:
|
|
|
|
WIDENEVENT we; // Flag to indicate start-cap, end-cap, etc.
|
|
POINTFIX ptfxThis; // Point at which to add cap or join
|
|
PLINEDATA pldIn; // Vector of line entering 'ptfxThis' (used for
|
|
// end-caps and joins)
|
|
PLINEDATA pldOut; // Vector of line exiting 'ptfxThis' (used for
|
|
// start-caps and joins)
|
|
};
|
|
|
|
|
|
/*********************************class************************************\
|
|
* class STYLER
|
|
*
|
|
* Hacks up the path into itty bitty pieces to feed to the widener.
|
|
*
|
|
* History:
|
|
* 22-Oct-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
class STYLER : public LINER
|
|
{
|
|
private:
|
|
VOID vStyleNext(BOOL b) { vSetFlag(b, FW_STYLENEXT); }
|
|
VOID vDoingStyles(BOOL b) { vSetFlag(b, FW_DOINGSTYLES); }
|
|
|
|
BOOL bStyleNext() { return(fl & FW_STYLENEXT); }
|
|
BOOL bDoingStyles() { return(fl & FW_DOINGSTYLES); }
|
|
|
|
PFLOAT_LONG pstyleStart;
|
|
PFLOAT_LONG pstyleCurrent;
|
|
PFLOAT_LONG pstyleEnd;
|
|
|
|
EFLOAT efRemainingLength;// Length remaining in current line
|
|
EFLOAT efStyleLength; // Length of current dash or gap
|
|
EFLOAT efDoneLength; // Length of current line done
|
|
EFLOAT efLineLength; // efLineLength = efDoneLength + efRemainingLength
|
|
POINTFIX ptfxLineStart; // Start point of line
|
|
|
|
protected:
|
|
EFLOAT efWorldLength(EVECTORFX);
|
|
EFLOAT efNextStyleLength();
|
|
VOID vResetStyles() { pstyleCurrent = pstyleStart; }
|
|
|
|
// These two actually get initialized by the derived class because it's
|
|
// a bit of work, and it will know if we'll need them:
|
|
|
|
MATRIX mxDeviceToWorld;
|
|
EXFORMOBJ exoDeviceToWorld;
|
|
|
|
public:
|
|
STYLER(EPATHOBJ&, PLINEATTRS);
|
|
|
|
VOID vNextStyleEvent();
|
|
};
|
|
|
|
// Prototype used in WIDENER:
|
|
|
|
VOID vAddNice(WIDEPATHOBJ&, PPOINTFIX, PEVECTORFX, BOOL);
|
|
|
|
/*********************************class************************************\
|
|
* class WIDENER
|
|
*
|
|
* Widens the path.
|
|
*
|
|
* History:
|
|
* 22-Oct-1991 -by- J. Andrew Goossen [andrewgo]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
class WIDENER : public STYLER
|
|
{
|
|
friend VOID WIDEPENOBJ::vAddRoundEndCap(WIDENER&, LINEDATA&, BOOL, BOOL);
|
|
friend COUNT WIDEPENOBJ::cptAddRound(WIDENER&, LINEDATA&, LINEDATA&,
|
|
BOOL, BOOL, BOOL);
|
|
|
|
private:
|
|
WIDEPENOBJ wpen;
|
|
|
|
WIDEPATHOBJ wpathLeft;
|
|
WIDEPATHOBJ wpathRight;
|
|
|
|
ULONG iJoin;
|
|
ULONG iEndCap;
|
|
|
|
VOID vFigureStyled(BOOL b) { vSetFlag(b, FW_FIGURESTYLED); }
|
|
VOID vAllRound(BOOL b) { vSetFlag(b, FW_ALLROUND); }
|
|
|
|
BOOL bFigureStyled() { return(fl & FW_FIGURESTYLED); }
|
|
BOOL bAllRound() { return(fl & FW_ALLROUND); }
|
|
|
|
EFLOAT efHalfWidthMiterLimitSquared;
|
|
EFLOAT efHalfWidth;
|
|
|
|
VOID vVecPerpCompute(LINEDATA&);
|
|
VOID vVecSquareCompute(LINEDATA&);
|
|
VOID vVecDrawCompute(LINEDATA&);
|
|
|
|
protected:
|
|
|
|
BOOL bMiterInLimit(EVECTORFX);
|
|
|
|
EVECTORFX vecInDraw() { if (!pldIn->bVecDrawComputed())
|
|
vVecDrawCompute(*pldIn);
|
|
|
|
return(pldIn->vecDraw); }
|
|
|
|
EVECTORFX vecInPerp() { if (!pldIn->bVecPerpComputed())
|
|
vVecPerpCompute(*pldIn);
|
|
|
|
return(pldIn->vecPerp); }
|
|
|
|
EVECTORFX vecInSquare() { if (!pldIn->bVecSquareComputed())
|
|
vVecSquareCompute(*pldIn);
|
|
|
|
return(pldIn->vecSquare); }
|
|
|
|
EVECTORFX vecOutDraw() { if (!pldOut->bVecDrawComputed())
|
|
vVecDrawCompute(*pldOut);
|
|
|
|
return(pldOut->vecDraw); }
|
|
|
|
EVECTORFX vecOutPerp() { if (!pldOut->bVecPerpComputed())
|
|
vVecPerpCompute(*pldOut);
|
|
|
|
return(pldOut->vecPerp); }
|
|
|
|
EVECTORFX vecOutSquare() { if (!pldOut->bVecSquareComputed())
|
|
vVecSquareCompute(*pldOut);
|
|
|
|
return(pldOut->vecSquare); }
|
|
|
|
VOID vAddLeft(EVECTORFX& vec, BOOL bInvert = FALSE)
|
|
{ wpathLeft.vAddPoint(&ptfxThis, &vec, !bInvert); }
|
|
|
|
VOID vAddLeft(PEVECTORFX pvec, BOOL bInvert)
|
|
{ wpathLeft.vAddPoint(&ptfxThis, pvec, !bInvert); }
|
|
|
|
VOID vAddLeft() { wpathLeft.vAddPoint(&ptfxThis); }
|
|
|
|
VOID vAddLeftNice(PEVECTORFX pvec, BOOL bInvert)
|
|
{ vAddNice(wpathLeft, &ptfxThis, pvec, !bInvert); }
|
|
|
|
|
|
VOID vAddRight(EVECTORFX& vec, BOOL bInvert = FALSE)
|
|
{ wpathRight.vAddPoint(&ptfxThis, &vec, bInvert); }
|
|
|
|
VOID vAddRight(PEVECTORFX pvec, BOOL bInvert)
|
|
{ wpathRight.vAddPoint(&ptfxThis, pvec, bInvert); }
|
|
|
|
VOID vAddRight() { wpathRight.vAddPoint(&ptfxThis); }
|
|
|
|
VOID vAddRightNice(PEVECTORFX pvec, BOOL bInvert)
|
|
{ vAddNice(wpathRight, &ptfxThis, pvec, bInvert); }
|
|
|
|
VOID vAddJoin(BOOL);
|
|
VOID vAddRoundJoin(BOOL);
|
|
VOID vAddEndCap();
|
|
VOID vAddStartCap();
|
|
BOOL bWiden();
|
|
VOID vSetError() { wpathRight.vSetError(); }
|
|
|
|
public:
|
|
WIDENER(EPATHOBJ&, EXFORMOBJ&, PLINEATTRS);
|
|
BOOL bValid() { return(wpathRight.bValid() &&
|
|
wpathLeft.bValid() &&
|
|
wpen.bValid()); }
|
|
VOID vMakeItWide(EPATHOBJ&);
|
|
};
|