PathProcessorStroke Class Reference

This is the abstract base class for all PathProcessors. More...

#include <ppstroke.h>

Inheritance diagram for PathProcessorStroke:

PathProcessor CCObject SimpleCCObject PathProcessorStrokeAirbrush PathProcessorStrokeVector List of all members.

Public Member Functions

 PathProcessorStroke ()
 Constructor.
virtual void ProcessPath (Path *pPath, RenderRegion *pRender, PathShape ShapePath=PATHSHAPE_PATH)
 Called by the RenderRegion to apply the path processing operation to the given path.
virtual BOOL WillChangeFillAndStrokeSeparately (void)
 Called by the RenderRegion to determine if this PathProcessorStroke affects the "fill" and "stroke" portions of the path separately. (Generally speaking, only fill/stroke providers will cause these two different "bits" of a path to be rendered separately). This call is made BEFORE this Processor's ProcessPath function will be called.
virtual BOOL IsDifferent (PathProcessorStroke *pOther)
 Equality operator.
virtual PathProcessorStrokeClone (void)
 To copy PathProcessorStroke or derived-class object.
virtual BOOL NeedsTransparency () const
virtual BOOL DoBecomeA (BecomeA *pBecomeA, Path *pPath, Node *pParent)
 To return the processed path to a BecomeA object. Does pretty much the same as process path but withot rendering anything.
virtual BOOL DoesActuallyDoAnything (RenderRegion *pRender)
 Allows the render region to know whether this PPS will do anything, if not then it can DrawPath normally allowing Dash patterns to be applied to nodes with constant VarWidth attributes applied to them.
virtual BOOL IsAPathProcessorStroke ()
NodePathGetProcessedPath (Path *pPath, Node *pParent)
 To return the stroked path.
PathGetProcessedPath (Path *pPath, CCAttrMap *pAttrMap)
 This is a rehash of Diccon's GetProcessedPath method, except you needn't worry about any nodes but the four NodeAttributes below, which must live in the supplied attr-map.
NodePathGetSmoothProcessedPath (Path *pPath, Node *pParent)

Protected Member Functions

TrapsListPrepareTrapsForStroke (Path *pPath, RenderRegion *pRender, INT32 LineWidth)
 Precalculation function to be used in tandem with CreateVarWidthStroke(). If you want to create several strokes along the same path, then precalculating the trapezoids will give a large performance improvement.
PathCreateVarWidthStroke (Path *pPath, RenderRegion *pRender, INT32 LineWidth, TrapsList *pTrapezoids=NULL)
 Strokes the given path according to variable width parameters in the given render region, producing a new path representing the outline of a variable-width stroke.
BOOL GetRequiredAttributes (CCAttrMap *pAttrMap, INT32 *pLineWidth, LineCapType *pLineCap, ValueFunction **ppValFunc, JointType *pJoinStyle)
 Extracts the following values, required for path stroking, from the supplied attribute map: Line width. Line start-cap - eg square or round end. Pointer to any applied width function - may be NULL. Join style - eg bevelled, mitred, round.
PathCreateSmoothVarWidthStroke (Path *pPath, RenderRegion *pRender, INT32 LineWidth, TrapsList *pTrapezoids=NULL)

Private Member Functions

 CC_DECLARE_DYNAMIC (PathProcessorStroke)

Friends

class RenderRegion

Detailed Description

This is the abstract base class for all PathProcessors.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/12/96
These classes are created by attributes (or similar) when rendered, and placed on a stack in the RenderRegion. Whenever RenderRegion::DrawPath is invoked to render a path, all stacked PathProcessors will be called in turn, and they call back to RenderRegion functions to render whatever they wish (usually a modified form of the original path).

This can be used to "filter" almost any rendering, but is mainly intended for use by stroke and fill providers, which replace input paths with more suitable shapes to be rendered.

See also:
RenderRegion::DrawPath; PathProcessor::ProcessPath

Definition at line 134 of file ppstroke.h.


Constructor & Destructor Documentation

PathProcessorStroke::PathProcessorStroke  ) 
 

Constructor.

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

Definition at line 142 of file ppstroke.cpp.

00143 {
00144 }


Member Function Documentation

PathProcessorStroke::CC_DECLARE_DYNAMIC PathProcessorStroke   )  [private]
 

PathProcessorStroke * PathProcessorStroke::Clone void   )  [virtual]
 

To copy PathProcessorStroke or derived-class object.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
8/1/97
Returns:
NULL if we're out of memory, else a pointer to a clone (exact copy) of this object

Reimplemented in PathProcessorStrokeAirbrush, and PathProcessorStrokeVector.

Definition at line 577 of file ppstroke.cpp.

00578 {
00579     // Clone this object - this can be done by just creating a new one
00580     PathProcessorStroke *pClone = new PathProcessorStroke;
00581 
00582     // And copy the (base class) parent-attribute pointer so we know when our
00583     // parent attribute is "current" in the render region.
00584     if (pClone != NULL)
00585         pClone->SetParentAttr(GetParentAttr());
00586 
00587     return(pClone);
00588 }

Path * PathProcessorStroke::CreateSmoothVarWidthStroke Path pPath,
RenderRegion pRender,
INT32  LineWidth,
TrapsList pTrapezoids = NULL
[protected]
 

Definition at line 1076 of file ppstroke.cpp.

01078 {
01079     ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params");
01080     ERROR3IF(!pPath->IsStroked, "PathProcessor expects to be given a stroked path");
01081 
01082     // --- Ignore infinitely thin strokes
01083     if (LineWidth < 1)
01084         return(NULL);
01085 
01086     // --- Create a new path to be rendered in place of the provided path
01087     // Note that I use a large allocation size so that reallocation need not be done
01088     // frequently, which also helps reduce memory fragmentation.
01089     Path *pOutput = new Path;
01090     if (pOutput == NULL)
01091         return(NULL);
01092 
01093     pOutput->Initialise(128, 128);
01094 
01095     // --- Get the current cap style from the render region
01096     // In case of failure, we initialise with suitable defaults
01097     LineCapType LineCap = LineCapButt;
01098     // BLOCK
01099     {
01100         StartCapAttribute *pCapAttr = (StartCapAttribute *) pRender->GetCurrentAttribute(ATTR_STARTCAP);
01101         if (pCapAttr != NULL)
01102             LineCap = pCapAttr->StartCap;
01103     }
01104 
01105     // --- Get the variable line width descriptor from the render region
01106     ValueFunction *pValFunc = NULL;
01107     // BLOCK
01108     {
01109         VariableWidthAttrValue *pVarWidthAttr = (VariableWidthAttrValue *) pRender->GetCurrentAttribute(ATTR_VARWIDTH);
01110         if (pVarWidthAttr != NULL)
01111             pValFunc = pVarWidthAttr->GetWidthFunction();
01112 
01113         // If it is a constant width stroke, we'll just get GDraw to stroke it for us,
01114         // as that code is optimised assembler, and need not worry about variable width,
01115         // and as a result is about 4 times faster!
01116         if (pValFunc == NULL || IS_A(pValFunc, ValueFunctionConstant))
01117         {
01118             // Get the current line join style from the render region
01119             JointType JoinStyle = RoundJoin;
01120             JoinTypeAttribute *pJoinAttr = (JoinTypeAttribute *) pRender->GetCurrentAttribute(ATTR_JOINTYPE);
01121             if (pJoinAttr != NULL)
01122                 JoinStyle = pJoinAttr->JoinType;
01123 
01124             pPath->StrokePathToPath(LineWidth, LineCap, JoinStyle, NULL, pOutput);
01125 
01126             pOutput->IsFilled  = TRUE;
01127             pOutput->IsStroked = FALSE;
01128             return(pOutput);
01129         }
01130     }
01131 
01132     // --- If none were passed in, generate the set of trapezoids for the dest path
01133     BOOL MustDeleteTraps = FALSE;
01134     if (pTrapezoids == NULL)
01135     {
01136         MustDeleteTraps = TRUE;
01137         pTrapezoids = PrepareTrapsForStroke(pPath, pRender, LineWidth);
01138         if (pTrapezoids == NULL)
01139             return(NULL);
01140     }
01141 
01142     // --- Stroke the trapezoids into a variable-width path
01143     PathStroker Stroker(pValFunc, LineWidth, LineCap);
01144     
01145     // our new option allows us to only get the forward mapped path
01146 
01147     if (!Stroker.StrokeSmoothPath(pTrapezoids, pOutput))
01148     {
01149         if (MustDeleteTraps)
01150             delete pTrapezoids;
01151         return(NULL);
01152     }
01153 
01154 
01155     if (MustDeleteTraps)
01156         delete pTrapezoids;
01157 
01158     return(pOutput);
01159 }

Path * PathProcessorStroke::CreateVarWidthStroke Path pPath,
RenderRegion pRender,
INT32  LineWidth,
TrapsList pTrapezoids = NULL
[protected]
 

Strokes the given path according to variable width parameters in the given render region, producing a new path representing the outline of a variable-width stroke.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/12/96 (split into new function, 6/2/97)
Parameters:
pPath - The source path to be stroked [INPUTS] pRender - The render region it will be drawn to
LineWidth - The maximum width of the stroke. Normally this is the current line width from the RndRgn, but derived classes like airbrushes like to vary this value, hence it is a parameter.

pTrapezoids - NULL (in which case this function will generate the TrapList for itself), or a pointer to a precalculated trapezoid list (this should be generated by calling PathProcessorStroke::PrepareTrapsForStroke, and should be used if you are generating multiple strokes from one source (e.g. see the Airbrush stroker - ppairbsh.cpp)). (NOTE that using one TrapsList for multiple strokes will also give more consistent positioning of width/pattern elements along the path length)

Returns:
NULL if it failed, else a pointer to a new Path object (which the caller must delete) to be drawn instead of the provided pPath parameter.
Internal helper funciton for this class and derived classes.

See also:
PathProcessorStroke::ProcessPath; PathProcessorStroke::PrepareTrapsForStroke

Definition at line 737 of file ppstroke.cpp.

00739 {
00740     ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params");
00741     ERROR3IF(!pPath->IsStroked, "PathProcessor expects to be given a stroked path");
00742 
00743     // --- Ignore infinitely thin strokes
00744     if (LineWidth < 1)
00745         return(NULL);
00746 
00747     // --- Create a new path to be rendered in place of the provided path
00748     // Note that I use a large allocation size so that reallocation need not be done
00749     // frequently, which also helps reduce memory fragmentation.
00750     Path *pOutput = new Path;
00751     if (pOutput == NULL)
00752         return(NULL);
00753 
00754     pOutput->Initialise(128, 128);
00755 
00756     // --- Get the current cap style from the render region
00757     // In case of failure, we initialise with suitable defaults
00758     LineCapType LineCap = LineCapButt;
00759     // BLOCK
00760     {
00761         StartCapAttribute *pCapAttr = (StartCapAttribute *) pRender->GetCurrentAttribute(ATTR_STARTCAP);
00762         if (pCapAttr != NULL)
00763             LineCap = pCapAttr->StartCap;
00764     }
00765 
00766     // --- Get the variable line width descriptor from the render region
00767     ValueFunction *pValFunc = NULL;
00768     // BLOCK
00769     {
00770         VariableWidthAttrValue *pVarWidthAttr = (VariableWidthAttrValue *) pRender->GetCurrentAttribute(ATTR_VARWIDTH);
00771         if (pVarWidthAttr != NULL)
00772             pValFunc = pVarWidthAttr->GetWidthFunction();
00773 
00774         // If it is a constant width stroke, we'll just get GDraw to stroke it for us,
00775         // as that code is optimised assembler, and need not worry about variable width,
00776         // and as a result is about 4 times faster!
00777         if (pValFunc == NULL || IS_A(pValFunc, ValueFunctionConstant))
00778         {
00779             // Get the current line join style from the render region
00780             JointType JoinStyle = RoundJoin;
00781             JoinTypeAttribute *pJoinAttr = (JoinTypeAttribute *) pRender->GetCurrentAttribute(ATTR_JOINTYPE);
00782             if (pJoinAttr != NULL)
00783                 JoinStyle = pJoinAttr->JoinType;
00784 
00785             pPath->StrokePathToPath(LineWidth, LineCap, JoinStyle, NULL, pOutput);
00786 
00787             pOutput->IsFilled  = TRUE;
00788             pOutput->IsStroked = FALSE;
00789             return(pOutput);
00790         }
00791     }
00792 
00793     // --- If none were passed in, generate the set of trapezoids for the dest path
00794     BOOL MustDeleteTraps = FALSE;
00795     if (pTrapezoids == NULL)
00796     {
00797         MustDeleteTraps = TRUE;
00798         pTrapezoids = PrepareTrapsForStroke(pPath, pRender, LineWidth);
00799         if (pTrapezoids == NULL)
00800             return(NULL);
00801     }
00802 
00803     // --- Stroke the trapezoids into a variable-width path
00804     PathStroker Stroker(pValFunc, LineWidth, LineCap);
00805     
00806     // our new option allows us toonly get the forward mapped path
00807 
00808     if (!Stroker.StrokePath(pTrapezoids, pOutput))
00809     {
00810         if (MustDeleteTraps)
00811             delete pTrapezoids;
00812         return(NULL);
00813     }
00814 
00815     if (MustDeleteTraps)
00816         delete pTrapezoids;
00817 
00818     return(pOutput);
00819 }

BOOL PathProcessorStroke::DoBecomeA BecomeA pBecomeA,
Path pPath,
Node pParent
[virtual]
 

To return the processed path to a BecomeA object. Does pretty much the same as process path but withot rendering anything.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/3/2000
Parameters:
pBecomeA - the object that tells us what to become, and recieves the results [INPUTS] pPath - the path that we are processing pParent- the node that this brush is applied to
[OUTPUTS] 
Returns:
TRUE if everything went ok,
Note: Because of the problems with bevelling and contouring this function will never be called as part of the normal DoBecomeA procedure. You have to specifically locate the AttrStrokeType and call its DoBecomeA directly if you wish to extract the paths from a stroke. This should be resolved somehow after the release.

25/10/2000 Extra note: We are now working out a mechanism which uses GetProcessedPath and GetOutlinePath, so this function may become obsolete

Reimplemented from PathProcessor.

Definition at line 325 of file ppstroke.cpp.

00326 {
00327     ERROR2IF(pBecomeA == NULL, FALSE, "BecomeA pointer is NULL in PathProcessorStroke::DoBecomeA");
00328     ERROR2IF(pParent == NULL, FALSE, "Parent is NULL in PathProcessorStroke::DoBecomeA");
00329     ERROR2IF(pPath == NULL, FALSE, "Path is NULL in PathProcessorStroke::DoBecomeA");
00330     
00331 
00332     // we need to make a new nodepath
00333     NodePath* pNewNode = GetSmoothProcessedPath(pPath, pParent);
00334 
00335     if (pNewNode == FALSE)
00336         return FALSE;
00337 
00338     BOOL Success = FALSE;
00339     // now what we do depends on what type of BecomeA we've got
00340     if (pBecomeA->BAPath())
00341     {
00342         switch (pBecomeA->GetReason())
00343         {
00344             case BECOMEA_REPLACE:
00345             {
00346                 UndoableOperation* pUndoOp = pBecomeA->GetUndoOp();
00347                 ERROR2IF(pUndoOp == NULL, FALSE, "No op pointer in PathProcessorStroke::DoBecomeA");
00348                 //  apply attributes to our new node
00349                 // Get the attributes
00350                 CCAttrMap AttribMap(30);
00351                 if (!((NodeRenderableInk*)pParent)->FindAppliedAttributes(&AttribMap))
00352                     break;
00353                 
00354                 // another bodge: this time if we have a stroked path that is not closed and 
00355                 // we have given it a stroke colour then we want this stroke colour to become
00356                 // the fill colour of the new shape
00357                 AttrStrokeColour * pColour = NULL;
00358             //  if (!pParent->IsNodePath() && ((NodePath*)pParent)->InkPath.IsClosed())
00359                 {
00360                     // look up the stroke colour attribute
00361                     
00362                     //AttribMap.Lookup((void *)CC_RUNTIME_CLASS(AttrStrokeColour),
00363                     //  (void *&)pColour);
00364                     ((NodeRenderableInk*)pParent)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), (NodeAttribute**)&pColour);
00365                     // make a new flat fill attribute and apply this to the node
00366                     if (pColour)
00367                     {
00368                         StrokeColourAttribute * pAttrVal = (StrokeColourAttribute *)pColour->GetAttributeValue();
00369 
00370                         if (pAttrVal)
00371                         {
00372                             AttrFlatColourFill *pFill = NULL;
00373                             // create and insert at first child
00374                             ALLOC_WITH_FAIL(pFill, new AttrFlatColourFill(pNewNode, FIRSTCHILD), pUndoOp);
00375 
00376                             pFill->SetStartColour(&(pAttrVal->Colour));
00377                             // remove from the map so we don't duplicate
00378                             AttribMap.RemoveKey(pFill->GetAttributeType());
00379                         }
00380                     }
00381 
00382                 }
00383 
00384                 if (!pNewNode->ApplyAttributes(&AttribMap))
00385                     break;
00386             
00387                 // insert the new node and delete the original
00388                 BOOL ok = TRUE;
00389                 // If we don't own the parent node, we should insert after (on top of) it
00390                 if (pBecomeA->IsSecondary())
00391                     ok = pUndoOp->DoInsertNewNode(pNewNode,pParent,NEXT,FALSE,FALSE,FALSE,FALSE);
00392                 else
00393                 {
00394                     ok = pUndoOp->DoInsertNewNode(pNewNode,pParent,PREV,FALSE,FALSE,FALSE,FALSE);
00395                     // If this BecomeA is a primary, then delete the source node
00396                     if (ok)
00397                         ok = pUndoOp->DoHideNode((NodeRenderableInk*)pParent, TRUE);
00398                 }
00399 
00400                 if (!ok)
00401                     break;
00402 
00403 
00404                 if (!pBecomeA->IsCombineBecomeA())
00405                 {
00406                     // pass it back then
00407                     pBecomeA->PassBack(pNewNode,(NodeRenderableInk*)pParent);
00408                 }
00409                 else
00410                 {
00411                     CombineBecomeA* pPassback = (CombineBecomeA*) pBecomeA;
00412                 
00413                     pPassback->SetStrokeCreatedPassbackPath(TRUE);
00414                     pBecomeA->PassBack(pNewNode,(NodeRenderableInk*)pParent);
00415                     pPassback->SetStrokeCreatedPassbackPath(FALSE);
00416                 }
00417                 Success = TRUE;
00418             }
00419             break;
00420 
00421             case BECOMEA_PASSBACK :
00422             {
00423                 if (!pBecomeA->IsCombineBecomeA ())
00424                 {
00425                     // pass it back then
00426                     Success = pBecomeA->PassBack(pNewNode,(NodeRenderableInk*)pParent);
00427                 }
00428                 else
00429                 {
00430                     CombineBecomeA* pPassback = (CombineBecomeA*) pBecomeA;
00431 
00432                     pPassback->SetStrokeCreatedPassbackPath(TRUE);
00433                     Success = pBecomeA->PassBack(pNewNode,(NodeRenderableInk*)pParent);
00434                     pPassback->SetStrokeCreatedPassbackPath(FALSE);
00435                 }
00436             }
00437             break;
00438 
00439             default:
00440                 break;
00441         }
00442     }
00443     
00444     
00445     if (!Success)
00446         delete pNewNode;
00447 
00448     return Success;
00449 }

BOOL PathProcessorStroke::DoesActuallyDoAnything RenderRegion pRender  )  [virtual]
 

Allows the render region to know whether this PPS will do anything, if not then it can DrawPath normally allowing Dash patterns to be applied to nodes with constant VarWidth attributes applied to them.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/9/2000
Parameters:
pRender - the render region we are about to render into. Note that it is [INPUTS] important that the region has had all its attributes rendered into it
Returns:
TRUE if this PPS is going to change the path, FALSE if it will not.

Reimplemented from PathProcessor.

Definition at line 607 of file ppstroke.cpp.

00608 {
00609     ERROR2IF(pRender == NULL, FALSE, "RenderRegion is NULL in PathProcessorStroke::DoesActuallyDoAnything");
00610 
00611     if (IsDisabled())
00612         return FALSE;
00613 
00614     // Get the value function from the render region and have a look at it
00615     ValueFunction *pValFunc = NULL;
00616 
00617     VariableWidthAttrValue *pVarWidthAttr = (VariableWidthAttrValue *) pRender->GetCurrentAttribute(ATTR_VARWIDTH);
00618     if (pVarWidthAttr != NULL)
00619         pValFunc = pVarWidthAttr->GetWidthFunction();
00620 
00621     // If it is a constant width stroke, then we don't really do anything
00622     if (pValFunc == NULL || IS_A(pValFunc, ValueFunctionConstant))
00623         return FALSE;
00624 
00625     // likewise if we have a brush don't do anything either, because we will use the stroke to 
00626     // generate a pressure curve for the brush
00627     BrushAttrValue* pBrush  = (BrushAttrValue*) pRender->GetCurrentAttribute(ATTR_BRUSHTYPE);
00628     if (pBrush != NULL && pBrush->GetBrushHandle() != BrushHandle_NoBrush)
00629         return FALSE;
00630 
00631     return TRUE;
00632 }

Path * PathProcessorStroke::GetProcessedPath Path pPath,
CCAttrMap pAttrMap
 

This is a rehash of Diccon's GetProcessedPath method, except you needn't worry about any nodes but the four NodeAttributes below, which must live in the supplied attr-map.

Author:
Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/11/2000
Parameters:
pPath the path to stroke [INPUTS] pAttrMap the attr-map to get things like line-width and cap styles from.
Returns:
ptr to a new path which is a stroked version of the supplied source path, or NULL if unsuccessful.
We also don't use render-regions, as their not actually necessary (the other version of this method does).

Notes: The following valid NodeAttributes must live in the attr-map: AttrLineWidth AttrStartCap AttrVariableWidth AttrJoinType

Returns:
Errors: ERROR2 with FALSE if anything goes wrong, or our inputs are NULL or invalid.
See also: Diccon's GetProcessedPath() higher up this file.

Definition at line 853 of file ppstroke.cpp.

00854 {
00855     ERROR2IF(pPath == NULL || pAttrMap == NULL, NULL,
00856             "PathProcessorStroke::GetProcessedPath; NULL input parameters!");
00857 
00858     INT32           LineWidth;
00859     LineCapType     LineCap;
00860     ValueFunction*  pValFunc;
00861     JointType       JoinStyle;
00862 
00863     if (!GetRequiredAttributes(pAttrMap, &LineWidth, &LineCap, &pValFunc, &JoinStyle))
00864         return NULL;
00865 
00866     if (LineWidth < 1)
00867         return NULL;
00868 
00869     // Create a path to hold our stroking exploits!
00870     // We'll prob'ly be generating loads of data, so be generous with our path's
00871     // initialisation, so it's not continually reallocating memory as it runs out.
00872     Path* pStroke = new Path;
00873     if (pStroke == NULL)
00874         return NULL;
00875     if (!pStroke->Initialise(128, 128))
00876     {
00877         delete pStroke;
00878         return NULL;
00879     }
00880 
00881     // if it's a constant-width stroke, ask GDraw to stroke it - it's
00882     // quicker and if it goes wrong, it's Gavin's fault (only joking ;o)
00883     if (pValFunc == NULL || IS_A(pValFunc, ValueFunctionConstant))
00884     {
00885         pPath->StrokePathToPath(LineWidth, LineCap, JoinStyle, NULL, pStroke);
00886         pStroke->IsFilled   = TRUE;
00887         pStroke->IsStroked  = TRUE;
00888         return pStroke;
00889     }
00890 
00891     // ok, GDraw didn't deal with it, so let's get down to business.
00892 
00893     // Generate the set of trapezoids for the dest path.
00894     ProcessPathToTrapezoids GenerateTraps(64);
00895     TrapsList *pTrapezoids = new TrapsList;
00896     BOOL    ok = (pTrapezoids != NULL);
00897     if (ok) ok = GenerateTraps.Init(pPath, pTrapezoids);
00898     if (ok)
00899     {
00900         // Flags are: Flatten, QuantiseLines, QuantiseAll
00901         ProcessFlags PFlags(TRUE, FALSE, FALSE);
00902         ok = GenerateTraps.Process(PFlags, TrapTravel_Parametric, JoinStyle);
00903     }
00904 
00905     // Stroke the trapezoids into a variable-width path.
00906     if (ok)
00907     {
00908         PathStroker Stroker(pValFunc, LineWidth, LineCap);
00909         ok = Stroker.StrokeSmoothPath(pTrapezoids, pStroke);
00910     }
00911 
00912     // tidy up temporary info.
00913     if (pTrapezoids != NULL)
00914     {
00915         delete pTrapezoids;
00916         pTrapezoids = NULL;
00917     }
00918 
00919     // tidy up the path and pass it out.
00920     if (pStroke != NULL)
00921     {
00922         if (ok)
00923         {
00924             if (!pStroke->IsClosed())
00925                 pStroke->TryToClose();
00926         }
00927         else
00928         {
00929             delete pStroke;
00930             pStroke = NULL;
00931         }
00932     }
00933 
00934     return pStroke;
00935 }

NodePath * PathProcessorStroke::GetProcessedPath Path pPath,
Node pParent
 

To return the stroked path.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/3/2000
Parameters:
pPath - the path that we are processing [INPUTS] pParent- the node that this brush is applied to
[OUTPUTS] 
Returns:
A NodePath, containing the path generated by our path stroker
Notes:

Definition at line 467 of file ppstroke.cpp.

00468 {
00469     // we need to fake a renderregion as our helper functions need one,
00470     // luckily FormatRegion is on hand from the text stuff
00471     FormatRegion FakeRender;
00472 
00473     if (!FakeRender.Init((NodeRenderableInk*)pParent)) // init renders all applied attributes into the region
00474         return NULL;
00475 
00476     
00477     // From here copied from ProcessPath:
00478     // --- Get the current line width, cap style, and join style from the render region
00479     // In case of failure, we initialise with suitable defaults
00480     INT32 LineWidth = 5000;
00481 
00482     // BLOCK
00483     {
00484         LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) FakeRender.GetCurrentAttribute(ATTR_LINEWIDTH);
00485         if (pWidthAttr != NULL)
00486             LineWidth = pWidthAttr->LineWidth;
00487     }
00488 
00489     // --- Create a stroke outline by calling our helper function
00490     Path *pOutput = CreateVarWidthStroke(pPath, &FakeRender, LineWidth);
00491     if (pOutput == NULL)
00492         return FALSE;
00493 
00494     if (!pOutput->IsClosed())
00495         pOutput->TryToClose();
00496 
00497     // we need to make a new nodepath
00498     NodePath* pNewNode = new NodePath; 
00499         
00500     if (pNewNode == NULL)
00501     {
00502         delete pOutput;
00503         return FALSE;
00504     }
00505     
00506     // initialise the path
00507     if (!pNewNode->InkPath.Initialise(pOutput->GetNumCoords(), 128))
00508     {
00509         delete pOutput;
00510         delete pNewNode;
00511         return FALSE;
00512     }
00513 
00514     // Copy our path data into it
00515     //CALL_WITH_FAIL(!pNewNode->InkPath.CopyPathDataFrom(pOutput), pUndoOp, Success)
00516     if (!pNewNode->InkPath.CopyPathDataFrom(pOutput))
00517     {
00518         delete pOutput;
00519         delete pNewNode;
00520         return FALSE;
00521     }
00522     // don't need that path anymore
00523     delete pOutput;
00524     pOutput = NULL;
00525 
00526     return pNewNode;
00527 }

BOOL PathProcessorStroke::GetRequiredAttributes CCAttrMap pAttrMap,
INT32 *  pLineWidth,
LineCapType pLineCap,
ValueFunction **  ppValFunc,
JointType pJoinStyle
[protected]
 

Extracts the following values, required for path stroking, from the supplied attribute map: Line width. Line start-cap - eg square or round end. Pointer to any applied width function - may be NULL. Join style - eg bevelled, mitred, round.

Parameters:
pAttrMap ptr to the attr-map to search. [INPUTS] pLineWidth line width ptr to fill. pLineCap end-cap type ptr to fill. ppValFunc variable line-width function ptr to fill. pJoinStyle join style ptr to fill.
If successful, the supplied pointers are filled with the appropriate values [OUTPUTS] from the attribute map, otherwise they are filled with default values.
Returns:
TRUE if successful, FALSE otherwise.
Notes: If this function fails, *DO NOT* use the output values! They are only there in case you screw up and *do* decide to use them, in which case they should hopefully not bring Camelot down around your ears!

Returns:
Errors: An error message is output to TRACE if we were unsuccessful. I'm not putting in an ERROR2 or 3, as I think from a user view-point, a quiet failure is more graceful.

Definition at line 977 of file ppstroke.cpp.

00982 {
00983     AttrLineWidth*      pAttrWidth      = NULL;
00984     AttrStartCap*       pAttrCap        = NULL;
00985     AttrVariableWidth*  pAttrVarWidth   = NULL;
00986     AttrJoinType*       pAttrJoinType   = NULL;
00987 
00988     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrLineWidth),  (void*&)pAttrWidth);
00989     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartCap),       (void*&)pAttrCap);
00990     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrVariableWidth),(void*&)pAttrVarWidth);
00991     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrJoinType),       (void*&)pAttrJoinType);
00992 
00993     if (pAttrWidth      == NULL || pAttrCap     == NULL ||
00994         pAttrVarWidth   == NULL || pAttrJoinType    == NULL)
00995     {
00996         TRACEALL( _T("PathProcessorStroke::GetProcessedPath; AttrMap doesn't contain the required attrs!") );
00997         *pLineWidth = 0;
00998         *pLineCap   = LineCapButt;
00999         *ppValFunc  = NULL;
01000         *pJoinStyle = RoundJoin;
01001         return FALSE;
01002     }
01003 
01004     *pLineWidth = pAttrWidth->Value.LineWidth;
01005     *pLineCap   = pAttrCap->Value.StartCap;
01006     *ppValFunc  = pAttrVarWidth->Value.GetWidthFunction();
01007     *pJoinStyle = pAttrJoinType->Value.JoinType;
01008 
01009     return TRUE;
01010 }

NodePath * PathProcessorStroke::GetSmoothProcessedPath Path pPath,
Node pParent
 

Definition at line 1014 of file ppstroke.cpp.

01015 {
01016     // we need to fake a renderregion as our helper functions need one,
01017     // luckily FormatRegion is on hand from the text stuff
01018     FormatRegion FakeRender;
01019 
01020     if (!FakeRender.Init((NodeRenderableInk*)pParent)) // init renders all applied attributes into the region
01021         return FALSE;
01022     
01023     // From here copied from ProcessPath:
01024     // --- Get the current line width, cap style, and join style from the render region
01025     // In case of failure, we initialise with suitable defaults
01026     INT32 LineWidth = 5000;
01027 
01028     // BLOCK
01029     {
01030         LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) FakeRender.GetCurrentAttribute(ATTR_LINEWIDTH);
01031         if (pWidthAttr != NULL)
01032             LineWidth = pWidthAttr->LineWidth;
01033     }
01034 
01035     // --- Create a stroke outline by calling our helper function
01036     Path *pOutput = CreateSmoothVarWidthStroke(pPath, &FakeRender, LineWidth);
01037     if (pOutput == NULL)
01038         return FALSE;
01039 
01040     if (!pOutput->IsClosed())
01041         pOutput->TryToClose();
01042 
01043     // we need to make a new nodepath
01044     NodePath* pNewNode = new NodePath; 
01045         
01046     if (pNewNode == NULL)
01047     {
01048         delete pOutput;
01049         return FALSE;
01050     }
01051 
01052     // initialise the path
01053     if (!pNewNode->InkPath.Initialise(pOutput->GetNumCoords(), 128))
01054     {
01055         delete pOutput;
01056         delete pNewNode;
01057         return FALSE;
01058     }
01059 
01060     // Copy our path data into it
01061     //CALL_WITH_FAIL(!pNewNode->InkPath.CopyPathDataFrom(pOutput), pUndoOp, Success)
01062     if (!pNewNode->InkPath.CopyPathDataFrom(pOutput))
01063     {
01064         delete pOutput;
01065         delete pNewNode;
01066         return FALSE;
01067     }
01068     // don't need that path anymore
01069     delete pOutput;
01070     pOutput = NULL;
01071 
01072     return pNewNode;
01073 }

virtual BOOL PathProcessorStroke::IsAPathProcessorStroke  )  [inline, virtual]
 

Reimplemented from PathProcessor.

Definition at line 162 of file ppstroke.h.

00162 {return TRUE;}

BOOL PathProcessorStroke::IsDifferent PathProcessorStroke pOther  )  [virtual]
 

Equality operator.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
8/1/97
Parameters:
pOther - The other PathProcessorStroke [INPUTS]
Returns:
TRUE if they're considered different, FALSE if they are equivalent
Notes: The base class implementation compares the runtime classes of the 2 objects to see if they are different classes. If they are the same class, it assumes they're cnsidered equal - derived classes should override this behaviour if further comparisons are necessary.

Reimplemented in PathProcessorStrokeAirbrush, and PathProcessorStrokeVector.

Definition at line 550 of file ppstroke.cpp.

00551 {
00552     ERROR3IF(pOther == NULL, "Illegal NULL param");
00553 
00554     if (GetRuntimeClass() != pOther->GetRuntimeClass())
00555         return(TRUE);
00556 
00557     // Assume that we're the same, as the base class is very simple
00558     return(FALSE);
00559 }

virtual BOOL PathProcessorStroke::NeedsTransparency void   )  const [inline, virtual]
 

Reimplemented from PathProcessor.

Reimplemented in PathProcessorStrokeAirbrush, and PathProcessorStrokeVector.

Definition at line 155 of file ppstroke.h.

00155 {return FALSE;};

TrapsList * PathProcessorStroke::PrepareTrapsForStroke Path pPath,
RenderRegion pRender,
INT32  LineWidth
[protected]
 

Precalculation function to be used in tandem with CreateVarWidthStroke(). If you want to create several strokes along the same path, then precalculating the trapezoids will give a large performance improvement.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/12/96 (split into new function, 6/2/97)
Parameters:
pPath - The source path to be stroked [INPUTS] pRender - The render region it will be drawn to LineWidth - The maximum width of all strokes you intend to render with the resulting TrapsList. Normally this is the current line width from the output RenderRegion.
Returns:
NULL if it failed, else a pointer to a new TrapsList object (which the caller must delete).
Call this with the width of the largest stroke you intend to render, and then render all strokes using the provided trapezoids.

See also:
PathProcessorStroke::CreateVarWidthStroke

Definition at line 662 of file ppstroke.cpp.

00663 {
00664     LineCapType LineCap = LineCapButt;
00665     JointType JoinStyle = RoundJoin;
00666 
00667     // BLOCK
00668     {
00669         // --- Get the current line cap style from the render region
00670         StartCapAttribute *pCapAttr = (StartCapAttribute *) pRender->GetCurrentAttribute(ATTR_STARTCAP);
00671         if (pCapAttr != NULL)
00672             LineCap = pCapAttr->StartCap;
00673 
00674         // --- Get the current line join style from the render region
00675         JoinTypeAttribute *pJoinAttr = (JoinTypeAttribute *) pRender->GetCurrentAttribute(ATTR_JOINTYPE);
00676         if (pJoinAttr != NULL)
00677             JoinStyle = pJoinAttr->JoinType;
00678     }
00679 
00680     ProcessPathToTrapezoids GenerateTraps(64);
00681     TrapsList *pTrapezoids = new TrapsList;
00682 
00683     if (pTrapezoids != NULL && GenerateTraps.Init(pPath, pTrapezoids))
00684     {
00685         // Flags are: Flatten, QuantiseLines, QuantiseAll
00686         ProcessFlags PFlags(TRUE, FALSE, FALSE);
00687         if (!GenerateTraps.Process(PFlags, TrapTravel_Parametric, JoinStyle))
00688         {
00689             delete pTrapezoids;
00690             pTrapezoids = NULL;
00691         }
00692     }
00693 
00694     return pTrapezoids;
00695 }

void PathProcessorStroke::ProcessPath Path pPath,
RenderRegion pRender,
PathShape  ShapePath = PATHSHAPE_PATH
[virtual]
 

Called by the RenderRegion to apply the path processing operation to the given path.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/12/96
The PathProcessorStroke class changes the stroking (only) of paths passed into it.

Notes: * When rendering a path, always pass in your 'this' pointer to RenderRegion::DrawPath, so that you don't start an infinite recursion!

To stop rendering of the path, simply return without calling the RR

To render this path unchanged, simply call directly back to the RR: pRender->DrawPath(pPath, this);

Only affect the fill of this path if pPath->IsFilled

Only affect the stroke of this path if pPath->IsStroked

If converting a path into a "filled path" for stroking, the output path should be rendered with IsStroked=FALSE or it'll get a line around the outside!

Implements PathProcessor.

Reimplemented in PathProcessorStrokeAirbrush, and PathProcessorStrokeVector.

Definition at line 212 of file ppstroke.cpp.

00215 {
00216     TRACEUSER( "Diccon", _T("Rendering stroke\n"));
00217     ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params");
00218 
00219     // --- If the provided path is not stroked, then we'll just pass it straight through
00220     // We also don't touch it if we're doing EOR rendering
00221     if (!pPath->IsStroked || pRender->DrawingMode != DM_COPYPEN)
00222     {
00223         pRender->DrawPath(pPath, this, ShapePath);
00224         return;
00225     }
00226 
00227     // --- If the quality is set low, strokes are just rendered as centrelines
00228     // BLOCK
00229     {
00230         QualityAttribute *pQuality = (QualityAttribute *) pRender->GetCurrentAttribute(ATTR_QUALITY);
00231         if (pQuality != NULL && pQuality->QualityValue.GetLineQuality() != Quality::FullLine)
00232         {
00233             pRender->DrawPath(pPath, this, ShapePath);
00234             return;
00235         }
00236     }
00237 
00238     // --- If the attribute which created us is not the current StrokeType attribute, then
00239     // we have been overridden by a different stroke type, so we do nothing.
00240     // BLOCK
00241     {
00242         StrokeTypeAttrValue *pTypeAttr = (StrokeTypeAttrValue *) pRender->GetCurrentAttribute(ATTR_STROKETYPE);
00243         if (pTypeAttr != NULL && pTypeAttr != GetParentAttr())
00244         {
00245             pRender->DrawPath(pPath, this);
00246             return;
00247         }
00248     }
00249 
00250     // --- We don't expect the input path to be stroked AND filled on entry
00251     ERROR3IF(pPath->IsFilled, "PathProcessor expected RenderRegion to handle IsFilled case");
00252 
00253     // --- Get the current line width, cap style, and join style from the render region
00254     // In case of failure, we initialise with suitable defaults
00255     INT32 LineWidth = 5000;
00256 
00257     // BLOCK
00258     {
00259         LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) pRender->GetCurrentAttribute(ATTR_LINEWIDTH);
00260         if (pWidthAttr != NULL)
00261             LineWidth = pWidthAttr->LineWidth;
00262     }
00263 
00264     // --- Create a stroke outline by calling our helper function
00265 
00266     // (ChrisG 4/11/00) - Use smoothed paths with AIExport. This is only done for the export, as the smooth
00267     //  path creation function is about five times slower than the non-smoothed one.
00268     Path * pOutput = NULL;
00269     if (pRender->IsKindOf (CC_RUNTIME_CLASS (AIEPSRenderRegion)))
00270     {
00271         pOutput = CreateSmoothVarWidthStroke(pPath, pRender, LineWidth);
00272     }
00273     else
00274     {
00275         pOutput = CreateVarWidthStroke(pPath, pRender, LineWidth);
00276     }
00277     
00278     if (pOutput == NULL)
00279     {
00280         pRender->DrawPath(pPath, this);
00281         return;
00282     }
00283 
00284     // --- Finally, render the new stroke outline path in place of the one we were given
00285     pRender->SaveContext();
00286 
00287         // !!!!****ToDo - for now, strokes always render flat-filled with the stroke colour
00288         StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR);
00289         if (pStrokeColour != NULL)
00290             pRender->SetFillColour(pStrokeColour->Colour);
00291 
00292         pRender->SetWindingRule(NonZeroWinding);
00293         pRender->DrawPath(pOutput, this);
00294 
00295     pRender->RestoreContext();
00296 
00297     // --- And clean up
00298     delete pOutput;
00299 }

BOOL PathProcessorStroke::WillChangeFillAndStrokeSeparately void   )  [virtual]
 

Called by the RenderRegion to determine if this PathProcessorStroke affects the "fill" and "stroke" portions of the path separately. (Generally speaking, only fill/stroke providers will cause these two different "bits" of a path to be rendered separately). This call is made BEFORE this Processor's ProcessPath function will be called.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/12/96
Returns:
TRUE
If the caller gets a TRUE back, the stroke and fill paths will be rendered separately.

Notes: Base class implementation returns FALSE. Derived Stroke and Fill processors (such as this one) override this method to return TRUE.

Reimplemented from PathProcessor.

Reimplemented in PathProcessorStrokeAirbrush, and PathProcessorStrokeVector.

Definition at line 171 of file ppstroke.cpp.

00172 {
00173     return(TRUE);
00174 }


Friends And Related Function Documentation

friend class RenderRegion [friend]
 

Reimplemented from PathProcessor.

Reimplemented in PathProcessorStrokeAirbrush, and PathProcessorStrokeVector.

Definition at line 136 of file ppstroke.h.


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