PathStroker Class Reference

Abstract Base class Converts a Trapezoid (See ProcessPathToTrapezoids, pathtrap.h) stroke definition into an output path. More...

#include <pathstrk.h>

Inheritance diagram for PathStroker:

PathStrokerVector List of all members.

Public Member Functions

 PathStroker ()
 Default Constructor - DO NOT USE THIS FORM!
 PathStroker (ValueFunction *WidthFunction, INT32 LineWidth, LineCapType CapType)
 Constructor.
virtual ~PathStroker ()
virtual BOOL StrokePath (TrapsList *pTraps, Path *pOutput)
 "Strokes" a path according to the "style" set in construction.
virtual BOOL StrokeSmoothPath (TrapsList *pTraps, Path *pOutput)
 "Strokes" a path as above, but SMOOTHS its forwards and backwards paths to reduce points

Protected Member Functions

BOOL MapLineForwards (TrapEdgeList *Traps, Path *pOutput)
 Maps points along the trapezoids, generating an outline path for the "forwards" side of the stroke.
void RecursiveMapLineForwards (TrapEdge *pEdge1, DocCoord &Point1, TrapEdge *pEdge2, DocCoord &Point2, Path *pOutput)
 Recursive method which maps points within a given trapezoid by recursively "flattening" the curve between the two trapezoid edges.
BOOL MapLineBackwards (TrapEdgeList *Traps, Path *pOutput)
 Maps points along the trapezoids, generating an outline path for the "Backwards" side of the stroke.
void RecursiveMapLineBackwards (TrapEdge *pEdge1, DocCoord &Point1, TrapEdge *pEdge2, DocCoord &Point2, Path *pOutput)
 Recursive method which maps points within a given trapezoid by recursively "flattening" the curve between the two trapezoid edges.
BOOL MapLineCap (LineCapType CapType, TrapEdge *pEdge, BOOL IsStartCap, Path *pOutput)
 Maps a line cap onto the path by appending appropriate extra path elements to the end of it.

Protected Attributes

ValueFunctionpWidthFunction
INT32 MaxWidth
LineCapType CapStyle
INT32 RecursionDepth

Private Member Functions

 CC_DECLARE_MEMDUMP (PathStroker)

Detailed Description

Abstract Base class Converts a Trapezoid (See ProcessPathToTrapezoids, pathtrap.h) stroke definition into an output path.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/12/96
The base class strokes a path with variable-width

Definition at line 133 of file pathstrk.h.


Constructor & Destructor Documentation

PathStroker::PathStroker  ) 
 

Default Constructor - DO NOT USE THIS FORM!

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/12/96

Definition at line 155 of file pathstrk.cpp.

00156 {
00157     ERROR3("Please don't use this PathStroker constructor again");
00158 }

PathStroker::PathStroker ValueFunction WidthFunction,
INT32  LineWidth,
LineCapType  CapType
 

Constructor.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/12/96
Parameters:
WidthFunction - NULL, or a pointer to a width function for the stroke [INPUTS] LineWidth - The maximum width, in millipoints, of the stroke CapType - The cap style (LineCapButt, LineCapRound, or LineCapSquare)

Definition at line 176 of file pathstrk.cpp.

00177 {
00178     ERROR3IF(WidthFunction == NULL, "Illegal NULL param");
00179     pWidthFunction = WidthFunction;
00180 
00181     MaxWidth = LineWidth / 2;   // MaxWidth is the RADIUS of the "brush", not diameter
00182 
00183     CapStyle = CapType;
00184 
00185     RecursionDepth = 0;         // Reset recursion depth counter to 0
00186 }

virtual PathStroker::~PathStroker  )  [inline, virtual]
 

Definition at line 140 of file pathstrk.h.

00140 { }


Member Function Documentation

PathStroker::CC_DECLARE_MEMDUMP PathStroker   )  [private]
 

BOOL PathStroker::MapLineBackwards TrapEdgeList pTraps,
Path pOutput
[protected]
 

Maps points along the trapezoids, generating an outline path for the "Backwards" side of the stroke.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/12/96
Parameters:
pTraps - A pointer to a trapezoid-descriptiuon of the path being stroked [INPUTS] (May not be NULL)
pOutput - A pointer to a path in which the output will be generated [OUTPUTS] (May not be NULL)
Returns:
FALSE if it fails. (No error will be set at this level)
Notes: Expects the first point on this edge to have been written (as a LINETO) to the output path before this function was called.

Definition at line 490 of file pathstrk.cpp.

00491 {
00492     TrapEdge *pEdge     = NULL;
00493     TrapEdge *pLastEdge = NULL;
00494     INT32    Width;
00495     DocCoord LastPoint;
00496     DocCoord NewPoint;
00497 
00498     for (INT32 Index = pTraps->GetNumEdges() - 1; Index >= 0; Index--)
00499     {
00500         pLastEdge = pEdge;
00501         pEdge = pTraps->GetTrapEdge(Index);
00502 
00503         Width       = (INT32) (MaxWidth * pWidthFunction->GetValue(pEdge->Position));
00504         NewPoint.x  = pEdge->Centre.x - (INT32) (pEdge->Normal.x * Width);
00505         NewPoint.y  = pEdge->Centre.y - (INT32) (pEdge->Normal.y * Width);
00506 
00507         // The first point has already been added by the caller. The first iteration
00508         // of this loop is just to calculate the first "LastPoint" value.
00509         if (pLastEdge != NULL)
00510         {
00511             RecursionDepth = 0;                     // Reset recursion depth counter to 0
00512             RecursiveMapLineBackwards(pLastEdge, LastPoint, pEdge, NewPoint, pOutput);
00513         }
00514 
00515         LastPoint = NewPoint;
00516     }
00517 
00518     return(TRUE);
00519 }

BOOL PathStroker::MapLineCap LineCapType  CapType,
TrapEdge pEdge,
BOOL  IsStartCap,
Path pOutput
[protected]
 

Maps a line cap onto the path by appending appropriate extra path elements to the end of it.

Parameters:
CapType - The cap style (LineCapButt, LineCapRound, or LineCapSquare) [INPUTS] pEdge - A pointer to the end trapezoid for this end of the stroke (May not be NULL) IsStartCap - TRUE if this is the start cap, FALSE if it's the end cap. This lets us get the cap orientation right
pOutput - A pointer to a path in which the output will be generated [OUTPUTS] (May not be NULL)
Returns:
FALSE if it fails. (No error will be set at this level)
Notes: This maps points from the end of the backward outline to the start of the forward outline. It is expected that the StartPoint of the cap (the end point of the backward outline) has been written to the output immediately beforehand.

e.g. for the "leftmost" round cap, we have a situation like this: EndPoint +----> forward outline / | (MidPoint) + + ----centreline (pEdge->Centre) | \ StartPoint +<---- backward outline

Definition at line 662 of file pathstrk.cpp.

00663 {
00664     ERROR3IF(pEdge == NULL || pOutput == NULL, "Illegal NULL params");
00665 
00666     // Work out dx,dy. These are tangential (dx) and perpendicular (dy) to the centreline
00667     // Orientation of the End cap is in the opposite direction to that of the start cap
00668     const INT32 Width       = (INT32) (MaxWidth * pWidthFunction->GetValue(pEdge->Position));
00669     const INT32 Orientation = (IsStartCap) ? 1 : -1;
00670     const INT32 dx          = Orientation * (INT32) (pEdge->Normal.x * Width);
00671     const INT32 dy          = Orientation * (INT32) (pEdge->Normal.y * Width);
00672 
00673     // Calculate the point at the "end" of the cap outline
00674     DocCoord EndPoint(pEdge->Centre.x + dx, pEdge->Centre.y + dy);                  // Last point on cap
00675 
00676     switch (CapType)
00677     {
00678         case LineCapButt:
00679             // Simply join the 2 outlines with a straight line
00680             pOutput->AddLineTo(EndPoint);
00681             break;
00682 
00683 
00684         case LineCapRound:
00685             {
00686                 // We are adding a semicircular arc onto the end of the stroke. This is done
00687                 // as two quarter circles: from the end of the outline to the extended centreline,
00688                 // then from the centreline to the start of the opposite outline.
00689                 DocCoord StartPoint(pEdge->Centre.x - dx, pEdge->Centre.y - dy);    // 1st point on cap
00690                 DocCoord MidPoint(pEdge->Centre.x - dy, pEdge->Centre.y + dx);      // midpoint on the arc
00691 
00692                 // Determine the distance the control points should be away from the endpoints
00693                 // to get a reasonable circular arc out of the bezier curve.
00694                 const INT32 CPdx    = (INT32) ( ((double)dx) * 0.552 );
00695                 const INT32 CPdy    = (INT32) ( ((double)dy) * 0.552 );
00696 
00697                 // Draw an arc from the backward outline of the stroke to the centreline
00698                 DocCoord Control1(StartPoint.x - CPdy, StartPoint.y + CPdx);
00699                 DocCoord Control2(MidPoint.x   - CPdx, MidPoint.y   - CPdy);
00700                 pOutput->AddCurveTo(Control1, Control2, MidPoint);
00701 
00702                 // Draw an arc from the centreline to the start of the forward stroke
00703                 DocCoord Control3(MidPoint.x + CPdx, MidPoint.y + CPdy);
00704                 DocCoord Control4(EndPoint.x - CPdy, EndPoint.y + CPdx);
00705                 pOutput->AddCurveTo(Control3, Control4, EndPoint);
00706             }
00707             break;
00708 
00709 
00710         case LineCapSquare:
00711             {
00712                 // Add 3 lines making up a half square centred on the centreline endpoint
00713                 DocCoord StartPoint(pEdge->Centre.x - dx, pEdge->Centre.y - dy);    // 1st point on cap
00714 
00715                 pOutput->AddLineTo(DocCoord(StartPoint.x - dy, StartPoint.y + dx));
00716                 pOutput->AddLineTo(DocCoord(EndPoint.x - dy, EndPoint.y + dx));
00717                 pOutput->AddLineTo(EndPoint);
00718             }
00719             break;
00720 
00721         default:
00722             ERROR3("Unknown line cap style");
00723             break;
00724     }
00725 
00726     return(TRUE);
00727 }

BOOL PathStroker::MapLineForwards TrapEdgeList pTraps,
Path pOutput
[protected]
 

Maps points along the trapezoids, generating an outline path for the "forwards" side of the stroke.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/12/96
Parameters:
pTraps - A pointer to a trapezoid-descriptiuon of the path being stroked [INPUTS] (May not be NULL)
pOutput - A pointer to a path in which the output will be generated [OUTPUTS] (May not be NULL)
Returns:
FALSE if it fails. (No error will be set at this level)
Notes: Expects the first point on this edge to have been written (as a MOVETO) to the output path before this function was called.

Definition at line 334 of file pathstrk.cpp.

00335 {
00336     TrapEdge *pEdge     = NULL;
00337     TrapEdge *pLastEdge = NULL;
00338     INT32    Width;
00339     DocCoord LastPoint;
00340     DocCoord NewPoint;
00341 
00342     for (UINT32 Index = 0; Index < pTraps->GetNumEdges(); Index++)
00343     {
00344         pLastEdge = pEdge;
00345         pEdge = pTraps->GetTrapEdge(Index);
00346 
00347         Width       = (INT32) (MaxWidth * pWidthFunction->GetValue(pEdge->Position));
00348         NewPoint.x  = pEdge->Centre.x + (INT32) (pEdge->Normal.x * Width);
00349         NewPoint.y  = pEdge->Centre.y + (INT32) (pEdge->Normal.y * Width);
00350 
00351         // The first point has already been added by the caller. The first iteration
00352         // of this loop is just to calculate the first "LastPoint" value.
00353         if (pLastEdge != NULL)
00354         {
00355             RecursionDepth = 0;                     // Reset recursion depth counter to 0
00356             RecursiveMapLineForwards(pLastEdge, LastPoint, pEdge, NewPoint, pOutput);
00357         }
00358 
00359         LastPoint = NewPoint;
00360     }
00361 
00362     return(TRUE);
00363 }

void PathStroker::RecursiveMapLineBackwards TrapEdge pEdge1,
DocCoord Point1,
TrapEdge pEdge2,
DocCoord Point2,
Path pOutput
[protected]
 

Recursive method which maps points within a given trapezoid by recursively "flattening" the curve between the two trapezoid edges.

Parameters:
pEdge1,Point1 - The source TrapEdge and coordinate of the first point [INPUTS] (which must have already been added to the output path)
pEdge2, Point2 - The source TrapEdge and coordinate of the second point (which must NOT have been added to the output path)

Parameters:
pOutput - A pointer to a path in which the output will be generated [OUTPUTS] (May not be NULL)
It inserts extra mapped points between the two original points passed in to it, until the flatness criteria is met.

Definition at line 548 of file pathstrk.cpp.

00549 {
00550     ERROR3IF(pEdge1 == NULL || pEdge2 == NULL || pOutput == NULL, "Illegal NULL params");
00551 
00552     // --- Calculate the midpoint of the curve we are mapping
00553     // Calculate the midpoint "position" value
00554     TrapEdge MidEdge;
00555     MidEdge.Position = (pEdge1->Position + pEdge2->Position) / 2.0;
00556 
00557     // Calculate the midpoint normal vector
00558     MidEdge.Normal.x = (pEdge1->Normal.x + pEdge2->Normal.x) / 2.0;
00559     MidEdge.Normal.y = (pEdge1->Normal.y + pEdge2->Normal.y) / 2.0;
00560 
00561     // (Note in the 'backwards' case the "PrevTrap" flag is in pEdge1)
00562     MidEdge.PrevTrapJoin = pEdge1->PrevTrapJoin;
00563     if (MidEdge.PrevTrapJoin == TrapJoin_MitredOrBevelled)
00564     {
00565         // Work out if this on the inside or outside of the join
00566         double Val = (pEdge1->Normal.x * pEdge2->Normal.y) - (pEdge1->Normal.y * pEdge2->Normal.x);
00567         if (Val > 0.0)
00568         {
00569             // We are doing the inside of a join
00570 
00571             // If this is the special mitre join edge then just skip it
00572             // This removes the artifacts from the inside of mitre joins
00573             if (fabs(pEdge2->Normal.GetLength() - 1.0) > 0.0001)
00574                 return;
00575 
00576             MidEdge.Normal.Normalise();
00577         }
00578     }
00579     else
00580     {
00581         MidEdge.Normal.Normalise();
00582     }
00583 
00584     // Calculate the (approximate) centreline midpoint
00585     MidEdge.Centre.x = (pEdge1->Centre.x / 2) + (pEdge2->Centre.x / 2);
00586     MidEdge.Centre.y = (pEdge1->Centre.y / 2) + (pEdge2->Centre.y / 2);
00587 
00588     // Now, calculate the mapped midpoint
00589     const INT32 Width = (INT32) (MaxWidth * pWidthFunction->GetValue(MidEdge.Position));
00590     DocCoord MidPoint(MidEdge.Centre);
00591     MidPoint.x -= (INT32) (MidEdge.Normal.x * Width);
00592     MidPoint.y -= (INT32) (MidEdge.Normal.y * Width);
00593 
00594     // --- Calculate the midpoint of the straight line segment
00595     DocCoord ApproximateMidPoint(Point1.x/2 + Point2.x/2, Point1.y/2 + Point2.y/2);
00596 
00597     // --- Calculate the error in the midpoint position
00598     const double dx = MidPoint.x - ApproximateMidPoint.x;
00599     const double dy = MidPoint.y - ApproximateMidPoint.y;
00600     const double Dist2 = dx * dx + dy * dy;
00601 
00602     RecursionDepth++;
00603 
00604     // --- If the straight-line approximation is not close enough to the curve, recurse,
00605     // Don't bother to recurse for mitred or bevelled joins as they should be straight lines
00606     if ( MidEdge.PrevTrapJoin!=TrapJoin_MitredOrBevelled &&
00607          (Dist2>Flatness2 || RecursionDepth<=pWidthFunction->GetMinimumRecursionDepth()) &&
00608          RecursionDepth<=MaxRecursionDepth )
00609     {
00610 
00611         // Recurse on the left and right sides of the new midpoint
00612         RecursiveMapLineBackwards(pEdge1,   Point1,  &MidEdge, MidPoint, pOutput);
00613         RecursiveMapLineBackwards(&MidEdge, MidPoint, pEdge2,   Point2,  pOutput);
00614     }
00615     else
00616     {
00617         pOutput->AddLineTo(Point2);
00618     }
00619 
00620     RecursionDepth--;
00621 }

void PathStroker::RecursiveMapLineForwards TrapEdge pEdge1,
DocCoord Point1,
TrapEdge pEdge2,
DocCoord Point2,
Path pOutput
[protected]
 

Recursive method which maps points within a given trapezoid by recursively "flattening" the curve between the two trapezoid edges.

Parameters:
pEdge1,Point1 - The source TrapEdge and coordinate of the first point [INPUTS] (which must have already been added to the output path)
pEdge2, Point2 - The source TrapEdge and coordinate of the second point (which must NOT have been added to the output path)

Parameters:
pOutput - A pointer to a path in which the output will be generated [OUTPUTS] (May not be NULL)
It inserts extra mapped points between the two original points passed in to it, until the flatness criteria is met.

Definition at line 392 of file pathstrk.cpp.

00393 {
00394     ERROR3IF(pEdge1 == NULL || pEdge2 == NULL || pOutput == NULL, "Illegal NULL params");
00395 
00396     // --- Calculate the midpoint of the curve we are mapping
00397     // Calculate the midpoint "position" value
00398     TrapEdge MidEdge;
00399     MidEdge.Position = (pEdge1->Position + pEdge2->Position) / 2.0;
00400 
00401     // Calculate the midpoint normal vector
00402     MidEdge.Normal.x = (pEdge1->Normal.x + pEdge2->Normal.x) / 2.0;
00403     MidEdge.Normal.y = (pEdge1->Normal.y + pEdge2->Normal.y) / 2.0;
00404 
00405     MidEdge.PrevTrapJoin = pEdge2->PrevTrapJoin;
00406     if (MidEdge.PrevTrapJoin == TrapJoin_MitredOrBevelled)
00407     {
00408         // Work out if this on the inside or outside of the join
00409         double Val = (pEdge1->Normal.x * pEdge2->Normal.y) - (pEdge1->Normal.y * pEdge2->Normal.x);
00410         if (Val > 0.0)
00411         {
00412             // We are doing the inside of a join
00413 
00414             // If this is the special mitre join edge then just skip it
00415             // This removes the artifacts from the inside of mitre joins
00416             if (fabs(pEdge2->Normal.GetLength() - 1.0) > 0.0001)
00417                 return;
00418 
00419             MidEdge.Normal.Normalise();
00420         }
00421     }
00422     else
00423     {
00424         MidEdge.Normal.Normalise();
00425     }
00426 
00427     // Calculate the (approximate) centreline midpoint
00428     MidEdge.Centre.x = (pEdge1->Centre.x / 2) + (pEdge2->Centre.x / 2);
00429     MidEdge.Centre.y = (pEdge1->Centre.y / 2) + (pEdge2->Centre.y / 2);
00430 
00431     // Now, calculate the mapped midpoint
00432     const INT32 Width = (INT32) (MaxWidth * pWidthFunction->GetValue(MidEdge.Position));
00433     DocCoord MidPoint(MidEdge.Centre);
00434     MidPoint.x += (INT32) (MidEdge.Normal.x * Width);
00435     MidPoint.y += (INT32) (MidEdge.Normal.y * Width);
00436 
00437     // --- Calculate the midpoint of the straight line segment
00438     DocCoord ApproximateMidPoint(Point1.x/2 + Point2.x/2, Point1.y/2 + Point2.y/2);
00439 
00440     // --- Calculate the error in the midpoint position
00441     const double dx = MidPoint.x - ApproximateMidPoint.x;
00442     const double dy = MidPoint.y - ApproximateMidPoint.y;
00443     const double Dist2 = dx * dx + dy * dy;
00444 
00445     RecursionDepth++;
00446 
00447     // --- If the straight-line approximation is not close enough to the curve, recurse,
00448     // Don't bother to recurse for mitred or bevelled joins as they should be straight lines
00449     if ( MidEdge.PrevTrapJoin!=TrapJoin_MitredOrBevelled && 
00450          (Dist2>Flatness2 || RecursionDepth<=pWidthFunction->GetMinimumRecursionDepth()) &&
00451          RecursionDepth<=MaxRecursionDepth )
00452     {
00453         // Recurse on the left and right sides of the new midpoint
00454         RecursiveMapLineForwards(pEdge1,   Point1,   &MidEdge, MidPoint, pOutput);
00455         RecursiveMapLineForwards(&MidEdge, MidPoint, pEdge2,   Point2,   pOutput);
00456     }
00457     else
00458     {
00459         pOutput->AddLineTo(Point2);
00460     }
00461 
00462     RecursionDepth--;
00463 }

BOOL PathStroker::StrokePath TrapsList pTraps,
Path pOutput
[virtual]
 

"Strokes" a path according to the "style" set in construction.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/12/96
Parameters:
pTraps - A trapezoidal description of the path to be stroked [INPUTS] (May not be NULL)
pOutput - This path is filled in with a "filled outline" of the stroke [OUTPUTS] It's IsFilled flag will be TRUE, IsStroked will be FALSE.
Returns:
FALSE if it fails. (No error will be set at this level)
This is the second stage in the stroking process (the first stage being breaking a path down into a trapezoidal description).

Stroking is achieved by mapping the intersections of trapezoid edges with the width function, and then recursively flattening the mapped curve between those points until required "flatness" is achieved.

The stroke outline is built up of 5 main components: A MOVETO point 1 1+---------------+2 A mapped outline between 1 & 2 ("FORWARDS") | | A line cap between 2 & 3 4+---------------+3 A mapped outline between 3 & 4 ("BACKWARDS") A line cap between 4 & 1

The distance between points on the forwards & backwards outlines (the stroke width) is governed by the LineWidth and WidthFunction passed to the constructor.

See also:
PathStroker::MapLineForwards; PathStroker::MapLineBackwards; PathStroker::MapLineCap

Reimplemented in PathStrokerVector.

Definition at line 231 of file pathstrk.cpp.

00232 {
00233     ERROR3IF(pTraps == NULL || pOutput == NULL, "Illegal NULL params");
00234 
00235     // For each trapezoid list generated, add a subpath to the pOutput path
00236     for (UINT32 Index = 0; Index < pTraps->GetNumTraps(); Index++)
00237     {
00238         TrapEdgeList *pTrapEdges = pTraps->GetTrapEdgeList(Index);
00239         if (pTrapEdges->GetNumEdges() < 2)
00240         {
00241             ERROR3("No map traps when stroking! Subpath stripped\n");
00242             continue;
00243         }
00244 
00245 #if FALSE
00246         // Useful bit of code to dump out the TrapEdges
00247         {
00248             for (UINT32 i = 0; i < pTrapEdges->GetNumEdges(); i++)
00249             {
00250                 TrapEdge *pEdge = pTrapEdges->GetTrapEdge(i);
00251                 TRACE(_T("Edge % 5d  Position = %g  Type = %s  Centre = (%d, %d)  Normal = (%g, %g)\n"),
00252                     i, pEdge->Position, 
00253                     (pEdge->PrevTrapJoin == TrapJoin_None ? _T("N") : 
00254                         pEdge->PrevTrapJoin == TrapJoin_Round ? _T("R") :
00255                         pEdge->PrevTrapJoin == TrapJoin_MitredOrBevelled ? _T("M") : _T("U")),
00256                     pEdge->Centre.x, pEdge->Centre.y,
00257                     pEdge->Normal.x, pEdge->Normal.y);
00258             }
00259         }
00260 #endif
00261 
00262         // Check if this subpath is closed (ends in a join). If so, we must remove the line caps!
00263         LineCapType CapType = CapStyle;
00264         TrapEdge *pEdge = pTrapEdges->GetLastTrapEdge();
00265         if (pEdge->PrevTrapJoin != TrapJoin_None)
00266             CapType = LineCapButt;
00267 
00268         // Start a new sub-path with a MoveTo to the first point
00269         pEdge = pTrapEdges->GetTrapEdge(0);
00270         INT32 Width = (INT32) (MaxWidth * pWidthFunction->GetValue(pEdge->Position));
00271         INT32 dx       = (INT32) (pEdge->Normal.x * Width);
00272         INT32 dy       = (INT32) (pEdge->Normal.y * Width);
00273         DocCoord StartPoint(pEdge->Centre.x + dx, pEdge->Centre.y + dy);
00274         pOutput->AddMoveTo(StartPoint);
00275 
00276         // Map the "forwards" outline
00277         MapLineForwards(pTrapEdges, pOutput);
00278 
00279         // Add the line cap at the end of the line
00280         MapLineCap(CapType, pTrapEdges->GetLastTrapEdge(), FALSE, pOutput);
00281 
00282         // Map the "backwards" outline
00283         MapLineBackwards(pTrapEdges, pOutput);
00284 
00285         // Add the line cap at the end of the line, and we should meet back at the start!
00286         MapLineCap(CapType, pTrapEdges->GetTrapEdge(0), TRUE, pOutput);
00287 
00288         // And set the PT_CLOSEFIGURE flag on the last point, just to be safe
00289         INT32           indCoord = pOutput->GetNumCoords() - 1;
00290         PathVerb       *pVerbs = pOutput->GetVerbArray();
00291         pVerbs[indCoord] |= PT_CLOSEFIGURE;
00292     }
00293 
00294     pOutput->IsFilled   = TRUE;
00295     pOutput->IsStroked  = FALSE;
00296 
00297 #ifdef _DEBUG
00298     if(pTraps && pTraps->GetNumTraps() > 0 && pOutput)
00299     {
00300         TRACEUSER( "Matt", _T("Path stroked: %ld subpaths, (1st is %ld Traps) -> %ld Coords\n"),
00301                                 pTraps->GetNumTraps(), pTraps->GetTrapEdgeList(0)->GetNumEdges(),
00302                                 pOutput->GetNumCoords());
00303     }
00304 #endif
00305 
00306     return(TRUE);
00307 }

BOOL PathStroker::StrokeSmoothPath TrapsList pTraps,
Path pOutput
[virtual]
 

"Strokes" a path as above, but SMOOTHS its forwards and backwards paths to reduce points

Author:
Priestley (Xara Group Ltd) <camelotdev@xara.com> - totally ripped from Jason above
Date:
18/11/2000
Parameters:
pTraps - A trapezoidal description of the path to be stroked (May not be NULL) [INPUTS]
pOutput - This path is filled in with a "filled outline" of the stroke [OUTPUTS] It's IsFilled flag will be TRUE, IsStroked will be FALSE.
Returns:
FALSE if it fails. (No error will be set at this level)

Definition at line 749 of file pathstrk.cpp.

00750 {
00751     ERROR3IF(pTraps == NULL || pOutput == NULL, "Illegal NULL params");
00752 
00753     // For each trapezoid list generated, add a subpath to the pOutput path
00754     for (UINT32 Index = 0; Index < pTraps->GetNumTraps(); Index++)
00755     {
00756         TrapEdgeList *pTrapEdges = pTraps->GetTrapEdgeList(Index);
00757         if (pTrapEdges->GetNumEdges() < 2)
00758         {
00759             ERROR3("No map traps when stroking! Subpath stripped\n");
00760             continue;
00761         }
00762 
00763         // Check if this subpath is closed (ends in a join). If so, we must remove the line caps!
00764         LineCapType CapType = CapStyle;
00765         TrapEdge *pEdge = pTrapEdges->GetLastTrapEdge();
00766         if (pEdge->PrevTrapJoin != TrapJoin_None)
00767             CapType = LineCapButt;
00768 
00769         // Start a new sub-path with a MoveTo to the first point
00770         pEdge = pTrapEdges->GetTrapEdge(0);
00771         INT32 Width = (INT32) (MaxWidth * pWidthFunction->GetValue(pEdge->Position));
00772         INT32 dx       = (INT32) (pEdge->Normal.x * Width);
00773         INT32 dy       = (INT32) (pEdge->Normal.y * Width);
00774         DocCoord StartPoint(pEdge->Centre.x + dx, pEdge->Centre.y + dy);
00775         pOutput->AddMoveTo(StartPoint);
00776 
00777         INT32 first = 0;
00778         INT32 last = -1;
00779 
00780         // Map the "forwards" outline
00781         MapLineForwards(pTrapEdges, pOutput);
00782         pOutput->SmoothSection(first, &last, 1.25 * Flatness/*2500*/, 0);
00783 
00784         // Add the line cap at the end of the line (if the height at this point of the value function is greater
00785         // than some threshold above zero).
00786         double height = pWidthFunction->GetValue(1);
00787         if (height > 0.05)
00788         {
00789             MapLineCap(CapType, pTrapEdges->GetLastTrapEdge(), FALSE, pOutput);
00790         }
00791 
00792         // Map the "backwards" outline
00793         first = pOutput->GetNumCoords() - 1;
00794         MapLineBackwards(pTrapEdges, pOutput);
00795         last = -1l;
00796         pOutput->SmoothSection(first, &last, 1.25 * Flatness/*2500*/, 0);
00797         
00798 
00799         INT32           indCoord;
00800         PathVerb       *pVerbs = pOutput->GetVerbArray();
00801 
00802         // Check all but the last verb to see if the path has been closed - if so, UNclose it!!!
00803         for( indCoord = 0; indCoord < pOutput->GetNumCoords() - 2; indCoord++ )
00804         {
00805             pVerbs[indCoord] &= ~PT_CLOSEFIGURE;
00806         }
00807 
00808         indCoord = pOutput->GetNumCoords() - 1;
00809         
00810         // Check to see if the last verb in the array has a CLOSEFIGURE type - if so then don't close it again!!!
00811         if (!(pVerbs[indCoord] & PT_CLOSEFIGURE))
00812         {
00813             // Add the line cap at the end of the line, and we should meet back at the start!
00814             MapLineCap(CapType, pTrapEdges->GetTrapEdge(0), TRUE, pOutput);
00815 
00816             // And set the PT_CLOSEFIGURE flag on the last point, just to be safe
00817             indCoord = pOutput->GetNumCoords() - 1;
00818             PathVerb *pVerbs = pOutput->GetVerbArray();
00819             pVerbs[indCoord] |= PT_CLOSEFIGURE;
00820         }
00821     }
00822 
00823     pOutput->IsFilled   = TRUE;
00824     pOutput->IsStroked  = FALSE;
00825 
00826 TRACEUSER( "Matt", _T("Path SMOOTHLY stroked: %ld subpaths, (1st is %ld Traps) -> %ld Coords\n"),
00827                             pTraps->GetNumTraps(), pTraps->GetTrapEdgeList(0)->GetNumEdges(),
00828                             pOutput->GetNumCoords());
00829 
00830     return(TRUE);
00831 }


Member Data Documentation

LineCapType PathStroker::CapStyle [protected]
 

Definition at line 167 of file pathstrk.h.

INT32 PathStroker::MaxWidth [protected]
 

Definition at line 166 of file pathstrk.h.

ValueFunction* PathStroker::pWidthFunction [protected]
 

Definition at line 165 of file pathstrk.h.

INT32 PathStroker::RecursionDepth [protected]
 

Definition at line 168 of file pathstrk.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:59:40 2007 for Camelot by  doxygen 1.4.4