Path Class Reference

Creation, manipulation and use of Paths. A path is an arbitary collection of MoveTo, LineTo and CurveTo segments Public Member variables :- BOOL IsFilled - TRUE if this path if filled, FALSE otherwise. More...

#include <paths.h>

List of all members.

Public Member Functions

 Path ()
 constructor - just sets a few things to sensible values
 ~Path ()
 Destructor - releases the memory that the path has been using to store coords in.
BOOL CopyPathDataFrom (Path *SrcPath)
 Copy the coords, verbs and flags from the SrcPath to this path. You must already have initialised this path by calling Path::Initialise(). Pass it an Initial size big enough the hold the path you want to copy.
BOOL CopyPathDataFrom (DocCoord *Coords, PathVerb *Verbs, INT32 NumCoords, BOOL Filled=FALSE, BOOL Stroked=TRUE)
 Copy the specified coords and verbs to this path. The path's flags will be the defaults as specified in the constructors. You must already have initialised this path by calling Path::Initialise(). Pass it an Initial size big enough to hold the path you want to copy.
BOOL CreatePathFromDocRect (DocRect *pRect)
 Creates a filled path from a given DocRect.
BOOL Initialise (INT32 InitialSize=24, INT32 BlockSize=12)
 Allocates memory in the path for the three arrays - The Verbs, Coordinates and the Flags.
BOOL FindStartOfPath ()
 Sets Pos to the first element in the path.
void FindStartOfSubPath ()
 Searches backwards from the current position until it finds the start of the sub path that the current position is in.
void FindStartOfSubPath (INT32 *Index) const
 Searches backwards from the current position from Index until it find the start of the subpath (always a moveto).
void FindEndOfSubPath ()
 Searches forwards until it finds the end of the current sub-path. ie pos will point at the last element in the sub path.
void FindEndOfSubPath (INT32 *Index) const
 Searches forwards until it finds the end of the current sub-path. ie Index will point at the last element in the sub path.
void FindEndElOfSubPath (INT32 *Index) const
 Searches forwards until it finds the last element of the current sub-path. ie 0 1 2 3 {MT,CT,CT,CT} => Index = 3. See Also: FindEndOfSubPath (Note equivelent).
void ExpandRange (INT32 *start, INT32 *end, INT32 num)
 given the region [*start, *end] expand the region in both directions by num elements. The region will not be expanded beyond its outer limits described by the set {moveto,.....,endofsubpath}.
BOOL FindNext ()
 Finds the next path element in this path. The position will become invalid if you try to search past the start of the path. This can be checked by using Pos->IsValid.
BOOL FindNext (INT32 *Index) const
 Finds the next path element in this path. The position will become invalid if you try to search past the start of the path. This can be checked by using Pos->IsValid.
BOOL FindPrev ()
 Finds the prev path element in this path starting the search from CurrentPos.
BOOL FindPrev (INT32 *Index) const
 Finds the previous path element in this path starting from the value (index).
BOOL FindPrevEndPoint (INT32 *index) const
 Finds the previous path endpoint in this path.
BOOL FindNextEndPoint (INT32 *index) const
 Finds the next path endpoint in this path.
BOOL GetSubPathEnds (DocCoord *start, DocCoord *end)
 This function returns whether the path is open or closed. This is independent of the IsFilled flag, because some programs allow open paths to be filled. Basically, if there's no gap in the subpath, it's closed, otherwise it's open. These are the same rules as ArtWorks followed. Initial implementation just scans the subpath and checks the last element in the subpath.
BOOL FindNearestPoint (DocCoord pos, UINT32 flags, INT32 *position)
 This function searches for a point in the path which is both selected and lies inside the largest blob bounding rectangle surrounding 'pos'. Points checked for are as follows... if ENDPOINTS is set check all selected endpoints in this path. if CONTROLPOINTS is set check all control points lying directly next to selected endpoints The rules are that control points are only enabled when a single end point is selected and hence a maximum of 2 control points will be checked. If any of these points are close enough to be clicked on, the function returns TRUE, with position holding the index to the point that was clicked.
BOOL PointCloseToLine (DocCoord pos, INT32 *position)
 This function takes the coordinate pos, and sees if it is close to a line (close enough to drag the line around). It returns TRUE if the point is close enough, and position is an index to the element that it was closest to.
BOOL ClosestSelectedEndpoint (DocCoord pos, INT32 *position, double *distance)
 This function finds the closest selected line end to the cursor position passed in. If the path has no selected line ends, the function returns FALSE.
BOOL FindNextSelected (INT32 *Index)
 Searches the point set {*index, usedslots-1} for a selected end point and returns its index if found.
BOOL FindSelectionLimits (INT32 index, INT32 *p, INT32 *q)
 Finds the next connected region of selected control handles.
INT32 FindOppositeControlPoint (INT32 ThisIndex)
 Given a bezier control point, this function returns the index of the control point that is opposite this one (with an endpoint between). This routine takes closed paths into account.
INT32 FindPrevControlPoint (INT32 position)
 This routine will scan back from an endpoint to find the attached bezier control point. It takes account of closed and open paths and complex paths, and will wrap around the path if necessary.
INT32 FindNextControlPoint (INT32 position)
 This routine will scan forwards from an endpoint to find the attached bezier control point. It takes account of closed and open paths and complex paths, and will wrap around the path if necessary.
double SqrDistanceToPoint (const DocCoord pt, INT32 *NearEl, double *mu)
 Finds the distance to the closest point on the path. For efficiency it does not evaluate the closest point. Use this routine in conjunction with ClosestPoint to find the actual closest point.
DocCoord ClosestPointTo (const double t, const INT32 index)
 This function returns the point at which the closest distance on the path occurs.
BOOL IsPointCloseTo (const DocCoord ICoord, INT32 range, INT32 *NearElement, double *mu)
 This routine can be used to determin whether a point is close enough to a path to allow some action to occur. The range input parameter can be used to determin the size of the sensitive area.
double SqrLength ()
 Find the length of a path in millipoints. The length is calculated by flattening the path and finding straight line segment lengths and so is a discrete numeric approximation to a line integral.
double GetPathLength (double dFlatness=64.0)
 Find the length of a path in millipoints.
double DistReparameterise (const double sqrdist, INT32 *Element)
DocCoord ConvSqrDistToCoord (const double sqrdist)
 Finds the coordinate which is dist units along 'this' path.
INT32 BreakInTwo (Path *pChildPath)
 Tests a path to see if it is valid. This is only built into DEBUG versions of Camelot so always surround calls to it with an ifdef _DEBUG block. If the path is not valid in some way, this function will dump an explanation to the debug terminal and return FALSE.This function will attempt to break the current path at its first selected point. All selected points should still be in place in both parent and child.
INT32 NumSplinters ()
 Returns the number of splinters a selected path will be broken into when calls to BreakPath is called. Splinters include opened subpaths, ie if the algorithm will open a closed subpath, this is classed as a spinter along with breaking a path in two.
BOOL DistanceTo (INT32 index, double t, double *distance, double dFlatness=64.0)
 This function takes a description of a point lying on a path. The point is described by (i,t) where i is the index of the element t lies in, and t is a parametric variable 0<=t<=1. The function calculates the distance along this path to the point described by (i,t). This routine complements SqrDistanceToPoint() which calculates the pair (i,t) for a given coordinate close to the path.
BOOL DistanceTo (DocCoord Coord, double *dist, double dFlatness=64.0)
 This function takes as input a coordinate (usually a mouse click point). It will calculate the closest point on the path to this coordinate and return the distance along the path from its start point to this coordinate.
BOOL SplitAtPoint (const DocCoord &SplitPoint, INT32 *SplitAt, INT32 *NewElements)
 This function takes a coordinate (typically not on but) close to this path and splits the path at a calculated point on the path which happens to be closest to the input coord. By Split I mean a new coordinate in will appear in the path, but the path will not have changed its shape in anyway.
BOOL GetPointAtDistance (MILLIPOINT Distance, DocCoord *pPoint, double *pTangent=NULL, UINT32 *pPressure=NULL)
 Gets the coordinate of a point a certain distance along this path.
BOOL GetDistanceToPoint (DocCoord Point, MILLIPOINT *Distance)
 Gets the distance along the path for a given point.
void Scale (const DocCoord dcOrigin, const double dDPI=96.0)
 This function is called on a path specified in DocCoords, to convert it into pixel coordinates.
INT32 GetPathPosition ()
 Find out where in the path we are.
void SetPathPosition (INT32)
 Sets the current path position to the value supplied. This represents the Coord number in the path.
BOOL IsInPath ()
 Determine if the path current position is still inside the path.
PathVerb GetVerb () const
 finds the verb associated with the path position
DocCoord GetCoord () const
 finds the DocCoord associated with the path position
PathFlags GetFlags () const
 finds the flags associated with the path position
PathWidth GetWidth () const
 Fetches width values from the path.
PathTypeEnum GetPathType () const
 This determines whether the path is a line or a shape. It does this by seeing if it has a PT_CLOSEFIGURE bit set in its last verb.
INT32 GetPathByteLength () const
 Calculates the length of the path in bytes. This figures includes the size of the 3 arrays (Coordinates, Verbs and Flags) only.
INT32 GetNumElements () const
 This function counts the number of elements in the path. This ignores MoveTos, hence giving you the total number of visible path elements (i.e. all the lines and curves).
INT32 GetNumCoords () const
 This returns the number of coordinates that make the path up.
INT32 GetNumEndPoints () const
 Goes through the path and counts all open ends in the path. For example, a straight line has 2 open ends, a closed shape has no open ends and a complex path could have any number of open ends. You should use this function before calling GetAllOpenEnds that will fill an array for their coords for you.
INT32 GetAllOpenEnds (INT32 MaxElements, DocCoord *EndCoords) const
 Goes through the path and copies the coordinates of all the Open ends of the path into the array, until MaxElements elements have been added to the array. Call GetNumEndPoints to find out how big to make your array in the first place.
INT32 GetNumSelEndPoints () const
 determine how many selected endpoints there are within this path. Useful indirectly for finding whether there's a subselection.
INT32 GetNumSubpaths () const
 Gets the number of subpaths in this path.
DocRect GetBoundingRect () const
 Calculates the bounding rectangle of the paths coordinates. This is calculated on the fly, so don't over use it.
DocRect GetBlobRect () const
 Calculates the bounding rectangle of the paths coordinates expanded by the current blob size. This is calculated on the fly, so don't over use it.
BOOL GetTrueBoundingRect (DocRect *pRect, MILLIPOINT LineWidth=0, CCAttrMap *pAttrMap=NULL)
 Calculate the bounding rectangle of a path using GDraw.
DocCoord GetEndPoint ()
 Finds the endpoint of a given path element and returns it. For MoveTos and LineTos, the point returned will be its associated coord, but for a CurveTo the last coord will be returned.
DocCoord GetControl1 ()
 Finds the first control point of a bezier.
DocCoord GetControl2 ()
 Finds the second control point of a Bezier.
DocCoordGetCoordArray () const
 Gives you access to the coordinate array. This array is simply a list of all the coordinates in the path, in order. This should be very useful if you need to perform transformations or other actions that effect all the coordinates. The coordinates are in the corect order for the NT PolyDraw() function handle.
PathVerbGetVerbArray () const
 This array holds a list of all the path elements used in the path. The structure used is the same as the NT structure and can in fact be passed striaght on to the NT PolyDraw function. The verbs must be one of the following PC_MoveTo, PC_LineTo or PC_CurveTo. LineTo and CurveTo verbs can be combined with a ClosePath Flag.
PathFlagsGetFlagArray () const
 This array holds a set of flags for each and every coordinate in the path. These flags are used to record information specific to each coordinate, such as its selection state, to determine if it should smooth this part of the path etc.
PathWidthGetWidthArray ()
 The array holds the width of all the points in the path. DO NOT MODIFY THE CONTENTS OF THE ARRAY.
void GetPathArrays (PathVerb **pV, DocCoord **pC=NULL, PathFlags **pF=NULL)
 Easy way of getting the path pointers into variables. Combines three function calls into one.
void GetFlags (PathFlags *NewFlags)
 returns all the flags for the current path position
void SetFlags (const PathFlags &NewFlags)
 Sets the flags at the current path position to the flags provided.
void InitialiseFlags ()
 This generates a legal path flags array based on the all path verbs. It sets all flags to default values and then scans all end points setting their end point flag to TRUE.
void InitialiseFlags (const INT32 Startindex, const INT32 Len)
 This generates a legal path flags array based on the path verbs within the specified region. It sets all flags to default values and then scans all end points setting their end point flag to TRUE.
void InitialiseFlags (PathVerb *pVerbs, PathFlags *pFlags, const INT32 Len)
 This generates a legal path flags array based on the path verbs in pVerbs within the specified region. It sets all flags in pFlags to default values and then scans all end points setting their end point flag to TRUE.
BOOL InsertMoveTo (DocCoord p1, PathFlags *NewFlags=NULL)
 Inserts a MoveTo element into the middle of the Path and asks for extra memory if we need it. It will return FALSE if we fail to get the memory.
BOOL InsertLineTo (DocCoord p1, PathFlags *NewFlags=NULL)
 Inserts a LineTo into the path at the Current Path Position.
BOOL InsertCurveTo (DocCoord p1, DocCoord p2, DocCoord p3, PathFlags *NewFlags=NULL)
 Inserts a Curve into the path at the Current Path Position.
BOOL CloseSubPath ()
 To indicate that a path is closed with a line, you should call CloseSubPath with the Current Path Position indicator somewhere inside the sub-path that you want closed. This function will adjust the verb of the last line segment in the sub-path by adding the PT_CLOSEFIGURE element into as described in the NT Prog Reference guides for the PolyDraw() function (page 304 of book 4 at last count) The Current Path Position is left on the element at the end of the subpath.
BOOL InsertSection (INT32 StartSlot, INT32 NumSlots)
 This routine is the corollary to DeleteSection - it inserts a section into the path at a given position and a given size, but does not put any data into the path. Note that this routine is likely to move the path data around in memory, so after calling it you should re-read any pointers to the path you might have had.
BOOL AddMoveTo (DocCoord p1, PathFlags *NewFlags=NULL)
 Adds a new MoveTo to the end of the path.
BOOL AddLineTo (DocCoord p1, PathFlags *NewFlags=NULL)
 Adds a new LineTo to the end of the path.
BOOL AddCurveTo (DocCoord p1, DocCoord p2, DocCoord p3, PathFlags *NewFlags=NULL)
 Adds a Curve to the end of the path.
BOOL AddCurveTo (DocCoord p1, PathFlags *NewFlags=NULL)
 Adds a straight line version of a curve to the end of the path. The control points are positioned 1/3 and 2/3 along the line between its end points.
BOOL DeleteSection (INT32 StartSlot, INT32 NumSlots)
 Deletes sections out of the middle of the path. Used by DeleteElement and for Deleting sub paths etc.
BOOL DeleteElement ()
 Deletes the element at the Current Path Position. May free some memory if the path gets to have too much unused space in the path. The Current Path Position points at the slot before the one being deleted.
BOOL DeleteFromElement (INT32 ElementNum)
 Deletes all the elements in the path from ElementNum to the end of the path.
BOOL ClearPath ()
 Empties the path of all its entries and tries to free up excessive amounts of unused memory left over at the end. It does keep some memory though, ready for a new path to be put into it. It also now resets CurrentPos back to zero.
BOOL ClearPath (BOOL compress)
 Empties the path of all its entries. If compress is TRUE the routine will try to free up excessive amounts of unused memory left over at the end. It also now resets CurrentPos back to zero.
BOOL Compact ()
 Removes any extraneous unused slots in a path. It will a maximum of 2n-1 slots free where n is the size of an allocation chunk when increasing the buffer (see Path::Initialise).
BOOL IsSelected ()
 return the Selected flag for the coordinate
BOOL IsSmooth ()
 returns the Smooth flag for the Current Path Position
BOOL IsRotate ()
 returns the Rotate flag for the coordinate
BOOL IsEndPoint ()
 return the IsEndPoint flag for the coordinate
BOOL IsSubSelection ()
 determine if the path has a subselection
BOOL IsNearOpenEnd (const DocRect &BlobRect, INT32 *SlotNum)
 Determines if the Coordinate is near any of the path open ends. This function looks through all the open ends in complex paths and returns TRUE if any of them are near the TestCoord.
BOOL IsOpenEnd (const INT32 index)
 Tests to see if the index provided specifies either the first or last element in an open subpath. ie the index is a true end point.
BOOL IsComplexPath ()
 Tests to see if the path is a complex path (ie it has multiple sub-paths).
BOOL IsIsometric (const Path &OtherPath, Matrix *pTransform, const double &Tolerance=1.0) const
 Determines whether two paths are isometric. In this context, isometric does not include true isomtric paths with different starting points. This can then be used to provide a transformation of this path, resulting in the given otherPath.
INT32 CalcCRC ()
 Calculates a cyclic redundancy check value for a path. This CRC is invariant under translation only. It can be used to determine whether a new path matches that of an old path whose CRC we already know, whether the new path has been translated or not.
INT32 CalcRegionCRC (const INT32 StartIndex, const INT32 EndIndex)
 Calculates a cyclic redundancy check value for a path region. This CRC is only invariant under translation. It can be used to determine whether a new path matches that of an old path whose CRC we already know, whether the new path has been translated or not.
INT32 CalcSelectedCRC ()
 Calculates a cyclic redundancy check value for a paths selected coordinates. This CRC is invariant under translation only. It can be used to determine whether a new path matches that of an old path whose CRC we already know, whether the new path has been translated or not.
INT32 CalcSelPointsCRC (const INT32 StartIndex, const INT32 EndIndex)
 Calculates a cyclic redundancy check value for a paths selected coordinates. This CRC is invariant under translation only. It can be used to determine whether a new path matches that of an old path whose CRC we already know, whether the new path has been translated or not.
XLONG CalcArea ()
 Calculate the area of this path.
INT32 ComparePathToPath (Path *pComparePath, BOOL QuickCheck=TRUE)
 Compares athis path to a passed in path. It firswt does a quick check on the number of coords and if they are equal does a more thoughour check on the verb array and coord array.
void DumpPath ()
 Dumps the whole path out to the debug terminal.
void GetDebugDetails (StringBase *Str)
 Dumps the whole path out during tree display debugging.
void RenderPathBlobs (Spread *pSpread)
 Draws all the selection blobs for a path. Useful for putting the blobs on or taking them back off again. This goes into its own RenderOnTop loop and calls RenderPathBlobs(RenderRegion* pRender).
void RenderPathBlobs (RenderRegion *pRender)
 Draws all the selection blobs for a path. Useful for putting the blobs on or taking them back off again.
void RenderPathControlBlobs (Spread *Spread, INT32 EndPtIndex)
 Draws the control points selection blobs for an endpoint on a path. Used by RenderPathBlobs and also the Bezier tool. This goes into its own RenderOnTop loop.
void RenderPathControlBlobs (RenderRegion *pRender, INT32 EndPtIndex)
 Draws all the control points selection blobs for a path. Used by RenderPathBlobs and also the Bezier tool.
void RenderPathSelectedControlBlobs (Spread *pSpread, BOOL Removing=TRUE)
 Draws all the control points selection blobs for an entire path. If you are to change the selection flags on a path then call this to remove all selection blobs, do your change, then call this again to draw the new blobs. This goes into its own RenderOnTop loop.
void RenderPathSelectedControlBlobs (Spread *pSpread, RenderRegion *pRender)
 Draws all the control points selection blobs for an entire path into a specified render region. Called by the above function.
void RenderSelectedControlBlobsToPendingRegions (Spread *pSpread)
 Draws all the control points selection blobs for an entire path into all the pending render regions.
void RenderPathPenBlobs (Spread *pSpread)
 Draws all the selection blobs and pen blobs for a path. Useful for putting the blobs on or taking them back off again.
void RenderPathPenBlobs (RenderRegion *pRegion)
 Draws all the selection blobs and pen blobs for a path. Useful for putting the blobs on or taking them back off again.
void DrawBlob (RenderRegion *, const DocCoord &, BOOL)
 Draws a single blob, either selected or un-selected.
void DrawControlBlob (RenderRegion *, const DocCoord &)
 Draws a blob for a Bezier control point.
void DrawControlLine (RenderRegion *, const DocCoord &, const DocCoord &)
 Draws a line from the Bezier control point to its endpoint.
void ClearSubSelection ()
 Goes through the path and sets all the IsSelected flags to FALSE, clearing any selected control points in the path.
void SetAllSubSelection ()
 Goes through the path and sets all the IsSelected flags to TRUE, also selecting all control points in the path.
void EnsureSelection (BOOL UseStarts)
 Goes through the path ensuring that the selection status of the ends/starts of subpaths equal the selection state of the start/ends of that subpath Also selects/deselectes control points as appropiate.
void SmoothCurve (BOOL SetRenderFlags=FALSE, BOOL SnapEnds=FALSE, INT32 SnapIndex=0)
 Smooths the path on the areas that have the IsSmooth flag set to TRUE. This can change any or all of the path.
void CalcDoubleCurve (DocCoord &, DocCoord &, DocCoord &, DocCoord *, DocCoord *)
 Calculates the position of the two control points on either side of p2, using the position of the coords of either side of it to help (p1 & p3).
void CalcPointCurve (DocCoord &, DocCoord &, DocCoord &, DocCoord *)
 Calculates the position of the control point adjacent to p2 between p2 and p3, using the position of the coords of either side of it to help (p1 & p3).
void CalcPointLine (DocCoord &, DocCoord &, DocCoord &, DocCoord *)
 Calculates the position of the control point that appears after p2, which is part of the curve ending at p3. The control point should be colinear with p1 & p2 and 1/3 the distance between p2 & p3 from p2!
void CalcPointEnd (DocCoord &, DocCoord &, DocCoord *)
 Calculates the position of the last control point in the sub-path.
void CalcRotate (DocCoord &, DocCoord *, DocCoord *, DocCoord &)
void Reverse ()
 Reverses this path, so that it is rendered and traversed etc in the other direction. This involves reversing the order of all the coords etc in the path.
void ReverseSection (INT32 StartSlot, INT32 SubPathLen)
 Reverses the direction of the section of the path specified. This is typically used to reverse subpaths of a complex path. It is also called by Reverse, to reverse the entire path.
void TryToClose ()
 Tries to close the path. If the start coord and the end coord are the same, it will close the path with a PT_CLOSEFIGURE and set the IsFilled flag. It searches all the sub-paths in the path and if any of them are closed, the whole path is marked as filled.
void RotateElementsLeft (const INT32 Start, const INT32 End, INT32 Rotate)
 Rotates the specified elements in a path by the number of positions indicated. Elements will be rotated from right to left.
BOOL MergeTwoPaths (const Path &Other)
 Combines the two paths into a single complex path.
BOOL MergeTwoPaths (DocCoord *OtherCoords, PathVerb *OtherVerbs, PathFlags *OtherFlags, INT32 Length, BOOL Filled)
 Appends the data in the three given arrays to the arrays in this path.
BOOL SplitAtPoint (const DocCoord SplitPt, INT32 *SplitElement, UINT32 *NumElements, PathVerb *Verbs, DocCoord *Coords)
 This function finds the element (line or curve) on which the closest point to SplitPt occurs. A parameter t describes the point on this element and is used to split the element into two distinct pieces. The verbs and coordinates of these pieces are returned to the caller in the output lists. NumElements will describe how many path components have been created and stored in the lists This will be a value of 2 for lines and 6 for curves.
BOOL ChangeStartElement (INT32 StartIndex)
 This will rotate the path so that the element that was at StartIndex is now at index 0. You should only call this for closed paths that don't contain subpaths.
void Translate (const INT32 x, const INT32 y)
 Translate all coordinate within 'this' path.
void Translate (const DocCoord &coord)
 Translate all coordinate within 'this' path.
INT32 ClipPathToPath (const Path &Src, Path *const pDest, UINT32 Flags, UINT32 Tolerance=100, double SrcFlatness=750.0, double ClipFlatness=750.0)
 This is an interface to Gavin's ClipPathToPath.
BOOL StrokePathToPath (MILLIPOINT LineWidth=250, LineCapType LineCap=LineCapButt, JointType JoinStyle=MitreJoin, DashType *pDash=NULL, Path *pDest=NULL, double Flatness=200.0, BOOL Close=FALSE)
 Strokes the path, and places result in pDest. If pDest == NULL, the result is placed back in this path.
double CalculateFlatnessValueFromPath (double DividerValue=375.0, double LowerLimit=1.0, double UpperLimit=375.0)
 To calculate a suitable flatness value to be used with Contouring, Clipping and Stroking. The value is based on the actual size of the paths dimensions.
INT32 InitializeContourValues (UINT32 Width, JoinStyles JoinS=JOIN_ROUND, BOOL IsAnOuterContour=TRUE, double Flatness=200.0, BOOL ClosePath=TRUE, BOOL UseContourMode=TRUE, CapStyles CapS=CAPS_ROUND, UINT32 MitreLimit=751941)
INT32 GetContourForStep (Path *pDest, double StepValue=1.0)
void ClearNeedToRender ()
 Sets the NeedToRender flags on all of the path elements to FALSE.
BOOL CopySectionFrom (const Path &Other, INT32 StartIndex, INT32 NumToCopy)
 Copies a specified section from a path to the end of this one.
BOOL CopySectionTo (Path *Dest, INT32 StartIndex, INT32 NumToCopy)
 Copies a specified section from this path to the end of another path.
BOOL MergeSectionFrom (INT32 DestinPos, const Path &Source, INT32 SourcePos, INT32 Length)
 Copies a specified section from a source path to a specified position in this path.
BOOL MergeSectionTo (INT32 SourcePos, INT32 Length, Path *Destin, INT32 DestinPos)
 Copies a specified section from this path to a specific position within another path. A gap is created if necessary to copy the data into.
BOOL MakePathFromSection (const INT32 Start, const INT32 Length, Path *pDestin)
 Copies a specified section from this path to a specific position within another path. A gap is created if necessary to copy the data into.
BOOL MakePathFromSubPath (const INT32 lSubpathIndex, Path *pDestin)
 Makes a subpath into a path in its own right.
BOOL CloneFrom (const Path &Other)
 Replace the data within this path with that of Other path.
BOOL SimpleJoin (Path *Other, INT32 *, BOOL *, BOOL *Reversed=NULL)
 Joins two paths to form a new, longer path. Both the paths invloved are simple (ie not complex).
BOOL ComplexJoin (Path *Other, INT32 *, BOOL *)
 Tries to Join the New Path (must be simple) to a complex path.
BOOL ComplexToSameComplexJoin (Path *Other, INT32 *, BOOL *)
 This path is assumed to be complex and Other is assumed to be a simple path. The start and end point of the Simple Path must be the same as the start or end point of one of the sub paths of this complex path. The function Moves the two sub paths that are touched by the simple path to the end of the path, and inserts the simple path between them. This means that the two touched sub-paths and the new simple path are combined into a single sub path. This may also mean that this complex path is no longer complex.
BOOL FindJoinedSubPathInfo (const DocCoord &JoinCoord, INT32 *Start, INT32 *Length, BOOL *JoinAtStart)
 This function searchs the path, compareing JoinCoord with the start and end points of each of the Sub-paths in the path. If it is the same as one of the start or end points, then the output params are filled and TRUE is returned.
BOOL JoinToAnother (Path *OtherPath, INT32 MainIndex, INT32 OtherIndex)
 This routine is used to join the end of a line to the end of another line. It will cope with the various possiblities: That both subpaths are in the same complex paths, that one or other of the subpaths are in different complex paths, and that one of the paths might need reversing. The other path is left untouched. This path will contain all subpaths from that one. This routine assumes that the two subpaths are different - it will not join the start and end of the same subpath.
BOOL RetroReplaceSection (INT32 StartSlot, INT32 NumSlots, Path *NewPath, BOOL KeepStart)
 Deletes all the elements in the path from StartSlot to StartSlot+NumSlots and then inserts the whole of NewPath into the hole. If the hole is not big enough, then it is made bigger and if it is too big, then it is shrunk.
BOOL SmoothRegions (const double error, BOOL smoothall, BOOL reselect)
 Given a path, search for regions of interest and smooth these regions. Regions are defined by sequences of connected selected points ie.
BOOL SmoothSection (INT32 index1, INT32 *index2, const double error, INT32 selection)
 Given a path, search for regions of interest and smooth these regions. Regions are defined by (start/end) selected points with any number of none selected points inbetween. If smoothall is true or there are no selected regions within the path, the whole path is smoothed. You should call this function with a path which you do not mind being corrupted, ie changed in an unpredictable way. The function may successfully smooth a number of regions within the path, then fail on one particular region. The result will be a path with m out of n regions smoothed.Smooth a path between the given section delimited by [index1,index2].
BOOL Smooth (const double error)
 Smooth a path, using the fitcurve function, which may turn out to be NOT the way to do it but I'll give it a try. You should generally call this funcion with a copy of the path you want to smooth. This smooth function will corrupt the path if it fails. Call the function SmoothSection() describing your entire path if you wish to smooth a path without corrupting anything on failure.
BOOL Quantise (const double threshold, Path *pOutput)
 Quantise a path. All curves within the path will be approximated by straight lines. pOutput may point at 'this' path ie a path can be quantised to itself. If the quantising fails for some reason, the output path will be unaffected EVEN if you're quantising a path to itself. Note, Quantising differs from flattening in that it will approximate straight lines within a path, generating n colinear points for each line it meets. Whereas flattening does nothing with lines.
BOOL Flatten (const double flatness, Path *pOutput)
 Flatten a path. All curves within the path will be approximated by straight lines. pOutput may point at 'this' path ie a path can be flattened to itself. If the flattening fails for some reason, the output path will be unaffected even if you are flattening a path to itself.
BOOL CreateFlatPath (const ProcessFlags &PFlags, const double flatness, Path *pOutput)
 Flatten a path. All curves within the path will be approximated by straight lines. pOutput may point at 'this' path ie a path can be flattened to itself. If the flattening fails for some reason, the output path will be unaffected even if you're flattening a path to itself.
BOOL MakeSpaceInPath (INT32 NumSlots)
 Checks to see if there is already enough memory available to make the insertion and if not will try to allocate some more memory. If this works it will move the path (after the position indicated by the path class variable CurrentPos) along to make room for the correct number of slots at that point.
BOOL MakeSpaceInPath (INT32 NumSlots, INT32 Position)
 Checks to see if there is already enough memory available to make the insertion and if not will try to allocate some more memory. If this works it will move the path after the position indicated by Position along to make room for the correct number of slots at that point.
BOOL MakeSpaceAtEnd (INT32 NumSlots)
 Will make enough room for NumSlots unused slots at the end of the path.
BOOL OpenGap (INT32 NumSlots)
 Will open a gap of NumSlots size in this path. The gap is positioned at CurrentPos (A path class variable).
BOOL OpenGap (INT32 NumSlots, INT32 Position)
 Will open up a gap of NumSlots at the position Position within the path. If Position is set to the end of the path ie the same value as usedslots, no data will be moved. FALSE will ofcourse always be returned if there is not enough free space in the form of unused slots on the end of the path for the gap to open. Use MakeSpaceInPath() if you know there isn't enough room. See Also: MakeSpaceInPath, MakeSpaceAtEnd.
BOOL EnsureVolume (INT32 NumSlots)
 This function ensures there are >= NumSlots in the path arrays. It may try to alter the size of the path arrays by increasing the number of unused slots to satisfy the request. It will never decrease the size of the arrays, if NumSlots < UsedSlots+UnusedSlots then the volume is automatically ensured. This allows path buffers to be resized ready for cloning.
BOOL ExternalArraysAdded (const INT32 Added)
 A hidden function to adjust the number of elements in a path. This has been added by me as a last resort and should not be used by others. (Hence hidden from the documentation). It is required to cope with changes in the path data external to the path class. This occurs when doing really nasty things like moulding paths.
BOOL ExternalArraysReplaced (const INT32 Size)
 A hidden function to adjust the number of elements in a path. This has been added by me as a last resort and should not be used by others. (Hence hidden from the documentation).
BOOL HasWidth ()
 To determine if the path has any width information.
void MapWidth (ChannelIndex)
 Alters the mapping of the Width Information to one of the ExtraInfo channels.
BOOL InitExtraInfo (ChannelIndex)
 Allocates memory in the path for the extra info arrays.
BOOL AddExtraInfo (ChannelIndex, INT32)
 Adds an extra Info Value at the current path position.
void SyncExtraInfo ()
 Sets the Extra Info Ptr to the current Path Position.
void NextExtraInfo ()
DocCoord SmoothControlPoint (INT32 Index, BOOL StartAndEndSnapped=FALSE, BOOL JoinedToAnother=FALSE, BOOL OtherIsCurve=TRUE, const DocCoord &OtherCoord=DocCoord(0, 0))
 This function will handle the smoothing of a path. It is designed to take account of all the possibilities that might occur (hence the huge list of parameters). The various places where this function might be needed are:Calculates the smoothed position of a control point in a path. The smoothing is calculated based on the endpoint to which the control point is attached, and the endpoints on either side of this point. Since we are guaranteed that one of these segments is a curve (that's where the control point comes from) the other possibilities are: The curve just terminates (at the end of a path); The curve is attached to another curve; It is attached to a line; It is at the end, but the end joins the start of the same path, which could be a line or a curve; and the curve could be at the end, but snapping to a completely separate path segment which might either be a line or curve (this is what the JoinedToAnother, OtherIsCurve and OtherCoord parameters indicate.
BOOL IsSubPathClosed (INT32 Index)
 Scans to the end of this subpath to see if it has the PT_CLOSEFIGURE flag set.
BOOL IsClosed ()
 Tells you whether all subpaths of this path are closed.
BOOL EnsureValid (BOOL *ChangesMade=NULL)
 Will attempt to make a path into a correct state. Checks are :- 1. All subpaths must start with a MoveTo 2. Consecutive MoveTos are removed 3. Zero element paths are unrepairable 4. MoveTos at the end of the path are removed 5. Should be three BezierTos in a row, only the last can be CloseFigure 6. A LineTo to the same location as the previous point is removed.
INT32 GetUsedSlots ()

Public Attributes

BOOL IsFilled
BOOL IsStroked

Private Member Functions

BOOL InsertSectionAtEnd (const Path *Other, INT32 StartPos, INT32 NumSlots)
 Copies a section (usually a sub-path) of a path to the end of another path. This is used extensivly to Join Paths together. If there is not enougth space in this path, then the operation will fail - It will NOT try to make the path bigger. It is up to the caller to ensure that there are sufficent UnUsedSlots in the path before calling.

Private Attributes

INT32 m_ContourWidth
JoinStyles m_ContourJoinS
CapStyles m_ContourCapS
double m_ContourFlatness
UINT32 m_ContourMitreLimit
UINT32 m_ContourLength
BOOL m_IsAnOuterContour
BOOL m_DoClosePath
BOOL m_UseContourMode
MHANDLE VerbHandle
MHANDLE CoordHandle
MHANDLE FlagsHandle
PathExtraInfoExtraInfo
INT32 UnUsedSlots
INT32 UsedSlots
INT32 SlotAllocSize
INT32 SlotInitSize
INT32 CurrentPos


Detailed Description

Creation, manipulation and use of Paths. A path is an arbitary collection of MoveTo, LineTo and CurveTo segments Public Member variables :- BOOL IsFilled - TRUE if this path if filled, FALSE otherwise.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94

Definition at line 253 of file paths.h.


Constructor & Destructor Documentation

Path::Path  ) 
 

constructor - just sets a few things to sensible values

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94

Definition at line 182 of file paths.cpp.

00183 {
00184     // We do not have any memory yet
00185     UnUsedSlots = 0;
00186     UsedSlots = 0;
00187     SlotInitSize = 0;
00188     SlotAllocSize = 0;
00189 
00190     // set all the handles to bad in case they are used
00191     VerbHandle = BAD_MHANDLE;
00192     CoordHandle = BAD_MHANDLE;
00193     FlagsHandle = BAD_MHANDLE;
00194 
00195     // Set the path flags
00196     IsFilled = FALSE;
00197     IsStroked = TRUE;
00198 
00199     // Set the current path position
00200     CurrentPos = 0;
00201 
00202     // Setup the Extra Info Channels
00203     ExtraInfo = NULL;
00204 
00205 #if !defined(EXCLUDE_FROM_XARLIB)
00206     // Set up the contouring variables
00207 //  m_pGPC = NULL;
00208 //  m_pGSC = NULL;
00209     m_ContourLength = 0;
00210     m_IsAnOuterContour = true;
00211     m_DoClosePath = false;
00212 
00213     // MRH New!
00214     m_ContourWidth = 100;
00215     m_ContourJoinS = JOIN_MITER;
00216     m_ContourCapS = CAPS_BUTT;
00217     m_ContourFlatness = 200.0;
00218 
00219     // Set the mitre limit to 10 shifted 16. It`s done in two parts as it can cause overflow
00220     // problems if done as one call.
00221     m_ContourMitreLimit = 10;
00222     m_ContourMitreLimit <<= 16;
00223     m_UseContourMode = TRUE;
00224 #endif
00225 }

Path::~Path  ) 
 

Destructor - releases the memory that the path has been using to store coords in.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94

Definition at line 238 of file paths.cpp.

00239 {
00240     // Free the memory that the path is using to store its data in
00241     if (VerbHandle != BAD_MHANDLE)
00242         ReleaseBlock(VerbHandle);
00243     
00244     if (CoordHandle != BAD_MHANDLE)
00245         ReleaseBlock(CoordHandle);
00246 
00247     if (FlagsHandle != BAD_MHANDLE)
00248         ReleaseBlock(FlagsHandle);
00249 
00250     if (ExtraInfo != NULL)
00251         delete ExtraInfo;
00252 /*  
00253     if(m_pGPC != NULL)
00254     {
00255         delete m_pGPC;
00256         m_pGPC = NULL;
00257     }
00258 
00259     if(m_pGSC != NULL)
00260     {
00261         delete m_pGSC;
00262         m_pGSC = NULL;
00263     }
00264 */
00265 }


Member Function Documentation

BOOL Path::AddCurveTo DocCoord  p3,
PathFlags NewFlags = NULL
 

Adds a straight line version of a curve to the end of the path. The control points are positioned 1/3 and 2/3 along the line between its end points.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/12/94
Parameters:
p3 - The endpoint [INPUTS] NewFlags - The flags to set the new coords to
Returns:
FALSE if there was an error, TRUE otherwise

Errors: Can fail if it can not get enough memory to add the curve

See also:
Path::AddLineTo; Path::AddMoveTo

Definition at line 2008 of file paths.cpp.

02009 {
02010     ERROR1IF( UsedSlots==0,FALSE,"No previous path elements when calling Path::AddCurveTo()" );
02011     // set the current pos.
02012     CurrentPos = UsedSlots;
02013 
02014     // Find the coord of the last point in the path
02015     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
02016     DocCoord prev = Coords[CurrentPos-1];
02017 
02018     // Create some temp coords
02019     DocCoord p1,p2;
02020 
02021     // calculate the intermediary control points
02022     p1.x = (2*prev.x + p3.x)/3;
02023     p1.y = (2*prev.y + p3.y)/3;
02024     p2.x = (prev.x + 2*p3.x)/3;
02025     p2.y = (prev.y + 2*p3.y)/3;
02026 
02027     return InsertCurveTo(p1,p2,p3,NewFlags);
02028 }

BOOL Path::AddCurveTo DocCoord  p1,
DocCoord  p2,
DocCoord  p3,
PathFlags NewFlags = NULL
 

Adds a Curve to the end of the path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/11/94
Parameters:
p1 - The first control point [INPUTS] p2 - The second control point p3 - The endpoint NewFlags - The flags to set the new coords to
Returns:
FALSE if there was an error, TRUE otherwise

Errors: Can fail if it can not get enough memory to add the curve

See also:
Path::AddLineTo; Path::AddMoveTo

Definition at line 1986 of file paths.cpp.

01987 {
01988     CurrentPos = UsedSlots;
01989     return InsertCurveTo(p1,p2,p3,NewFlags);
01990 }

BOOL Path::AddExtraInfo ChannelIndex  Index,
INT32  ExtraValue
 

Adds an extra Info Value at the current path position.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/06/94
Parameters:
- [INPUTS]
Returns:
TRUE if all went well, FALSE if not

Errors: Can fail if it runs out of memory

Definition at line 8215 of file paths.cpp.

08216 {
08217     ENSURE(ExtraInfo != NULL, "ExtraInfo Pointer is NULL in AddExtraInfo");
08218     return ExtraInfo->Add(Index, ExtraValue);
08219 }

BOOL Path::AddLineTo DocCoord  p1,
PathFlags NewFlags = NULL
 

Adds a new LineTo to the end of the path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/11/94
Parameters:
p1 - the coord to draw the line to [INPUTS] NewFlags - Flags associtaed with the coord
Returns:
TRUE if it worked, FALSE if it failed to get more memory
See also:
Path::AddMoveTo; Path::AddCurveTo

Definition at line 1961 of file paths.cpp.

01962 {
01963     CurrentPos = UsedSlots;
01964     return InsertLineTo(p1, NewFlags);
01965 }

BOOL Path::AddMoveTo DocCoord  p1,
PathFlags NewFlags = NULL
 

Adds a new MoveTo to the end of the path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/11/94
Parameters:
p1 - the coord to draw the line to [INPUTS] NewFlags - Flags associtaed with the coord
Returns:
TRUE if it worked, FALSE if it failed to get more memory
See also:
Path::AddLineTo; Path::AddCurveTo

Definition at line 1933 of file paths.cpp.

01934 {
01935     // Sadly there is no way for the outside world to set the insert position
01936     // to the end of the path!! SetPathPosition() for instance sets the currentpos to
01937     // usedslots-1, when passed usedslots which means you can never ever call InsertLineTo
01938     // and expect a line to be added to the pathend, it will be inserted before the element
01939     // which is the last in the path. Ok so this function does the job.
01940         
01941     CurrentPos = UsedSlots;
01942     return InsertMoveTo(p1, NewFlags);
01943 }

INT32 Path::BreakInTwo Path pChildPath  ) 
 

Tests a path to see if it is valid. This is only built into DEBUG versions of Camelot so always surround calls to it with an ifdef _DEBUG block. If the path is not valid in some way, this function will dump an explanation to the debug terminal and return FALSE.This function will attempt to break the current path at its first selected point. All selected points should still be in place in both parent and child.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/8/94
Parameters:
pChildPath,a pointer to a split path which should have been passed to new() [INPUTS]
- [OUTPUTS]
Returns:
-1 If unable to claim enough memory to split the path. Note pChildPath is unchanged and 'this' is also unaffected 0 If no selected points were found in the path. 1 Then the current path is opened at the first selected point. pChildPath is unaffected. 2 Then the current path now contains the left child data of the split and pChildPath points at a new path object containing the right child data.

Errors: -

See also:
-

Definition at line 8780 of file paths.cpp.

08781 {
08782     // Get arrays of flags,verbs and points.
08783 
08784     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
08785     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
08786     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
08787 
08788     // p,q indexes to selected point and endof(sub)path
08789     INT32 p = -1;
08790     INT32 q = -1;
08791     INT32 s = 0;
08792 
08793     // vp,vq local verb holders
08794     PathVerb vp;
08795     PathVerb vq;
08796 
08797     while (p++, FindNextSelected(&p))
08798     {
08799         q = p;
08800 
08801         FindEndElOfSubPath(&q);                         // returns index of last element in this subpath/path
08802         if (p>q) return 0;                              // just a quick check on sanity.
08803 
08804         s = p;
08805         FindStartOfSubPath(&s);                         // grab the start of the subpath
08806 
08807         if (p==q)
08808         {
08809             if (!(Verbs[p] & PT_CLOSEFIGURE)) continue; // ignore selected points at end of open subpaths
08810             p=s;
08811         }   
08812 
08813         vp = (Verbs[p] & ~PT_CLOSEFIGURE);
08814         vq = (Verbs[q]);
08815 
08816 
08817         // Have we found a selected start point?
08818         if (vp == PT_MOVETO)
08819         {
08820             if (vq & PT_CLOSEFIGURE)
08821             {
08822                 // subpath figure is closed, so open the path and resolve flags
08823                 Verbs[q] &= ~PT_CLOSEFIGURE;
08824                 if (Flags[q].IsSelected)
08825                 {
08826                     Flags[q].IsSelected = FALSE;
08827                     Flags[q].IsSmooth = FALSE;
08828                     if (Verbs[q] == PT_BEZIERTO)
08829                     {
08830                         Flags[q-1].IsSelected = FALSE;
08831                         Flags[q-1].IsSmooth = FALSE;
08832                     }
08833                     if (Verbs[p+1] == PT_BEZIERTO)
08834                         Flags[p+1].IsSmooth = FALSE;
08835                 }
08836                 return 1;
08837             }
08838             continue;
08839         }
08840 
08841         // Note these elements should not need to be checked against PT_CLOSEFIGURE as
08842         // (p!=q) and q is the following close element.
08843         
08844         if ((vp == PT_LINETO) || (vp == PT_BEZIERTO))
08845         {
08846 
08847             // ok, we have a selected element on a lineto/curveto. We need to check
08848             // whether we are in a closed subpath or an open one
08849 
08850             if ( vq & PT_CLOSEFIGURE )                  // is this sub path closed?
08851             {
08852 
08853                 // We need to reorder the subpath points and open the path.
08854                 // This involves
08855                 // (1) insert moveto(p) at p+1
08856                 // (2) increment q
08857                 // (3) remove closefigure at q
08858                 // (4) replace moveto(s) by lineto(s)
08859                 // (5) rotate the whole path left/right until element p
08860                 //     lies at element s
08861 
08862                 // subpath figure is closed, so open the path in parent
08863 
08864                 if ((Coords[s].x == Coords[q].x) && (Coords[s].y == Coords[q].y))
08865                 {
08866 
08867                     // I'm not totally convinced about this but here goes nothing!
08868                     // When dealing with a chain of bezier control points, the previous 
08869                     // and following points are selected also. What we select and deselect
08870                     // depends on which point (the start or end) we want selected when the
08871                     // path is opened. I thought it would be sensible to leave the end point
08872                     // selected but the click logic then does not allow you to drag the damn
08873                     // point around! as it still lies on top of the deselected start point.
08874                     // So lets try to select the new moveto and see what happens.
08875 
08876                     Flags[p].IsSelected = FALSE;            // deselect the current control point
08877                     Flags[p].IsSmooth = FALSE;
08878                     if (vp == PT_BEZIERTO)
08879                     {
08880                         Flags[p-1].IsSelected = FALSE;
08881                         Flags[p-1].IsSmooth = FALSE;
08882                     }
08883 
08884                     CurrentPos = s;
08885                     DeleteElement();                        // Get rid of the original moveto
08886                     CurrentPos = p;
08887                     InsertMoveTo(Coords[p-1]);
08888 
08889                     Flags = (PathFlags*) DescribeHandle(FlagsHandle);
08890                     Verbs = (PathVerb*) DescribeHandle(VerbHandle);
08891 
08892                     Flags[p].IsSelected = TRUE;             // make sure the moveto is selected
08893                     Flags[p].IsSmooth = FALSE;              // but not smooth
08894 
08895                     if ((Verbs[p+1] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
08896                         Flags[p+1].IsSmooth = FALSE;
08897 
08898                     Verbs[q] &= ~PT_CLOSEFIGURE;            // open the subpath.
08899                     RotateElementsLeft(s,q,p-s);            // rotate elements 
08900                     return 1;
08901                 }
08902                 else
08903                 {
08904 
08905                     // this section definitely needs more work!
08906 
08907                     CurrentPos = p+1;
08908                     if (!InsertMoveTo(Coords[p]))
08909                         return -1;
08910                 
08911                     q++;
08912 
08913                     Verbs = (PathVerb*) DescribeHandle(VerbHandle);
08914                     Verbs[q] &= ~PT_CLOSEFIGURE;            // open the subpath.
08915                     Verbs[s] = PT_LINETO;                   // alter move to line
08916                     RotateElementsLeft(s,q,p-s+1);          // rotate elements 
08917                     return 1;
08918                 }
08919             }
08920             else
08921             {
08922                 // I need to alter the current path object and create a completely new
08923                 // path object in the tree. This will contain the split section of the
08924                 // parent path. This involves
08925 
08926                 // (1) create newpath(p => q) by
08927                 //   (1.1) creating enough space for elements (p-q + 1)
08928                 //   (1.2) copying elements in
08929                 //   (1.3) replacing verb(p) by moveto
08930                 // (2) removal of elements (p+1 => q)
08931 
08932                 // Initialise the path with enough space for splinter
08933 
08934                 q = UsedSlots-1;
08935 
08936                 if (!pChildPath->Initialise(q-p+1,12))  
08937                     return -1;
08938 
08939                 // Copy the section out of the current path into the child  
08940                 if (!(CopySectionTo(pChildPath, p, q-p+1)))
08941                     return -1;
08942 
08943                 // Alter the childs first element once split, to a moveto.
08944                 PathVerb* pChildVerbs = (PathVerb*) DescribeHandle(pChildPath->VerbHandle);
08945                 PathFlags* pChildFlags = (PathFlags*) DescribeHandle(pChildPath->FlagsHandle);
08946                 pChildVerbs[0] = PT_MOVETO;
08947 
08948                 // Make sure the child paths first element is no longer smooth
08949                 pChildFlags[0].IsSmooth = FALSE;
08950                 if (pChildVerbs[1] == PT_BEZIERTO)
08951                     pChildFlags[1].IsSmooth = FALSE;
08952 
08953                 // Make sure the parent subpath start is deselected. It may have been selected
08954                 // by the previous instructions from a previous iteration.
08955                 Flags[s].IsSelected = FALSE;
08956                 if (Verbs[s] == PT_BEZIERTO)
08957                     Flags[s+1].IsSelected = FALSE;
08958 
08959                 // Remove the parents end point smooth bit, but leave it selected
08960                 Flags[p].IsSmooth = FALSE;
08961                 if (vp == PT_BEZIERTO)
08962                     Flags[p-1].IsSmooth = FALSE;
08963 
08964                 // ok remove the necessary elements from the original path
08965                 DeleteFromElement(p+1);
08966 
08967                 return 2;
08968             }
08969         }
08970     }
08971     return 0;
08972 }

XLONG Path::CalcArea  ) 
 

Calculate the area of this path.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/03/2005
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
Area of path in path units (typically millipoints) Or -1 if no area could be calculated
See also:
-

Definition at line 10290 of file paths.cpp.

10291 {
10292     // Check whether it's closed!
10293     if (!IsFilled)
10294         return 0;
10295 
10296     // First, use ClipPathToPath to get a path that has no self-intersections...
10297 
10298     // Next flatten it
10299     Path FlatPath;
10300     FlatPath.Initialise();
10301 
10302     BOOL bOK = Flatten(64, &FlatPath);
10303     if (!bOK)
10304         return -1;
10305 
10306     // Finally, compute the area under each flattened segment and sum them
10307     // (+dx adds to area, -dx subtracts from area)
10308     INT32 i = 0;
10309     XLONG area = 0;
10310     XLONG dx = 0;
10311     DocRect bounds = GetBoundingRect();
10312     INT32 baseline = bounds.lo.y;
10313 //  PathFlags* pFlags = FlatPath.GetFlagArray();
10314     DocCoord* pCoords = FlatPath.GetCoordArray();
10315     PathVerb* pVerbs  = FlatPath.GetVerbArray();
10316     DocCoord origin(0,0);
10317     for (i=0; i < FlatPath.GetNumCoords(); i++)
10318     {
10319         if (pVerbs[i] == PT_MOVETO)
10320             origin = pCoords[i];
10321         else if (pVerbs[i] == PT_LINETO)
10322         {
10323             // area of this segment is area of rectangle under origin.y + area of triangle from origin to current point
10324             dx = pCoords[i].x - origin.x;
10325             area += dx*(XLONG)(origin.y-baseline) + dx*(XLONG)((ABS(pCoords[i].y - origin.y))/2);
10326 
10327             origin = pCoords[i];
10328         }
10329         else if (pVerbs[i] == PT_CLOSEFIGURE)
10330         {
10331             // do nothing
10332         }
10333         else
10334             ERROR3("Unexpected path verb");
10335     }
10336 
10337     // Counter-clockwise paths will generate -ve areas
10338     return ABS(area);
10339 }

INT32 Path::CalcCRC  ) 
 

Calculates a cyclic redundancy check value for a path. This CRC is invariant under translation only. It can be used to determine whether a new path matches that of an old path whose CRC we already know, whether the new path has been translated or not.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/94
Parameters:
- [INPUTS]
Returns:
The CRC checksum for the path, relative to the first coord

Definition at line 8024 of file paths.cpp.

08025 {
08026     return CalcRegionCRC(0,UsedSlots-1);
08027 }

void Path::CalcDoubleCurve DocCoord p1,
DocCoord p2,
DocCoord p3,
DocCoord ControlPoint1,
DocCoord ControlPoint2
 

Calculates the position of the two control points on either side of p2, using the position of the coords of either side of it to help (p1 & p3).

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/11/93
Parameters:
p1,p2,p3 - The End points of the path elements before, after and at the [INPUTS] the current position in the path
ControlPoint1,ControlPoint2 - Pointers to the control points on either [OUTPUTS] side of the current point
See also:
Path::CalcPointLine; Path::CalcPointEnd

Definition at line 4797 of file paths.cpp.

04798 {
04799     // The positions of the two control points adjacent to p2 depend on:
04800     // a) The distance from p2 of p1 and p3, and
04801     // b) The angle between p1p2p3. The following logic is used:
04802     //
04803     // The distance from p2 to ControlPoint1 is 1/3 the distance from p2 to p1
04804     // The angle from p2 to ControlPoint1 and the horizontal is 90 degrees from the angle of the line
04805     // bisecting the angle p1p2p3. Whether it is -90 or +90 depends on whether the acute angle between p1p2p3
04806     // is negative or positive
04807 
04808 
04809     // Work out the angles
04810     double Alpha, Beta, Theta;
04811     Alpha = atan2((double)p3.y-p2.y, (double)p3.x-p2.x);            // Alpha = angle between line p2p3 and horizontal
04812     Beta = atan2((double)p1.y-p2.y, (double)p1.x-p2.x);             // beta = angle between line p2p1 and horizontal
04813     Theta = (Beta + ((Alpha - Beta)/2.0));          // Theta = bisection of Alpha and Beta
04814 
04815     // And calculate the distance between the various control points
04816     double Distp2p1, Distp2p3, lx, ly;
04817     lx = p2.x - p1.x;
04818     ly = p2.y - p1.y;
04819     Distp2p1 = sqrt( lx*lx + ly*ly ) / 3.0;
04820 
04821     lx = p2.x - p3.x;
04822     ly = p2.y - p3.y;
04823     Distp2p3 = sqrt( lx*lx + ly*ly ) / 3.0;
04824 
04825     if (Alpha - Beta < 0)
04826     {
04827         // Angle p2p1 is greater than p2p3, so we have to swap the angle used
04828 
04829         ControlPoint1->x = p2.x + (INT32)(Distp2p1 * cos(Theta + PI/2.0));
04830         ControlPoint1->y = p2.y + (INT32)(Distp2p1 * sin(Theta + PI/2.0));
04831         ControlPoint2->x = p2.x + (INT32)(Distp2p3 * cos(Theta - PI/2.0));
04832         ControlPoint2->y = p2.y + (INT32)(Distp2p3 * sin(Theta - PI/2.0));
04833 
04834     }
04835     else
04836     {
04837         ControlPoint1->x = p2.x + (INT32)(Distp2p1 * cos(Theta - PI/2.0));
04838         ControlPoint1->y = p2.y + (INT32)(Distp2p1 * sin(Theta - PI/2.0));
04839         ControlPoint2->x = p2.x + (INT32)(Distp2p3 * cos(Theta + PI/2.0));
04840         ControlPoint2->y = p2.y + (INT32)(Distp2p3 * sin(Theta + PI/2.0));
04841 
04842     }
04843 
04844 
04845 //  // Work out all the angles
04846 //  double Alpha, Beta, Theta;
04847 //  Alpha = atan2( (p3.y-p2.y), (p3.x - p2.x) );
04848 //  Beta  = atan2( (p2.x - p1.x), (p2.y - p1.y) );
04849 //  Theta = (PI/2.0 - Alpha - Beta) / 2.0;
04850 
04851 //  // And calculate the distance between the various control points
04852 //  double DistA, DistB, lx, ly;
04853 //  lx = p2.x - p1.x;
04854 //  ly = p2.y - p1.y;
04855 //  DistA = sqrt( lx*lx + ly*ly ) / 3.0;
04856 
04857 //  lx = p2.x - p3.x;
04858 //  ly = p2.y - p3.y;
04859 //  DistB = sqrt( lx*lx + ly*ly ) / 3.0;
04860 //
04861 //  if (Theta < PI/2.0)
04862 //  {
04863   //
04864 //  // Set the control point
04865 //  ControlPoint1->x = p2.x - (INT32)(DistA*sin(Theta+Beta));
04866 //  ControlPoint1->y = p2.y - (INT32)(DistA*cos(Theta+Beta));
04867 
04868 //  ControlPoint2->x = p2.x + (INT32)(DistB*cos(Theta+Alpha));
04869 //  ControlPoint2->y = p2.y + (INT32)(DistB*sin(Theta+Alpha));
04870     
04871 //  }
04872 //  else
04873 //  {
04874 
04875 //  // Set the control point
04876 //  ControlPoint1->x = p2.x + (INT32)(DistA*sin(Theta+Beta));
04877 //  ControlPoint1->y = p2.y + (INT32)(DistA*cos(Theta+Beta));
04878 
04879 //  ControlPoint2->x = p2.x - (INT32)(DistB*cos(Theta+Alpha));
04880 //  ControlPoint2->y = p2.y - (INT32)(DistB*sin(Theta+Alpha));
04881     
04882 //
04883 //  }
04884 
04885 }

void Path::CalcPointCurve DocCoord p1,
DocCoord p2,
DocCoord p3,
DocCoord ControlPoint
 

Calculates the position of the control point adjacent to p2 between p2 and p3, using the position of the coords of either side of it to help (p1 & p3).

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/11/93
Parameters:
p1,p2,p3 - The End points of the path elements before, after and at the [INPUTS] the current position in the path
ControlPoint - Pointer to the control point that appears just after p2. [OUTPUTS]
imagine the following path structure: moveto p1 curveto pa curveto pb curveto p2 <- This is the endpoint to which the ctrl point is attached curveto pc <- This is the control point being calculated curveto pd curveto p3

See also:
Path::CalcPointLine; Path::CalcPointEnd

Definition at line 4913 of file paths.cpp.

04914 {
04915     // Work out all the angles
04916     double Alpha, Beta, Theta;
04917     Alpha = atan2((double)p3.y-p2.y, (double)p3.x-p2.x);
04918     Beta = atan2((double)p1.y-p2.y, (double)p1.x-p2.x);
04919     Theta = Beta - ((Beta - Alpha)/2.0);
04920 
04921 
04922     // And calculate the distance between the various control points
04923     double Dist, lx, ly;
04924     lx = p2.x - p3.x;
04925     ly = p2.y - p3.y;
04926     Dist = sqrt( lx*lx + ly*ly ) / 3.0;
04927 
04928     if (Beta - Alpha < 0)
04929         Theta += PI/2.0;
04930     else
04931         Theta -= PI/2.0;
04932 
04933     ControlPoint->x = p2.x + (INT32)(Dist * cos(Theta));
04934     ControlPoint->y = p2.y + (INT32)(Dist * sin(Theta));
04935 
04936 /*
04937     if (Theta < PI/2.0)
04938     {
04939 
04940         // Set the control point
04941         ControlPoint->x = p2.x - (INT32)(Dist*sin(Theta+Beta));
04942         ControlPoint->y = p2.y - (INT32)(Dist*cos(Theta+Beta));
04943     }
04944     else
04945     {
04946 
04947         // Set the control point
04948         ControlPoint->x = p2.x + (INT32)(Dist*sin(Theta+Beta));
04949         ControlPoint->y = p2.y + (INT32)(Dist*cos(Theta+Beta));
04950         
04951     }
04952 */
04953 
04954 }

void Path::CalcPointEnd DocCoord p1,
DocCoord p2,
DocCoord ControlPoint
 

Calculates the position of the last control point in the sub-path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/11/93
Parameters:
p1,p2 - The coords of the last two points in the curve [INPUTS]
ControlPoint - The Coord of the last control point [OUTPUTS]
See also:
Path::CalcPointLine; Path::CalcPointCurve

Definition at line 5009 of file paths.cpp.

05010 {
05011     ControlPoint->x = p1.x + ((p2.x - p1.x) / 3);
05012     ControlPoint->y = p1.y + ((p2.y - p1.y) / 3);
05013 }

void Path::CalcPointLine DocCoord p1,
DocCoord p2,
DocCoord p3,
DocCoord ControlPoint
 

Calculates the position of the control point that appears after p2, which is part of the curve ending at p3. The control point should be colinear with p1 & p2 and 1/3 the distance between p2 & p3 from p2!

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/11/93
Parameters:
p1,p2,p3 - The End points of the path elements before, after and at the [INPUTS] the current position in the path
ControlPoint - Pointers to the control point between p2 and p3 [OUTPUTS]
See also:
Path::CalcPointLine; Path::CalcPointEnd

Definition at line 4972 of file paths.cpp.

04973 {
04974     // Calc 1/3 the distance from p2 to p3
04975     double DistA, DistB, lx, ly;
04976     lx = p2.x - p3.x;
04977     ly = p2.y - p3.y;
04978     DistA = sqrt( lx*lx + ly*ly ) / 3.0;
04979 
04980     // calc the length of p1 to p2
04981     lx = p2.x - p1.x;
04982     ly = p2.y - p1.y;
04983     DistB = sqrt( lx*lx + ly*ly );
04984 
04985     // Calculate the scale factor
04986     double Factor = (DistB==0.0) ? 1.0 : (DistA / DistB);
04987     lx *= Factor;
04988     ly *= Factor;
04989 
04990     // Calc the position of the new control points
04991     ControlPoint->x = p2.x + (INT32)lx;
04992     ControlPoint->y = p2.y + (INT32)ly;
04993 }

INT32 Path::CalcRegionCRC const INT32  StartIndex,
const INT32  EndIndex
 

Calculates a cyclic redundancy check value for a path region. This CRC is only invariant under translation. It can be used to determine whether a new path matches that of an old path whose CRC we already know, whether the new path has been translated or not.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>/Mike
Date:
11/11/94
Parameters:
StartIndex = index into coord array to start calculating from [INPUTS] EndIndex = index into coord array to end calculation (inclusive)
Returns:
The CRC checksum for the region, relative to StartIndex

Definition at line 8047 of file paths.cpp.

08048 {
08049     INT32 TotalCRC = 0;
08050     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
08051 
08052     for (INT32 i=StartIndex; i<(EndIndex+1); i++)
08053     {
08054         // Get the coords relative from the first coord
08055         // making this process transparent to translation
08056         // Add it in to the CRC total
08057         TotalCRC += (Coords[i].x-Coords[StartIndex].x) + 
08058                     (Coords[i].y-Coords[StartIndex].y);
08059     }
08060     return TotalCRC;
08061 }

void Path::CalcRotate DocCoord p2,
DocCoord p1,
DocCoord p3,
DocCoord MouseOffset
 

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/11/93
Parameters:
p1,p2,p3 - The End points of the path elements before, after and at the [INPUTS] the current position in the path
ControlPoint - Pointers to the control point between p2 and p3 [OUTPUTS]
See also:
Path::CalcPointLine; Path::CalcPointEnd

Definition at line 5033 of file paths.cpp.

05034 {
05035     double dx, dy, Length;
05036 
05037     // Find the length of the vector from the middle to the point not being dragged
05038     dx = p2.x - p3->x;
05039     dy = p2.y - p3->y;
05040     Length = sqrt( dx*dx + dy*dy );
05041 
05042     // Move the point being dragged
05043     p1->x += MouseOffset.x;
05044     p1->y += MouseOffset.y;
05045 
05046     // Calculate the vector from the point being dragged to the centre
05047     double VecLen;
05048     dx = p1->x - p2.x;
05049     dy = p1->y - p2.y;
05050     VecLen = sqrt( dx*dx + dy*dy );
05051     if (VecLen == 0.0)
05052         // the dragged point is over the centre point, so leave the other control point where it is
05053         return;
05054 
05055     // Normalise the vector and
05056     // Scale the vector by the Length of the other side
05057     dx = dx * Length / VecLen;
05058     dy = dy * Length / VecLen;
05059 
05060     // Set the opposite point to the centre offset by the vector
05061     p3->x = p2.x - (INT32)dx;
05062     p3->y = p2.y - (INT32)dy;
05063 }

INT32 Path::CalcSelectedCRC  ) 
 

Calculates a cyclic redundancy check value for a paths selected coordinates. This CRC is invariant under translation only. It can be used to determine whether a new path matches that of an old path whose CRC we already know, whether the new path has been translated or not.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/94
Parameters:
- [INPUTS]
Returns:
The CRC checksum for the path, relative to the first coord

Definition at line 8081 of file paths.cpp.

08082 {
08083     return CalcSelPointsCRC(0,UsedSlots-1);
08084 }

INT32 Path::CalcSelPointsCRC const INT32  StartIndex,
const INT32  EndIndex
 

Calculates a cyclic redundancy check value for a paths selected coordinates. This CRC is invariant under translation only. It can be used to determine whether a new path matches that of an old path whose CRC we already know, whether the new path has been translated or not.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>/Mike
Date:
11/11/94
Parameters:
StartIndex = index into coord array to start calculating from [INPUTS] EndIndex = index into coord array to end calculation (inclusive)
Returns:
The CRC checksum for the region, relative to StartIndex

Definition at line 8104 of file paths.cpp.

08105 {
08106     INT32 TotalCRC = 0;
08107     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
08108     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
08109 
08110     for (INT32 i=StartIndex; i<(EndIndex+1); i++)
08111     {
08112         if (Flags[i].IsSelected)
08113             TotalCRC += (Coords[i].x-Coords[StartIndex].x) + 
08114                         (Coords[i].y-Coords[StartIndex].y);
08115     }
08116     return TotalCRC;
08117 }

double Path::CalculateFlatnessValueFromPath double  DividerValue = 375.0,
double  LowerLimit = 1.0,
double  UpperLimit = 375.0
 

To calculate a suitable flatness value to be used with Contouring, Clipping and Stroking. The value is based on the actual size of the paths dimensions.

Author:
Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/10/2000
Parameters:
Divider Value which is incorperated into the calculation. [INPUTS] Lower and Upper Limits that the return value should be within.
Returns:
New calculated flatness value OR 0.0 if the path is empty!

Definition at line 5394 of file paths.cpp.

05395 {
05396     // Check to see if this path is empty, if so then just return 0.
05397     if(UsedSlots == 0)
05398         return 2.0;
05399 
05400     // Check to see if we`ve been given suitable values to use!
05401     if(LowerLimit < 1.0)
05402     {
05403         ERROR3("When I said give me a lower limit, I meant one larger than 1!");
05404         LowerLimit = 2.0;
05405     }
05406 
05407     if(UpperLimit < 1.0 || UpperLimit < LowerLimit)
05408     {
05409         ERROR3("When I said give me an Upper limit, I meant one larger than the Lower limit!");
05410         UpperLimit = 375.0;
05411     }
05412 
05413     if(DividerValue < 1.0)
05414     {
05415         ERROR3("When I said give me a Divider Value, I meant one greater than 1!");
05416         DividerValue = 375.0;
05417     }
05418 
05419     // Set up the CalcFlatness value
05420     double CalcFlatness = 375.0;
05421 
05422     // Get the smallest dimesion, Width or Height.
05423     DocRect drBounds = GetBoundingRect();
05424     double Smallest = drBounds.Height() < drBounds.Width() ? (double)drBounds.Height() : (double)drBounds.Width();
05425 
05426     // now make the flatness value equal to the smallest dimesion divided by the passed in DividerValue!
05427     CalcFlatness = Smallest / DividerValue;
05428 
05429     // Check to see if we`re within the specified limits
05430     if(LowerLimit > CalcFlatness) CalcFlatness = LowerLimit;
05431     if(UpperLimit < CalcFlatness) CalcFlatness = UpperLimit;
05432 
05433     TRACEUSER( "MarkH", _T("Calculated Flatness = %lf\n"),CalcFlatness);
05434 
05435     // Return the new calculated flatness value!
05436     return CalcFlatness;
05437 }

BOOL Path::ChangeStartElement INT32  StartIndex  ) 
 

This will rotate the path so that the element that was at StartIndex is now at index 0. You should only call this for closed paths that don't contain subpaths.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
8/11/94
Parameters:
StartIndex - The index to the element in the path that you want to be the start [INPUTS]
- [OUTPUTS]
Returns:
TRUE if OK, FALSE otherwise

Errors: In debug builds, an error is given if the last coord != first coord

Definition at line 9141 of file paths.cpp.

09142 {
09143     if (StartIndex < 1 || StartIndex >= UsedSlots)
09144     {
09145         ERROR3_PF(("StartIndex out of range : %ld",StartIndex));
09146         return FALSE;
09147     }
09148 
09149     DocCoord*  pCoords = GetCoordArray();
09150     PathVerb*  pVerbs  = GetVerbArray();
09151     PathFlags* pFlags  = GetFlagArray();
09152 
09153     ERROR3IF(pCoords[0] != pCoords[UsedSlots-1],"Not closed because first coord != last coord");
09154 
09155     // Make sure the last verb has the PT_CLOSEFIGURE flag cleared
09156     pVerbs[UsedSlots-1] = pVerbs[UsedSlots-1] & ~PT_CLOSEFIGURE;
09157 
09158     // Delete the MoveTo
09159     CurrentPos = 0;
09160     DeleteElement();
09161 
09162     ERROR3IF(UnUsedSlots < 1,"DeleteElement() didn't leave me any unused slots");
09163     if (UnUsedSlots < 1) return FALSE;
09164 
09165     // Rotate the element at StartIndex to index 0
09166     RotateElementsLeft(0,UsedSlots-1,StartIndex-1);
09167 
09168     // We need a duplicate element type & verb to finish the path off, so copy on end of arrays
09169     pCoords[UsedSlots] = pCoords[0];
09170     pVerbs [UsedSlots] = pVerbs [0] | PT_CLOSEFIGURE;   // Make sure last verb has also got this flag set
09171     pFlags [UsedSlots] = pFlags [0];
09172 
09173     // The first element is always a MoveTo
09174     pVerbs[0] = PT_MOVETO;
09175 
09176     // Update the path vars.
09177     UsedSlots++;
09178     UnUsedSlots--;
09179 
09180     return TRUE;
09181 }

void Path::ClearNeedToRender  ) 
 

Sets the NeedToRender flags on all of the path elements to FALSE.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/1/95
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

Definition at line 9545 of file paths.cpp.

09546 {
09547     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
09548     for (INT32 loop = GetNumCoords()-1; loop >= 0 ; loop--)
09549     {
09550         Flags[loop].NeedToRender = FALSE;
09551     }
09552 }

BOOL Path::ClearPath BOOL  compress  ) 
 

Empties the path of all its entries. If compress is TRUE the routine will try to free up excessive amounts of unused memory left over at the end. It also now resets CurrentPos back to zero.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/11/94
Parameters:
compress - a boolean, to describe whether to compress the paths memory [INPUTS] or not.
Returns:
TRUE if it was able to free up the unused parts of the path, FALSE if there was a memory de-alloc error
See also:
Path::Compact();

Definition at line 2438 of file paths.cpp.

02439 {
02440     if (UsedSlots>0)
02441     {
02442         // reset the path definitions
02443         UnUsedSlots+=UsedSlots;
02444         UsedSlots=0;
02445         CurrentPos=0;
02446         // make sure we compress memory if necessary
02447         if (compress)
02448             Compact();                      // ignore any error coming from here
02449     }   
02450     return TRUE;
02451 } 

BOOL Path::ClearPath  ) 
 

Empties the path of all its entries and tries to free up excessive amounts of unused memory left over at the end. It does keep some memory though, ready for a new path to be put into it. It also now resets CurrentPos back to zero.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/02/94
Returns:
TRUE if it was able to free up the unused parts of the path, FALSE if there was a memory de-alloc error

Definition at line 2408 of file paths.cpp.

02409 {
02410     if (UsedSlots==0)
02411         return TRUE;
02412 
02413     BOOL ok = DeleteSection(0,UsedSlots);
02414     if (ok)
02415         CurrentPos=0;
02416     return ok;
02417 }

void Path::ClearSubSelection  ) 
 

Goes through the path and sets all the IsSelected flags to FALSE, clearing any selected control points in the path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/4/94

Definition at line 3572 of file paths.cpp.

03573 {
03574     // We need to find all the selected control points in the path and de-select them
03575     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
03576 
03577     for (INT32 i=0; i<UsedSlots; i++)
03578         Flags[i].IsSelected = FALSE;
03579 } 

INT32 Path::ClipPathToPath const Path Src,
Path *const   pDest,
UINT32  Flags,
UINT32  Tolerance = 100,
double  SrcFlatness = 750.0,
double  ClipFlatness = 750.0
 

This is an interface to Gavin's ClipPathToPath.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/1/95
Parameters:
Src = source path to clip [INPUTS] pDest = ptr to path to place the result in Flags = Gavin's ClipPathToPath flags (see below) Tolerence = Two points closer than this value are considered the same point SrcFlatness = the value used to flatten the src path ClipPath = the value used to flatten the clip path
If returned a value >=0, *pDest contains the resultant path. [OUTPUTS]
Returns:
The length of the resultant path in pDest, or -1 for an error.
'this' path is used as the clip path. Src is clipped to this path and the result is placed in pDest.

'Flags' controls how Src will be clipped to this path (taken from gclip.h - complaints go to Gavin) CLIPPING_STYLE - Clip style 001 - Source AND NOT Clip (subtract Clip from Source) 010 - Source AND Clip (Intersection) 011 - Source 100 - NOT Source AND Clip (subtract Source from Clip) 101 - Source EOR Clip 110 - Clip 111 - Source OR Clip (Union)

  • If stroked then 000 - Source AND Clip (Intersection) ??? - Source AND NOT Clip CLIPPING_SOURCE_WINDING - Source path winding. CLIPPING_CLIP_WINDING - Clip path winding. CLIPPING_IS_STROKED - Source is stroked, not filled CLIPPING_IS_CLOSED - Source path is to be closed (only applicable if stroked).

NOTE: The path placed in pDest will not have its flags array initialised. If you require this (e.g. the path is part of a NodePath and is going in the tree) call Path::InitialiseFlags() on pDest. If you don't, the path won't be editable via the bezier tool.

Definition at line 5483 of file paths.cpp.

05485 {
05486     ERROR2IF(pDest == NULL,-1,"pDest == NULL");
05487 
05488     // We need a temp path to place the result in (return -1 if it fails to initialise)
05489     Path Output;
05490     if (!Output.Initialise()) return -1;
05491 
05492     // Mark Howitt - 1/9/00
05493     // Guessing is not good practice. The major problem in this function is that we need
05494     // to allocate memory before we know how much to allocate!!! This results in more memory than needed being used
05495     // and also the risk of under estimating leading to failure!
05496     // The way to fix this is get Gavin to do the allocation for us and then return the amount. This is currently the
05497     // way the contouring code works which results in no guessing and exact memory allocation. NO WASTE!
05498     // To quickly fix this problem I`m going to make it so that if it comes back with buffer overflow, we double the
05499     // allocation and try again. If this fails after 5 times then return -1 and error2 with failure. This is still not
05500     // very good but will fix a majority of the bugs we are seeing. MUST BE REPLACED!!!!!
05501 
05502     // Try and guess how big the destination path's buffers will have to be in order to take the result.
05503     INT32 NewSize = ((UsedSlots + Src.UsedSlots)*2)+1000;
05504 
05505     // Make sure the destination path is big enough
05506     if (!Output.MakeSpaceInPath(NewSize)) return -1;
05507 
05508     // Set up the params for ClipPathToPath, Gavin-style!
05509     PPOINT SPoints,CPoints,OPoints ;
05510     PBYTE  STypes ,CTypes ,OTypes  ;
05511     UINT32  SLength,CLength,OLength ;
05512 
05513     if ( (Flags & 7)==6 && !(Flags & 0x40) )
05514     {
05515         SPoints = NULL;
05516         STypes  = NULL;
05517         SLength = 0;
05518     }
05519     else
05520     {
05521         SPoints = (PPOINT)  Src.GetCoordArray();
05522         STypes  = (PBYTE)   Src.GetVerbArray();
05523         SLength =           Src.UsedSlots;
05524     }
05525     if ( (Flags & 7)==3 && !(Flags & 0x40) )
05526     {
05527         CPoints = NULL;
05528         CTypes  = NULL;
05529         CLength = 0;
05530     }
05531     else
05532     {
05533         CPoints = (PPOINT)  GetCoordArray();
05534         CTypes  = (PBYTE)   GetVerbArray();
05535         CLength =           UsedSlots;
05536     }
05537 
05538     OPoints = (PPOINT)  Output.GetCoordArray();
05539     OTypes  = (PBYTE)   Output.GetVerbArray();
05540     OLength = NewSize;
05541     INT32 len = -2;
05542     INT32 Passes = 0;
05543 
05544     // Mark Howitt 1/9/00
05545     // New loop to help fix under allocation bugs. NEEDS REPLACING WITH BETTER CODE!!! See above!
05546     while(len == -2 && Passes++ < 10)
05547     {
05548         len = ::ClipPathToPath( SPoints,STypes,SLength,SrcFlatness,
05549                                         CPoints,CTypes,CLength,ClipFlatness,
05550                                         Flags,Tolerance,
05551                                         OPoints,OTypes,OLength-10);     // -10 to safe guard against possible minor buffer overflow
05552 
05553         if(len == -1)
05554             return -1;
05555         else if(len == -2)
05556         {
05557             // Ok, we under estimated so double it and reset the output path variables!
05558             OLength <<= 1;
05559             if (!Output.EnsureVolume(OLength)) return -1;
05560             Output.ClearPath();
05561             OPoints = (PPOINT)  Output.GetCoordArray();
05562             OTypes  = (PBYTE)   Output.GetVerbArray();
05563         }
05564     }
05565 
05566     // If we get here with len == -2 then we failed in 5 attempts to allocate enough space!
05567     if(len < 0)
05568         return -1;
05569 
05570     // Clear pDest and make sure there's enough space in pDest for the result
05571     pDest->ClearPath();
05572     if (!pDest->MakeSpaceInPath(len)) return -1;
05573 
05574     // Copy the resultant path into it.
05575     if (!pDest->MergeTwoPaths(Output.GetCoordArray(),Output.GetVerbArray(),Output.GetFlagArray(),len,Src.IsFilled))
05576         return -1;
05577 
05578     // YES! we have a result
05579     return len; 
05580 }

BOOL Path::CloneFrom const Path Other  ) 
 

Replace the data within this path with that of Other path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/10/94
Parameters:
Other = pointer to a path to copy data from [INPUTS] Returns TRUE if successful FALSE if unable in increase the size of this path to cope with all data in 'Other'

Definition at line 7277 of file paths.cpp.

07278 {
07279     // Make space to copy all the data from the other path into this one
07280     INT32 SlotsToCopy = Other.UsedSlots;
07281     INT32 SlotsToAdd  = SlotsToCopy-UsedSlots;
07282 
07283     if (SlotsToAdd>0)
07284     {
07285         if (!MakeSpaceAtEnd(SlotsToAdd))
07286             return FALSE;
07287     }
07288 
07289     // We will need all the arrays from the other path
07290     DocCoord*  SCoords = (DocCoord*)  DescribeHandle(Other.CoordHandle);
07291     PathVerb*  SVerbs  = (PathVerb*)  DescribeHandle(Other.VerbHandle);
07292     PathFlags* SFlags  = (PathFlags*) DescribeHandle(Other.FlagsHandle);
07293 
07294     // Get the destination arrays
07295     DocCoord*  DCoords = (DocCoord*)  DescribeHandle(CoordHandle);
07296     PathVerb*  DVerbs  = (PathVerb*)  DescribeHandle(VerbHandle);
07297     PathFlags* DFlags  = (PathFlags*) DescribeHandle(FlagsHandle);
07298 
07299     // copy all arrays from the source to destination
07300     if (SlotsToCopy>0)
07301     {
07302         if (SCoords != NULL) memmove((void*)(DCoords), (void*)(SCoords), SlotsToCopy*sizeof(DocCoord));
07303         if (SVerbs  != NULL) memmove((void*)(DVerbs),  (void*)(SVerbs),  SlotsToCopy*sizeof(PathVerb));
07304         if (SFlags  != NULL) memmove((void*)(DFlags),  (void*)(SFlags),  SlotsToCopy*sizeof(PathFlags));
07305     }
07306 
07307     // Now update the array variables
07308     UsedSlots   += SlotsToAdd;
07309     UnUsedSlots -= SlotsToAdd;
07310     CurrentPos   = UsedSlots;
07311 
07312     return TRUE;
07313 }

DocCoord Path::ClosestPointTo const double  t,
const INT32  index
 

This function returns the point at which the closest distance on the path occurs.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
t = closest distance parameter [INPUTS] index = closest distance path element index
[OUTPUTS] 
Returns:
DocCoord, the closest point on the path

Errors: Ensures the indexed path element is either a lineto or bezierto

Definition at line 7004 of file paths.cpp.

07005 {
07006     // Get the coord list and verb list for this path instance
07007 
07008     DocCoord* Coords = GetCoordArray();
07009     PathVerb* Verbs = GetVerbArray();
07010     PathVerb Verb = Verbs[index] & ~PT_CLOSEFIGURE;
07011 
07012     if ((t==0) && (index==0))
07013         return Coords[0];
07014 
07015     ENSURE(UsedSlots>1, "Not enough elements in path");
07016     ENSURE(index>=0, "invalid formal parameter: index");
07017     ENSURE((Verb == PT_LINETO) || (Verb == PT_BEZIERTO), 
07018             "Unable to find point on path. Index does not specify line or curve");
07019 
07020     if (index<UsedSlots)
07021     {
07022         switch (Verb)
07023         {
07024             case PT_LINETO:
07025                 return PathUtil::PointOnLine(t,&Coords[index-1]);
07026                 break;
07027             case PT_BEZIERTO:
07028                 return PathUtil::PointOnCurve(t,&Coords[index-1]);
07029                 break;
07030         }
07031     }
07032 
07033     // code should not really get here! if it does, return the first element
07034     // of the curve
07035 
07036     return (Coords[0]);
07037 }

BOOL Path::ClosestSelectedEndpoint DocCoord  pos,
INT32 *  position,
double *  distance
 

This function finds the closest selected line end to the cursor position passed in. If the path has no selected line ends, the function returns FALSE.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/4/94
Parameters:
pos - mouse position to be tested [INPUTS]
position - index to the point that was matched [OUTPUTS] unchanged if no match distance - distance between the specified point and the closest selected endpoint (unchanged if there are none)
Returns:
TRUE if a match was found, FALSE if not

Definition at line 7213 of file paths.cpp.

07214 {
07215     // Get arrays for this path
07216     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
07217     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
07218     PathFlags* PFlags = (PathFlags*) DescribeHandle(FlagsHandle);
07219 
07220     double nearest = 0;
07221     double tempdistance = 0;
07222     BOOL foundany = FALSE;
07223 
07224     // Scan from the end of the path to the start. We remember the last point in the subpath
07225     // and go back until we hit a MoveTo. then we look at both the elements, and if the 
07226     // CloseFigure flag isn't set in the end element, the subpath must be open, in which
07227     // case we look at the endpoints and see if they are closer to pos than others.
07228 
07229     INT32 endpoint = UsedSlots-1;
07230     for (INT32 i=UsedSlots-1;i>=0;i--)
07231     {
07232         if (Verbs[i] == PT_MOVETO)
07233         {
07234             // only check the ends if CLOSEFIGURE is not set in the end verb
07235             if (!(Verbs[endpoint] & PT_CLOSEFIGURE))
07236             {
07237                 // first check the moveto
07238                 tempdistance = Coords[i].Distance(pos);
07239                 if ((PFlags[i].IsSelected) && (!foundany || (nearest>tempdistance)))
07240                 {
07241                     *position = i;
07242                     nearest = tempdistance;
07243                     foundany = TRUE;
07244                 }
07245 
07246                 // Now check the end point
07247                 tempdistance = Coords[endpoint].Distance(pos);
07248                 if ((PFlags[endpoint].IsSelected) && (!foundany || (nearest>tempdistance)))
07249                 {
07250                     *position = endpoint;
07251                     nearest = tempdistance;
07252                     foundany = TRUE;
07253                 }
07254             }
07255             endpoint = i-1;
07256         }
07257     }
07258     return(foundany);
07259     
07260 }

BOOL Path::CloseSubPath  ) 
 

To indicate that a path is closed with a line, you should call CloseSubPath with the Current Path Position indicator somewhere inside the sub-path that you want closed. This function will adjust the verb of the last line segment in the sub-path by adding the PT_CLOSEFIGURE element into as described in the NT Prog Reference guides for the PolyDraw() function (page 304 of book 4 at last count) The Current Path Position is left on the element at the end of the subpath.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
TRUE if it worked, FALSE if it fails (ie you tried to close a path that only had a PT_MOVETO element in it.

Definition at line 2226 of file paths.cpp.

02227 {
02228     // need to search for either a MoveTo or the end of the path and insert a close
02229     // path just before it. We start from the position supplied
02230     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
02231 
02232     // We are inside the path somewhere
02233     while (CurrentPos+1<UsedSlots)
02234     {
02235         if (Verbs[CurrentPos+1]==PT_MOVETO)
02236         {
02237             // go back one and close the path
02238             ENSURE( Verbs[CurrentPos]!=PT_MOVETO, "You can not close a path at a moveto" );
02239             if (Verbs[CurrentPos]==PT_MOVETO)
02240                 return FALSE;
02241 
02242             Verbs[CurrentPos] = Verbs[CurrentPos] | PT_CLOSEFIGURE;
02243             return TRUE;
02244         }
02245 
02246         CurrentPos++;
02247     }
02248 
02249     // Make sure we are in the path
02250     if (CurrentPos>=UsedSlots)
02251         CurrentPos = UsedSlots-1;
02252 
02253     // We are right at the end of the path, so change the last path element
02254     ENSURE( Verbs[CurrentPos]!=PT_MOVETO, "You can not close a path at a moveto" );
02255     if (Verbs[CurrentPos]==PT_MOVETO)
02256         return FALSE;
02257 
02258     Verbs[CurrentPos] = Verbs[CurrentPos] | PT_CLOSEFIGURE;
02259     CurrentPos++;
02260     return TRUE;
02261 }

BOOL Path::Compact  ) 
 

Removes any extraneous unused slots in a path. It will a maximum of 2n-1 slots free where n is the size of an allocation chunk when increasing the buffer (see Path::Initialise).

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/11/94
Parameters:
- [INPUTS]
Returns:
FALSE if the path failed to compact

Definition at line 4025 of file paths.cpp.

04026 {
04027     // Calculate the buffer reduction factor.
04028     INT32 reduction = ((UnUsedSlots / SlotAllocSize)-1)*SlotAllocSize;
04029 
04030     if (reduction>0)
04031     {
04032         // reduce the number of free slots NOW, incase m out of the n
04033         // following reductions fail.
04034         UnUsedSlots -= reduction;
04035 
04036         if ((DecreaseBlock(VerbHandle, sizeof(PathVerb)*reduction)==FALSE) ||
04037             (DecreaseBlock(FlagsHandle, sizeof(PathFlags)*reduction)==FALSE) ||
04038             (DecreaseBlock(CoordHandle, sizeof(DocCoord)*reduction)==FALSE) ||
04039             (ExtraInfo!=NULL && ExtraInfo->DecreaseExtraBlocks(reduction)==FALSE))
04040         {
04041             // Memory shrink failed, so pass that back to the person using the Path
04042             // The path should still be useable at this stage so long as all handles
04043             // are valid.
04044             return FALSE;
04045         }
04046     }
04047     return TRUE;
04048 }

INT32 Path::ComparePathToPath Path pComparePath,
BOOL  QuickCheck = TRUE
 

Compares athis path to a passed in path. It firswt does a quick check on the number of coords and if they are equal does a more thoughour check on the verb array and coord array.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> howitt
Date:
05/12/00
Parameters:
A path to compare against. [INPUTS] A flag to say wether to return as soon as it finds a difference (Default TRUE)
Returns:
The difference in number of coords + or -.

Definition at line 1066 of file paths.cpp.

01067 {
01068     // Setup a default return value. This is basically the negative value of this paths
01069     // number of coords!
01070     INT32 ThisPathLength = (INT32)GetNumCoords();
01071     INT32 Difference = -ThisPathLength;
01072 
01073     // Only do any comparing if we`ve got valid pointers
01074     if(pComparePath)
01075     {
01076         // quick check first!
01077         if(ThisPathLength == pComparePath->GetNumCoords())
01078         {
01079             // Get the Coord array and Verb array for both paths.
01080             DocCoord* SPoint = GetCoordArray();
01081             DocCoord* CPoint = pComparePath->GetCoordArray();
01082             PBYTE SVerb = GetVerbArray();
01083             PBYTE CVerb = pComparePath->GetVerbArray();
01084 
01085             // Reset the Difference Value
01086             Difference = 0;
01087             
01088             // Now go throught each element of the arrays calculating the differences
01089             for( INT32 i = 0; i < ThisPathLength; i++)
01090             {
01091                 // If either the points OR verbs are different then increment the Diff counter
01092                 if(SPoint[i] != CPoint[i] || SVerb[i] != CVerb[i])
01093                 {
01094                     Difference++;
01095                     if(QuickCheck)
01096                         break;
01097                 }
01098             }
01099         }
01100         else
01101         {
01102             // Ok! there`s different so calcualte the difference
01103             Difference = ThisPathLength - (INT32)pComparePath->GetNumCoords();
01104         }
01105     }
01106 
01107     // return the Differance
01108     return Difference;
01109 }

BOOL Path::ComplexJoin Path Other,
INT32 *  OtherStartSlot,
BOOL *  IsOtherReversed
 

Tries to Join the New Path (must be simple) to a complex path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/4/94
Parameters:
Other - The New path that needs Joining in [INPUTS]
OtherStartSlot - The Slot number in the combined path where the path [OUTPUTS] Other starts. IsOtherReversed - TRUE if the 'Other' path was reversed during the joining process. FALSE if it was not
Returns:
TRUE if it worked, FALSE if it failed

Definition at line 6412 of file paths.cpp.

06413 {
06414     // We have not reversed the other path yet
06415     *IsOtherReversed = FALSE;
06416 
06417     // Do we need to reverse any elements of this path
06418     INT32 StartSlot = 0;
06419     INT32 NumSlots = 0;
06420     INT32 JoinStart = 0;
06421     INT32 JoinLen = 0;
06422     BOOL JoinedAtStart = FALSE;
06423     BOOL JoinFound = FALSE;
06424     DocCoord*  OtherCoords = (DocCoord*)  DescribeHandle(Other->CoordHandle);
06425 
06426     // Find out if we need to reverse this path to help with the joining
06427     if (FindJoinedSubPathInfo(OtherCoords[0], &StartSlot, &NumSlots, &JoinedAtStart))
06428     {
06429         // We found a join
06430         JoinFound = TRUE;
06431         JoinStart = StartSlot;
06432         JoinLen = NumSlots;
06433 
06434         // Maybe need to reverse this path
06435         if (JoinedAtStart)
06436             ReverseSection(StartSlot, NumSlots);
06437     }
06438 
06439     // And check to see if the other end needs checking as well.
06440     if (FindJoinedSubPathInfo(OtherCoords[Other->UsedSlots-1], &StartSlot, &NumSlots, &JoinedAtStart))
06441     {
06442         // We found a join
06443         JoinFound = TRUE;
06444         JoinStart = StartSlot;
06445         JoinLen = NumSlots;
06446 
06447         // Reverse the joining path always
06448         Other->Reverse();
06449 
06450         // We have reversed the other path
06451         *IsOtherReversed = TRUE;
06452 
06453         // and maybe reverse this path
06454         if (JoinedAtStart)
06455             ReverseSection(StartSlot, NumSlots);
06456     }
06457 
06458     // If we found a join then everything is fabby
06459     if (JoinFound)
06460     {
06461         // Make sure that there is room in the path to copy one of the sub-paths
06462         CurrentPos = UsedSlots;
06463         if (!MakeSpaceInPath(JoinLen))
06464             return FALSE;
06465 
06466         // copy the sub path
06467         if (!InsertSectionAtEnd(this, JoinStart, JoinLen))
06468             return FALSE;
06469 
06470         // delete the original version of the sub path
06471         DeleteSection(JoinStart, JoinLen);
06472         
06473         // Make sure that there is enough room for the new path
06474         CurrentPos = UsedSlots;
06475         if (!MakeSpaceInPath(Other->UsedSlots-1))
06476             return FALSE;
06477 
06478         // copy the new path
06479         *OtherStartSlot = UsedSlots-1;
06480         if (!InsertSectionAtEnd(Other, 1, Other->UsedSlots-1))
06481             return FALSE;
06482     }
06483     else
06484     {
06485         // We did not find a join
06486         return FALSE;
06487     }
06488 
06489     // See if we can close anything
06490     TryToClose();
06491 
06492     // Must have worked, so Move the insertion point to the end and return happy
06493     CurrentPos = UsedSlots;
06494     return TRUE;
06495 }

BOOL Path::ComplexToSameComplexJoin Path Other,
INT32 *  OtherStartSlot,
BOOL *  IsOtherReversed
 

This path is assumed to be complex and Other is assumed to be a simple path. The start and end point of the Simple Path must be the same as the start or end point of one of the sub paths of this complex path. The function Moves the two sub paths that are touched by the simple path to the end of the path, and inserts the simple path between them. This means that the two touched sub-paths and the new simple path are combined into a single sub path. This may also mean that this complex path is no longer complex.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/4/94
Parameters:
Other - The path to Join with this complex path. [INPUTS]
OtherStartSlot - The Slot number in the combined path where the path [OUTPUTS] Other starts. IsOtherReversed - TRUE if the 'Other' path was reversed during the joining process. FALSE if it was not

Definition at line 6520 of file paths.cpp.

06521 {
06522     INT32 BackStartSlot, BackNumSlots;
06523     INT32 FrontStartSlot, FrontNumSlots;
06524     BOOL FrontJoinedAtStart, BackJoinedAtStart;
06525 
06526     // We have not reversed the other path yet
06527     *IsOtherReversed = FALSE;
06528 
06529     // Get a few arrays
06530     DocCoord*  OtherCoords = (DocCoord*)  DescribeHandle(Other->CoordHandle);
06531 
06532     // First we have to gather data about the subpaths we are joined to
06533     if (!FindJoinedSubPathInfo(OtherCoords[0], &FrontStartSlot, &FrontNumSlots, &FrontJoinedAtStart))
06534         return FALSE;
06535 
06536     // And the other sub path, Fail if we there is no intersection
06537     if (!FindJoinedSubPathInfo(OtherCoords[Other->UsedSlots-1], &BackStartSlot, &BackNumSlots, &BackJoinedAtStart))
06538         return FALSE;
06539 
06540     // If this was trying to join a sub path to the other end of the same sub path
06541     // then we need to use a different function
06542     if (FrontStartSlot == BackStartSlot)
06543         return ComplexJoin(Other, OtherStartSlot, IsOtherReversed);
06544 
06545     // Build a path to store the combined paths in
06546     Path InsertPath;
06547     InsertPath.Initialise(FrontNumSlots+BackNumSlots+Other->UsedSlots);
06548 
06549     // Reverse the first subpath if we need to
06550     if (FrontJoinedAtStart)
06551         ReverseSection(FrontStartSlot, FrontNumSlots);
06552     
06553     // Reverse the Second subpath if we need to
06554     if (!BackJoinedAtStart)
06555         ReverseSection(BackStartSlot, BackNumSlots);
06556 
06557     // Make copys of all the path sections
06558     // The path joined to the start of the new path
06559     if (!InsertPath.InsertSectionAtEnd(this, FrontStartSlot, FrontNumSlots))
06560         return FALSE;
06561 
06562     // followed by the new path
06563     *OtherStartSlot = InsertPath.UsedSlots-1;
06564     if (!InsertPath.InsertSectionAtEnd(Other, 1, Other->UsedSlots-1))
06565         return FALSE;
06566 
06567     // followed by the path joined to the end of the new path
06568     if (!InsertPath.InsertSectionAtEnd(this, BackStartSlot+1, BackNumSlots-1))
06569         return FALSE;
06570 
06571     // Get rid of the original sub-path
06572     DeleteSection(FrontStartSlot, FrontNumSlots);
06573 
06574     // Go find the Other Coords array again as it may have moved
06575     OtherCoords = (DocCoord*)  DescribeHandle(Other->CoordHandle);
06576 
06577     // Find the location of the Second path again, as deleting the first path may have moved it
06578     if (!FindJoinedSubPathInfo(OtherCoords[Other->UsedSlots-1], &BackStartSlot, &BackNumSlots, &BackJoinedAtStart))
06579         return FALSE;
06580 
06581     // Get rid of the second sub-path
06582     DeleteSection(BackStartSlot, BackNumSlots);
06583 
06584     // Make enough space in the path to store a copy of the two subpaths and the new path
06585     CurrentPos = UsedSlots;
06586     if (!MakeSpaceInPath(InsertPath.UsedSlots))
06587         return FALSE;
06588 
06589     // copy the Insert Path to the end of the original path
06590     *OtherStartSlot += UsedSlots;
06591     if (!InsertSectionAtEnd(&InsertPath, 0, InsertPath.UsedSlots))
06592         return FALSE;
06593 
06594     // Must have worked, so return happy
06595     CurrentPos = UsedSlots;
06596     return TRUE;
06597 }

DocCoord Path::ConvSqrDistToCoord const double  sqrdist  ) 
 

Finds the coordinate which is dist units along 'this' path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/11/94
Parameters:
sqrdist = squared distance along the path [INPUTS]
[OUTPUTS] 
Returns:
a doccoord which is dist units along the path

Definition at line 7971 of file paths.cpp.

07972 {
07973     INT32 Index;
07974     double mu = DistReparameterise(sqrdist, &Index);
07975     return ClosestPointTo(mu, Index);   
07976 }

BOOL Path::CopyPathDataFrom DocCoord Coords,
PathVerb Verbs,
INT32  NumCoords,
BOOL  Filled = FALSE,
BOOL  Stroked = TRUE
 

Copy the specified coords and verbs to this path. The path's flags will be the defaults as specified in the constructors. You must already have initialised this path by calling Path::Initialise(). Pass it an Initial size big enough to hold the path you want to copy.

BOOL Path::CopyPathDataFrom( DocCoord* Coords, PathVerb* Verbs, INT32 NumCoords, BOOL IsFilled = FALSE, BOOL IsStroked = TRUE)

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
03/02/94
Parameters:
Coords - The path coords you want to copy [INPUTS] Verbs - The verbs you want to copy NumCoords - The number of coords to copy IsFilled - Is the path filled ? IsStroked - Is the path stroked ?
Returns:
TRUE if it worked, FALSE otherwise. Can fail if there is not enough space in the path to copy the data into.

Definition at line 452 of file paths.cpp.

00454 {
00455 
00456     // Check that this path has enough slots
00457     if (UsedSlots+UnUsedSlots < NumCoords)
00458     {
00459         // There is not enough space in this path to copy the SrcPath to
00460         TRACEUSER( "Simon", _T("Not enough space in path to copy data to\n") );
00461         return FALSE;
00462     }
00463 
00464     // copy the data across
00465     memcpy((void*)DescribeHandle(VerbHandle), (void*)Verbs, 
00466            (size_t)NumCoords*sizeof(PathVerb));
00467 
00468     memcpy((void*)DescribeHandle(CoordHandle), (void*)Coords, 
00469            (size_t)NumCoords*sizeof(DocCoord));
00470 
00471     // Every point on the path has the default constructor flags set
00472     PathFlags f;
00473     PathFlags* pFlags = (PathFlags*) DescribeHandle(FlagsHandle); 
00474 
00475     for (INT32 i = 0; i< NumCoords; i++)
00476     {
00477         pFlags[i] = f;      
00478     }
00479 
00480     // Set the vars that tell us how much mem has been used
00481     UnUsedSlots = (UsedSlots+UnUsedSlots) - NumCoords;
00482     UsedSlots = NumCoords;
00483 
00484     // Keep track of the current path position
00485     CurrentPos = 0; 
00486 
00487     IsFilled = Filled; 
00488     IsStroked = Stroked;
00489 
00490     // Well, as far as I can tell its worked
00491     return TRUE;
00492 
00493 } 

BOOL Path::CopyPathDataFrom Path SrcPath  ) 
 

Copy the coords, verbs and flags from the SrcPath to this path. You must already have initialised this path by calling Path::Initialise(). Pass it an Initial size big enough the hold the path you want to copy.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94
Parameters:
SrcPath - The path that you want to copy data from [INPUTS]
Returns:
TRUE if it worked, FALSE otherwise. Can fail if there is not enough space in the path to copy SrcPaths data into.

Definition at line 383 of file paths.cpp.

00384 {
00385     // Ensure that a non-null path is being used.
00386     if ( SrcPath == NULL )
00387         return FALSE;
00388 
00389     // Find out how much space we need to alloc in this new path
00390     INT32 NumCoords = SrcPath->GetNumCoords();
00391 
00392     if (UsedSlots+UnUsedSlots < NumCoords)
00393     {
00394         // There is not enough space in this path to copy the SrcPath to
00395         //if (IsUserName("Rik")) TRACE( _T("Not enough space in path to copy data to\n") );
00396         ERROR3 ("Not enough space in path to copy data to!");
00397         return FALSE;
00398     }
00399 
00400     // copy the data across
00401     memcpy((void*)DescribeHandle(VerbHandle), (void*)DescribeHandle(SrcPath->VerbHandle), 
00402            (size_t)NumCoords*sizeof(PathVerb));
00403 
00404     memcpy((void*)DescribeHandle(CoordHandle), (void*)DescribeHandle(SrcPath->CoordHandle), 
00405            (size_t)NumCoords*sizeof(DocCoord));
00406 
00407     memcpy((void*)DescribeHandle(FlagsHandle), (void*)DescribeHandle(SrcPath->FlagsHandle), 
00408            (size_t)NumCoords*sizeof(PathFlags));
00409 
00410     // If the source path has extra info in it then we need to copy that too
00411     if (SrcPath->ExtraInfo != NULL) 
00412         ExtraInfo->CopyExtraInfo(SrcPath->ExtraInfo);
00413 
00414     // Set the vars that tell us how much mem has been used
00415     UnUsedSlots = (UsedSlots+UnUsedSlots) - NumCoords;
00416     UsedSlots = NumCoords;
00417 
00418     // copy any other flags of value
00419     IsFilled = SrcPath->IsFilled;
00420     IsStroked = SrcPath->IsStroked;
00421 
00422     // Keep track of the current path position
00423     CurrentPos = 0;
00424 
00425     // Well, as far as I can tell its worked
00426     return TRUE;
00427 }

BOOL Path::CopySectionFrom const Path Other,
INT32  StartIndex,
INT32  NumToCopy
 

Copies a specified section from a path to the end of this one.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/7/94
Parameters:
Other - A reference to another path to merge with this one [INPUTS]
Returns:
TRUE if the merge was a success, FALSE if it failed (lack of memory)

Definition at line 6017 of file paths.cpp.

06018 {
06019     return MergeSectionFrom(UsedSlots, Other, StartIndex, NumToCopy);
06020 } 

BOOL Path::CopySectionTo Path Dest,
INT32  StartIndex,
INT32  NumToCopy
 

Copies a specified section from this path to the end of another path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/09/94
Parameters:
Dest - A pointer to another path to add the data to [INPUTS]
Returns:
TRUE if the copy was a success, FALSE if it failed (lack of memory)

Definition at line 6035 of file paths.cpp.

06036 {
06037     return MergeSectionTo(StartIndex, NumToCopy, Dest, Dest->UsedSlots);
06038 }

BOOL Path::CreateFlatPath const ProcessFlags PFlags,
const double  flatness,
Path pOutput
 

Flatten a path. All curves within the path will be approximated by straight lines. pOutput may point at 'this' path ie a path can be flattened to itself. If the flattening fails for some reason, the output path will be unaffected even if you're flattening a path to itself.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/10/94
Parameters:
PFlags = process flags, to control the path processor function [INPUTS] (see classes ProcessPath and ProcessFlags) flatness = How flat the curves should be (around 64 is good)
pOutput = will contain the flattened path [OUTPUTS]
Returns:
BOOL = TRUE if the path was flattened successfully = FALSE then output path will be unaffected

Definition at line 7885 of file paths.cpp.

07886 {
07887 
07888     // create a flattening object
07889     ProcessFlatten FlattenObj(flatness);
07890 //  INT32 numcoords = pOutput->GetNumCoords();
07891 
07892     // ok, generate a flattened path on the end of Output
07893     return FlattenObj.FlattenPath(PFlags, this, pOutput);
07894 
07895 }

BOOL Path::CreatePathFromDocRect DocRect pRect  ) 
 

Creates a filled path from a given DocRect.

Author:
Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/99
Parameters:
BOOL to say whether or not it was successful [OUTPUTS]

Definition at line 506 of file paths.cpp.

00507 {
00508     DocCoord TopLeft(pRect->lo.x,pRect->hi.y);
00509     DocCoord TopRight(pRect->hi.x,pRect->hi.y);
00510     DocCoord BottomLeft(pRect->lo.x,pRect->lo.y);
00511     DocCoord BottomRight(pRect->hi.x,pRect->lo.y);
00512 
00513     InsertMoveTo(TopLeft);
00514     InsertLineTo(TopRight);
00515     InsertLineTo(BottomRight);
00516     InsertLineTo(BottomLeft);
00517     InsertLineTo(TopLeft);
00518 
00519     IsFilled = TRUE;
00520 
00521     return TRUE;
00522 }

BOOL Path::DeleteElement  ) 
 

Deletes the element at the Current Path Position. May free some memory if the path gets to have too much unused space in the path. The Current Path Position points at the slot before the one being deleted.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94

Definition at line 2325 of file paths.cpp.

02326 {
02327     // Dereference the pointers
02328     PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
02329 //  DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
02330 
02331     // Saftey Checks
02332     ENSURE( CurrentPos<UsedSlots, "PathPosition is off end of path in Path::DeleteElement" );
02333     ENSURE( CurrentPos>=0, "PathPosition is off beginning of path in Path::DeleteElement" );
02334     ENSURE( ((PathFlags*) DescribeHandle(FlagsHandle))[CurrentPos].IsEndPoint==TRUE, "Delete Element called when Path Position was not on an endpoint");
02335 
02336     // Find the start of the element
02337     INT32 StartSlot = CurrentPos;
02338 
02339     // Work out how many slots we need to delete
02340     INT32 NumSlots;
02341     if ((Verbs[CurrentPos] & (~PT_CLOSEFIGURE)) == PT_BEZIERTO)
02342     {
02343         NumSlots  = 3;
02344         StartSlot -= 2;
02345     }
02346     else
02347     {
02348         NumSlots = 1;
02349     }
02350 
02351     // Delete the element
02352     BOOL RetVal = DeleteSection(StartSlot, NumSlots);
02353 
02354     // tidy up the Current Path Position
02355     CurrentPos = StartSlot-1;
02356     if (CurrentPos<0)
02357         CurrentPos = 0;
02358 
02359     return RetVal;
02360 }

BOOL Path::DeleteFromElement INT32  ElementNum  ) 
 

Deletes all the elements in the path from ElementNum to the end of the path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/4/94
Parameters:
ElementNum - the number of the element to start deleting from. [INPUTS]
Returns:
TRUE if the deletion was a success

Definition at line 2378 of file paths.cpp.

02379 {
02380     // Find out how many slots there are from ElementNum to the end
02381     INT32 SlotsToDelete = UsedSlots-ElementNum;
02382 
02383     // go and delete the end of the path
02384     BOOL RetVal = DeleteSection(ElementNum, SlotsToDelete);
02385 
02386     // Set the current Path position to just after the path, ready for further additions
02387     CurrentPos = UsedSlots;
02388 
02389     return RetVal;
02390 }

BOOL Path::DeleteSection INT32  StartSlot,
INT32  NumSlots
 

Deletes sections out of the middle of the path. Used by DeleteElement and for Deleting sub paths etc.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/4/94
Parameters:
StartSlot - The slot number to start deleting from [INPUTS] NumSlots - The number of slots to delete
Returns:
TRUE if it worked, FALSE if it failed

Definition at line 2277 of file paths.cpp.

02278 {
02279     // Saftey Checks
02280     ENSURE( StartSlot<UsedSlots, "PathPosition is off end of path in Path::DeleteElement" );
02281     ENSURE( StartSlot>=0, "PathPosition is off beginning of path in Path::DeleteElement" );
02282     ENSURE( NumSlots>0, "Trying to delete Zero slots from the path!" );
02283 
02284     if (NumSlots==0)
02285         return TRUE;
02286 
02287     // Find out how much memory to move about and adjust the element counters
02288     INT32 SlotsToMove = UsedSlots-StartSlot-NumSlots;
02289 
02290     // and move it all about if we need to
02291     if (SlotsToMove>0)
02292     {
02293         // Dereference the pointers
02294         PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
02295         DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
02296         PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
02297 
02298         memmove((void*)(&Verbs[StartSlot]), (void*)(&Verbs[StartSlot+NumSlots]), SlotsToMove*sizeof(PathVerb));
02299         memmove((void*)(&Flags[StartSlot]), (void*)(&Flags[StartSlot+NumSlots]), SlotsToMove*sizeof(PathFlags));
02300         memmove((void*)(&Coords[StartSlot]), (void*)(&Coords[StartSlot+NumSlots]), SlotsToMove*sizeof(DocCoord));
02301         if (ExtraInfo != NULL)
02302             ExtraInfo->ShiftDownExtraInfo(StartSlot, NumSlots, SlotsToMove);
02303     }
02304 
02305     // Update the path details
02306     UsedSlots   -= NumSlots;
02307     UnUsedSlots += NumSlots;
02308 
02309     return Compact();
02310 }

BOOL Path::DistanceTo DocCoord  Coord,
double *  dist,
double  dFlatness = 64.0
 

This function takes as input a coordinate (usually a mouse click point). It will calculate the closest point on the path to this coordinate and return the distance along the path from its start point to this coordinate.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/06/95
Parameters:
Coord - A coordinate [INPUTS]
distance - a 72000 inch measurement [OUTPUTS]
Returns:
TRUE if distance was calculated FALSE if not

Definition at line 9677 of file paths.cpp.

09678 {
09679     Path TempPath;
09680     INT32 SplitAt;
09681     INT32 NumNewEl;
09682 
09683     if (!TempPath.Initialise(GetNumCoords(),24))
09684         return FALSE;
09685 
09686     if (!TempPath.CopyPathDataFrom(this))
09687         return FALSE;
09688 
09689     if (!TempPath.SplitAtPoint(Coord, &SplitAt, &NumNewEl))
09690         return FALSE;
09691 
09692     ProcessLength LengthObj(dFlatness);
09693     if (!LengthObj.PathLength(&TempPath, dist, SplitAt))
09694         return FALSE;
09695 
09696     return TRUE;
09697 }

BOOL Path::DistanceTo INT32  index,
double  t,
double *  distance,
double  dFlatness = 64.0
 

This function takes a description of a point lying on a path. The point is described by (i,t) where i is the index of the element t lies in, and t is a parametric variable 0<=t<=1. The function calculates the distance along this path to the point described by (i,t). This routine complements SqrDistanceToPoint() which calculates the pair (i,t) for a given coordinate close to the path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/06/95
Parameters:
index = an index into the path arrays describing the first coordinate [INPUTS] of an element. t = a parameter 0..1 describing a point on the path element
distance- a 72000 inch measurement [OUTPUTS]
Returns:
TRUE if distance was calculated FALSE if not
See also:
SqrDistanceToPoint

Definition at line 9579 of file paths.cpp.

09580 {
09581     PathVerb* InVerbs = GetVerbArray();
09582     PathVerb vb = InVerbs[index] & ~PT_CLOSEFIGURE;
09583     DocCoord* InCoords = GetCoordArray();
09584     double LoDist = 0.0;
09585     double HiDist = 0.0;
09586 
09587     if (GetNumCoords()==0)
09588         return FALSE;
09589     
09590     // If t is near 1 then we can skip forward to the next segment
09591     // this is to avoid math problems with splitting beziers near their ends
09592     INT32 IndexEP = index;
09593     if (t>=0.99995 && vb==PT_BEZIERTO)
09594     {
09595         // Move up to next complete segment
09596         if (IndexEP != GetNumCoords()-1)
09597         {
09598             if (!FindNextEndPoint(&IndexEP))
09599                 return FALSE;
09600             t = 0.0;
09601         }
09602     }
09603     
09604     // find the length to the path up to the start of the nearest element
09605     // specified by index.
09606     ProcessLength LengthObj(dFlatness);
09607     if (!LengthObj.PathLength(this, &LoDist, IndexEP-1))
09608         return FALSE;
09609 
09610     // ok we need to evaluate the distance along the
09611     // path element i at parameter 0<=t<1
09612     switch (vb)
09613     {
09614         case PT_LINETO:
09615         {
09616             double TotalLength = InCoords[index-1].Distance(InCoords[index]);
09617             HiDist = TotalLength * t;
09618         }
09619         break;
09620 
09621         case PT_BEZIERTO:
09622         {
09623             if ((t>0.00005) && (t<0.99995))     // avoids problems at the extremes.
09624             {
09625                 UINT32 NumElements;
09626 
09627                 PathVerb NewVerbs[6];
09628                 DocCoord NewCoords[6];
09629                 Path     TempPath;
09630 
09631                 BOOL    ok = TempPath.Initialise(12,12);
09632                 if (ok) ok = PathUtil::SplitCurve(t, &InCoords[index-1], &NumElements, NewVerbs, NewCoords);
09633                 if (ok) ok = TempPath.CopyPathDataFrom(NewCoords, NewVerbs, 3);
09634                 if (ok)
09635                 {
09636                     TempPath.SetPathPosition(0);
09637                     ok = TempPath.InsertMoveTo(InCoords[index-1]);
09638                 }
09639                 if (ok)
09640                 {
09641                     ProcessLength LengthObj2(64);
09642                     ok = LengthObj2.PathLength(&TempPath, &HiDist);
09643                 }
09644                 if (!ok)
09645                     return FALSE;
09646             }
09647         }
09648         break;
09649 
09650         default:
09651             ERROR3("Unable to find point on path. Index does not specify line or curve");
09652             break;
09653     }
09654 
09655     *distance = LoDist+HiDist;
09656 
09657     return TRUE;
09658 }

double Path::DistReparameterise const double  sqrdist,
INT32 *  Element
 

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/11/94
Parameters:
sqrdist = squared distance along the path [INPUTS]
Element = index of element which bounds dist [OUTPUTS] as a half open interval, (El.Plo < dist <= El.Phi)
Returns:
a double, being the parameter along the returned element, which is dist units along the whole path.
See also:
ConvDistToCoord() ClosestPointTo()

Definition at line 7997 of file paths.cpp.

07998 {
07999     // set up a distance object and call its processor
08000     double Acc = 64;
08001     ProcessDistance DistanceObj(Acc);
08002     return DistanceObj.PathDistance(sqrdist, this, Element);
08003 }

void Path::DrawBlob RenderRegion pRender,
const DocCoord Coord,
BOOL  DrawSelected
 

Draws a single blob, either selected or un-selected.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/02/94
Parameters:
pRender - Render region to draw to [INPUTS] Coord - the coord that the blob should be centred on DrawSelected - Draw a selected blob or an unselected blob

Definition at line 3486 of file paths.cpp.

03487 {
03488 #if !defined(EXCLUDE_FROM_RALPH)
03489     if (DrawSelected)
03490     {
03491         // Set the colours to draw the selected blob colours
03492         pRender->SetLineColour(COLOUR_BEZIERBLOB);
03493         pRender->SetFillColour(COLOUR_TRANS);
03494 
03495         // Draw a Selected blob to the render region
03496         pRender->DrawBlob(Coord, BT_SELECTED);
03497     }
03498     else
03499     {
03500         // Draw an UnSelected Blob to the render region
03501         // Set the colours back
03502 //      pRender->SetLineColour(COLOUR_UNSELECTEDBLOB);
03503         pRender->SetLineColour(COLOUR_NONE);
03504         pRender->SetFillColour(COLOUR_UNSELECTEDBLOB);
03505         pRender->DrawBlob(Coord, BT_UNSELECTED);
03506     }
03507 #endif
03508 }

void Path::DrawControlBlob RenderRegion pRender,
const DocCoord Coord
 

Draws a blob for a Bezier control point.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/02/94
Parameters:
pRender - Render region to draw to [INPUTS] Coord - the coord that the blob should be centred on

Definition at line 3523 of file paths.cpp.

03524 {
03525 #if !defined(EXCLUDE_FROM_RALPH)
03526     // Draw a Control blob to the render region
03527 //  pRender->SetLineColour(COLOUR_BEZIERBLOB);
03528     pRender->SetLineColour(COLOUR_NONE);        // A line colour leads to bad rendering probs
03529                                                 // on some video drivers. Best solution is not
03530                                                 // to use one.
03531     pRender->SetFillColour(COLOUR_BEZIERBLOB);
03532     pRender->DrawBlob(Coord, BT_UNSELECTED);
03533 #endif
03534 }

void Path::DrawControlLine RenderRegion pRender,
const DocCoord Start,
const DocCoord End
 

Draws a line from the Bezier control point to its endpoint.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/02/94
Parameters:
pRender - Render region to draw to [INPUTS] Coord - the coord that the blob should be centred on

Definition at line 3549 of file paths.cpp.

03550 {
03551 #if !defined(EXCLUDE_FROM_RALPH)
03552     // Draw a line to the render region
03553     pRender->SetLineColour(COLOUR_BEZIERLINE);
03554     pRender->DrawLine( Start, End );
03555 #endif
03556 }

void Path::DumpPath  ) 
 

Dumps the whole path out to the debug terminal.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/02/94

Definition at line 2841 of file paths.cpp.

02842 {
02843 #ifdef _DEBUG
02844     TRACE( _T("\nStarting Path Dump\n") );
02845     TRACE( _T("[%d=PT_MOVETO, %d=PT_LINETO, %d=PT_BEZIERTO, %d=PT_CLOSEFIGURE]\n"), 
02846            PT_MOVETO, PT_LINETO, PT_BEZIERTO, PT_CLOSEFIGURE );
02847     TRACE( _T("UsedSlots=%ld, UnUsedSlots=%ld, CurrentPos=%ld\n"), UsedSlots, UnUsedSlots, CurrentPos );
02848     TRACE( _T("Path Size in Bytes=%ld\n"), GetPathByteLength() );
02849     TRACE( _T("\tVerb\tCoord\n") );
02850 
02851     // de-reference the pointers
02852     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
02853     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
02854     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02855 
02856     // loop through all the coords, displaying their type and position
02857     for (INT32 i=0; i<UsedSlots; i++)
02858     {
02859         TRACE( _T("%d\t%d\t(%ld, %ld)"), i, Verbs[i], Coords[i].x, Coords[i].y );
02860         if (Flags[i].IsSmooth)
02861             TRACE( _T("\tS"));
02862         else
02863             TRACE( _T("\t "));
02864 
02865         if (Flags[i].IsRotate)
02866             TRACE( _T("R"));
02867         else
02868             TRACE( _T(" "));
02869 
02870         if (Flags[i].IsEndPoint)
02871             TRACE( _T("E"));
02872         else
02873             TRACE( _T(" "));
02874 
02875         if (Flags[i].IsSelected)
02876             TRACE( _T("(sel)"));
02877 
02878         TRACE( _T("\n"));
02879     }
02880 #endif
02881 }

void Path::EnsureSelection BOOL  UseStarts  ) 
 

Goes through the path ensuring that the selection status of the ends/starts of subpaths equal the selection state of the start/ends of that subpath Also selects/deselectes control points as appropiate.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/1/95
Parameters:
UseStarts - TRUE if the selection state of the start of subpaths should be used [INPUTS] the set the ends. FALSE if the end sel state should be used to set the starts

Definition at line 3597 of file paths.cpp.

03598 {
03599 #if !defined(EXCLUDE_FROM_RALPH)
03600     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
03601     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
03602 
03603     // Ensure the selection state of the sub paths
03604     const INT32 NumCoords = GetNumCoords();
03605     if (UseStarts)
03606     {
03607         INT32 Start = 0;
03608         INT32 End = 0;
03609         while (End < NumCoords-1)
03610         {
03611             FindEndElOfSubPath(&End);
03612             if (Verbs[End] & PT_CLOSEFIGURE)
03613                 Flags[End].IsSelected = Flags[Start].IsSelected;
03614             Start = ++End;
03615         }
03616     }
03617     else
03618     {
03619         INT32 Close = NumCoords-1;
03620         INT32 Offset = NumCoords-1;
03621         while (Offset > -1)
03622         {
03623             FindStartOfSubPath(&Offset);
03624             if (Verbs[Close] & PT_CLOSEFIGURE)
03625                 Flags[Offset].IsSelected = Flags[Close].IsSelected;
03626             Close = Offset-1;
03627             Offset = Close;
03628         }
03629     }
03630 
03631     // Now set the selection state of the  control points.depending on their endpoints
03632     for (INT32 loop = 0; loop < NumCoords; loop++)
03633     {
03634         if (!Flags[loop].IsEndPoint)
03635         {
03636             ERROR3IF(loop==0, "Path started with a non-endpoint!");
03637             ERROR3IF(Verbs[loop]!=PT_BEZIERTO, "Found an non-endpoint that wasn't a Bezier");
03638             if (loop > 0)
03639             {
03640                 if (Flags[loop-1].IsEndPoint)
03641                     Flags[loop].IsSelected = Flags[loop-1].IsSelected;
03642                 else
03643                     Flags[loop].IsSelected = Flags[loop+1].IsSelected;
03644             }
03645         }
03646     }
03647 #endif
03648 }

BOOL Path::EnsureValid BOOL *  ChangesMade = NULL  ) 
 

Will attempt to make a path into a correct state. Checks are :- 1. All subpaths must start with a MoveTo 2. Consecutive MoveTos are removed 3. Zero element paths are unrepairable 4. MoveTos at the end of the path are removed 5. Should be three BezierTos in a row, only the last can be CloseFigure 6. A LineTo to the same location as the previous point is removed.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/1/95
Parameters:
Pointer to a BOOL to return a result in (you can pass in NULL) [INPUTS]
ChangesMade will be TRUE if changes have been made to the path, FALSE if otherwise [OUTPUTS]
Returns:
TRUE for success, FALSE for failure (see below)
ERRORs: FALSE is returned if the path was knackered OR if we encountered an error in trying to repair it. (SetError will have been called)

Definition at line 9381 of file paths.cpp.

09382 {
09383 
09384     BOOL PathOK = FALSE;
09385     BOOL Temp;
09386     BOOL* pChangeFlag;
09387     pChangeFlag = (ChangesMade == NULL) ? &Temp : ChangesMade;
09388     *pChangeFlag = FALSE;
09389 
09390     while (!PathOK)
09391     {
09392         // Recache the path pointers as things may have moved
09393         PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
09394         DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
09395         PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
09396         INT32 NumCoords = GetNumCoords();
09397 
09398         // (3) Check for zero element path
09399         if (NumCoords == 0) 
09400         {
09401             TRACEALL( _T("Empty path detected\n") );
09402             Error::SetError(_R(IDE_INVALID_PATH));
09403             return FALSE;
09404         }
09405 
09406         INT32 Counter = 0;
09407 
09408         while (Counter < NumCoords)
09409         {
09410             // Recache the path pointers in case the previous pass caused the arrays to move
09411             Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
09412             Coords = (DocCoord*)  DescribeHandle(CoordHandle);
09413             Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
09414 
09415             // (1) Check that all subpaths start with a MoveTo
09416             if ( (Counter == 0) || (Verbs[Counter-1] & PT_CLOSEFIGURE) )
09417             {
09418                 if ((Verbs[Counter] & ~PT_CLOSEFIGURE) != PT_MOVETO)
09419                 {
09420                     // Insert a MoveTo at the same location as this point
09421                     TRACEALL( _T("Inserting a MoveTo at %d\n"), Counter );
09422                     SetPathPosition(Counter);
09423                     *pChangeFlag = TRUE;
09424                     if (!InsertMoveTo(Coords[Counter]))
09425                         return FALSE;
09426                     break;
09427                 }
09428             }
09429 
09430             // (2) Check there are no two consecutive MoveTos
09431             if ( (Counter != NumCoords-1) && (Verbs[Counter] == PT_MOVETO) )
09432             {
09433                 if (Verbs[Counter+1] == PT_MOVETO)
09434                 {
09435                     // Remove this MoveTo
09436                     TRACEALL( _T("Removing a MoveTo at %d\n"), Counter );
09437                     SetPathPosition(Counter);
09438                     *pChangeFlag = TRUE;
09439                     if (!DeleteElement())
09440                         return FALSE;
09441                     break;
09442                 }
09443             }
09444 
09445             // (4) Check for trailing moveto at the end of a path
09446             if ( (Counter == NumCoords-1) && (Verbs[Counter] == PT_MOVETO) )
09447             {
09448                 // Remove this MoveTo
09449                 TRACEALL( _T("Removing a MoveTo at the end (%d)\n"), Counter );
09450                 SetPathPosition(Counter);
09451                 *pChangeFlag = TRUE;
09452                 if (!DeleteElement())
09453                     return FALSE;
09454                 break;
09455             }
09456 
09457             switch (Verbs[Counter] & ~PT_CLOSEFIGURE)
09458             {
09459                 case PT_MOVETO: 
09460                     // MoveTos shouldn't have CloseFigures
09461                     if (Verbs[Counter] != PT_MOVETO)
09462                     {
09463                         TRACEALL( _T("Detected a MoveTo+CloseFigure combination\n at %d"), Counter );
09464                         Verbs[Counter] = PT_MOVETO;
09465                         *pChangeFlag = TRUE;
09466                     }
09467                     Counter++;
09468                     break;
09469                 case PT_LINETO:
09470                     // If the coord of this is the same as the last (which must be a MoveTo) then delete it
09471                     if ((Counter > 0) && (Coords[Counter] == Coords[Counter-1]) && (Verbs[Counter-1] == PT_MOVETO))
09472                     {
09473                         TRACEALL( _T("Removing a LineTo at %d\n"), Counter );
09474                         SetPathPosition(Counter);
09475                         *pChangeFlag = TRUE;
09476 
09477                         // If the LineTo has the PT_CLOSEFIGURE bit set, ensure that the element
09478                         // before it has this bit set.
09479                         // If we don't then it is possible for shapes to become lines.
09480                         if ((Verbs[Counter] & PT_CLOSEFIGURE) && (Verbs[Counter-1] != PT_MOVETO))
09481                             Verbs[Counter-1] |= PT_CLOSEFIGURE;
09482 
09483                         // Delete the surplus LineTo element
09484                         if (!DeleteElement())
09485                             return FALSE;
09486 
09487                         Counter = NumCoords+1;      // So we go round the entire path again
09488                     }
09489                     else
09490                     {
09491                         // This point should be endpoint
09492                         if (!Flags[Counter].IsEndPoint)
09493                         {
09494                             TRACEALL( _T("Fixing endpoint status at %d\n"), Counter );
09495                             *pChangeFlag = TRUE;
09496                             Flags[Counter].IsEndPoint = TRUE;
09497                         }
09498                         Counter ++;
09499                     }
09500                     break;
09501                 case PT_BEZIERTO:
09502                     // (5) Should be three BezierTos in a row, only the last can be CloseFigure
09503                     if (Counter >= NumCoords-2)
09504                     {
09505                         TRACEALL( _T("Path ends with a short Bezier section\n") );
09506                         return FALSE;
09507                     }
09508                     if ( (Verbs[Counter] != PT_BEZIERTO) || (Verbs[Counter+1] != PT_BEZIERTO) ||
09509                                                 ((Verbs[Counter] & ~PT_CLOSEFIGURE) != PT_BEZIERTO) )
09510                     {
09511                         TRACEALL( _T("InvalidBezier section detected starting at %d\n"), Counter );
09512                         return FALSE;
09513                     }
09514                     Flags[Counter++].IsEndPoint = FALSE;
09515                     Flags[Counter++].IsEndPoint = FALSE;
09516                     Flags[Counter++].IsEndPoint = TRUE;
09517                     break;
09518                 default:
09519                     TRACEALL( _T("This path is *very* corrupt (Invalid verb found)\n") );
09520                     return FALSE;
09521             }
09522             if (Counter == NumCoords)
09523                 PathOK = TRUE;
09524         }
09525     }
09526 
09527     return TRUE;
09528 }

BOOL Path::EnsureVolume INT32  NumSlots  ) 
 

This function ensures there are >= NumSlots in the path arrays. It may try to alter the size of the path arrays by increasing the number of unused slots to satisfy the request. It will never decrease the size of the arrays, if NumSlots < UsedSlots+UnusedSlots then the volume is automatically ensured. This allows path buffers to be resized ready for cloning.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
02/02/95
Parameters:
NumSlots - The minimum number of slots you need in the path arrays [INPUTS]
Returns:
TRUE if it was able to find the memory, FALSE if it failed

Definition at line 4104 of file paths.cpp.

04105 {
04106     INT32 Slots=NumSlots-UsedSlots;
04107     if (Slots>0)
04108         return MakeSpaceAtEnd(Slots);
04109     return TRUE;
04110 }

void Path::ExpandRange INT32 *  start,
INT32 *  end,
INT32  num
 

given the region [*start, *end] expand the region in both directions by num elements. The region will not be expanded beyond its outer limits described by the set {moveto,.....,endofsubpath}.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/11/94
Parameters:
start = pointer to an index holding the region start [INPUTS] end = pointer to an index holding the region end num = number of endpoints to expand the region by
start = will be updated [OUTPUTS] end = will be updated

Definition at line 3784 of file paths.cpp.

03785 {
03786     
03787     ENSURE( (*start)<UsedSlots, "start index was not valid in ExpandRange" );
03788     ENSURE( (*start)>=0, "start index less than zero in ExpandRange" );
03789 
03790     ENSURE( (*end)<UsedSlots, "end index was not valid in ExpandRange" );
03791     ENSURE( (*end)>=0, "end index less than zero in ExpandRange" );
03792 
03793     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
03794     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
03795 
03796     // clamp the indexes
03797 
03798     INT32 starti = *start;
03799     INT32 endi = *end;
03800 
03801     if (starti<0) 
03802         starti = 0;
03803     if (endi<0)
03804         endi = 0;
03805 
03806     if (starti >= UsedSlots)
03807         starti = UsedSlots-1;
03808     if (endi >= UsedSlots)
03809         endi = UsedSlots-1;
03810 
03811     INT32 prev = starti;
03812     INT32 next = endi;
03813 
03814     while (num>0)
03815     {
03816         if (Verbs[starti] != PT_MOVETO)
03817         { 
03818             if (FindPrev(&prev))
03819             {
03820                 if (Flags[prev].IsEndPoint)
03821                     starti = prev;
03822             }
03823         }
03824 
03825         if (FindNextEndPoint(&next))
03826         {   
03827             if ((Flags[next].IsEndPoint) &&
03828                 (Verbs[next] != PT_MOVETO))
03829                     endi = next;
03830         }                   
03831         num-=1;
03832     }
03833     *start = starti;
03834     *end = endi;
03835 }

BOOL Path::ExternalArraysAdded const INT32  Added  ) 
 

A hidden function to adjust the number of elements in a path. This has been added by me as a last resort and should not be used by others. (Hence hidden from the documentation). It is required to cope with changes in the path data external to the path class. This occurs when doing really nasty things like moulding paths.

BOOL Path::ExternalArraysAdded(const INT32 Added)

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/12/94
Parameters:
Added = the number of new elements added to path arrays. [INPUTS]
Returns:
TRUE if the external arrays have been validated FALSE if the external array additions have been ignored

Definition at line 5968 of file paths.cpp.

05969 {
05970     ERROR1IF(Added<1 || Added>UnUsedSlots, FALSE, "Path::ExternalArraysAdded() called with illegal additon");
05971 
05972     UsedSlots+=Added;
05973     UnUsedSlots-=Added;
05974 
05975     return TRUE;
05976 } 

BOOL Path::ExternalArraysReplaced const INT32  Size  ) 
 

A hidden function to adjust the number of elements in a path. This has been added by me as a last resort and should not be used by others. (Hence hidden from the documentation).

BOOL Path::ExternalArraysReplaced(const INT32 Size)

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/12/94
Parameters:
Size = the number of elements replaced in the path arrays [INPUTS]
Returns:
TRUE if the external arrays have been validated FALSE if the external array replacements have been ignored

Definition at line 5994 of file paths.cpp.

05995 {
05996     ERROR1IF(Size<1 || Size>(UsedSlots+UnUsedSlots), FALSE, "Path::ExternalArraysCloned() called with an illegal clone");
05997 
05998     UnUsedSlots = (UsedSlots+UnUsedSlots)-Size;
05999     UsedSlots   = Size;
06000 
06001     return TRUE;
06002 }

void Path::FindEndElOfSubPath INT32 *  Index  )  const
 

Searches forwards until it finds the last element of the current sub-path. ie 0 1 2 3 {MT,CT,CT,CT} => Index = 3. See Also: FindEndOfSubPath (Note equivelent).

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/09/94
Parameters:
Index - The position in the path to start looking from [INPUTS]
Index - the position of the last element of the subpath, ie the final bezier [OUTPUTS] control point, or the final line to etc.

Definition at line 9235 of file paths.cpp.

09236 {
09237     ENSURE( (*Index)<UsedSlots, "Path position was not valid in FindEndOfSubPath" );
09238     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
09239 
09240     do
09241     {
09242         (*Index)++;
09243     } while (((*Index)<UsedSlots) && (Verbs[(*Index)]!=PT_MOVETO));
09244 
09245     (*Index)--;
09246 }

void Path::FindEndOfSubPath INT32 *  Index  )  const
 

Searches forwards until it finds the end of the current sub-path. ie Index will point at the last element in the sub path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
Index - The position in the path to start looking from [INPUTS]
Index - the position of the end of the subpath [OUTPUTS]

Definition at line 653 of file paths.cpp.

00654 {
00655     ENSURE( (*Index)<UsedSlots, "Path position was not valid in FindEndOfSubPath" );
00656 
00657     // I am already in a path, so start working backwards until I find the moveto
00658     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00659     INT32 PrevIndex;
00660 
00661     do
00662     {
00663         PrevIndex = (*Index);
00664         FindNext(Index);
00665     } while (((*Index)<UsedSlots) && (Verbs[(*Index)]!=PT_MOVETO));
00666 
00667     // So we have either fallen off the end of the world, or we are now on a MoveTo
00668     // either way we need the info from the previous position
00669     (*Index) = PrevIndex;
00670 }

void Path::FindEndOfSubPath  ) 
 

Searches forwards until it finds the end of the current sub-path. ie pos will point at the last element in the sub path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
Pos - The position in the path to start looking from [INPUTS]
Pos - the position of the end of the subpath [OUTPUTS]

Definition at line 621 of file paths.cpp.

00622 {
00623     ENSURE( CurrentPos<UsedSlots, "Path position was not valid in FindEndOfSubPath" );
00624 
00625     // I am already in a path, so start working backwards until I find the moveto
00626     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00627     INT32 PrevIndex;
00628 
00629     do
00630     {
00631         PrevIndex = CurrentPos;
00632         FindNext();
00633     } while ((CurrentPos<UsedSlots) && (Verbs[CurrentPos]!=PT_MOVETO));
00634 
00635     // So we have either fallen off the end of the world, or we are now on a MoveTo
00636     // either way we need the info from the previous position
00637     CurrentPos = PrevIndex;
00638 }

BOOL Path::FindJoinedSubPathInfo const DocCoord JoinCoord,
INT32 *  Start,
INT32 *  Length,
BOOL *  JoinAtStart
 

This function searchs the path, compareing JoinCoord with the start and end points of each of the Sub-paths in the path. If it is the same as one of the start or end points, then the output params are filled and TRUE is returned.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/4/94
Parameters:
JoinCoord - The Coord to compare with the start and end points od sub paths [INPUTS]
Start - Pointer to an INT32 to hold the starting slot number of the sub path [OUTPUTS] Length - The number of slots in the found Sub Path JoinAtStart - TRUE if JoinCoord intersected the start of the Sub Path, FALSE otherwise
Returns:
TRUE if an intersection was found, FALSE if not

Definition at line 6619 of file paths.cpp.

06620 {
06621     // We will need all the arrays for both paths
06622     DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
06623     PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
06624 
06625     // walk through all the coords, looking for start and end points in SubPaths
06626     INT32 EndPos = UsedSlots-1;
06627     for (INT32 i=UsedSlots-1; i>=0; i--)
06628     {
06629         // See if we are at the start of a sub path
06630         if (Verbs[i] == PT_MOVETO)
06631         {
06632             // Set these to the start and end positions of the sub path
06633             *Start = i;
06634             *Length = EndPos - i + 1;
06635 
06636             // We are, so check the start and end of the sub path against the coord
06637             if (Coords[i] == JoinCoord)
06638             {
06639                 // This is Joined at the start, so set the values and return
06640                 *JoinAtStart = TRUE;
06641                 return TRUE;
06642             }
06643 
06644             if (Coords[EndPos] == JoinCoord)
06645             {
06646                 // This is Joined at the End, so set the values and return
06647                 *JoinAtStart = FALSE;
06648                 return TRUE;
06649             }
06650 
06651             EndPos = i-1;
06652         }
06653     }
06654 
06655     // We did not find an intersection with the subpaths, so fail
06656     return FALSE;
06657 }

BOOL Path::FindNearestPoint DocCoord  pos,
UINT32  flags,
INT32 *  position
 

This function searches for a point in the path which is both selected and lies inside the largest blob bounding rectangle surrounding 'pos'. Points checked for are as follows... if ENDPOINTS is set check all selected endpoints in this path. if CONTROLPOINTS is set check all control points lying directly next to selected endpoints The rules are that control points are only enabled when a single end point is selected and hence a maximum of 2 control points will be checked. If any of these points are close enough to be clicked on, the function returns TRUE, with position holding the index to the point that was clicked.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/4/94
Parameters:
pos - mouse position to be tested [INPUTS] flags - POINTFLAG_ENDPOINTS = look at endpoints POINTFLAG_CONTROLPOINTS - look at control points
(the flag POINTFLAG_ENDSFIRST has been removed and has no effect - the endpoints are always scanned first)
Parameters:
position - index to the point that was matched [OUTPUTS] unchanged if no match
Returns:
TRUE if a match was found, FALSE if not

Definition at line 6752 of file paths.cpp.

06753 {
06754 #if !defined(EXCLUDE_FROM_XARLIB)
06755     // If neither ENDPOINTS or CONTROLPOINTS flags are set, return FALSE since the caller
06756     // obviously doesn't want to look at anything!
06757     if (!(flags & (POINTFLAG_ENDPOINTS | POINTFLAG_CONTROLPOINTS)))
06758         return (FALSE);
06759 
06760     // Always set POINTFLAG_ENDSFIRST
06761     flags |= POINTFLAG_ENDSFIRST;
06762 
06763     // Get arrays for this path
06764     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
06765     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
06766     PathFlags* PFlags = (PathFlags*) DescribeHandle(FlagsHandle);
06767 
06768     // Get a pointer to the DocView so we can do blob proximity checks
06769     DocView* pDocView = DocView::GetSelected();
06770     ERROR3IF(pDocView == NULL, "Path::FindNearestPoint: Can't find selected DocView");
06771     if (pDocView == NULL)
06772         return(FALSE);
06773 
06774     DocRect BlobRect;
06775     // INT32    numloops;
06776     
06777     // Now to calculate a rectangle around the pointer position which is
06778     // the same size as the biggest possible blob. We then go through the
06779     // path and see if any of the coordinates fall into that rectangle.
06780     // This is a very cunning reversal of the normal logic - go through the
06781     // path, find a blob rectangle for each point, then see if the pointer 
06782     // coordinate falls inside it. The only problem with this method is that
06783     // it assumes that all blobs are the same size, but since this is only 
06784     // for click detection, and we need a little bit of leeway, I think 
06785     // it's all right. Anyway, the usual code for this also makes this assumption,
06786     // although it doesn't rely on it.
06787 
06788     OSRenderRegion::GetBlobRect(pDocView->GetViewScale(), pos,
06789                                 BT_SELECTEDLARGEST, &BlobRect);
06790 
06791     // Now BlobRect holds a rectangle around the pointer position.
06792 
06793     // We have to first go through and look at the endpoints, counting them as we go
06794     INT32 EndCount = 0;
06795     INT32 EndIndex = 0;
06796     INT32 i;
06797     
06798     for (i=0; i<UsedSlots; i++)
06799     {
06800         // check to see if it's an endpoint, and if we want this kind of point
06801         if ((PFlags[i].IsEndPoint && (flags & POINTFLAG_ENDPOINTS)))
06802         {
06803             if (BlobRect.ContainsCoord(Coords[i]))
06804             {
06805                 *position = i;
06806                 return(TRUE);
06807             }
06808         }
06809         if (PFlags[i].IsEndPoint && PFlags[i].IsSelected && ((Verbs[i] & PT_CLOSEFIGURE) == 0))
06810         {
06811             EndCount++;
06812             EndIndex = i;
06813         }
06814     }
06815 
06816     // Now we've scanned the path for endpoints, let's look at any adjacent control points
06817     // if EndCount == 1, EndIndex is the index of the selected enpoint, ie there is only one
06818     // selected endpoint and its control handles will be enabled.
06819 
06820     if ( (EndCount==1) && (flags & POINTFLAG_CONTROLPOINTS) )
06821     {
06822         INT32 Index = FindPrevControlPoint(EndIndex);
06823         if (Index>=0)
06824         {
06825             // There is a previous control point, so look at it (and the one before it)
06826             if (BlobRect.ContainsCoord(Coords[Index]))
06827             {
06828                 *position = Index;
06829                 return TRUE;
06830             }
06831 
06832             if (BlobRect.ContainsCoord(Coords[Index-1]))
06833             {
06834                 *position = Index-1;
06835                 return TRUE;
06836             }
06837         }
06838 
06839         // Now look at the next control point (if it's there)
06840         Index = FindNextControlPoint(EndIndex);
06841         if (Index>=0)
06842         {
06843             // Look at the next one
06844             if (BlobRect.ContainsCoord(Coords[Index]))
06845             {
06846                 *position = Index;
06847                 return TRUE;
06848             }
06849 
06850             if (BlobRect.ContainsCoord(Coords[Index+1]))
06851             {
06852                 *position = Index+1;
06853                 return TRUE;
06854             }
06855         }
06856     }
06857 #endif
06858     return FALSE;
06859 }

BOOL Path::FindNext INT32 *  Index  )  const
 

Finds the next path element in this path. The position will become invalid if you try to search past the start of the path. This can be checked by using Pos->IsValid.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
Index is a pointer to an index into the path to start from [INPUTS]
Index will point at the next element in the path [OUTPUTS]
Returns:
TRUE if valid next element found FALSE if there is no next element, Index is set to NumCoords
See also:
Path::FindPrev

Definition at line 855 of file paths.cpp.

00856 {
00857     ENSURE( (*Index)<=UsedSlots, "Path position was not valid in FindNext" );
00858     ENSURE( (*Index)>=0, "Path Position less than zero!" );
00859 
00860     // de-reference the verb array
00861     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00862 
00863     // Move to the next path element
00864     if ((Verbs[(*Index)] & (~PT_CLOSEFIGURE))==PT_BEZIERTO)
00865         (*Index) += 3;
00866     else
00867         (*Index) ++;
00868 
00869     // Check to see if we fell off the end of the path
00870     if ((*Index)>=UsedSlots)
00871     {
00872         (*Index) = UsedSlots;
00873         return FALSE;
00874     }
00875 
00876     // we did it, so return happy
00877     return TRUE;
00878 }

BOOL Path::FindNext void   ) 
 

Finds the next path element in this path. The position will become invalid if you try to search past the start of the path. This can be checked by using Pos->IsValid.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
See also:
Path::FindPrev

Definition at line 733 of file paths.cpp.

00734 {
00735     ENSURE( CurrentPos<=UsedSlots, "Path position was not valid in FindNext" );
00736     ENSURE( CurrentPos>=0, "Path Position less than zero!" );
00737 
00738     // de-reference the verb array
00739     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00740 
00741     // Move to the next path element
00742     if ((Verbs[CurrentPos] & (~PT_CLOSEFIGURE))==PT_BEZIERTO)
00743         CurrentPos += 3;
00744     else
00745         CurrentPos ++;
00746 
00747     // Check to see if we fell off the end of the path
00748     if (CurrentPos>=UsedSlots)
00749     {
00750         CurrentPos = UsedSlots;
00751         return FALSE;
00752     }
00753 
00754     // we did it, so return happy
00755     return TRUE;
00756 }

INT32 Path::FindNextControlPoint INT32  Index  ) 
 

This routine will scan forwards from an endpoint to find the attached bezier control point. It takes account of closed and open paths and complex paths, and will wrap around the path if necessary.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/8/94
Parameters:
Index gives the endpoint whose next control point I want [INPUTS]
- [OUTPUTS]
Returns:
Index to the control point (or -1 if none)

Errors: -

See also:
-

Definition at line 3432 of file paths.cpp.

03433 {
03434 //  DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
03435 //  PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
03436     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
03437     
03438     // See if this is the end of a path (no more elements or next point is moveto)
03439     if (Index+1 == UsedSlots || Verbs[Index+1] == PT_MOVETO)
03440     {
03441         // This is the last element, so see if we should wrap around
03442         if (Verbs[Index] & PT_CLOSEFIGURE)
03443         {
03444             // The path is closed, so we have to scan backwards to find the start
03445             INT32 i=Index;
03446             FindStartOfSubPath(&i);     // i points at start of subpath
03447             
03448             // return next control point if next element is a bezier, -1 otherwise
03449             if (Verbs[i+1] == PT_BEZIERTO)
03450                 return i+1;
03451             return -1;
03452         }
03453         else
03454         {
03455             // Path is open, so no next control point
03456             return -1;
03457         }
03458     }
03459     else
03460     {
03461         // This element isn't the last in this subpath, so look at next element
03462         // if not bezier, return -1, otherwise return next element
03463         if (Verbs[Index+1] == PT_BEZIERTO)
03464             return Index+1;
03465         return -1;
03466     }
03467     return -1;
03468 }

BOOL Path::FindNextEndPoint INT32 *  index  )  const
 

Finds the next path endpoint in this path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/11/94
Parameters:
Index = pointer to a INT32 indicating where to start from [INPUTS] Outpus: Index = points to an index which is the next element
Returns:
TRUE if the next end point has been found FALSE if there are no more end points in this path
See also:
Path::FindPrevEndPoint

Definition at line 774 of file paths.cpp.

00775 {
00776     ENSURE( (*index)<=UsedSlots, "Path position was not valid in FindNextEndPoint" );
00777     ENSURE( (*index)>=0, "Path Position less than zero in FindNextEndPoint" );
00778 
00779     // de-reference the verb array
00780     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00781 
00782     (*index)++;
00783 
00784     if ((*index) >= UsedSlots)
00785     {
00786         ((*index) = UsedSlots-1);
00787         return FALSE;
00788     }
00789 
00790     if ((Verbs[(*index)] & (~PT_CLOSEFIGURE))==PT_BEZIERTO)
00791         (*index) += 2;
00792 
00793     return TRUE;
00794 }

BOOL Path::FindNextSelected INT32 *  Index  ) 
 

Searches the point set {*index, usedslots-1} for a selected end point and returns its index if found.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/09/94
Parameters:
Index - The position in the path to start looking from [INPUTS]
Index - the position of the next selected element [OUTPUTS]
Returns:
TRUE if there exists a selected point at or beyond index FALSE if there is no more selected points along the path

Definition at line 9199 of file paths.cpp.

09200 {
09201     ENSURE( (*Index)<=UsedSlots, "Path position was not valid in FindNextSelected" );
09202     ENSURE( (*Index)>=0, "Path Position less than zero in FindNextSelected" );
09203 
09204     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
09205 
09206     while (   
09207             ((*Index)<UsedSlots) && 
09208             !(  (Flags[(*Index)].IsSelected) && 
09209                 (Flags[*Index].IsEndPoint)
09210              )
09211           )
09212             (*Index)++;
09213     
09214     return ((*Index)<UsedSlots);
09215     
09216 }

INT32 Path::FindOppositeControlPoint INT32  ThisIndex  ) 
 

Given a bezier control point, this function returns the index of the control point that is opposite this one (with an endpoint between). This routine takes closed paths into account.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/8/94
Returns:
The index of the control point opposite the indexed one (or -1)

Definition at line 1219 of file paths.cpp.

01220 {
01221     // Get arrays of flags and verbs
01222     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
01223     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
01224 
01225     // If this isn't a control point, ensure!
01226     ENSURE(!Flags[ThisIndex].IsEndPoint,"Point is not a control point in FindOppositeControlPoint");
01227 
01228     // First see if this is the first or second control point in a curve element. If the 
01229     // previous point is an endpoint, then this is the first control point
01230     if (Flags[ThisIndex-1].IsEndPoint)
01231     {
01232         // if the previous endpoint is a moveto, we might have to wrap
01233         if (Verbs[ThisIndex-1] == PT_MOVETO)
01234         {
01235             INT32 i;
01236             for (i = ThisIndex;i<UsedSlots && Verbs[i]!=PT_MOVETO;i++); // ; deliberate
01237             i--;
01238             // Now i gives us the endpoint of the subpath
01239             // If the path is closed and the last point is a curve, return the opposite point
01240             // otherwise return -1
01241             if ((Verbs[i] & PT_CLOSEFIGURE) && ((Verbs[i] & ~PT_CLOSEFIGURE)==PT_BEZIERTO))
01242                 return i-1;
01243             else
01244                 return -1;
01245         }
01246         else
01247         {
01248             if ((Verbs[ThisIndex-1] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
01249                 return ThisIndex-2;
01250             else
01251                 return -1;
01252         }
01253     }
01254     else
01255     {
01256         // This is the second control point. If the next point has the CloseFigure flag
01257         // set we'll have to scan back. Otherwise, return ThisIndex+2 unless the next element 
01258         // isn't a curve, or there is no next element.
01259         if (Verbs[ThisIndex+1] & PT_CLOSEFIGURE)
01260         {
01261             // The path is closed - scan back for the moveto
01262             INT32 i;
01263             for (i=ThisIndex;Verbs[i] != PT_MOVETO;i--);    // ; deliberate
01264 
01265             // Move to the next point - if it's a BezierTo we return it, otherwise return -1
01266             if (Verbs[i+1] == PT_BEZIERTO)
01267                 return i+1;
01268             else
01269                 return -1;
01270         }
01271         else
01272         {
01273             // The path isn't closed here, so see if there's another element
01274             if (ThisIndex+2 >= UsedSlots || Verbs[ThisIndex+2] != PT_BEZIERTO)
01275             {
01276                 // No next element so return -1
01277                 return -1;
01278             }
01279             else
01280             {
01281                 // Next element is also a curve so return index of control point
01282                 return ThisIndex+2;
01283             }
01284         }
01285     }
01286 }

BOOL Path::FindPrev INT32 *  index  )  const
 

Finds the previous path element in this path starting from the value (index).

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/11/94
Parameters:
Index is a pointer to an index into the path to start from [INPUTS]
Index will point at the previous element in the path [OUTPUTS]
Returns:
TRUE if valid previous element found FALSE if there is no previous element
See also:
Path::FindNext

Definition at line 948 of file paths.cpp.

00949 {
00950     ENSURE( (*index)<=UsedSlots, "Path position was not valid in FindPrev" );
00951     ENSURE( (*index)>=0, "Path Position less than zero!" );
00952 
00953     // de-reference the verb array
00954     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00955 
00956     // Move to the prev path element
00957     if ((*index)==UsedSlots)
00958     {
00959         // The current pos is at the end of the path, so move to the last element in the path
00960         (*index) --;
00961     }
00962     else
00963     {
00964         // see if we were now in the middle of a curve
00965         (*index)--;
00966 
00967         if ((Verbs[(*index)] & (~PT_CLOSEFIGURE))==PT_BEZIERTO)
00968             (*index) -= 2;
00969     }
00970 
00971     // Make sure we are still in bounds
00972     if ((*index)<0)
00973     {
00974         // we are not, so set the current pos back to the start and fail
00975         (*index) = 0;
00976         return FALSE;
00977     }
00978 
00979     // we are in the path, so succeed
00980     return TRUE;
00981 }

BOOL Path::FindPrev  ) 
 

Finds the prev path element in this path starting the search from CurrentPos.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if valid previous element found FALSE if there is no previous element
See also:
Path::FindNext

Definition at line 896 of file paths.cpp.

00897 {
00898     ENSURE( CurrentPos<=UsedSlots, "Path position was not valid in FindPrev" );
00899     ENSURE( CurrentPos>=0, "Path Position less than zero!" );
00900 
00901     // de-reference the verb array
00902     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00903 
00904     // Move to the prev path element
00905     if (CurrentPos==UsedSlots)
00906     {
00907         // The current pos is at the end of the path, so move to the last element in the path
00908         CurrentPos --;
00909     }
00910     else
00911     {
00912         // see if we were now in the middle of a curve
00913         CurrentPos--;
00914 
00915         if ((Verbs[CurrentPos] & (~PT_CLOSEFIGURE))==PT_BEZIERTO)
00916             CurrentPos -= 2;
00917     }
00918 
00919     // Make sure we are still in bounds
00920     if (CurrentPos<0)
00921     {
00922         // we are not, so set the current pos back to the start and fail
00923         CurrentPos = 0;
00924         return FALSE;
00925     }
00926 
00927     // we are in the path, so succeed
00928     return TRUE;
00929 }

INT32 Path::FindPrevControlPoint INT32  Index  ) 
 

This routine will scan back from an endpoint to find the attached bezier control point. It takes account of closed and open paths and complex paths, and will wrap around the path if necessary.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/8/94
Parameters:
Index gives the endpoint whose previous control point I want [INPUTS]
- [OUTPUTS]
Returns:
Index to the control point (or -1 if none)

Errors: -

See also:
-

Definition at line 3382 of file paths.cpp.

03383 {
03384 //  DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
03385 //  PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
03386     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
03387     INT32 i;
03388     if (Verbs[Index] == PT_MOVETO)
03389     {
03390         // This is the start of a path - if the path is open, return -1
03391         // otherwise return the index of the last control point. If the last 
03392         // element is a line, return -1
03393         i = Index;
03394         FindEndOfSubPath(&i);
03395         // If the last segment isn't a bezier, return -1
03396         if (Verbs[i] != PT_BEZIERTO)
03397             return -1;
03398 
03399         // if the CLOSEFIGURE flag is set in the final element, return i+1
03400         // otherwise return -1
03401         if (Verbs[i+2] & PT_CLOSEFIGURE)
03402             return i+1;
03403         return -1;
03404     }
03405     else
03406     {
03407         // It isn't the start of a path, so see what kind of endpoint this is
03408         // and if it is a bezier, return the control point, otherwise return -1
03409         if ((Verbs[Index] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
03410             return Index-1;
03411         return -1;
03412     }
03413 }

BOOL Path::FindPrevEndPoint INT32 *  index  )  const
 

Finds the previous path endpoint in this path.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/1/95
Parameters:
Index = pointer to a INT32 indicating where to start from [INPUTS] Outpus: Index = points to an index which is the previous endpoint
Returns:
TRUE if the previous end point has been found FALSE if there are no more end points in this path

Errors: ERROR2's if Index is beyond the end of the path, OR before the start

See also:
Path::FindNextEndPoint

Definition at line 814 of file paths.cpp.

00815 {
00816     ERROR2IF(*index > UsedSlots, FALSE, "Path position was not valid in FindPrevEndPoint" );
00817     ERROR2IF(*index < 0, FALSE, "Path Position less than zero in FindPrevEndPoint" );
00818 
00819     // de-reference the verb array
00820     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00821 
00822     if ((Verbs[*index] & (~PT_CLOSEFIGURE))==PT_BEZIERTO)
00823         *index -= 3;
00824     else
00825         *index -= 1;
00826 
00827     if (*index < 0)
00828     {
00829         *index = 0;
00830         return FALSE;
00831     }
00832 
00833     return TRUE;
00834 }

BOOL Path::FindSelectionLimits INT32  index,
INT32 *  p,
INT32 *  q
 

Finds the next connected region of selected control handles.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/11/94
Parameters:
index = search start point [INPUTS]
p = index of first selected point in region [OUTPUTS] q = index of last selected point in region
Returns:
TRUE if the point set {index,....,UsedSlots-1} contains a set of selected control handles {p,...,q} where p and q are the limits of the selection and all points between are selected. FALSE if no points are selected within the region.

Definition at line 3722 of file paths.cpp.

03723 {
03724     ENSURE( index<UsedSlots, "Path position was not valid in FindSelectionLimits" );
03725     ENSURE( index>=0, "Path Position less than zero in FindSelectionLimits" );
03726 
03727     INT32 start = index;
03728 
03729     // clamp the index
03730     if (start<0)
03731         start=0;
03732     if (start>=UsedSlots)
03733         start=UsedSlots-1;
03734 
03735     if (!FindNextSelected(&start))
03736         return FALSE;
03737 
03738     INT32 end = start;
03739     INT32 search = start;
03740         
03741     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
03742     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
03743 
03744     BOOL done = FALSE;
03745 
03746     while (FindNextEndPoint(&search) && (!done))
03747     {
03748         if ((Flags[search].IsSelected) && (Flags[search].IsEndPoint))
03749         {
03750             if (Verbs[search] != PT_MOVETO)
03751                 end = search;
03752             else
03753                 done = TRUE;
03754         }
03755         else
03756             done = TRUE;
03757     }
03758 
03759     *p = start;
03760     *q = end; 
03761 
03762     return TRUE;
03763 }

BOOL Path::FindStartOfPath  ) 
 

Sets Pos to the first element in the path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
Pos - Holds the position of the start of the path [OUTPUTS]

Definition at line 536 of file paths.cpp.

00537 {
00538     // set the position to the start of the path
00539     CurrentPos = 0;
00540 
00541     // see if this a valid path position
00542     if (UsedSlots==0)
00543         return FALSE;
00544     else
00545         return TRUE;
00546 }

void Path::FindStartOfSubPath INT32 *  Index  )  const
 

Searches backwards from the current position from Index until it find the start of the subpath (always a moveto).

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/7/94
Parameters:
Index - the index of the current element (pointer!) [INPUTS]
Index - Holds the position of the start of the sub path [OUTPUTS]
Returns:
Errors: ENSUREs if the start of the path does not seem to be a MoveTo

Definition at line 592 of file paths.cpp.

00593 {
00594     ENSURE( ((*Index)<UsedSlots && (Index)>=0), "Path position was not valid in FindStartOfSubPath" );
00595 
00596     // I am already in a path, so start working backwards until I find the moveto
00597     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00598 
00599     while (((*Index)>0) && (Verbs[*Index]!=PT_MOVETO))
00600         (*Index)--;
00601 
00602     // The index will either be pointing at a moveto or the begining of the path
00603     // Either way, it should be a moveto
00604     ENSURE( (Verbs[(*Index)]==PT_MOVETO), "Did not find a start to this sub path" );
00605 }

void Path::FindStartOfSubPath  ) 
 

Searches backwards from the current position until it finds the start of the sub path that the current position is in.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
Errors: ENSUREs if the start of the path does not seem to be a MoveTo

Definition at line 563 of file paths.cpp.

00564 {
00565     ENSURE( CurrentPos<UsedSlots, "Path position was not valid in FindStartOfSubPath" );
00566 
00567     // I am already in a path, so start working backwards until I find the moveto
00568     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00569 
00570     while ((CurrentPos>0) && (Verbs[CurrentPos]!=PT_MOVETO))
00571         CurrentPos--;
00572 
00573     // The index will either be pointing at a moveto or the begining of the path
00574     // Either way, it should be a moveto
00575     ENSURE( (Verbs[CurrentPos]==PT_MOVETO), "Did not find a start to this sub path" );
00576 }

BOOL Path::Flatten const double  flatness,
Path pOutput
 

Flatten a path. All curves within the path will be approximated by straight lines. pOutput may point at 'this' path ie a path can be flattened to itself. If the flattening fails for some reason, the output path will be unaffected even if you are flattening a path to itself.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/10/94
Parameters:
flatness = How flat the curves should be (around 64 is good) [INPUTS]
pOutput = will contain the flattened path [OUTPUTS]
Returns:
BOOL = TRUE if the path was flattened successfully = FALSE then output path will be unaffected

Definition at line 7854 of file paths.cpp.

07855 {
07856     // when flattening, flatten curves but dont quantise lines
07857     ProcessFlags FlatFlags(TRUE,FALSE);
07858     return CreateFlatPath(FlatFlags, flatness, pOutput);
07859 }

INT32 Path::GetAllOpenEnds INT32  MaxElements,
DocCoord EndCoords
const
 

Goes through the path and copies the coordinates of all the Open ends of the path into the array, until MaxElements elements have been added to the array. Call GetNumEndPoints to find out how big to make your array in the first place.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/4/94
Parameters:
MaxElements - The maximum number of coords that can be written to the [INPUTS] array
Coords - A array of DocCoords [OUTPUTS]
Returns:
The number of coords in the array
See also:
Path::GetNumEndPoints

Definition at line 1482 of file paths.cpp.

01483 {
01484     // de-reference the verb array
01485     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
01486     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
01487 
01488     INT32 Count = 0;
01489     for (INT32 i=0; i<UsedSlots; i++)
01490     {
01491         if (Verbs[i]==PT_MOVETO)
01492         {
01493             // Count this moveto
01494             EndCoords[Count] = Coords[i];
01495             Count++;
01496 
01497             // Check to see we have hit the maximum allowed entries
01498             if (Count==MaxElements)
01499                 return Count;
01500             
01501             if ((i>0) && (Verbs[i-1]&PT_CLOSEFIGURE))
01502             {
01503                 // The previous element was a close figure, so it corresponding MoveTo
01504                 // should not count
01505                 Count--;
01506             }
01507             else
01508             {
01509                 // The previous elment was not a close figure, so it was an Open End
01510                 EndCoords[Count] = Coords[i-1];
01511                 Count++;
01512 
01513                 // Check to see we have hit the maximum allowed entries
01514                 if (Count==MaxElements)
01515                     return Count;
01516 
01517             }
01518         }
01519     }
01520 
01521     // Check to see if the very last element in the path was a close figure or not
01522     if (Verbs[UsedSlots-1] & PT_CLOSEFIGURE)
01523         Count--;
01524     else
01525     {
01526         EndCoords[Count] = Coords[UsedSlots-1];
01527         Count++;
01528     }
01529 
01530     // return the number of coords we are stored
01531     return Count;
01532 }

DocRect Path::GetBlobRect  )  const
 

Calculates the bounding rectangle of the paths coordinates expanded by the current blob size. This is calculated on the fly, so don't over use it.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/12/94
Returns:
The bounding box of the path and blobs

Definition at line 1715 of file paths.cpp.

01716 {
01717     // If the path is