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 empty, then return an empty rectangle
01718     if (UsedSlots==0)
01719         return DocRect(0,0,0,0);
01720 
01721     // de-reference the coord array
01722     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
01723     DocRect BlobRect;
01724 
01725     for (INT32 i=0; i<UsedSlots; i++)
01726     {
01727         DocRect TempRect;
01728         GetApplication()->GetBlobManager()->GetBlobRect(Coords[i],&TempRect);
01729 
01730         if (i==0)
01731             BlobRect = TempRect;                    // For first coord, set BlobRect = rect of blob
01732         else
01733             BlobRect = BlobRect.Union(TempRect);    // for other coords, find the union
01734     }
01735 
01736     // return the completed rectangle
01737     return BlobRect;
01738 }

DocRect Path::GetBoundingRect  )  const
 

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

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
The bounding box of the path

Definition at line 1549 of file paths.cpp.

01550 {
01551     // If the path is empty, then return an empty rectangle
01552     if (UsedSlots==0)
01553         return DocRect(0,0,0,0);
01554 
01555     // de-reference the coord array
01556     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
01557     DocRect BoundingRect(Coords[0], Coords[0]);
01558 
01559     // include each point in the path to the bounding rectangle
01560     for (INT32 i=1; i<UsedSlots; i++)
01561         BoundingRect.IncludePoint(Coords[i]);
01562             
01563     // return the completed rectangle
01564     return BoundingRect;
01565 }

INT32 Path::GetContourForStep Path pDest,
double  StepValue = 1.0
 

Definition at line 5725 of file paths.cpp.

05726 {
05727     // First Check to see if the Path pasted in is valid!
05728     ERROR2IF(pDest==NULL,0,"Init GenPathContour Recieved a NULL Pointer!");
05729 
05730     PPOINT SPoints = (PPOINT)GetCoordArray();
05731     PBYTE STypes = (PBYTE)GetVerbArray();
05732     INT32 SLength = GetNumCoords();
05733 
05734     PPOINT OPoints = NULL;
05735     PBYTE OTypes = NULL;
05736     PPOINT INPoints = NULL;
05737     PBYTE INTypes = NULL;
05738 
05739     ERROR3IF(SLength < 0,"We`ve got a problem got a path with negative length!");
05740 
05741     Path CopyPath;
05742     CopyPath.Initialise();
05743 
05744     Path StrokedPath;
05745     StrokedPath.Initialise();
05746 
05747     INT32 PathLength = -1;
05748     INT32 Width = 100;
05749     Width = (INT32)(StepValue * m_ContourWidth);
05750 
05751     JointType JoinS = (m_ContourJoinS==JOIN_MITER) ? MitreJoin : (m_ContourJoinS==JOIN_ROUND) ? RoundJoin : BevelledJoin;
05752     LineCapType CapS = (m_ContourCapS==CAPS_BUTT) ? LineCapButt : (m_ContourCapS==CAPS_ROUND) ? LineCapRound : LineCapSquare;
05753 
05754     TRACEUSER( "MarkH", _T("Contouring with flatness %lf\n"),m_ContourFlatness);
05755     INT32 NewPathLength = -2;
05756     INT32 Passes = 0;
05757 
05758     // If we`re not using the contouring mode and we want to use the StrokePathToPAth function then do it here!
05759     if(!m_UseContourMode)
05760         PathLength = StrokePathToPath(Width, CapS, JoinS, NULL, &StrokedPath, m_ContourFlatness, m_DoClosePath);
05761 
05762     if(pDest->GetNumCoords() > 0)
05763     {
05764         // Now copy the Destination path as it needs to be clipped with the intermediate Path!
05765         CopyPath.CloneFrom(*pDest);
05766         pDest->ClearPath();
05767     }
05768     else
05769     {
05770         pDest->SetPathPosition(0);
05771     }
05772 
05773     // Check again to see if we`re doing the contour mode or the stroke path to path mode
05774     if(m_UseContourMode)
05775     {
05776         // now initialize and get the Points and Type pointers from a tempary path
05777         // that holds the intermediate step
05778         GenPathContour GStroke;
05779         // [Phil, 18/08/2005] Should this be assigning to NewPathLength? The test marked !!! below will always fail...
05780         PathLength = GStroke.ContourPath(SPoints, STypes, SLength, &OPoints, &OTypes,
05781                                         Width, m_ContourMitreLimit, m_ContourFlatness,
05782                                         m_ContourJoinS, (m_IsAnOuterContour == TRUE));
05783 
05784         INT32 OLength = (PathLength * 4)+1000;
05785 
05786         if ( PathLength > 0 && OPoints && OTypes)
05787         {
05788             if ( !m_IsAnOuterContour )
05789             {
05790                 // Create two new Arrays which are larger than the current OPoints and OTypes
05791                 // as gavin allocates his own memory for these points!
05792                 INPoints = new POINT[OLength];
05793                 INTypes = new BYTE[OLength];
05794 
05795                 if(INPoints && INTypes)
05796                 {
05797                     memcpy(INPoints,OPoints,sizeof(POINT) * PathLength);
05798                     memcpy(INTypes,OTypes,PathLength);
05799                     delete OPoints;
05800                     OPoints = INPoints;
05801                     delete OTypes;
05802                     OTypes = INTypes;
05803                 }
05804                 else
05805                 {
05806                     delete OTypes;
05807                     delete OPoints;
05808 
05809                     // If the NewPathLength is 0 then there`s no point continueing so
05810                     // make sure the destination path contains the data it came in with
05811                     // and return!
05812                     if(NewPathLength == 0)              // !!!
05813                         pDest->CloneFrom(CopyPath);
05814                     
05815                     return NewPathLength;
05816                 }
05817 
05818                 RECT obbox ;
05819                 XaDraw_CalcSimpleBBox( OPoints,PathLength,&obbox ) ;
05820                 OPoints[PathLength+0].x = obbox.right +0x1000 ;
05821                 OPoints[PathLength+0].y = obbox.top   -0x1000 ;
05822                 OPoints[PathLength+1].x = obbox.right +0x1000 ;
05823                 OPoints[PathLength+1].y = obbox.bottom+0x1000 ;
05824                 OPoints[PathLength+2].x = obbox.left  -0x1000 ;
05825                 OPoints[PathLength+2].y = obbox.bottom+0x1000 ;
05826                 OPoints[PathLength+3].x = obbox.left  -0x1000 ;
05827                 OPoints[PathLength+3].y = obbox.top   -0x1000 ;
05828                 OTypes[PathLength+0] = PT_MOVETO ;
05829                 OTypes[PathLength+1] = PT_LINETO ;
05830                 OTypes[PathLength+2] = PT_LINETO ;
05831                 OTypes[PathLength+3] = PT_LINETO|PT_CLOSEFIGURE ;
05832                 
05833                 while(NewPathLength == -2 && Passes++ < 6)
05834                 {
05835                     NewPathLength = ::ClipPathToPath(OPoints, OTypes, PathLength+4, m_ContourFlatness,
05836                                                     OPoints+PathLength, OTypes+PathLength, 4, m_ContourFlatness,
05837                                                     4 | 1<<4 | 1<<5, 30,
05838                                                     OPoints, OTypes, OLength);
05839                 }
05840 
05841                 PathLength = NewPathLength;
05842 
05843                 if(NewPathLength <= 0)
05844                 {
05845                     delete OTypes;
05846                     delete OPoints;
05847 
05848                     // If the NewPathLength is 0 then there`s no point continueing so
05849                     // make sure the destination path contains the data it came in with
05850                     // and return!
05851                     if(NewPathLength == 0)
05852                         pDest->CloneFrom(CopyPath);
05853                     
05854                     return NewPathLength;
05855                 }
05856             }
05857 
05858             pDest->EnsureVolume(OLength);
05859 
05860             PPOINT DPoints = (PPOINT)pDest->GetCoordArray();
05861             PBYTE DTypes = (PBYTE)pDest->GetVerbArray();
05862 //          INT32 DLength = pDest->GetNumCoords();
05863 
05864             PPOINT CPoints = (PPOINT)CopyPath.GetCoordArray();
05865             PBYTE CTypes = (PBYTE)CopyPath.GetVerbArray();
05866             INT32 CLength = CopyPath.GetNumCoords();
05867 
05868             NewPathLength = -2;
05869 
05870             while(NewPathLength == -2 && Passes++ < 6)
05871             {
05872                 NewPathLength = ::ClipPathToPath(   OPoints, OTypes, PathLength, m_ContourFlatness,
05873                                                 CPoints, CTypes, CLength, m_ContourFlatness,
05874                                                 7 | 1<<4, 30,
05875                                                 DPoints, DTypes, OLength);
05876 
05877                 if(NewPathLength == -2)
05878                 {
05879                     OLength <<= 1;
05880                     pDest->EnsureVolume(OLength);
05881                     pDest->SetPathPosition(0);
05882                     DPoints = (PPOINT)pDest->GetCoordArray();
05883                     DTypes = (PBYTE)pDest->GetVerbArray();
05884                     TRACEUSER( "MarkH", _T("Path to short so using new length %d\n"),OLength);
05885                 }
05886             }
05887 
05888             if(NewPathLength <= 0)
05889             {
05890                 delete OTypes;
05891                 delete OPoints;
05892 
05893                 // If the NewPathLength is 0 then there`s no point continueing so
05894                 // make sure the destination path contains the data it came in with
05895                 // and return!
05896                 if(NewPathLength == 0)
05897                     pDest->CloneFrom(CopyPath);
05898 
05899                 return NewPathLength;
05900             }
05901 
05902             pDest->UsedSlots += NewPathLength;
05903             pDest->UnUsedSlots -= NewPathLength;
05904 
05905             delete OTypes;
05906             delete OPoints;
05907 
05908             // Now try to close the destination path and tidyup the slot allocations!
05909             pDest->TryToClose();
05910         }
05911         else
05912         {
05913             delete OTypes;
05914             delete OPoints;
05915 
05916             // If the NewPathLength is 0 then there`s no point continueing so
05917             // make sure the destination path contains the data it came in with
05918             // and return!
05919 //          if(NewPathLength == 0)
05920             if (NewPathLength <=0)
05921             {
05922                 pDest->CloneFrom(CopyPath);
05923                 return 0;
05924             }
05925         }
05926     }
05927     else
05928     {
05929         // With the stroke path to path method we need to clean up the resultant path!
05930         PathLength = CopyPath.ClipPathToPath(StrokedPath, pDest, 7|(1<<4), 30, m_ContourFlatness, m_ContourFlatness);
05931         
05932         if(PathLength <= 0)
05933         {
05934             // If the NewPathLength is 0 then there`s no point continueing so
05935             // make sure the destination path contains the data it came in with
05936             // and return!
05937             if(PathLength == 0)
05938                 pDest->CloneFrom(CopyPath);
05939 
05940             TRACEUSER( "MarkH", _T("ClipFailed so copying path! PATHS\n"));
05941         }
05942     }
05943 
05944     // Return the New Path Length
05945     return PathLength;
05946 }

DocCoord Path::GetControl1  ) 
 

Finds the first control point of a bezier.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/02/94
Returns:
DocCoord - the Coord of the first control point

Definition at line 1785 of file paths.cpp.

01786 {
01787     ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetEndPoint" );
01788 
01789     // de-reference the coord array
01790     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
01791     
01792     ENSURE((((PathVerb*) DescribeHandle(VerbHandle)) [CurrentPos] & (~PT_CLOSEFIGURE))==PT_BEZIERTO, "Not a Bezier in Path::GetControl1()");
01793 
01794     return Coords[CurrentPos];
01795 }

DocCoord Path::GetControl2  ) 
 

Finds the second control point of a Bezier.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/02/94
Returns:
DocCoord - The coord of the seconds control point

Definition at line 1809 of file paths.cpp.

01810 {
01811     ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetEndPoint" );
01812 
01813     // de-reference the arrays
01814     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
01815     
01816     ENSURE((((PathVerb*) DescribeHandle(VerbHandle))[CurrentPos+1] & (~PT_CLOSEFIGURE))==PT_BEZIERTO, "Not a Bezier in Path::GetControl2()");
01817 
01818     return Coords[CurrentPos+1];
01819 }

DocCoord Path::GetCoord  )  const
 

finds the DocCoord associated with the path position

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
The DocCoord at the Current Path position

Errors: Ensures if the position if not valid or out of bounds

Definition at line 1146 of file paths.cpp.

01147 {
01148     ENSURE( CurrentPos<UsedSlots, "Index out of bounds in Path::GetCoord" );
01149 
01150     // de-reference the coord array
01151     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
01152 
01153     return Coords[CurrentPos];
01154 }

DocCoord * Path::GetCoordArray  )  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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
Pointer to the Array of coords held by the path.

Definition at line 1837 of file paths.cpp.

01838 {
01839     // de-reference the coord array
01840     return (DocCoord*) DescribeHandle(CoordHandle);
01841 }

void Path::GetDebugDetails StringBase Str  ) 
 

Dumps the whole path out during tree display debugging.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>; Karim 26/05/2000
Date:
20/12/94
(Karim) I'm updating this method to give a little bit more info, so's it isn't necessary to manually dump path data every time you need to. It doesn't currently seem to be called from anywhere, so my changes should have zero effect on existing code. Please feel free to use this method and alter it to display more info if required.

Info returned: Number of handles and bytes used by the path data. Whether the path is filled or not. Each handle's verbs, coords and flags Verbs - L - LineTo C - CurveTo M - MoveTo S - ClosePath

Notes: For example of use, see NodeClipViewController::GetDebugDetails().

Definition at line 2912 of file paths.cpp.

02913 {
02914 #ifdef _DEBUG
02915     String_256 TempStr;
02916 
02917     // output number of handles and space used by the path.
02918     INT32 nSlots = GetNumCoords();
02919     TempStr._MakeMsg( TEXT("#1%ld handles, #2%ld bytes used\r\n"),  nSlots,
02920                                                                     GetPathByteLength() );
02921     (*Str) += TempStr;
02922 
02923     // output whether or not the path is filled.
02924     TempStr._MakeMsg( TEXT("Path is#1%s Filled and is#2%s Stroked\r\n"),
02925                                                                 IsFilled    ? "" : " not",
02926                                                                 IsStroked   ? "" : " not" );
02927     (*Str) += TempStr;
02928 
02929     // output the path's handle information.
02930     (*Str) += TEXT( "Num\tType\tX Coord\tY Coord\r\n" );
02931     PathVerb *  Verbs   = GetVerbArray();
02932     DocCoord *  Coords  = GetCoordArray();
02933     PathFlags * Flags   = GetFlagArray();
02934     for (INT32 i=0; i < nSlots; i ++)
02935     {
02936         String_32 VerbStr;
02937         VerbStr._MakeMsg(TEXT("#1%d ("), Verbs[i]);
02938         if (Verbs[i] & PT_CLOSEFIGURE)  VerbStr += TEXT("S");
02939         if (Verbs[i] & PT_LINETO)       VerbStr += TEXT("L");
02940         if (Verbs[i] & PT_BEZIERTO)     VerbStr += TEXT("C");
02941         if (Verbs[i] & PT_MOVETO)       VerbStr += TEXT("M");
02942         VerbStr += TEXT(")");
02943 
02944         TempStr._MakeMsg( TEXT("#1%d.\t#2%S\t#3%ld,\t#4%ld\t"),
02945                           i, &VerbStr, Coords[i].x, Coords[i].y );
02946 
02947         if (Flags[i].IsSmooth)      TempStr += TEXT("S");
02948         if (Flags[i].IsRotate)      TempStr += TEXT("R");
02949         if (Flags[i].IsEndPoint)    TempStr += TEXT("E");
02950         if (Flags[i].IsSelected)    TempStr += TEXT("(sel)");
02951 
02952         TempStr += TEXT("\r\n");
02953         (*Str) += TempStr;
02954     }
02955 #endif
02956 }

BOOL Path::GetDistanceToPoint DocCoord  Point,
MILLIPOINT Distance
 

Gets the distance along the path for a given point.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/8/96
Parameters:
Point - A DocCoord [INPUTS]
Distance - a length along the path [OUTPUTS]
Returns:
TRUE/FALSE for success/failure

Definition at line 9852 of file paths.cpp.

09853 {
09854     ERROR2IF(Distance==NULL, FALSE, "NULL output parameter");
09855 
09856     INT32 NextEndpoint = 0;
09857     double dDistance = 0.0;
09858     double mu = 0.0;
09859     BOOL ok = (SqrDistanceToPoint(Point, &NextEndpoint, &mu) != -1);
09860     ERROR3IF(!ok, "SqrDistanceToPoint failed");
09861     if (ok)
09862     {
09863         ok = DistanceTo(NextEndpoint, mu, &dDistance);
09864         ERROR3IF(!ok, "Path::DistanceTo failed");
09865     }
09866 
09867     *Distance = (MILLIPOINT)dDistance;
09868 
09869     return ok;
09870 }

DocCoord Path::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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
The Endpoint of the Path Element pointed at by Current Path position

Errors: Ensures if the position is not valid or out of bounds

Definition at line 1756 of file paths.cpp.

01757 {
01758     ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetEndPoint" );
01759 
01760     // de-reference the verb array
01761     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
01762 
01763     // de-reference the coord array
01764     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
01765     
01766     if ((Verbs[CurrentPos] & (~PT_CLOSEFIGURE))==PT_BEZIERTO)
01767         return Coords[CurrentPos+2];
01768     else
01769         return Coords[CurrentPos];
01770 }

PathFlags * Path::GetFlagArray  )  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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
A pointer to an array of Path Flags
See also:
PathFlag

Definition at line 1881 of file paths.cpp.

01882 {
01883     // de-reference the Flag array
01884     return (PathFlags*) DescribeHandle(FlagsHandle);
01885 }

void Path::GetFlags PathFlags NewFlags  ) 
 

returns all the flags for the current path position

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/02/94
Parameters:
NewFlags - Holds the flags for the current path position [OUTPUTS]

Definition at line 2689 of file paths.cpp.

02690 {
02691     ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsEndPoint" );
02692 
02693     // Get the flags array
02694     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02695 
02696     // and return the selected flag
02697     *NewFlags = Flags[CurrentPos];
02698 }

PathFlags Path::GetFlags  )  const
 

finds the flags associated with the path position

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
The flag at the current path position

Errors: Ensures if the position if not valid or out of bounds

Definition at line 1168 of file paths.cpp.

01169 {
01170     ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetFlags" );
01171 
01172     // de-reference the flag array
01173     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
01174 
01175     return Flags[CurrentPos];   
01176 }

INT32 Path::GetNumCoords  )  const
 

This returns the number of coordinates that make the path up.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
The number of coordinates in the path

Definition at line 1391 of file paths.cpp.

01392 {
01393     return UsedSlots;
01394 }

INT32 Path::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).

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/11/94
Returns:
The number of path elements in all sub paths.

Definition at line 1326 of file paths.cpp.

01327 {
01328     // The routine relies on the path beginning with a MoveTo
01329     PathVerb* pVerbs = (PathVerb*) DescribeHandle(VerbHandle);
01330     INT32 Index=0,Count=0;
01331     while (FindNextEndPoint(&Index))
01332     {
01333         if ((pVerbs[Index] & ~PT_CLOSEFIGURE) != PT_MOVETO)
01334             Count++;
01335     }
01336 
01337     return Count;
01338 }

INT32 Path::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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/4/94
Returns:
The number of open ends to the path.
See also:
Path::GetAllOpenEnds

Definition at line 1444 of file paths.cpp.

01445 {
01446     // de-reference the verb array
01447     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
01448     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
01449 
01450     INT32 Count = 0;
01451     for (INT32 i=0; i<UsedSlots; i++)
01452     {
01453         if (Flags[i].IsEndPoint)
01454             Count++;
01455 
01456         if ((i>0) && (Verbs[i]==PT_MOVETO) && (Verbs[i-1] & PT_CLOSEFIGURE))
01457             Count--;
01458     }
01459 
01460     // return the number of 'on the path' end points
01461     return Count;
01462 }

INT32 Path::GetNumSelEndPoints  )  const
 

determine how many selected endpoints there are within this path. Useful indirectly for finding whether there's a subselection.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/10/94
Returns:
Number of selected endpoints within this path
See also:
IsSubSelected()

Definition at line 1411 of file paths.cpp.

01412 {
01413     // We need to find all the selected control points in the path
01414     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
01415     INT32 count = 0;
01416 
01417     // look for selected coords
01418     for (INT32 i=0; i<UsedSlots; i++)
01419     {
01420         if ((Flags[i].IsSelected) && (Flags[i].IsEndPoint))
01421             count++;
01422     }
01423     return count;
01424 }

INT32 Path::GetNumSubpaths  )  const
 

Gets the number of subpaths in this path.

Author:
Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/4/97
Returns:
The number of subpaths in this path

Definition at line 1351 of file paths.cpp.

01352 {
01353     //This variable will tell us our current position in the path
01354     INT32 lCurPos=0;
01355 
01356     //And this will keep a count of the subpaths we find
01357     INT32 lSubpaths=0;
01358 
01359     //Now, while we are still in the path
01360     while (lCurPos<GetNumCoords())
01361     {
01362         //Set lCurPos to the end of the subpath we are in
01363         FindEndElOfSubPath(&lCurPos);
01364 
01365         //Add one to the number of subpaths found
01366         lSubpaths++;
01367 
01368         //And move the current position on by one place, to move it
01369         //either into the next subpath or off the end of the path
01370         lCurPos++;
01371     }
01372 
01373     //And return the number of subpaths we found
01374     return lSubpaths;
01375     
01376 }

void Path::GetPathArrays PathVerb **  VerbArray,
DocCoord **  CoordArray = NULL,
PathFlags **  FlagsArray = NULL
 

Easy way of getting the path pointers into variables. Combines three function calls into one.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/4/95
Parameters:
VerbArray - pointer to a pointer to a PathVerb object [INPUTS] CoordArray - pointer to a pointer to a DocCoord FlagsArray - pointer to a pointer to a PathFlags object
VerbArray points to the verbs array [OUTPUTS] CoordArray points to the coordinates array FlagsArray points to the flags array
Returns:
-

Errors: -

Definition at line 1907 of file paths.cpp.

01908 {
01909     if (VerbArray != NULL)
01910         *VerbArray = (PathVerb*) DescribeHandle(VerbHandle);
01911     if (CoordArray != NULL)
01912         *CoordArray = (DocCoord*) DescribeHandle(CoordHandle);
01913     if (FlagsArray != NULL)
01914         *FlagsArray = (PathFlags*) DescribeHandle(FlagsHandle);
01915 }

INT32 Path::GetPathByteLength  )  const
 

Calculates the length of the path in bytes. This figures includes the size of the 3 arrays (Coordinates, Verbs and Flags) only.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
The Length of the path in bytes

Definition at line 1300 of file paths.cpp.

01301 {
01302     INT32 Total;
01303 
01304     // Add up the size of each of the Arrays
01305     Total  = UsedSlots * sizeof(DocCoord);
01306     Total += UsedSlots * sizeof(PathVerb);
01307     Total += UsedSlots * sizeof(PathFlags);
01308 
01309     return Total;
01310 }

double Path::GetPathLength double  dFlatness = 64.0  ) 
 

Find the length of a path in millipoints.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/8/96
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
The length of the path in millipoints

Definition at line 7938 of file paths.cpp.

07939 {
07940     double TotalLength = 0.0;
07941     INT32 LastEndPoint = GetNumCoords()-1;
07942     
07943     if (LastEndPoint==-1)
07944         return 0.0;
07945 
07946     BOOL ok = DistanceTo(LastEndPoint, 1.0, &TotalLength, dFlatness);
07947     ERROR3IF(!ok, "Path.DistanceTo failed");
07948 
07949     if (ok)
07950         return TotalLength;
07951     else
07952         return 0.0;
07953 }

INT32 Path::GetPathPosition  ) 
 

Find out where in the path we are.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/02/94
Returns:
The Coord number in the path that the Current Path Position is at

Definition at line 999 of file paths.cpp.

01000 {
01001     return CurrentPos;
01002 }

PathTypeEnum Path::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.

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

Definition at line 1195 of file paths.cpp.

01196 {
01197     PathVerb* pVerbs = GetVerbArray();
01198 
01199     if (pVerbs[UsedSlots-1] & PT_CLOSEFIGURE)
01200         return (PATHTYPE_SHAPE);
01201     else
01202         return (PATHTYPE_LINE);
01203 }

BOOL Path::GetPointAtDistance MILLIPOINT  Distance,
DocCoord pPoint,
double *  pTangent = NULL,
UINT32 pPressure = NULL
 

Gets the coordinate of a point a certain distance along this path.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/3/96
Parameters:
Distance - a length along the path [INPUTS]
pPoint - the coordinate of the point that distance along the path [OUTPUTS] pTangent = tangent at this point (can be NULL if tangent not required)
Returns:
TRUE/FALSE for success/failure

Definition at line 9828 of file paths.cpp.

09829 {
09830     ERROR2IF(pPoint==NULL, FALSE, "NULL output parameter");
09831     ERROR2IF(Distance<0, FALSE, "-ve distance");
09832 
09833     ProcessPathDistance PathProc(64);
09834     BOOL Found = FALSE;
09835     BOOL ok = PathProc.GetCoordAndTangent(pPoint, pTangent, &Found, Distance, this, pPressure);
09836 
09837     return ok && Found;
09838 }

BOOL Path::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.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/3/94
Parameters:
- [INPUTS]
start,end are the coords of the start and end (if function returned TRUE) [OUTPUTS]
Returns:
TRUE if subpath is open, FALSE otherwise CurrentPos in the path is set to the end of the subpath.

Errors: -

See also:
-

Definition at line 693 of file paths.cpp.

00694 {
00695     DocCoord temp1;
00696 
00697     FindStartOfSubPath();
00698     temp1 = GetCoord();
00699     FindEndOfSubPath();
00700 
00701 // Find out if this path is really closed. If the PT_CLOSEFIGURE flag is set in the end
00702 // verb, the path is closed, so return FALSE, otherwise return TRUE, with *start and *end 
00703 // set up accordingly.
00704 
00705     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
00706     if (Verbs[CurrentPos] & PT_CLOSEFIGURE)
00707     {
00708         return FALSE;
00709     }
00710     else
00711     {
00712         *end = GetEndPoint();
00713         *start = temp1;
00714         return TRUE;
00715     }
00716 }

BOOL Path::GetTrueBoundingRect DocRect pRect,
MILLIPOINT  LineWidth = 0,
CCAttrMap pAttrMap = NULL
 

Calculate the bounding rectangle of a path using GDraw.

Added by Diccon 22/5/2000 LineWidth - the width of the path, note that this defaults to zero so you don't have to supply anything unless you want to.

pAttrMap ptr to an attrmap, from which to take modification info. note that if we can extract a LineWidth value from it, then the attrmap's value will override that passed in directly.

Parameters:
if successful, pRect will contain the bounds of the path, [OUTPUTS] otherwise pRect will be made empty.
Returns:
TRUE if successful, FALSE otherwise.
Notes: This gives the true bounds, including all the curvy bits - not just the bounds of the control points, which is what GetBoundingRect() returns.

By using one or other of the extra parameters to this method, you can find out the bounds for thick lines, or lines with arrow-heads/tails.

Returns:
Errors: ERROR3's with FALSE if pRect is NULL.
See also:
GDrawContext::CalcStrokeBBox.

Definition at line 1603 of file paths.cpp.

01604 {
01605     // validate inputs.
01606     if (pRect == NULL)
01607     {
01608         ERROR3("Path::GetTrueBoundingRect; NULL input rectangle!");
01609         return FALSE;
01610     }
01611     if (LineWidth < 0)
01612     {
01613         //ERROR3("Negative line width supplied to Path::GetTrueBoundingRect");
01614         LineWidth = 0;  // we can recover from this
01615     }
01616 
01617     // check the attr map for any attrs which we think may alter
01618     // the bounds of the path, eg line width, arrow heads.
01619     ArrowRec*   pArrow1 = NULL;
01620     ArrowRec*   pArrow2 = NULL;
01621     JoinStyles  JoinStyle = JOIN_ROUND;
01622     if (pAttrMap != NULL)
01623     {
01624         AttrLineWidth*      pLineWidth  = NULL;
01625         AttrStrokeColour*   pLineColour = NULL;
01626         AttrStartArrow*     pStartArrow = NULL;
01627         AttrEndArrow*       pEndArrow   = NULL;
01628         AttrJoinType*       pJoinType   = NULL;
01629 
01630         // note that we only use the path's LineWidth if its outline is not transparent.
01631         pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrLineWidth), (void*&)pLineWidth);
01632         pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeColour), (void*&)pLineColour);
01633 
01634         if (pLineColour != NULL && pLineWidth != NULL)
01635         {
01636             LineWidth = 0;
01637             DocColour* pCol = pLineColour->GetStartColour();
01638             if (pCol != NULL && !pCol->IsTransparent())
01639                 LineWidth = pLineWidth->Value.LineWidth;
01640         }
01641 
01642         // ok, if we have a line width then we'll need to look for stuff like
01643         // arrowheads and join-style (esp. Mitre joins).
01644         if (LineWidth > 0)
01645         {
01646             pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartArrow), (void*&)pStartArrow);
01647             if (pStartArrow != NULL)
01648                 pArrow1 = &(pStartArrow->Value.StartArrow);
01649 
01650             pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrEndArrow), (void*&)pEndArrow);
01651             if (pEndArrow != NULL)
01652                 pArrow2 = &(pEndArrow->Value.EndArrow);
01653 
01654             pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrJoinType), (void*&)pJoinType);
01655             if (pJoinType != NULL)
01656             {
01657                 JointType jt = pJoinType->Value.JoinType;
01658 
01659                 JoinStyle = (jt == MitreJoin) ? JOIN_MITER :
01660                             (jt == RoundJoin) ? JOIN_ROUND :
01661                                                 JOIN_BEVEL;
01662             }
01663         }
01664     }
01665 
01666     // ok, let's get the path's bounds!
01667     pRect->MakeEmpty();
01668     BOOL fSuccess = FALSE;
01669     DocRect drBounds;
01670     GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
01671 
01672     if (GD == NULL)
01673         return FALSE;
01674 
01675     fSuccess = GD->CalcStrokeBBox(  (POINT*)GetCoordArray(), GetVerbArray(), GetNumCoords(),
01676                                     (RECT *)(&drBounds), IsFilled, (DWORD)LineWidth,
01677                                     CAPS_ROUND, JoinStyle, NULL ) != -1;
01678 
01679     // if the bounds are invalid then make sure that we flag a failure.
01680     if (!drBounds.IsValid())
01681         fSuccess = FALSE;
01682 
01683     // ok so far - if we need to account for any arrowheads, do so now.
01684     if (fSuccess)
01685     {
01686         if (pArrow1 != NULL)
01687             drBounds = drBounds.Union(pArrow1->GetArrowBoundingRect(this, LineWidth, TRUE));
01688 
01689         if (pArrow2 != NULL)
01690             drBounds = drBounds.Union(pArrow2->GetArrowBoundingRect(this, LineWidth, FALSE));
01691     }
01692 
01693     // ok, if we're a success then record the bounds.
01694     if (fSuccess)
01695         *pRect = drBounds;
01696 
01697     return fSuccess;
01698 }

INT32 Path::GetUsedSlots  )  [inline]
 

Definition at line 573 of file paths.h.

00573 { return (UsedSlots); }

PathVerb Path::GetVerb  )  const
 

finds the verb associated with the path position

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
The verb at the current path position

Errors: Ensures if the position if not valid or out of bounds

Definition at line 1122 of file paths.cpp.

01123 {
01124     ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetVerb" );
01125 
01126     // de-reference the verb array
01127     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
01128 
01129     // return the verb with the close path bit removed
01130     return ((Verbs[CurrentPos]) & (~PT_CLOSEFIGURE));
01131 }

PathVerb * Path::GetVerbArray  )  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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
A pointer to the verb array held by the path.

Definition at line 1859 of file paths.cpp.

01860 {
01861     // de-reference the Verb array
01862     return (PathVerb*) DescribeHandle(VerbHandle);
01863 }

PathWidth Path::GetWidth void   )  const
 

Fetches width values from the path.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/06/94
Parameters:
- [INPUTS]
Returns:
The width of the path at the current path postion.

Errors: -

Definition at line 8255 of file paths.cpp.

08256 {
08257     if (ExtraInfo == NULL)
08258         return 0;
08259 
08260     return ExtraInfo->GetWidthInfo();   
08261 }

PathWidth * Path::GetWidthArray  ) 
 

The array holds the width of all the points in the path. DO NOT MODIFY THE CONTENTS OF THE ARRAY.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/06/94
Returns:
A pointer to an array of Path Width Info.

Definition at line 8275 of file paths.cpp.

08276 {
08277     if (ExtraInfo == NULL)
08278         return NULL;
08279 
08280     return ExtraInfo->GetWidthArray();  
08281 }

BOOL Path::HasWidth  ) 
 

To determine if the path has any width information.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/06/94
Returns:
TRUE if width information is available.

Definition at line 8294 of file paths.cpp.

08295 {
08296     if (ExtraInfo == NULL)
08297         return FALSE;
08298 
08299     return ExtraInfo->HasWidthInfo();
08300 }

BOOL Path::InitExtraInfo ChannelIndex  Index  ) 
 

Allocates memory in the path for the extra info arrays.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/06/94
Parameters:
The Index of the Channel to Initialise. [INPUTS]
Returns:
TRUE if we got all the memory we needed, FALSE if not

Errors: May error if it runs out of memory.

Definition at line 8184 of file paths.cpp.

08185 {
08186     TRACEUSER( "Will", _T("InitExtraInfo, Index=%d\n"), Index );
08187     ENSURE(Index <= NUMEXTRACHANNELS, "Index out of range in InitExtraInfo");
08188                         
08189     // If we haven't any extra info yet then we need to create some
08190     if (ExtraInfo == NULL)
08191     {
08192         ExtraInfo =  new PathExtraInfo();
08193         if (ExtraInfo == NULL)
08194             return FALSE;
08195     }
08196 
08197     // Now we can initialise the channel.
08198     // We use the same initial slot size as was used for the main path data.
08199     return ExtraInfo->Init(Index, SlotInitSize);
08200 }

BOOL Path::Initialise INT32  InitialSize = 24,
INT32  BlockSize = 12
 

Allocates memory in the path for the three arrays - The Verbs, Coordinates and the Flags.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
InitialSize - The number of coords the path can hold initially [INPUTS] BlockSize - The number of coords to allocate for each time we run out of space
Returns:
TRUE if we got all the memory we needed, FALSE if not

Errors: Can fail if it runs out of memory

Definition at line 284 of file paths.cpp.

00285 {
00286     // CGS (19/6/2000)  A few of camelots programmers seem to be assuming that calling initialise
00287     // on an already initialised path will clear out all previous pointers.  This is NOT the case
00288     // (or at least wasn't).  It is not unreasonable for the programmer to expect this to happen
00289     // (being viewed as a reinitialise), so I have added code to handle deletion automatically.
00290     // This should fix a considerable amount of camelots memory leaks!
00291 
00292     if (VerbHandle != BAD_MHANDLE)
00293         ReleaseBlock(VerbHandle);
00294     
00295     if (CoordHandle != BAD_MHANDLE)
00296         ReleaseBlock(CoordHandle);
00297 
00298     if (FlagsHandle != BAD_MHANDLE)
00299         ReleaseBlock(FlagsHandle);
00300     
00301     // The memory manager will not allocate blocks of less that 12 bytes and have to be multiples of 4!
00302     if (InitialSize<12)
00303     {
00304         InitialSize = 12;
00305     }
00306     else
00307     {
00308         // Make sure it is a multiple of 4, by shifting left 2 and then shifting it back again!
00309         InitialSize = (InitialSize+3) >> 2;
00310         InitialSize = InitialSize << 2;
00311     }
00312 
00313     if (BlockSize<12)
00314     {
00315         BlockSize = 12;
00316     }
00317     else
00318     {
00319         // Make sure it is a multiple of 4, by shifting left 2 and then shifting it back again!
00320         BlockSize = (BlockSize+3) >> 2;
00321         BlockSize = BlockSize << 2;
00322     }
00323 
00324     // try and get memory for the verbs
00325     VerbHandle = ClaimBlock(sizeof(PathVerb)*InitialSize);
00326     if (VerbHandle!=BAD_MHANDLE)
00327     {
00328         // try and get memory for the coords
00329         CoordHandle = ClaimBlock(sizeof(DocCoord)*InitialSize);
00330         if (CoordHandle != BAD_MHANDLE)
00331         {
00332             // try and get memory for the flags
00333             FlagsHandle = ClaimBlock(sizeof(PathFlags)*InitialSize);
00334             if (FlagsHandle != BAD_MHANDLE)
00335             {
00336                 // everything worked
00337                 UsedSlots = 0;
00338                 UnUsedSlots = InitialSize;
00339                 SlotInitSize = InitialSize;
00340                 SlotAllocSize = BlockSize;
00341             }
00342             else
00343             {
00344                 // failed to get the flag block, so release the other blocks and fail
00345                 ReleaseBlock( CoordHandle );
00346                 ReleaseBlock( VerbHandle );
00347                 return FALSE;
00348             }
00349         }
00350         else
00351         {
00352             // failed to get the coords block, so release the block we already have and fail
00353             ReleaseBlock( VerbHandle );
00354             return FALSE;
00355         }
00356     }
00357     else
00358     {
00359         // failed to get any memory, so fail
00360         return FALSE;
00361     }
00362 
00363     // a total success, so say so.
00364     return TRUE;
00365 }

void Path::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.

void Path::InitialiseFlags(PathVerb* pVerbs, PathFlags* pFlags, const INT32 Len)

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/1/95
Parameters:
pVerbs = ptr to a path verbs array [INPUTS] pFlags = ptr to buffer to place the initialised flags Len = num verbs in pVerbs, and num flags in pFlags
pFlags array contains valid flags for each of the verbs in pVerbs [OUTPUTS]
Returns:
-
See also:
-

Definition at line 2796 of file paths.cpp.

02797 {
02798     INT32 n;
02799 
02800     // Reset all the path flags to default values
02801     PathFlags DefaultPathFlags;
02802     for (n=0; n < Len; n++)
02803         pFlags[n] = DefaultPathFlags;
02804 
02805     // Scan the verbs, so that the end point flags can be set correctly
02806     for (n=0; n < Len; n++)
02807     {
02808         PathVerb Verb = pVerbs[n] & ~PT_CLOSEFIGURE;
02809         switch (Verb)
02810         {
02811             case PT_LINETO:
02812             case PT_MOVETO:
02813                 pFlags[n].IsEndPoint = TRUE;
02814                 break;
02815 
02816             case PT_BEZIERTO:
02817                 n += 2;
02818                 ERROR3IF(n>=Len,"Found a PT_BEZIERTO, but third pt is off the end of the array");
02819                 pFlags[n].IsEndPoint = TRUE;
02820                 break;
02821 
02822             default:
02823                 ERROR3_PF(("Illegal path verb found : %c",Verb));
02824                 break;
02825         }
02826     }
02827 }

void Path::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 Path::InitialiseFlags( const UINT32 Startindex, const INT32 Len)

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
8/11/94
Parameters:
Startindex = index of element at which to start [INPUTS] Len = num verbs to set corresponding flags for
The path's flags array contains valid flags for each of its verbs [OUTPUTS]
Returns:
-
See also:
-

Definition at line 2763 of file paths.cpp.

02765 {
02766     ERROR3IF(Startindex<0,"startindex off start of path in Path::SetPathFlags()");
02767     ERROR3IF(Startindex+Len>UsedSlots,"(startindex+len) of end of path in Path::SetPathFlags()"); 
02768 
02769     // Get the flags array
02770     PathFlags* pFlags = (PathFlags*) DescribeHandle(FlagsHandle);
02771     PathVerb* pVerbs = (PathVerb*)   DescribeHandle(VerbHandle);
02772 
02773     InitialiseFlags(pVerbs+Startindex,pFlags+Startindex,Len);
02774 }

void Path::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 Path::InitialiseFlags()

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/1/95
Parameters:
- [INPUTS]
The path's flags array contains valid flags for each of its verbs [OUTPUTS]
Returns:
-
See also:
-

Definition at line 2740 of file paths.cpp.

02741 {
02742     InitialiseFlags(0,UsedSlots);
02743 }

INT32 Path::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
 

Definition at line 5698 of file paths.cpp.

05700 {
05701     m_ContourWidth = Width;
05702     m_ContourJoinS = JoinS;
05703     m_ContourCapS = CapS;
05704     m_IsAnOuterContour = IsAnOuterContour;
05705     m_DoClosePath = ClosePath;
05706     m_UseContourMode = UseContourMode;
05707     m_ContourFlatness = Flatness;
05708     m_ContourMitreLimit = MitreLimit;
05709 
05710     return GetNumCoords();
05711 }

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

Inserts a Curve into the path at the Current Path Position.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/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::InsertLineTo; Path::InsertMoveTo

Definition at line 2154 of file paths.cpp.

02155 {
02156     // We need 3 empty slot to add a CurveTo
02157     if (!MakeSpaceInPath(3))
02158     {
02159         ERROR( _R(IDS_PATH_MEM_ERROR), FALSE );
02160     }
02161 
02162     // get all the pointers
02163     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
02164     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
02165     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02166 
02167     // Prepare the flags
02168     PathFlags UseFlags;
02169     if (NewFlags!=NULL)
02170         UseFlags = *NewFlags;
02171 
02172     UseFlags.IsEndPoint = FALSE;
02173 
02174     // There is now a hole in the middle of the path.
02175     // We can fill in the appropriate details for the first control point
02176     Verbs[CurrentPos] = PT_BEZIERTO;
02177     Coords[CurrentPos] = p1;
02178     Flags[CurrentPos] = UseFlags;
02179 
02180     SyncExtraInfo();
02181     CurrentPos++;
02182 
02183     // and the second control point
02184     Verbs[CurrentPos] = PT_BEZIERTO;
02185     Coords[CurrentPos] = p2;
02186     Flags[CurrentPos] = UseFlags;
02187     CurrentPos++;
02188 
02189     // and the endpoint
02190     UseFlags.IsEndPoint = TRUE;
02191     Verbs[CurrentPos] = PT_BEZIERTO;
02192     Coords[CurrentPos] = p3;
02193     Flags[CurrentPos] = UseFlags;
02194     CurrentPos++;
02195 
02196     // Update the memory usage vars
02197     UsedSlots += 3;
02198     UnUsedSlots -= 3;
02199 
02200     // The Current Path Position has already been updated and now points to the item
02201     // after the curveto (or off the end of the path, if this is the last element in the path
02202 
02203     return TRUE;
02204 }

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

Inserts a LineTo into the path at the Current Path Position.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/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

Definition at line 2098 of file paths.cpp.

02099 {
02100     // We need only 1 empty slot to add a LineTo
02101     if (!MakeSpaceInPath(1))
02102     {
02103         ERROR( _R(IDS_PATH_MEM_ERROR), FALSE );
02104     }
02105 
02106     // get all the pointers
02107     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
02108     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
02109     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02110 
02111     // Prepare the flags
02112     PathFlags UseFlags;
02113     if (NewFlags!=NULL)
02114         UseFlags = *NewFlags;
02115 
02116     UseFlags.IsEndPoint = TRUE;
02117 
02118     // There is now a hole in the middle of the path. We can fill in the appropriate details
02119     // and call it a day
02120     Verbs[CurrentPos] = PT_LINETO;
02121     Coords[CurrentPos] = p1;
02122     Flags[CurrentPos] = UseFlags;
02123 
02124     // Update the memory usage vars
02125     UsedSlots++;
02126     UnUsedSlots--;
02127 
02128     // move the position indicator to point to the thing after our new item
02129     SyncExtraInfo();
02130     CurrentPos++;
02131 
02132     return TRUE;
02133 }

BOOL Path::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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
p1 - The coordinate to move to [INPUTS] NewFlags - The flags associated with the coord
Returns:
TRUE if it worked, FALSE otherwise

Definition at line 2046 of file paths.cpp.

02047 {
02048     // We need only 1 empty slot to add a MoveTo
02049     if (!MakeSpaceInPath(1))
02050     {
02051         ERROR( _R(IDS_PATH_MEM_ERROR), FALSE );
02052     }
02053 
02054     // get all the pointers
02055     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
02056     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
02057     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02058 
02059     // Prepare the flags
02060     PathFlags UseFlags;
02061     if (NewFlags!=NULL)
02062         UseFlags = *NewFlags;
02063 
02064     UseFlags.IsEndPoint = TRUE;
02065 
02066     // There is now a hole in the middle of the path. We can fill in the appropriate details
02067     // and call it a day
02068     Verbs[CurrentPos] = PT_MOVETO;
02069     Coords[CurrentPos] = p1;
02070     Flags[CurrentPos] = UseFlags;
02071 
02072     // Update the memory usage vars
02073     UsedSlots++;
02074     UnUsedSlots--;
02075 
02076     // move the position indicator to point to the thing after our new item
02077     SyncExtraInfo();
02078     CurrentPos++;
02079 
02080     return TRUE;
02081 }

BOOL Path::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.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/6/94
Parameters:
StartSlot is the path slot where we want to insert the section [INPUTS] NumSlots is how many slots we want to insert
- [OUTPUTS]
Returns:
TRUE if successful, FALSE otherwise

Errors: -

See also:
Path::DeleteSection

Definition at line 4071 of file paths.cpp.

04072 {
04073     INT32 OldPosition = CurrentPos;
04074     CurrentPos = StartSlot;
04075     if (!MakeSpaceInPath(NumSlots))
04076     {
04077         CurrentPos = OldPosition;
04078         return FALSE;
04079     }
04080     CurrentPos = OldPosition;
04081     UsedSlots+=NumSlots;
04082     UnUsedSlots -= NumSlots;
04083     return TRUE;
04084 }

BOOL Path::InsertSectionAtEnd const Path Other,
INT32  StartSlot,
INT32  NumSlots
[private]
 

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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/4/94
Parameters:
Other - Pointer to the path to copy data from [INPUTS] StartSlot - The slot in the path to start copying from NumSlots - The number of slots to copy
Returns:
TRUE if the data was copied OK, FALSE if it failed

Definition at line 6679 of file paths.cpp.

06680 {
06681     // Make sure that there is room in the path to store this extra info
06682     if (UnUsedSlots<NumSlots)
06683     {
06684         TRACE( _T("There was not enough room in this path to copy data into"));
06685         return FALSE;
06686     }
06687 
06688     // We need to know about the path arrays
06689     DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
06690     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
06691     PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
06692 
06693     // and the new path
06694     DocCoord*  OtherCoords = (DocCoord*)  DescribeHandle(Other->CoordHandle);
06695     PathFlags* OtherFlags  = (PathFlags*) DescribeHandle(Other->FlagsHandle);
06696     PathVerb*  OtherVerbs  = (PathVerb*)  DescribeHandle(Other->VerbHandle);
06697 
06698     // Go though and copy all the element from one path to the other
06699     for (INT32 i=StartSlot; i<StartSlot+NumSlots; i++)
06700     {
06701         ENSURE(UnUsedSlots>0, "Ran out of space in a path that should have enough space in it" );
06702         if (UnUsedSlots<=0)
06703             return FALSE;
06704 
06705         // Copy the coords
06706         Coords[UsedSlots] = OtherCoords[i];
06707         Flags[UsedSlots] = OtherFlags[i];
06708         Verbs[UsedSlots] = OtherVerbs[i];
06709 
06710         // Move on to the next slots
06711         UsedSlots++;
06712         UnUsedSlots--;
06713     }
06714 
06715     return TRUE;
06716 }

BOOL Path::IsClosed  ) 
 

Tells you whether all subpaths of this path are closed.

Author:
Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
Date:
05 April 2000
Returns:
TRUE if all subpaths are cloesd, FALSE otherwise.
Notes: This code taken from BevelHelpers::IsPathClosed() - seems more appropriate for it to live here.

See also: IsSubPathClosed

Definition at line 4758 of file paths.cpp.

04759 {
04760     INT32 StartIndex    = 0;
04761     INT32 EndIndex  = 0;
04762 
04763     // test each subpath for closure.
04764     while (StartIndex < UsedSlots)
04765     {
04766         EndIndex = StartIndex;
04767         FindEndElOfSubPath(&EndIndex);
04768 
04769         if (!IsSubPathClosed(StartIndex))
04770             return FALSE;
04771         
04772         StartIndex = EndIndex + 1;
04773     }
04774 
04775     return TRUE;
04776 }

BOOL Path::IsComplexPath  ) 
 

Tests to see if the path is a complex path (ie it has multiple sub-paths).

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/4/94
Returns:
TRUE if the Path is Complex

Definition at line 2654 of file paths.cpp.

02655 {
02656     // Get the path verbs
02657     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
02658 
02659     INT32 SubPaths = 0;
02660     for (INT32 i=0; i<UsedSlots; i++)
02661     {
02662         // Count all the MoveTos in the path
02663         if (Verbs[i] == PT_MOVETO)
02664             SubPaths++;
02665     }
02666 
02667     // Make sure that there was a moveto in this path. This should not happen
02668     ENSURE( SubPaths>0, "Path::IsComplexPath() - Found a Path with no MoveTo in it!" );
02669 
02670     // If there was only one SubPath then it is simple, otherwise it is complex
02671     if (SubPaths==1)
02672         return FALSE;
02673     else
02674         return TRUE;
02675 }

BOOL Path::IsEndPoint  ) 
 

return the IsEndPoint flag for the coordinate

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/02/94
Returns:
TRUE if this point is an EndPoint (ie Not a Bezier control point)

Definition at line 2488 of file paths.cpp.

02489 {
02490     ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsEndPoint" );
02491 
02492     // Get the flags array
02493     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02494 
02495     // and return the selected flag
02496     return Flags[CurrentPos].IsEndPoint;
02497 }

BOOL Path::IsInPath  ) 
 

Determine if the path current position is still inside the path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/02/94
Returns:
TRUE if the current position is still in the path FALSE if it has gone past the last element in the path

Definition at line 1045 of file paths.cpp.

01046 {
01047     // We are still in the path if the current position has not gone past the last valid
01048     // item in the path
01049     return ((CurrentPos>=0) && (CurrentPos<UsedSlots));
01050 }

BOOL Path::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.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/08/96
Parameters:
OtherPath,: The path with which to compare this one [INPUTS] Tolerance: The accuracy to which this path transformed to the otherPath may be considered equal.
pTransform,: A pointer to the resulting transformation matrix if the return [OUTPUTS] value is TRUE
Returns:
TRUE : this path is Isometric to the otherPath FALSE : if not Isometric or inaccuracy losses

Definition at line 10039 of file paths.cpp.

10040 {
10041     // Check path lengths for equality
10042     if (GetNumCoords() != OtherPath.GetNumCoords())
10043     {
10044         // If not equal can't possibly be the same
10045         return FALSE;
10046     }
10047     
10048     // Determine the transformation matrix from the first three coords
10049     DocCoord*   ThisCoordArray = GetCoordArray();
10050     DocCoord*   OtherCoordArray = OtherPath.GetCoordArray();
10051 
10052     double  a, b, c, d, e, f = Tolerance;       // Matrix components
10053 
10054     // Find First Non-Colinear points
10055     INT32 First = FindNonColinear(ThisCoordArray, GetNumCoords());
10056     if (First == -1)
10057     {
10058         // this path was a straight line.
10059         // If the other one is we might be in with a chance
10060         First = FindNonColinear(OtherCoordArray, OtherPath.GetNumCoords());
10061         if (First != -1)
10062         {
10063             // Unfortunately it had a kink so it can't match
10064             return FALSE;
10065         }
10066         // Shears don't work with the following. But then I doubt they're that common
10067         DocCoord ef(- ThisCoordArray[0].x, - ThisCoordArray[0].y);
10068 
10069         DocCoord v1(ThisCoordArray[1].x - ThisCoordArray[0].x, ThisCoordArray[1].y - ThisCoordArray[0].y);
10070         DocCoord v2(OtherCoordArray[1].x - OtherCoordArray[0].x, OtherCoordArray[1].y - OtherCoordArray[0].y);
10071         double v1dotv2 = v1.x * v2.x + v1.y * v2.y;
10072         double modv1sqrd = v1.x * v1.x + v1.y * v1.y;
10073         double v1crossv2 = v1.x * v2.y - v1.y * v2.x;
10074         a = v1dotv2 / modv1sqrd;
10075         b = v1crossv2 / modv1sqrd;
10076         c = -b;
10077         d = a;
10078         e = a * (double)ef.x - b * (double)ef.y + OtherCoordArray[0].x;
10079         f = b * (double)ef.x + a * (double)ef.y + OtherCoordArray[0].y;
10080     }
10081     else
10082     {
10083         // We have three non-colinear points:
10084 
10085         /*
10086             In fact, we have:
10087                 ax00 + cy00 + e = x10
10088                 bx00 + dy00 + f = y10
10089             &
10090                 ax01 + cy01 + e = x11
10091                 bx01 + dy01 + f = y11
10092             &
10093                 ax02 + cy02 + e = x12
10094                 bx02 + dy02 + f = y12
10095 
10096             Hence need to solve 2 sets of simultaneous equations for (a,c,e) & (b,d,f)
10097         */
10098 
10099         // Try to find a solution for the a,b,e part
10100         CCVector3   x0s(ThisCoordArray[First].x, ThisCoordArray[First + 1].x, ThisCoordArray[First + 2].x);
10101         CCVector3   y0s(ThisCoordArray[First].y, ThisCoordArray[First + 1].y, ThisCoordArray[First + 2].y);
10102         CCVector3   x1s(OtherCoordArray[First].x, OtherCoordArray[First + 1].x, OtherCoordArray[First + 2].x);
10103 
10104         if (!Solve3Simultaneous(x0s, x1s, y0s, a, c, e))
10105         {
10106             return FALSE;
10107         }
10108 
10109         // Try to find a solution for the (b,d,f) part
10110         CCVector3   y1s(OtherCoordArray[First].y, OtherCoordArray[First + 1].y, OtherCoordArray[First + 2].y);
10111 
10112         if (!Solve3Simultaneous(x0s, y1s, y0s, b, d, f))
10113         {
10114             return FALSE;
10115         }
10116     }
10117 
10118     // Determine the transformation matrix from the first three coords
10119     Matrix Solution(a, b, c, d, INT32(e), INT32(f));
10120 
10121     // Check the flags & bits   
10122     PathVerb*   ThisVerbArray   = GetVerbArray();
10123     PathVerb*   OtherVerbArray  = OtherPath.GetVerbArray();
10124 
10125     INT32 lTolerance = (INT32)Tolerance;
10126     // For each remaining coordinate in this path, check we can transform to the otherPath
10127     DocCoord CurrentCoord;
10128     for (INT32 i = 0; i < GetNumCoords(); ++i)
10129     {
10130 //      Transform(ThisCoordArray[i], a, b, c, d, e, f, CurrentCoord);
10131 
10132         // Compare the flags & bits (unlikely to be different if coords same though)
10133         if (ThisVerbArray[i] != OtherVerbArray[i])
10134         {
10135             return FALSE;
10136         }
10137         CurrentCoord = ThisCoordArray[i];
10138         Solution.transform(&CurrentCoord);      
10139         if (!IsNear(CurrentCoord.x, OtherCoordArray[i].x, lTolerance) ||
10140             !IsNear(CurrentCoord.y, OtherCoordArray[i].y, lTolerance))
10141         {
10142             return FALSE;
10143         }
10144     }
10145 
10146     *pTransform = Solution;
10147 
10148     return TRUE;
10149 }

BOOL Path::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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/4/94
Parameters:
BlobRect - The rect to see if any of the endpoints are in [INPUTS]
Returns:
TRUE if the TestCoord is close to one of the endpoints

Definition at line 2563 of file paths.cpp.

02564 {
02565 #if !defined(EXCLUDE_FROM_RALPH)
02566     // Dereference a few pointers
02567     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
02568     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
02569 
02570     // Start searching all the coords for EndPoints
02571     INT32 EndSlot = UsedSlots-1;
02572     for (INT32 i=UsedSlots-1; i>=0; i--)
02573     {
02574         // Are we at the start of a sub-path yet
02575         if (Verbs[i] == PT_MOVETO)
02576         {
02577             // Is this sub path open?
02578             if ((Verbs[EndSlot] & PT_CLOSEFIGURE) == 0)
02579             {
02580                 // This is an open sub path, so test if they are close to the TestCoord
02581                 if (BlobRect.ContainsCoord(Coords[i]))
02582                 {
02583                     *SlotNum = i;
02584                     return TRUE;
02585                 }
02586 
02587                 if (BlobRect.ContainsCoord(Coords[EndSlot]))
02588                 {
02589                     *SlotNum = EndSlot;
02590                     return TRUE;
02591                 }
02592             }
02593 
02594             // That sub path did not intersect the rect, so carry on
02595             EndSlot = i-1;
02596         }
02597     }
02598 #endif
02599     // No luck, so fail
02600     return FALSE;
02601 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/2/95
Parameters:
index = index of element to check [INPUTS]
Returns:
TRUE if this index is set to either end of an open subpath

Definition at line 2617 of file paths.cpp.

02618 {
02619     // Do a quick sanity check
02620     if (index<0 || index>=UsedSlots || UsedSlots==0)
02621         return FALSE;
02622 
02623     // 0<=index<=UsedSlots-1
02624     // Dereference the verbs
02625     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
02626 
02627     // Check its not the end index
02628     INT32 end = index;
02629     FindEndElOfSubPath(&end);
02630     if (Verbs[end] & PT_CLOSEFIGURE)
02631         return FALSE;
02632 
02633     if (end==index)
02634         return TRUE;
02635 
02636     // Check for a start point
02637     return (Verbs[index]==PT_MOVETO);
02638 
02639 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
ICoord = DocCoord of point of interest (eg MouseCoord) [INPUTS] range = specifes the squared perpendicular distance away from the path forming a region inside which a ICoord is said to be 'in range'
NearElement = path index pointer of closest element to be retured [OUTPUTS] mu = element parameter of closest point to be returned
Returns:
True if ICoord is in range.

Definition at line 7065 of file paths.cpp.

07069 {
07070     double dist = SqrDistanceToPoint(ICoord, NearElement, mu);
07071 //  if (IsUserName("Jim")) TRACE( _T("Distance from path = %f\n"),dist);
07072     if (dist<0) return FALSE;                   // return false (not close to path)
07073     return (dist<range);
07074 }

BOOL Path::IsRotate  ) 
 

returns the Rotate flag for the coordinate

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
TRUE if the point has the rotate flag set, FALSE if not

Definition at line 2536 of file paths.cpp.

02537 {
02538     ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsRotate" );
02539 
02540     // Get the flags array
02541     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02542 
02543     // and return the selected flag
02544     return Flags[CurrentPos].IsRotate;
02545 }

BOOL Path::IsSelected  ) 
 

return the Selected flag for the coordinate

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
TRUE if the point is selected, FALSE if not

Definition at line 2465 of file paths.cpp.

02466 {
02467     ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsSelected" );
02468 
02469     // Get the flags array
02470     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02471 
02472     // and return the selected flag
02473     return Flags[CurrentPos].IsSelected;
02474 }

BOOL Path::IsSmooth  ) 
 

returns the Smooth flag for the Current Path Position

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Returns:
TRUE if the point is Smooth, FALSE if not

Definition at line 2512 of file paths.cpp.

02513 {
02514     ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsSmooth" );
02515 
02516     // Get the flags array
02517     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02518 
02519     // and return the selected flag
02520     return Flags[CurrentPos].IsSmooth;
02521 }

BOOL Path::IsSubPathClosed INT32  Index  ) 
 

Scans to the end of this subpath to see if it has the PT_CLOSEFIGURE flag set.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/7/94
Parameters:
Index is the index of a point in the subpath [INPUTS]
- [OUTPUTS]
Returns:
TRUE if subpath is closed, FALSE otherwise

Errors: -

See also:
-

Definition at line 4722 of file paths.cpp.

04723 {
04724     INT32 i = Index;
04725     PathVerb* Verbs = GetVerbArray();
04726     
04727     // skip through until we hit the end or a MoveTo
04728     do
04729     {
04730         i++;
04731     } while (i<UsedSlots && Verbs[i] != PT_MOVETO);
04732 
04733     // i points to the firsy element after this subpath (i.e. the top of the subpath)
04734     // Check the CloseFigure flag on the previous element to see if the subpath is closed
04735     if (Verbs[i-1] & PT_CLOSEFIGURE)
04736         return TRUE;
04737     return FALSE;
04738 }

BOOL Path::IsSubSelection  ) 
 

determine if the path has a subselection

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/4/94
Returns:
TRUE if any of the paths coords were selected

Definition at line 3684 of file paths.cpp.

03685 {
03686     // We need to find all the selected control points in the path and de-select them
03687     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
03688 
03689     // look for a selected coord
03690     for (INT32 i=0; i<UsedSlots; i++)
03691     {
03692         // if we find one then return TRUE
03693         if (Flags[i].IsSelected)
03694             return TRUE;
03695     }
03696 
03697     // we did not find one, so return FALSE
03698     return FALSE;
03699 }

BOOL Path::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.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/10/94
Parameters:
OtherPath is the path which we're joining to this one [INPUTS] MainIndex is the index of the point in this path we're joining OtherIndex is the index of the point in the other path we're joining to
- [OUTPUTS]
Returns:
TRUE if successful, FALSE otherwise

Errors: Returns FALSE if it failed (lack of memory, for example)

See also:
-

Definition at line 6164 of file paths.cpp.

06165 {
06166     // First, get some indices pointing at the start and end of these subpaths
06167     INT32 MainSubStart;         // Start of subpath in main path (this)
06168     INT32 MainSubEnd;           // End of subpath in this path
06169     INT32 OtherSubStart;            // Start of subpath in other path
06170     INT32 OtherSubEnd;          // End of subpath in other path
06171 
06172     MainSubStart = MainSubEnd = MainIndex;
06173     FindStartOfSubPath(&MainSubStart);      
06174     FindEndElOfSubPath(&MainSubEnd);
06175 
06176     OtherSubStart = OtherSubEnd = OtherIndex;
06177     OtherPath->FindStartOfSubPath(&OtherSubStart);
06178     OtherPath->FindEndElOfSubPath(&OtherSubEnd);
06179 
06180     ERROR2IF(((this == OtherPath) && (MainSubStart == OtherSubStart)), FALSE, "Attempted to join this subpath with itself");
06181 
06182     // Because we'll be messing around with the path, it's easier if we make the
06183     // two indices relative to the starts of their respective subpaths
06184     MainIndex = MainIndex - MainSubStart;
06185     OtherIndex = OtherIndex - OtherSubStart;
06186 
06187     // Now that we know which subpaths we're interested in, let's see if we have to join the two paths
06188 
06189     if (this != OtherPath)
06190     {
06191         // OtherPath is not the same, so copy it into this one and adjust the subpath indices
06192         OtherSubStart += UsedSlots;
06193         OtherSubEnd += UsedSlots;
06194         //OtherIndex += UsedSlots;
06195         if (!MergeTwoPaths(*OtherPath))
06196             return FALSE;
06197     }
06198 
06199     // Now this path contains both subpaths (and others, maybe)
06200     // If the subpaths were originally in the same path, it's possible that the other subpath
06201     // is below the main subpath. We don't want that possibility, so swap them if that's the case
06202     if (OtherSubStart < MainSubStart)
06203     {
06204         INT32 temp = OtherSubStart;
06205         OtherSubStart = MainSubStart;
06206         MainSubStart = temp;
06207         temp = OtherSubEnd;
06208         OtherSubEnd = MainSubEnd;
06209         MainSubEnd = temp;
06210         temp = OtherIndex;
06211         OtherIndex = MainIndex;
06212         MainIndex = temp;
06213     }
06214 
06215     // See if the two subpaths are adjacent now
06216     if (OtherSubStart - MainSubEnd >1)
06217     {
06218         // The two subpaths are not adjacent, so let's shuffle the path around...
06219         // It's just possible that the Othersection might be at the top of the path so move the
06220         // main section to the top.
06221         CurrentPos = UsedSlots;
06222         if (!MakeSpaceInPath(MainSubEnd-MainSubStart+1))
06223             return FALSE;
06224         if (!InsertSectionAtEnd(this, MainSubStart, MainSubEnd-MainSubStart+1))
06225             return FALSE;
06226         DeleteSection( MainSubStart, MainSubEnd-MainSubStart+1);
06227 
06228         // Recalculate the subpath indices
06229         MainSubEnd = MainSubEnd-MainSubStart+1;     // Change into length
06230         MainSubStart = UsedSlots - MainSubEnd;
06231         OtherSubStart -= MainSubEnd;
06232         OtherSubEnd -= MainSubEnd;
06233         MainSubEnd = UsedSlots-1;
06234 
06235         // Now, are the subpaths adjacent? Main is now above Other
06236         if (MainSubStart - OtherSubEnd > 1)
06237         {
06238             // Do the same as above, but with Other instead of Main
06239             CurrentPos = UsedSlots;
06240             if (!MakeSpaceInPath(OtherSubEnd-OtherSubStart+1))
06241                 return FALSE;
06242             if (!InsertSectionAtEnd(this, OtherSubStart, OtherSubEnd-OtherSubStart+1))
06243                 return FALSE;
06244             DeleteSection( OtherSubStart, OtherSubEnd-OtherSubStart+1);
06245 
06246             // Recalculate the subpath indices
06247             OtherSubEnd = OtherSubEnd-OtherSubStart+1;      // Change into length
06248             OtherSubStart = UsedSlots - OtherSubEnd;
06249             MainSubStart -= OtherSubEnd;
06250             MainSubEnd -= OtherSubEnd;
06251             OtherSubEnd = UsedSlots-1;
06252 
06253 
06254         }
06255         
06256         if (OtherSubStart < MainSubStart)
06257         {
06258             // Swap Main and Other indices
06259             INT32 temp = MainSubStart;
06260             MainSubStart = OtherSubStart;
06261             OtherSubStart = temp;
06262             temp = MainSubEnd;
06263             MainSubEnd = OtherSubEnd;
06264             OtherSubEnd = temp;
06265             temp = OtherIndex;
06266             OtherIndex = MainIndex;
06267             MainIndex = temp;
06268         }
06269     }
06270 
06271     // Now we are guaranteed that the two subpaths are adjacent and that Main is below Other
06272     // Let's see if we have to reverse anything
06273     MainIndex+=MainSubStart;
06274     OtherIndex+=OtherSubStart;
06275 
06276     if (MainIndex == MainSubStart)
06277     {
06278         // Because Main is below Other, this means we have to reverse this subpath...
06279         ReverseSection(MainSubStart, MainSubEnd-MainSubStart+1);
06280         MainIndex = MainSubEnd;
06281     }
06282 
06283     if (OtherIndex == OtherSubEnd)
06284     {
06285         // We have to reverse the other subpath
06286         ReverseSection(OtherSubStart, OtherSubEnd-OtherSubStart+1);
06287         OtherIndex = OtherSubStart;
06288     }
06289 
06290     // At INT32 last, it's possible just to join the subpaths - we do this by deleting the
06291     // MoveTo between them.
06292     DeleteSection(OtherSubStart,1);
06293 
06294     // And clear selection, then select just the point we want
06295     ClearSubSelection();
06296     PathVerb* Verbs = GetVerbArray();
06297     PathFlags* Flags = GetFlagArray();
06298     Flags[MainSubEnd].IsSelected = TRUE;
06299     if (Verbs[MainSubEnd] == PT_BEZIERTO)
06300         Flags[MainSubEnd-1].IsSelected = TRUE;
06301     if (Verbs[MainSubEnd+1] == PT_BEZIERTO)
06302         Flags[MainSubEnd+1].IsSelected = TRUE;
06303 
06304     return TRUE;
06305 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/10/94
Parameters:
Start = Position within this path to copy data from [INPUTS] Length = Number of items to copy pDestin = pointer to path to put copied section in.
Returns:
TRUE if the copy was a success, FALSE if it failed (lack of memory)

Definition at line 7716 of file paths.cpp.

07717 {
07718     // Validate the input params
07719     ERROR3IF(Start>(UsedSlots-1),"MakePathFromSection given an illegal start index");
07720     if (Start > (UsedSlots-1))
07721         return FALSE;
07722 
07723     ERROR3IF((Start+Length)>UsedSlots,"MakePathFromSection given an illegal Length");
07724     if ((Start+Length) > UsedSlots)
07725         return FALSE;
07726 
07727 //  PathVerb* SourceVerbs = GetVerbArray();
07728 
07729     BOOL ok = MergeSectionTo(Start, Length, pDestin, 0);
07730     if (ok)
07731     {
07732         PathVerb* pDestinVerbs = pDestin->GetVerbArray();
07733         pDestinVerbs[0] = PT_MOVETO;
07734     }
07735     return ok;
07736 }

BOOL Path::MakePathFromSubPath const INT32  lSubpathIndex,
Path ppthToFill
 

Makes a subpath into a path in its own right.

> BOOL Path::MakePathFromSubPath(const INT32 lSubpathIndex, Path* ppthToFill)

Author:
Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/5/97 - Enough is enough
Parameters:
lSubpathIndex Index of the subpath to copy - that is, [INPUTS] 0 copies the first subpath 1 copies the second etc ppthToFill Path to copy the subpath into
ppthToFill [OUTPUTS]
Returns:
TRUE if there were no problems
See also:
Imagemap::DrawPathToOutputDevice()

Definition at line 10230 of file paths.cpp.

10231 {
10232     //Check our variables
10233     ERROR2IF(ppthToFill==NULL,FALSE, "Path::MakePathFromSubPath - null parameter");
10234     ERROR2IF(lSubpathIndex>(GetNumSubpaths()-1),FALSE, "Path::MakePathFromSubPath - null parameter");
10235 
10236     //First we must find the start and end of the subpath
10237 
10238     //This variable will find the start of the subpath
10239     INT32 lStart=0;
10240 
10241     //For each subpath we must skip over
10242     for (INT32 l=0; l<lSubpathIndex; l++)
10243     {
10244         //Move to the end of the current subpath
10245         FindEndElOfSubPath(&lStart);
10246 
10247         //Move on one place to take us into the next subpath
10248         lStart++;
10249 
10250         //And if we haven't overshot the end of the path
10251         if (lStart<GetNumCoords())
10252         {
10253             //Move to the beginning of that subpath
10254             FindStartOfSubPath(&lStart);
10255         }
10256     }
10257 
10258     //If we have overshot the end of the path, return FALSE
10259     ERROR2IF(lStart>GetNumCoords(),FALSE, "Path::MakePathFromSubPath failed");
10260 
10261     //lLookPos is now pointing to the start of the subpath we want to copy
10262     //This variable will find the end of that subpath
10263     INT32 lEnd=lStart;
10264 
10265     //And move it to the end of the subpath
10266     FindEndElOfSubPath(&lEnd);
10267 
10268     //Now, copy the subpath into the path
10269     MakePathFromSection(lStart, (lEnd-lStart+1), ppthToFill);
10270 
10271     //And return TRUE
10272     return TRUE;
10273 }

BOOL Path::MakeSpaceAtEnd INT32  NumSlots  ) 
 

Will make enough room for NumSlots unused slots at the end of the path.

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

Definition at line 3907 of file paths.cpp.

03908 {
03909     ERROR2IF(SlotAllocSize <= 0,FALSE,"MakeSpaceAtEnd has ZERO Slot Allocation Size!");
03910     if (UnUsedSlots<NumSlots)
03911     {
03912         // Find out how many slots to ask for and make sure it is a multiple of 4
03913         INT32 SlotsNeeded = NumSlots-UnUsedSlots;
03914             SlotsNeeded = ((INT32)(SlotsNeeded/SlotAllocSize))*SlotAllocSize+SlotAllocSize;
03915             SlotsNeeded = ((SlotsNeeded+3) >> 2) << 2;
03916 
03917         // we are out of spare slots, so try to alloc some extra ones
03918         if (!IncreaseBlock(VerbHandle, sizeof(PathVerb)*SlotsNeeded))
03919             return FALSE;
03920                 
03921         if (!IncreaseBlock(CoordHandle, sizeof(DocCoord)*SlotsNeeded))
03922             return FALSE;
03923 
03924         if (!IncreaseBlock(FlagsHandle, sizeof(PathFlags)*SlotsNeeded))
03925             return FALSE;
03926 
03927         if (ExtraInfo != NULL)
03928             if (!ExtraInfo->IncreaseExtraBlocks(SlotsNeeded))
03929                 return FALSE;
03930 
03931         // Got the memory back that we asked for, so update a few vars
03932         UnUsedSlots += SlotsNeeded;
03933     }
03934     return TRUE;
03935 }

BOOL Path::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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/02/94
Parameters:
NumSlots - The number of slots you need to put your new thing in [INPUTS] Position - The position at which to put the slots
Returns:
TRUE if it was able to find the memory, FALSE if it failed

Definition at line 3883 of file paths.cpp.

03884 {
03885     if (!MakeSpaceAtEnd(NumSlots))
03886         return FALSE;
03887 
03888     return OpenGap(NumSlots,Position);
03889 }

BOOL Path::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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/02/94
Parameters:
NumSlots - The number of slots you need to put your new thing in [INPUTS]
Returns:
TRUE if it was able to find the memory, FALSE if it failed

Definition at line 3857 of file paths.cpp.

03858 {
03859     if (!MakeSpaceAtEnd(NumSlots))
03860         return FALSE;
03861 
03862     return OpenGap(NumSlots,CurrentPos);
03863 }

void Path::MapWidth ChannelIndex  Index  ) 
 

Alters the mapping of the Width Information to one of the ExtraInfo channels.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/06/94
Returns:
-

Definition at line 8313 of file paths.cpp.

08314 {
08315     ENSURE(Index <= NUMEXTRACHANNELS, "Index out of range in MapWidth()");
08316 
08317     ExtraInfo->MapWidthInfo(Index);
08318 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/10/94
Parameters:
DestinPos = Index of where to copy path elements to [INPUTS] All existing items from this index onwards will move up. Source = Object to take elements from SourcePos = Position in source to start copying elements from Length = Number of elements to copy over
Returns:
TRUE if the merge was a success, FALSE if it failed (lack of memory)

Definition at line 6061 of file paths.cpp.

06062 {
06063 
06064     // Make space to copy all the data from the other path into this one
06065     CurrentPos = DestinPos;
06066     if (!MakeSpaceInPath(Length))
06067         // Failed to get extra memory
06068         return FALSE;
06069 
06070     // We will need all the arrays for both paths
06071     DocCoord*  DCoords = (DocCoord*)  DescribeHandle(CoordHandle);
06072     PathFlags* DFlags  = (PathFlags*) DescribeHandle(FlagsHandle);
06073     PathVerb*  DVerbs  = (PathVerb*)  DescribeHandle(VerbHandle);
06074     
06075     DocCoord*  SCoords = (DocCoord*)  DescribeHandle(Source.CoordHandle);
06076     PathFlags* SFlags  = (PathFlags*) DescribeHandle(Source.FlagsHandle);
06077     PathVerb*  SVerbs  = (PathVerb*)  DescribeHandle(Source.VerbHandle);
06078 
06079     // Copy all the data
06080     memmove((void*)(DCoords+DestinPos), (void*)(SCoords+SourcePos), Length*sizeof(DocCoord));
06081     memmove((void*)(DVerbs+DestinPos),  (void*)(SVerbs+SourcePos),  Length*sizeof(PathVerb));
06082     memmove((void*)(DFlags+DestinPos),  (void*)(SFlags+SourcePos),  Length*sizeof(PathFlags));
06083 
06084     UsedSlots+=Length;
06085     UnUsedSlots-=Length;
06086 
06087     // and say that it worked
06088     return TRUE;
06089 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/10/94
Parameters:
SourcePos = Position within this path to copy data from [INPUTS] Length = Number of items to copy Destin = Pointer to path to copy items to DestinPos = Position in destin path top copy data to All existing items from this index and beyond will move up
Returns:
TRUE if the copy was a success, FALSE if it failed (lack of memory)

Definition at line 6110 of file paths.cpp.

06111 {
06112     // Make space to copy all the data this path to the destination
06113 
06114     Destin->CurrentPos = DestinPos;
06115     if (!Destin->MakeSpaceInPath(Length))
06116         // Failed to get extra memory
06117         return FALSE;
06118 
06119     // We will need all the arrays for both paths
06120     DocCoord*  SCoords = (DocCoord*)  DescribeHandle(CoordHandle);
06121     PathFlags* SFlags  = (PathFlags*) DescribeHandle(FlagsHandle);
06122     PathVerb*  SVerbs  = (PathVerb*)  DescribeHandle(VerbHandle);
06123     
06124     DocCoord*  DCoords = (DocCoord*)  DescribeHandle(Destin->CoordHandle);
06125     PathFlags* DFlags  = (PathFlags*) DescribeHandle(Destin->FlagsHandle);
06126     PathVerb*  DVerbs  = (PathVerb*)  DescribeHandle(Destin->VerbHandle);
06127 
06128     // Copy all the data
06129     memmove((void*)(DCoords+DestinPos), (void*)(SCoords+SourcePos), Length*sizeof(DocCoord));
06130     memmove((void*)(DVerbs+DestinPos),  (void*)(SVerbs+SourcePos),  Length*sizeof(PathVerb));
06131     memmove((void*)(DFlags+DestinPos),  (void*)(SFlags+SourcePos),  Length*sizeof(PathFlags));
06132 
06133     Destin->UsedSlots+=Length;
06134     Destin->UnUsedSlots-=Length;
06135 
06136     // and say that it worked
06137     return TRUE;
06138 }

BOOL Path::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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> (Split from Path& varient by Markn 22/11/94)
Date:
27/4/94
Parameters:
OtherCoords = ptr to a coords array [INPUTS] OtherVerbs = ptr to a verbs array OtherFlags = ptr to a flags array Length = the number of elements in the three arrays Filled = TRUE if the arrays represent a filled path
Returns:
TRUE if the merge was a success, FALSE if it failed (lack of memory)

Definition at line 5340 of file paths.cpp.

05341 {
05342     // Do we have enough room?
05343     if (UnUsedSlots < Length)
05344         return FALSE;
05345 
05346     // We will need all the arrays for both paths
05347     DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
05348     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
05349     PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
05350     
05351     // Copy all the data
05352     INT32 DestPos = UsedSlots;
05353     for (INT32 i=0; i<Length; i++)
05354     {
05355         // Copy this coord and its associated data
05356         Coords[DestPos] = OtherCoords[i];
05357         Flags[DestPos]  = OtherFlags[i];
05358         Verbs[DestPos]  = OtherVerbs[i];
05359 
05360         // move to the next position
05361         DestPos++;
05362         UsedSlots++;
05363         UnUsedSlots--;
05364     }
05365 
05366     // If the other path was closed and marked as filled, then
05367     // the new path should also be filled
05368     if (Filled)
05369         IsFilled = TRUE;
05370 
05371     // Put current pos to the end of the used slots
05372     CurrentPos = UsedSlots;
05373 
05374     // and say that it worked
05375     return TRUE;
05376 }

BOOL Path::MergeTwoPaths const Path Other  ) 
 

Combines the two paths into a single complex path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> (Split to arrays varient by Markn 22/11/94)
Date:
27/4/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 5309 of file paths.cpp.

05310 {
05311     // Make space to copy all the data from the other path into this one
05312     CurrentPos = UsedSlots;
05313     if (!MakeSpaceInPath(Other.UsedSlots))
05314         return FALSE;
05315 
05316     DocCoord*  OtherCoords = (DocCoord*)  DescribeHandle(Other.CoordHandle);
05317     PathVerb*  OtherVerbs  = (PathVerb*)  DescribeHandle(Other.VerbHandle);
05318     PathFlags* OtherFlags  = (PathFlags*) DescribeHandle(Other.FlagsHandle);
05319 
05320     return MergeTwoPaths(OtherCoords,OtherVerbs,OtherFlags,Other.UsedSlots,Other.IsFilled);
05321 }

void Path::NextExtraInfo  )  [inline]
 

Definition at line 525 of file paths.h.

00525 { ExtraInfo->Next(); }

INT32 Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> (& Markn)
Date:
4/9/94
Parameters:
[INPUTS] 
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 9268 of file paths.cpp.

09269 {
09270     // New implementation by Markn 15/2/95
09271     // This version will return 2 when there's a selected point in the middle of a line.  The old code
09272     // returned 1 in this case
09273 
09274     INT32 Index = -1;
09275     INT32 EndIndex = -1;
09276     INT32 LastEndIndex = -1;
09277     INT32 NumSplinters = 0;
09278     BOOL SubPathOpen;
09279 
09280     PathVerb* pVerbs = GetVerbArray();
09281 
09282     while (Index++, FindNextSelected(&Index))
09283     {
09284         PathVerb Verb = pVerbs[Index] & ~PT_CLOSEFIGURE;
09285 
09286         // Ignore selected moveto elements
09287         if (Verb == PT_MOVETO)
09288             continue;
09289 
09290         EndIndex = Index;
09291         FindEndElOfSubPath(&EndIndex);  // returns index of last element in this subpath/path
09292         SubPathOpen = !(pVerbs[EndIndex] & PT_CLOSEFIGURE);
09293 
09294         // ignore selected end points when the subpath is open
09295         if (Index == EndIndex && SubPathOpen)
09296             continue;
09297 
09298         NumSplinters++;
09299 
09300         if (EndIndex != LastEndIndex)
09301         {
09302             LastEndIndex = EndIndex;
09303 
09304             // if we have found a selected point in the middle of an open subpath
09305             // an extra splinter will be produced.
09306             if (SubPathOpen)
09307                 NumSplinters++;
09308         }
09309     }
09310 
09311     return NumSplinters;
09312 
09313 /*
09314     // Get array of verbs
09315     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
09316 
09317     // p,q indexes to selected point and endof(sub)path
09318     // vp,vq local verb holders
09319 
09320     INT32 p = -1;
09321     INT32 q = -1;
09322     PathVerb vp;
09323     PathVerb vq;
09324 
09325     INT32 splinters = 0;
09326     while (p++, FindNextSelected(&p))
09327     {
09328         q = p;
09329 
09330         FindEndElOfSubPath(&q);                         // returns index of last element in this subpath/path
09331         if (p>q) break;                                 // just a quick check on sanity.
09332 
09333         if (p==q)
09334         {
09335             if (!(Verbs[p] & PT_CLOSEFIGURE)) continue; // ignore selected points at end of open subpaths
09336         }   
09337 
09338         vp = (Verbs[p] & ~PT_CLOSEFIGURE);
09339         vq = (Verbs[q]);
09340 
09341         if (vp==PT_MOVETO)
09342         {
09343             if (!(vq & PT_CLOSEFIGURE))                 // is this sub path already open?
09344             {
09345                 p++;                                    // move forward past moveto
09346                 continue;                               // continue do loop
09347             }
09348         }
09349 
09350         if ((vp == PT_MOVETO) || (vp == PT_LINETO) || (vp == PT_BEZIERTO))
09351             splinters++;
09352     }   
09353 
09354     return splinters;
09355 */
09356 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/02/94
Parameters:
NumSlots = The size of the gap to open [INPUTS] Position = The index at which to open the gap (0...UsedSlots)
Returns:
TRUE if it was able to open the gap FALSE if it failed

Definition at line 3976 of file paths.cpp.

03977 {
03978     if (UnUsedSlots<NumSlots)
03979     {          
03980         ERROR3("Path::OpenGap() overflow: Gap request is too large");
03981         return FALSE;
03982     }
03983 
03984     if (Position<0 || Position>UsedSlots)
03985     {
03986         ERROR3("Path::OpenGap() called with an illegal gap position");
03987         return FALSE;
03988     }
03989 
03990     INT32 SlotsToMove = UsedSlots-Position;
03991 
03992     if (SlotsToMove>0)
03993     {
03994         PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
03995         memmove( (void*)(&Verbs[Position+NumSlots]), (void*)(&Verbs[Position]), SlotsToMove*sizeof(PathVerb) );
03996 
03997         DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
03998         memmove( (void*)&Coords[Position+NumSlots], (void*)&Coords[Position], SlotsToMove*sizeof(DocCoord) );
03999 
04000         PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
04001         memmove( (void*)&Flags[Position+NumSlots], (void*)&Flags[Position], SlotsToMove*sizeof(PathFlags) );
04002 
04003         if (ExtraInfo != NULL)
04004             ExtraInfo->ShiftUpExtraInfo(Position, NumSlots, SlotsToMove);
04005     }
04006 
04007     return TRUE;
04008 }

BOOL Path::OpenGap INT32  NumSlots  ) 
 

Will open a gap of NumSlots size in this path. The gap is positioned at CurrentPos (A path class variable).

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/02/94
Parameters:
NumSlots - The size of the gap to open [INPUTS]
Returns:
TRUE if it was able to find the memory, FALSE if it failed

Definition at line 3951 of file paths.cpp.

03952 {
03953     return OpenGap(NumSlots, CurrentPos);
03954 }

BOOL Path::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.

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
Returns:
TRUE if a match was found, FALSE if not
Since this routine requires maths beyond that of which I am capable, it returns FALSE at the moment

Definition at line 7163 of file paths.cpp.

07164 {
07165 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARLIB)
07166 /*
07167     double d;
07168     INT32 Near;
07169     double Param;
07170 
07171     d = SqrDistanceToPoint(pos, &Near, &Param);
07172 
07173     TRACE( _T("Index=%d\n"),Near);
07174 
07175     DocCoord coord;
07176     coord = ClosestPointTo(Param, Near);
07177 
07178     TRACE( _T("x=%d, y=%d\n"),coord.x,coord.y);
07179 
07180  */
07181 
07182     DocRect temp;
07183     GetApplication()->GetBlobManager()->GetBlobRect(DocCoord(0,0),&temp);
07184     double mu;
07185     INT32 width = (temp.Width())/2; 
07186     return (IsPointCloseTo(pos, width*width, position, &mu));
07187 
07188 //  return(FALSE);
07189 #else
07190     return FALSE;
07191 #endif
07192 }

BOOL Path::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.

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

Definition at line 7827 of file paths.cpp.

07828 {
07829     // when flattening, flatten curves but dont quantise lines
07830     ProcessFlags QuantFlags(TRUE,TRUE);
07831     return CreateFlatPath(QuantFlags, threshold, pOutput);
07832 }

void Path::RenderPathBlobs RenderRegion pRender  ) 
 

Draws all the selection blobs for a path. Useful for putting the blobs on or taking them back off again.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> (split from pSpread varient by Markn)
Date:
9/11/94
Parameters:
pRender - The render region to draw into [INPUTS]

Definition at line 3001 of file paths.cpp.

03002 {
03003 #if !defined(EXCLUDE_FROM_RALPH)
03004     // Dereference the pointers
03005     DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
03006     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
03007     PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
03008 
03009     BOOL PrevIsEndPoint;
03010     DocCoord StartCoord = Coords[0];
03011 
03012     // loop through the path and render each of the blobs
03013     INT32 endcount = 0;     // Count the number of selected endpoints
03014     INT32 EndPtIndex = 0;   // Index of only selected endpoint
03015     for (INT32 i=0; i<UsedSlots; i++)
03016     {
03017         if (Flags[i].IsEndPoint)
03018         {
03019             // Render a blob
03020             if (!((Verbs[i] & PT_CLOSEFIGURE) && Coords[i]==StartCoord))
03021             {
03022                 DrawBlob(pRender, Coords[i], Flags[i].IsSelected);
03023                 // count the number of selected endpoints
03024                 if (Flags[i].IsSelected)
03025                 {
03026                     EndPtIndex = i;
03027                     endcount++;
03028                 }
03029             }
03030             //GdiFlush();
03031             PrevIsEndPoint = TRUE;
03032             if (Verbs[i] == PT_MOVETO)
03033                 StartCoord = Coords[i];
03034         }
03035     }
03036     // Now render the control point blobs if there was just one selected endpoint
03037     if (endcount == 1)
03038     {
03039         RenderPathControlBlobs(pRender, EndPtIndex);
03040     }
03041 #endif
03042 }

void Path::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).

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/02/94
Parameters:
pSpread - spread to render into [INPUTS]

Definition at line 2974 of file paths.cpp.

02975 {
02976 #if !defined(EXCLUDE_FROM_RALPH)
02977     // Go into a RenderOnTop loop
02978     RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
02979     while (pRender!=NULL)
02980     {
02981         RenderPathBlobs(pRender);
02982         pRender = DocView::GetNextOnTop(NULL);
02983     }
02984 #endif
02985 }

void Path::RenderPathControlBlobs RenderRegion pRender,
INT32  EndPtIndex
 

Draws all the control points selection blobs for a path. Used by RenderPathBlobs and also the Bezier tool.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> (from Rik Code - split from pSpread varient by Markn)
Date:
9/11/94
Parameters:
pRender = ptr to render region to render into [INPUTS] EndPtIndex - the index of the endpoint around which the control points are to be rendered.

Definition at line 3216 of file paths.cpp.

03217 {
03218 #if !defined(EXCLUDE_FROM_RALPH)
03219     // Dereference the pointers
03220     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
03221 //  PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
03222 
03223     // Render the appropriate control points
03224     // We render the two control points adjacent to the only
03225     // selected endpoint, but we also render the two control points beyond 
03226     // those, because their positions might affect the curve.
03227     // A special case is when we have a closed path containing 
03228     // only a moveto and a curveto (it could happen) in which case
03229     // we'll have to spot that, and only render two controls instead
03230     // of four
03231 
03232     // find the index of the previous ctrl point of this endpoint
03233     INT32 i = FindPrevControlPoint(EndPtIndex);
03234     if (i>=0)
03235     {
03236         DrawControlBlob(pRender, Coords[i]);
03237         DrawControlLine(pRender, Coords[i], Coords[EndPtIndex]);
03238         DrawControlBlob(pRender, Coords[i-1]);
03239         DrawControlLine(pRender, Coords[i-1], Coords[i-2]);
03240     }
03241 
03242     // now do the next control point. Don't render if the next
03243     // is still part of the same path
03244     INT32 j = FindNextControlPoint(EndPtIndex);
03245     if (j>=0 && j!=i-1)
03246     {
03247         DrawControlBlob(pRender, Coords[j]);
03248         DrawControlLine(pRender, Coords[j], Coords[EndPtIndex]);
03249 
03250         DrawControlBlob(pRender, Coords[j+1]);
03251         DrawControlLine(pRender, Coords[j+1], Coords[j+2]);
03252     }
03253 #endif
03254 }

void Path::RenderPathControlBlobs Spread pSpread,
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.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> (from Rik Code)
Date:
19/10/94
Parameters:
pSpread - pointer to the spread containing the path [INPUTS] EndPtIndex - the index of the endpoint around which the control points are to be rendered.

Definition at line 3187 of file paths.cpp.

03188 {
03189 #if !defined(EXCLUDE_FROM_RALPH)
03190     // Go into a RenderOnTop loop
03191     RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
03192     while (pRender!=NULL)
03193     {
03194         RenderPathControlBlobs(pRender,EndPtIndex);     
03195         pRender = DocView::GetNextOnTop(NULL);
03196     }
03197 #endif
03198 }

void Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> (via Rik)
Date:
28/09/94
Parameters:
pRegion - The render region to draw into [INPUTS]

Definition at line 3298 of file paths.cpp.

03299 {
03300 #if !defined(EXCLUDE_FROM_RALPH)
03301     // Dereference the pointers
03302     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
03303     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
03304     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
03305 
03306     DocCoord StartCoord = Coords[0];
03307     INT32 SelEndPts = 0;
03308 
03309     // loop through the path and render each of the blobs
03310     INT32 EndPtIndex = 0;   // Index of only selected endpoint
03311     INT32 i;
03312     for (i=0; i<UsedSlots; i++)
03313     {
03314         if (Flags[i].IsEndPoint)
03315         {
03316             // Render a blob
03317             if (!((Verbs[i] & PT_CLOSEFIGURE) && Coords[i]==StartCoord))
03318             {
03319                 DrawBlob(pRegion, Coords[i], Flags[i].IsSelected);
03320                 // count the number of selected endpoints
03321                 if (Flags[i].IsSelected)
03322                 {
03323                     EndPtIndex = i;
03324                     SelEndPts++;
03325                 }
03326             }
03327             if (Verbs[i] == PT_MOVETO)
03328                 StartCoord = Coords[i];
03329         }
03330     }
03331 
03332     // now make sure the correct control handles are drawn
03333     if (SelEndPts == 1)
03334     {
03335         if (Flags[EndPtIndex].IsRotate && IsOpenEnd(EndPtIndex))
03336         { 
03337             if (Verbs[EndPtIndex] == PT_MOVETO)
03338                 i = FindNextControlPoint(EndPtIndex);
03339             else
03340                 i = FindPrevControlPoint(EndPtIndex);
03341 
03342             if (i>=0)
03343             {
03344                 DocCoord GhostPt;
03345                 GhostPt.x = Coords[EndPtIndex].x - (Coords[i].x - Coords[EndPtIndex].x);
03346                 GhostPt.y = Coords[EndPtIndex].y - (Coords[i].y - Coords[EndPtIndex].y);
03347 
03348                 pRegion -> SetLineColour(COLOUR_BEZIERLINE);
03349                 pRegion -> SetFillColour(COLOUR_TRANS);
03350                 pRegion -> DrawLine(GhostPt, Coords[i]);
03351 
03352                 pRegion -> SetLineColour(COLOUR_TRANS);
03353                 pRegion -> SetFillColour(COLOUR_UNSELECTEDBLOB);
03354                 pRegion -> DrawBlob(GhostPt, BT_UNSELECTED);
03355                 pRegion -> DrawBlob(Coords[i], BT_UNSELECTED);
03356             }
03357         }
03358     }
03359 #endif
03360 }

void Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/09/94
Parameters:
pSpread - The render spread to draw into [INPUTS]

Definition at line 3272 of file paths.cpp.

03273 {
03274 #if !defined(EXCLUDE_FROM_RALPH)
03275     // Go into a RenderOnTop loop
03276     RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
03277     while (pRender!=NULL)
03278     {
03279         RenderPathPenBlobs(pRender);
03280         pRender = DocView::GetNextOnTop(NULL);
03281     }
03282 #endif
03283 }

void Path::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.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/5/95
Parameters:
pSpread - pointer to the spread containing the path [INPUTS] pRender - pointer to region to render into
See also:
Path::RenderPathSelectedControlBlobs

Definition at line 3097 of file paths.cpp.

03098 {
03099 #if !defined(EXCLUDE_FROM_RALPH)
03100     ERROR3IF(pSpread == NULL, "pSpread was NULL");
03101     ERROR3IF(pRender == NULL, "pRender was NULL");
03102     if ((pRender == NULL) || (pSpread == NULL))
03103         return ;
03104 
03105     // loop through the path and count the selected blobs
03106     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
03107     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
03108     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
03109     const INT32 NumCoords = GetNumCoords();
03110     INT32 endcount = 0;     // Count the number of selected endpoints
03111     INT32 EndPtIndex = 0;   // Index of only selected endpoint
03112     for (INT32 i=0; i<NumCoords; i++)
03113     {
03114         if (Flags[i].IsEndPoint && Flags[i].IsSelected)
03115         {
03116             if (!(Verbs[i] & PT_CLOSEFIGURE))
03117             {
03118                 EndPtIndex = i;
03119                 endcount++;
03120                 DrawBlob(pRender, Coords[i], TRUE);
03121                 DrawBlob(pRender, Coords[i], FALSE);
03122             }
03123         }
03124     }
03125     if (endcount == 1)
03126     {
03127         // Remove the control points and lines
03128         RenderPathControlBlobs(pRender, EndPtIndex);        
03129     }
03130 #endif
03131 }

void Path::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.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/1/95
Parameters:
pSpread - pointer to the spread containing the path [INPUTS] Removing - TRUE if the blobs are being removed (ie rendered off)

Definition at line 3061 of file paths.cpp.

03062 {
03063 #if !defined(EXCLUDE_FROM_RALPH)
03064     // If removing then render on into pending render regions first
03065 //  if (Removing)
03066 //      RenderSelectedControlBlobsToPendingRegions(pSpread);
03067 
03068     // Render the blobs on the path
03069     RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
03070     while (pRender!=NULL)
03071     {
03072         RenderPathSelectedControlBlobs(pSpread, pRender);
03073         pRender = DocView::GetNextOnTop(NULL);
03074     }   
03075 
03076     // If putting back on then render back off in pender render regions
03077 //  if (!Removing)
03078 //      RenderSelectedControlBlobsToPendingRegions(pSpread);
03079 #endif
03080 }

void Path::RenderSelectedControlBlobsToPendingRegions Spread pSpread  ) 
 

Draws all the control points selection blobs for an entire path into all the pending render regions.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/5/95
Parameters:
pSpread - pointer to the spread containing the path [INPUTS]
See also:
Path::RenderPathSelectedControlBlobs

Definition at line 3147 of file paths.cpp.

03148 {
03149 #if !defined(EXCLUDE_FROM_RALPH)
03150     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
03151     if (!pRegionList->IsEmpty())
03152     {
03153         RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
03154 
03155         while (pRegion != NULL)
03156         {
03157             // Check the RenderRegion is for the same spread.
03158             if (pRegion->GetRenderSpread() == pSpread)
03159             {
03160                 // Render the blobs into this Render Region.
03161                 RenderPathSelectedControlBlobs(pSpread, pRegion);
03162             }
03163 
03164             // Get the Next render region
03165             pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
03166         }
03167     }
03168 #endif
03169 }

BOOL Path::RetroReplaceSection INT32  StartSlot,
INT32  Len,
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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/5/94
Parameters:
StartSlot - The slot to start replacing from [INPUTS] NumSlots - The number of slots to replace NewPath - The new path to place in the path to replace the elements from StartSlot to StartSlot+NumSlots KeepStart - TRUE if the initial moveto of the NewPath should be pasted into the path, FALSE if you want to throw away the initial moveto.
Returns:
TRUE if it worked, FALSE if it failed (Could not alloc memory if NewPath is bigger than the section it was replacing

Definition at line 7339 of file paths.cpp.

07340 {
07341     // Saftey Checks
07342     ENSURE( StartSlot<UsedSlots, "PathPosition is off end of path in Path::RetroReplaceSection" );
07343     ENSURE( StartSlot>=0, "PathPosition is off beginning of path in Path::RetroReplaceSection" );
07344 
07345     // Make enough space in the path to copy the new path in after the marked section has been removed
07346     INT32 SlotsToAdd = NewPath->UsedSlots - Len;
07347     if (SlotsToAdd>0)
07348     {
07349         // We need more space as the new path is bigger than the gap
07350         CurrentPos = StartSlot+1;
07351         if (!MakeSpaceInPath(SlotsToAdd))
07352             // Failed to get the memory, so fail
07353             return FALSE;
07354 
07355         // Update the usage counters
07356         UsedSlots += SlotsToAdd;
07357         UnUsedSlots -= SlotsToAdd;
07358     }
07359 
07360     // Dereference the pointers
07361     PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
07362     DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
07363     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
07364 
07365     // If the section to be replaced is bigger than the new path, then we should move the end of
07366     // the path down a bit
07367     if (SlotsToAdd<0)
07368     {
07369         // Find out how much memory to move about
07370         INT32 SlotToMoveFrom = StartSlot+Len;
07371         INT32 SlotToMoveTo   = StartSlot+NewPath->UsedSlots;
07372         INT32 SlotsToMove = UsedSlots-SlotToMoveFrom;
07373 
07374         // Does it need moving
07375         if (SlotsToMove>0)
07376         {
07377             // yep, move it
07378             memmove((void*)(&Verbs[SlotToMoveTo]), (void*)(&Verbs[SlotToMoveFrom]), SlotsToMove*sizeof(PathVerb));
07379             memmove((void*)(&Flags[SlotToMoveTo]), (void*)(&Flags[SlotToMoveFrom]), SlotsToMove*sizeof(PathFlags));
07380             memmove((void*)(&Coords[SlotToMoveTo]), (void*)(&Coords[SlotToMoveFrom]), SlotsToMove*sizeof(DocCoord));
07381         }
07382 
07383         // Change the path flags (SlotsToAdd is negative in here)
07384         UsedSlots += SlotsToAdd;
07385         UnUsedSlots -= SlotsToAdd;
07386     }
07387 
07388     // Find out about the pointers to the new path
07389     PathVerb*  NewVerbs  = (PathVerb*)  DescribeHandle(NewPath->VerbHandle);
07390     DocCoord*  NewCoords = (DocCoord*)  DescribeHandle(NewPath->CoordHandle);
07391     PathFlags* NewFlags  = (PathFlags*) DescribeHandle(NewPath->FlagsHandle);
07392 
07393     // Now we have to copy NewPath into the hole
07394     INT32 ReadStart, ReadLen, WriteStart;
07395 
07396     // Work out which section we are copying
07397     if (KeepStart)
07398     {
07399         // Here we are keeping the initial moveto in the replacement path
07400         ReadStart = 0;
07401         ReadLen = NewPath->UsedSlots;
07402         WriteStart = StartSlot;
07403     }
07404     else
07405     {
07406         // Here we are throwing away the Moveto in the replacement path
07407         ReadStart = 1;
07408         ReadLen = NewPath->UsedSlots-1;
07409         WriteStart = StartSlot+1;
07410     }
07411 
07412     // Go though the path replacing all the relavent sections
07413     for (INT32 i=ReadStart; i<ReadStart+ReadLen; i++)
07414     {
07415         // Copy the data from the new path into the old path
07416         Verbs[WriteStart] = NewVerbs[i];
07417         Flags[WriteStart] = NewFlags[i];
07418         Coords[WriteStart] = NewCoords[i];
07419 
07420         // increment the destination slot
07421         WriteStart++;       
07422     }
07423 
07424     // See if this is a closed shape
07425     TryToClose();
07426 
07427     // All worked, so return happy
07428     return TRUE;
07429 }

void Path::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.

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

Definition at line 5080 of file paths.cpp.

05081 {
05082     ReverseSection(0, UsedSlots);
05083 }

void Path::ReverseSection INT32  FirstPos,
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.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/4/94
Parameters:
StartSlot - The slot in the path where the sub path begins [INPUTS]
Returns:
Errors: ENSUREs if StartSlot is not at the start of a subpath

Definition at line 5100 of file paths.cpp.

05101 {
05102     // We will need to change all the arrays
05103     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
05104     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
05105     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
05106 
05107     // First we will reverse all the Coords and their flags
05108     INT32 LastPos  = FirstPos+SubPathLen-1;
05109     INT32 Start = FirstPos;
05110     DocCoord  SwapCoord;
05111     PathFlags SwapFlag;
05112     while (FirstPos<LastPos)
05113     {
05114         // change the order of the coords in the array
05115         SwapCoord = Coords[FirstPos];
05116         Coords[FirstPos] = Coords[LastPos];
05117         Coords[LastPos]  = SwapCoord;
05118 
05119         // Change the order of the flags associated with the coord
05120         SwapFlag = Flags[FirstPos];
05121         Flags[FirstPos] = Flags[LastPos];
05122         Flags[LastPos]  = SwapFlag;
05123 
05124         // find the next two coords/flags to swap
05125         FirstPos++;
05126         LastPos--;
05127     }
05128 
05129     // Now reverse the verbs.
05130     // The first verb always stays as a MoveTo and everything else gets sorted around it
05131     FirstPos = Start+1;
05132     LastPos  = Start+SubPathLen-1;
05133     PathVerb SwapVerb;
05134     while (FirstPos<LastPos)
05135     {
05136         SwapVerb = Verbs[FirstPos];
05137         Verbs[FirstPos] = Verbs[LastPos];
05138         Verbs[LastPos]  = SwapVerb;
05139 
05140         // Find the next two verbs to swap
05141         FirstPos++;
05142         LastPos--;
05143     }
05144 
05145     // added by Ed 23/5/95 - fix up screwed up closed paths!
05146     // ie first element of subpath has PT_CLOSEFIGURE rather than last!
05147     INT32 StartOfSubPath     = Start;
05148     INT32 EndElOfLastSubPath = Start+SubPathLen-1;
05149 
05150 #ifdef _DEBUG
05151     // check assumption that we are reversing a set of complete subpaths
05152     INT32 temp=StartOfSubPath;
05153     FindStartOfSubPath(&temp);
05154     ERROR3IF(StartOfSubPath!=temp,"Path::ReverseSection() - section does not start at the start of a subpath");
05155     temp=EndElOfLastSubPath-1;
05156     FindEndElOfSubPath(&temp);
05157     ERROR3IF(EndElOfLastSubPath!=temp,"Path::ReverseSection() - section does not end at the end of a subpath");
05158 #endif
05159 
05160     // for each subpath, if the second element has an erroneous PT_CLOSEFIGURE,
05161     // move it to the end element of the subpath
05162     while (StartOfSubPath<=EndElOfLastSubPath)
05163     {
05164         INT32 EndElOfSubPath=StartOfSubPath;
05165         FindEndElOfSubPath(&EndElOfSubPath);
05166         if (Verbs[StartOfSubPath+1] & PT_CLOSEFIGURE)
05167         {
05168             Verbs[StartOfSubPath+1]&=~PT_CLOSEFIGURE;
05169             Verbs[EndElOfSubPath]  |= PT_CLOSEFIGURE;
05170         }
05171         StartOfSubPath=EndElOfSubPath+1;
05172     }
05173 
05174     return;
05175 }

void Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/09/94
Parameters:
Start = The index of the first element in the component list [INPUTS] End = The index of the last element in the component list Rotate = The number of positions to rotate left by. This may be negative, in which case the path data will be rotated right by the specified amount.
- [OUTPUTS]
Returns:
-

Definition at line 8997 of file paths.cpp.

08998 {
08999     // just make sure the start and end positions are sensible
09000 
09001     INT32 Width = End-Start+1;
09002     if (Width<2) return;
09003     Rotate = Rotate % Width;
09004     if (Rotate==0) return;
09005     if (Start<0) return;
09006     if (End>=UsedSlots) return;
09007 
09008     // make a rotate right into a rotate left
09009     if (Rotate<0) Rotate=Width-Rotate;
09010 
09011     INT32 Shift = 64;
09012     INT32 Step = Rotate/Shift;
09013     INT32 Residual = Rotate % Shift;
09014 
09015     UINT32 Size = sizeof(PathVerb);
09016     if (Size<sizeof(PathFlags)) Size=sizeof(PathFlags);
09017     if (Size<sizeof(DocCoord)) Size=sizeof(DocCoord);
09018 
09019     void* TempBuff = (void*)CCMalloc(Shift*Size);
09020 
09021     // Get arrays of flags,verbs and points.
09022     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
09023     PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle);
09024     DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
09025 
09026     if (TempBuff!=NULL)
09027     {
09028         void* Destin;
09029         void* Source;
09030         while (Step>0)
09031         {
09032             Destin = TempBuff;
09033             Source = (void*)&Flags[Start];
09034             memmove(Destin, Source, Shift*sizeof(PathFlags));
09035             Destin = (void*)&Flags[Start];
09036             Source = (void*)&Flags[Start+Shift];
09037             memmove(Destin, Source, (Width-Shift)*sizeof(PathFlags));
09038             Destin = (void*)&Flags[End-Shift+1];
09039             Source = TempBuff;
09040             memmove(Destin, Source, Shift*sizeof(PathFlags));
09041 
09042             Destin = TempBuff;
09043             Source = (void*)&Verbs[Start];
09044             memmove(Destin, Source, Shift*sizeof(PathVerb));
09045             Destin = (void*)&Verbs[Start];
09046             Source = (void*)&Verbs[Start+Shift];
09047             memmove(Destin, Source, (Width-Shift)*sizeof(PathVerb));
09048             Destin = (void*)&Verbs[End-Shift+1];
09049             Source = TempBuff;
09050             memmove(Destin, Source, Shift*sizeof(PathVerb));
09051 
09052             Destin = TempBuff;
09053             Source = (void*)&Coords[Start];
09054             memmove(Destin, Source, Shift*sizeof(DocCoord));
09055             Destin = (void*)&Coords[Start];
09056             Source = (void*)&Coords[Start+Shift];
09057             memmove(Destin, Source, (Width-Shift)*sizeof(DocCoord));
09058             Destin = (void*)&Coords[End-Shift+1];
09059             Source = TempBuff;
09060             memmove(Destin, Source, Shift*sizeof(DocCoord));
09061 
09062             Step--;
09063         }
09064         if (Residual>0)
09065         {
09066 
09067             Destin = TempBuff;
09068             Source = (void*)&Flags[Start];
09069             memmove(Destin, Source, Residual*sizeof(PathFlags));
09070             Destin = (void*)&Flags[Start];
09071             Source = (void*)&Flags[Start+Residual];
09072             memmove(Destin, Source, (Width-Residual)*sizeof(PathFlags));
09073             Destin = (void*)&Flags[End-Residual+1];
09074             Source = TempBuff;
09075             memmove(Destin, Source, Residual*sizeof(PathFlags));
09076 
09077             Destin = TempBuff;
09078             Source = (void*)&Verbs[Start];
09079             memmove(Destin, Source, Residual*sizeof(PathVerb));
09080             Destin = (void*)&Verbs[Start];
09081             Source = (void*)&Verbs[Start+Residual];
09082             memmove(Destin, Source, (Width-Residual)*sizeof(PathVerb));
09083             Destin = (void*)&Verbs[End-Residual+1];
09084             Source = TempBuff;
09085             memmove(Destin, Source, Residual*sizeof(PathVerb));
09086 
09087             Destin = TempBuff;
09088             Source = (void*)&Coords[Start];
09089             memmove(Destin, Source, Residual*sizeof(DocCoord));
09090             Destin = (void*)&Coords[Start];
09091             Source = (void*)&Coords[Start+Residual];
09092             memmove(Destin, Source, (Width-Residual)*sizeof(DocCoord));
09093             Destin = (void*)&Coords[End-Residual+1];
09094             Source = TempBuff;
09095             memmove(Destin, Source, Residual*sizeof(DocCoord));
09096 
09097         }
09098         CCFree(TempBuff);
09099     }
09100     else
09101     {
09102         PathFlags TempFlags;
09103         PathVerb TempVerb;
09104         DocCoord TempCoord;
09105 
09106         while (Rotate>0)
09107         {
09108             TempFlags = Flags[Start];
09109             TempVerb = Verbs[Start];
09110             TempCoord = Coords[Start];
09111             for (INT32 i=Start; i<End; i++)
09112             {
09113                 Flags[i] = Flags[i+1];
09114                 Verbs[i] = Verbs[i+1];
09115                 Coords[i] = Coords[i+1];
09116             }
09117             Flags[End]=TempFlags;
09118             Verbs[End]=TempVerb;
09119             Coords[End]=TempCoord;
09120             Rotate--;
09121         }
09122     }
09123 }

void Path::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.

> void Path::Scale(const DocCoord dcOrigin, const double dDPI=96.0)

Author:
Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/4/97
Parameters:
dDPI The DPI by which to scale the path [INPUTS] dcOrigin The origin by which to scale the path
This point should be the top left hand corner of the region that is used to create a bitmap.

This is used in imagemaps, to convert a path specified in the document to a polygon to specify an imagemap clickable area over a bitmap.

This function does the following to all the coordinates in the path

a. Subtracts the origin dcOrigin b. Inverts the y-axis c. Multiplies the coordinates to convert them to the number of DPI specified.

See also:
Imagemap::AddPolygon()

Definition at line 10184 of file paths.cpp.

10185 {
10186     //First find out how many coordinates we have to process
10187     INT32 lNumCoords=GetNumCoords();
10188 
10189     //And get a pointer to the array
10190     DocCoord* pdcArray=GetCoordArray();
10191 
10192     //For every coord in the array
10193     for (INT32 l=0; l<lNumCoords; l++)
10194     {
10195         //Get a pointer to the coordinate we are changing
10196         DocCoord* pdcThisCoord=&pdcArray[l];
10197 
10198         if (pdcThisCoord==NULL)
10199         {
10200             ERROR2RAW("Path::Scale - coord error");
10201             return;
10202         }
10203 
10204         //And scale it
10205         pdcThisCoord->Scale(dcOrigin, (float)dDPI);
10206     }
10207 }

void Path::SetAllSubSelection  ) 
 

Goes through the path and sets all the IsSelected flags to TRUE, also selecting all control points in the path.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/1/95

Definition at line 3663 of file paths.cpp.

03664 {
03665     PathFlags* Flags  = (PathFlags*) DescribeHandle(FlagsHandle);
03666 
03667     for (INT32 i=0; i<UsedSlots; i++)
03668         Flags[i].IsSelected = TRUE;
03669 }

void Path::SetFlags const PathFlags NewFlags  ) 
 

Sets the flags at the current path position to the flags provided.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/02/94
Parameters:
NewFlags - The flags you want to set [INPUTS]

Definition at line 2712 of file paths.cpp.

02713 {
02714     ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsEndPoint" );
02715 
02716     // Get the flags array
02717     PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
02718 
02719     // and set the flags
02720     Flags[CurrentPos] = NewFlags;
02721 }

void Path::SetPathPosition INT32  NewPos  ) 
 

Sets the current path position to the value supplied. This represents the Coord number in the path.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/02/94
Parameters:
NewPos - the Position you want to go to [INPUTS]

Definition at line 1018 of file paths.cpp.

01019 {
01020     // Set the pos to the position supplied
01021     CurrentPos = NewPos;
01022 
01023     // make sure it was in bounds
01024     if (CurrentPos>=UsedSlots)
01025         CurrentPos = UsedSlots-1;
01026 
01027     if (CurrentPos<0)
01028         CurrentPos = 0;
01029 }

BOOL Path::SimpleJoin Path Other,
INT32 *  OtherStartSlot,
BOOL *  IsOtherReversed,
BOOL *  ThisReversed = NULL
 

Joins two paths to form a new, longer path. Both the paths invloved are simple (ie not complex).

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/4/94
Parameters:
Other - the path to join with this 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
Returns:
TRUE if the Join Worked, FALSE if it failed

Definition at line 6325 of file paths.cpp.

06326 {
06327     // We have not reversed the other path yet
06328     *IsOtherReversed = FALSE;
06329 
06330     // Make a note of where the new path will start after the merge
06331     INT32 PathStart = UsedSlots;
06332     
06333     if (ThisReversed != NULL)
06334         *ThisReversed = FALSE;
06335     // Do we need to reverse any elements of this path
06336     INT32 StartSlot, NumSlots;
06337     BOOL JoinedAtStart;
06338     DocCoord*  OtherCoords = (DocCoord*)  DescribeHandle(Other->CoordHandle);
06339 
06340     // Find out if we need to reverse this path to help with the joining
06341     if (FindJoinedSubPathInfo(OtherCoords[0], &StartSlot, &NumSlots, &JoinedAtStart))
06342     {
06343         // Maybe need to reverse this path
06344         if (JoinedAtStart)
06345         {
06346             Reverse();
06347             if (ThisReversed != NULL)
06348                 *ThisReversed = TRUE;
06349         }
06350     }
06351 
06352     // And check to see if the other end needs checking as well.
06353     if (FindJoinedSubPathInfo(OtherCoords[Other->UsedSlots-1], &StartSlot, &NumSlots, &JoinedAtStart))
06354     {
06355         // Reverse the joining path always
06356         Other->Reverse();
06357 
06358         // We have reversed the other path
06359         *IsOtherReversed = TRUE;
06360 
06361         // and maybe reverse this path
06362         if (JoinedAtStart)
06363         {
06364             Reverse();
06365             if (ThisReversed != NULL)
06366                 *ThisReversed = TRUE;
06367         }
06368     }
06369     
06370     // merge the paths
06371     if (MergeTwoPaths(*Other)==FALSE)
06372         return FALSE;
06373 
06374     // Make sure that the new path starts with a MoveTo
06375     #ifdef _DEBUG
06376         PathVerb* Verbs  = (PathVerb*) DescribeHandle(VerbHandle);
06377         ENSURE( Verbs[PathStart]==PT_MOVETO, "Start of SubPath is not a MoveTo in SimpleJoin()" );
06378     #endif
06379 
06380     // The merge must have worked, so remove the initial MoveTo
06381     CurrentPos = PathStart;
06382     DeleteElement();
06383 
06384     // See if we can make it a closed path
06385     TryToClose();
06386 
06387     // report that it all worked
06388     CurrentPos = UsedSlots;
06389     *OtherStartSlot = PathStart-1;
06390     return TRUE;
06391 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/94
Parameters:
error = a double describing the max error to use when smoothing [INPUTS]
Operates on this path. the path will be smoothed meaning that it [OUTPUTS] will change in an unpredictable manner. The number of elements in the path and control point positioning will change, if TRUE is returned.
Returns:
BOOL = TRUE if the path was smoothed successfully = FALSE then consider 'this' path has been corrupted
See also:
SmoothSection

Definition at line 7768 of file paths.cpp.

07769 {
07770 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARLIB)
07771     double QuantOrder = 1024;
07772 
07773     INT32 orignumcoords = UsedSlots;
07774 
07775     // create a path and quantise to it
07776     Path QuantPath;
07777     QuantPath.Initialise(24,12);
07778 
07779     // quantise original path to QuantPath
07780     Quantise(QuantOrder, &QuantPath);
07781 
07782     // create and fit a smooth curve to the data points.
07783     CurveFitObject Smoothed(&QuantPath, error);
07784     BOOL ok = Smoothed.Initialise(&QuantPath,QuantPath.GetNumCoords());
07785 
07786     if (ok)
07787     {
07788         Smoothed.FitCurve();
07789 
07790         // now that we've smoothed the curve lets check on the number
07791         // of coordinates we've generated. If its more, then we should
07792         // leave the original path as it was. If its less then replace
07793         if (QuantPath.GetNumCoords()<orignumcoords)
07794             ok = CloneFrom(QuantPath);
07795         
07796     }
07797     return ok;
07798 #else
07799     return FALSE;
07800 #endif
07801 }

DocCoord Path::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.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/7/94
Parameters:
Index Index into this path of the control point [INPUTS] StartEndSnapped TRUE if the start of the path snaps to the end JoinedToAnother TRUE if this path joins to another one OtherIsCurve TRUE if the other path element is a curve FALSE if other path element is a line OtherCoord Coordinate of element in other path
- [OUTPUTS]
Returns:
Coordinates of the smoothed point

Errors: -

See also:
Path::SmartSmoothCurve Documentation: Implemnt.doc

Definition at line 4347 of file paths.cpp.

04352 {
04353 #if !defined(EXCLUDE_FROM_RALPH)
04354     PathVerb* Verbs = GetVerbArray();
04355     DocCoord* Coords = GetCoordArray();
04356     PathFlags* Flags = GetFlagArray();
04357 
04358     // temp vars for calculating smoothness
04359     
04360     DocCoord p;     // Endpoint opposite the control point
04361     DocCoord q;     // Endpoint directly adjacent to control point
04362     DocCoord r;     // Endpoint on same side of control point but not adjacent
04363     DocCoord ret;   // Temp for returning value
04364 
04365     // We get the parameters for the calculation from different places depending on whether we're
04366     // at the first or second control point. We know this by looking at the EndPoint flags
04367 
04368     if (Flags[Index-1].IsEndPoint)
04369     {
04370         // This is the first control point of a curve
04371 
04372 /*
04373 
04374     These are the possibilities with the control point as the first one in the curve:
04375 
04376     1: Curve/Curve
04377     ...
04378     m/l/c   p
04379     c       a
04380     c       b
04381     c       q   <- endpoint to which point is attached
04382     c       c   <- Control point we're smoothing
04383     c       d
04384     c       r   
04385     ...
04386 
04387     2: Line/Curve
04388     ...
04389     m/l/c   p
04390     l       q
04391     c       a   <- Control point we're smoothing
04392     c       b
04393     c       r
04394     ...
04395 
04396     3: Curve/Open line
04397     m       q
04398     c       a   <- control point we're smoothing
04399     c       b
04400     c       r
04401     ...
04402 
04403     4: Curve/snapping to curve at end
04404     m       q
04405     c       a   <- control point we're snapping
04406     c       b
04407     c       r
04408     ...
04409     l/c     p
04410     c       c
04411     c       d
04412     c       q
04413 
04414     5: Curve/snapping to line at end
04415     m       q
04416     c       a   <- control point we're snapping to
04417     c       b
04418     c       r
04419     ...
04420     l/c     p
04421     l       q
04422 
04423     6: Curve/snapping to curve in another path
04424     7: Curve/snapping to line in another path
04425     m       q
04426     c       a   <- control point we're smoothing
04427     c       b
04428     c       r
04429     ...
04430 
04431     point p = OtherCoord
04432 */
04433 
04434         // The position of this point depends on: The previous endpoint (which is the point
04435         // to which this control point is 'attached'), the endpoint before that one, and the 
04436         // endpoint of the bezier segment containing the control point.
04437         // point q is the endpoint of the previous element (which always exists where we want it)
04438 
04439         q = Coords[Index-1];
04440 
04441         // point r is the endpoint of this curve element - again, always there
04442 
04443         r = Coords[Index+2];
04444 
04445         // point p, on the other hand, is problematical. It might not exist at all (if the 
04446         // previous element was a MoveTo and the path is open). It might be a lineto. It 
04447         // might be a CurveTo element, which is the simplest case. Or, it might be any of 
04448         // those three elements on a completely different path. Or it might be a curve or 
04449         // a line at the opposite end of the path (if the CLOSEFIGURE flag is set or the 
04450         // StartAndEndSnapped flag is TRUE).
04451 
04452         if (Verbs[Index-1] == PT_BEZIERTO)
04453         {
04454             // Simple - p = the start of this curve (case 1)
04455             p = Coords[Index-4];
04456             CalcPointCurve(p,q,r,&ret);
04457 
04458             // Bodge inserted by Peter to fix the problem that occurs when you have a closed path
04459             // consisting of just two Bezier segments.  In this case the returned position is wrong
04460             // - it positions the control point over the opposite one - so we will just flip it around
04461             /* Commented out by Markn 17/1/95 - replaced by new bodge written by Peter
04462             if ((GetNumCoords() == 7) && StartAndEndSnapped)
04463             {
04464                 ret = q - (ret - q);
04465             }
04466             */
04467 
04468             // New version of above bodge also by Peter (put in by Markn - 17/1/95)
04469             if ((GetNumCoords() == 7) && ((Verbs[GetNumCoords()-1] & PT_CLOSEFIGURE) || StartAndEndSnapped))
04470             {
04471                 ret = q - (ret - q);
04472             }
04473             return ret;
04474         }
04475         else if (Verbs[Index-1] == PT_LINETO)
04476         {
04477             // Simple - previous is a lineto, so get its start point and calculate (case 2)
04478             p = Coords[Index-2];
04479             CalcPointLine(p,q,r,&ret);
04480             return ret;
04481         }
04482         else
04483         {
04484             
04485             // Scan along to find the end element. This we find by scanning forward until
04486             // we find a MoveTo or we go off the end. Either way, the previous element is
04487             // the one we want.
04488 
04489             INT32 i = Index;
04490             while (i<UsedSlots && Verbs[i] != PT_MOVETO)
04491                 i++;
04492             
04493             // i either points after the end of the path, or at the next MoveTo. Move to the
04494             // previous element (could be the endpoint of a curve).
04495 
04496             i--;
04497             
04498             if (StartAndEndSnapped || (Verbs[i] & PT_CLOSEFIGURE) )
04499             {
04500                 // We have to get p from the end of the subpath (cases 4 & 5)
04501                 if ((Verbs[i] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
04502                 {
04503                     // Case 4
04504                     p = Coords[i-3];
04505                     CalcPointCurve(p,q,r,&ret);
04506 
04507                     // Bodge inserted by Peter to fix the problem that occurs when you have a path consisting
04508                     // of just two Bezier segments.  In this case the returned position is wrong - it
04509                     // positions the control point over the opposite one - so we will just flip it around
04510                     if (GetNumCoords() == 7)
04511                     {
04512                         ret = q - (ret - q);
04513                     }
04514 
04515                     return ret;
04516                 }
04517                 else
04518                 {
04519                     // Case 5
04520                     p = Coords[i-1];
04521                     CalcPointLine(p,q,r,&ret);
04522                     return ret;
04523                 }
04524             }
04525             else
04526             {
04527                 // This path hasn't snapped, and isn't closed. Check if it snaps with another
04528                 if (JoinedToAnother)
04529                 {
04530                     // Cases 6 & 7
04531                     p = OtherCoord;
04532                     if (OtherIsCurve)
04533                     {
04534                         // Case 6
04535                         CalcPointCurve(p,q,r,&ret);
04536                     }
04537                     else
04538                     {
04539                         // Case 7
04540                         CalcPointLine(p,q,r,&ret);
04541                     }
04542                     return ret;
04543                 }
04544                 else
04545                 {
04546                     // There's no snapping at all, so this point has to be calculated as an endpoint
04547                     CalcPointEnd(q,r,&ret);
04548                     return ret;
04549                 }
04550             }
04551         }
04552     }
04553     else
04554     {
04555         // This is the second control point of a curve
04556 
04557 /*
04558     These are the possible situations, with sections of path data
04559 
04560     1: Curve/Curve
04561         ...
04562         m/l/c   r
04563         c       a
04564         c       b   <- Control point pointed to by Index
04565         c       q   <- this is the endpoint to which the control point is connected
04566         c       c
04567         c       d
04568         c       p
04569         ...
04570 
04571     2: Curve/Line
04572         ...
04573         m/l/c   r
04574         c       a
04575         c       b   <- Control point pointed to by Index
04576         c       q   <- this is the endpoint to which the control point is connected
04577         l       p
04578         ...
04579 
04580     3: Curve/open line
04581         ...
04582         m/l/c   r
04583         c       a
04584         c       b   <- Control point pointed to by Index
04585         c       q   <- this is the endpoint to which the control point is connected
04586         either nothing or a moveto
04587         ...
04588 
04589     4: Curve/snapping to curve at start
04590         m       q
04591         c       c
04592         c       d
04593         c       p
04594         ...
04595         l/c     r
04596         c       a
04597         c       b   <- Control point pointed to by index
04598         c       q   <- Enpoint to which control is connected
04599         either nothing or moveto, CLOSEFIGURE or SnapToEnd set
04600         ...
04601 
04602     5: Curve/snapping to line at start
04603         m       q
04604         l       p
04605         ...
04606         l/c     r
04607         c       a
04608         c       b   <- Control point pointed to by index
04609         c       q   <- Enpoint to which control is connected
04610         either nothing or moveto, CLOSEFIGURE or SnapToEnd set
04611         ...
04612 
04613     6: Curve/snapping to curve in another path
04614     7: Curve/snapping to line in another path
04615         ...
04616         m/l/c   r
04617         c       a
04618         c       b   <- Control point pointed to by index
04619         c       q   <- Enpoint to which control is connected
04620         nothing/moveto
04621 
04622         point p = OtherCoord
04623 
04624 */
04625 
04626         // Point q is the endpoint of this curve
04627 
04628         q = Coords[Index+1];
04629 
04630         // Point r is the start point of this curve (always guaranteed to be there)
04631 
04632         r = Coords[Index-2];
04633 
04634         // Point p (as before) is difficult. It ight be a curve element. it might be a line
04635         // element. It might not exist at all (i.e. this might be the end point of an open subpath).
04636         // It also might be the start point of this subpath, either because this path is closed
04637         // or because we've been told to snap. Or even, it might be an element at the start or end 
04638         // of another path. My God, what a choice!
04639 
04640         // First check for the simple cases of curve/curve or curve/line (1 & 2)
04641         if (Index+2<UsedSlots && Verbs[Index+2] != PT_MOVETO)
04642         {
04643             // The next element is either a curve or a line
04644             if (Verbs[Index+2] == PT_BEZIERTO)
04645             {
04646                 // It's a curve, so point p is its endpoint
04647                 p = Coords[Index+4];
04648                 CalcPointCurve(p,q,r,&ret);
04649                 return ret;
04650             }
04651             {
04652                 // It's a line, so point p is the endpoint of that
04653                 p = Coords[Index+2];
04654                 CalcPointLine(p,q,r,&ret);
04655                 return ret;
04656             }
04657         }
04658         // Now we know there's nothing after this curve, so check snapping and stuff
04659         else if (StartAndEndSnapped || (Verbs[Index+1] & PT_CLOSEFIGURE))
04660         {
04661             // We're snapping to the start of this path (4 & 5) , so we have to find 
04662             // the start of this subpath
04663             INT32 i = Index;
04664             FindStartOfSubPath(&i);         // i returned pointing at start element
04665             i++;                            // Point at first element in path
04666             if (Verbs[i] == PT_BEZIERTO)
04667             {
04668                 p = Coords[i+2];
04669                 CalcPointCurve(p,q,r,&ret);
04670                 return ret;
04671             }
04672             else
04673             {
04674                 p = Coords[i];
04675                 CalcPointLine(p,q,r,&ret);
04676                 return ret;
04677             }
04678 
04679         }
04680         else if (JoinedToAnother)
04681         {
04682             // Joined to another path (6 & 7)
04683             p = OtherCoord;
04684             if (OtherIsCurve)
04685             {
04686                 CalcPointCurve(p,q,r,&ret);
04687             }
04688             else
04689             {
04690                 CalcPointLine(p,q,r,&ret);
04691             }
04692             return ret;
04693         }
04694         else
04695         {
04696             // The only thing left is a curve at the end of the path (3)
04697             CalcPointEnd(q,r,&ret);
04698             return ret;
04699         }
04700     }
04701 #else
04702     return DocCoord(0,0);
04703 #endif
04704 }

void Path::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.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/02/94
Parameters:
SetRenderFlag is TRUE if the smoothing should set the NeedToRender flags on points [INPUTS] as it's smoothing. SnapEnds tells the routine to snap two open ends together SnapIndex is an index into the subpath which is to be snapped

Definition at line 4130 of file paths.cpp.

04131 {
04132 
04133     // This is a less efficient (slightly) version of this routine (in that there is a 
04134     // certain amount of moving backward and forward in the path, but only for the start
04135     // and end points) but it copes with end snapping
04136 
04137     DocCoord* Coords = GetCoordArray();
04138     PathVerb* Verbs = GetVerbArray();
04139     PathFlags* Flags = GetFlagArray();
04140     INT32 StartSnapSub = 0;
04141     INT32 EndSnapSub = 0;       // Start and end of the subpath we're snapping
04142     DocCoord tempcoord(0,0);
04143     
04144     // Find the start and end of the subpath we're snapping
04145     if (SnapEnds)
04146     {
04147         StartSnapSub = EndSnapSub = SnapIndex;
04148         FindStartOfSubPath(&StartSnapSub);
04149         FindEndElOfSubPath(&EndSnapSub);
04150     }
04151     
04152     if (SetRenderFlags)
04153     {
04154         // As well as smoothing, we also set the NeedToRender flag on any path that's changed.
04155         // Notice that we never clear the NeedToRender flags - if they're rendered once, they're
04156         // rendered forever.
04157 
04158         for (INT32 i = 0; i < UsedSlots; i++)
04159         {
04160             if (Verbs[i] == PT_BEZIERTO && !(Flags[i].IsEndPoint) && Flags[i].IsSmooth)
04161             {
04162                 tempcoord = SmoothControlPoint(i, (SnapEnds && (i>=StartSnapSub && i<=EndSnapSub)));
04163                 if (Coords[i] != tempcoord)
04164                 {
04165                     if (Flags[i+1].IsEndPoint)
04166                         Flags[i+1].NeedToRender = TRUE;
04167                     else
04168                         Flags[i+2].NeedToRender = TRUE;
04169                 }
04170                 Coords[i] = tempcoord;
04171             }
04172         }
04173 
04174     }
04175     else
04176     {
04177         for (INT32 i = 0; i < UsedSlots; i++)
04178         {
04179             if (Verbs[i] == PT_BEZIERTO && !(Flags[i].IsEndPoint) && Flags[i].IsSmooth)
04180                 Coords[i] = SmoothControlPoint(i, (SnapEnds && (i>=StartSnapSub && i<=EndSnapSub)));
04181         }
04182     }
04183 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/94
Parameters:
error = a double describing the max error to use when smoothing [INPUTS] smoothall = true then ignore selected points within this path and smooth the whole path. reselect = a boolean indicating whether the path sections should be re selected after smoothing
Operates on this path. the path will be smoothed meaning that it [OUTPUTS] will change in an unpredictable manner. The number of elements in the path and control point positioning will change, if TRUE is returned.
Returns:
FALSE then unable to smooth the curve TRUE then the path has been smoothed successfully
if P is the set of all control points [p0,....,pn] then a region Q is a connected subset of P , [pi....pj] where all members of Q are selected.

If smoothall is true 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.

Definition at line 7468 of file paths.cpp.

07469 {
07470     INT32 index = 0;
07471     INT32 start = 0;
07472     INT32 end = UsedSlots-1;
07473 
07474     if (smoothall)
07475     {
07476         INT32 sel;
07477         (reselect) ? sel=4 : sel=0;
07478         return (Path::SmoothSection(start,&end,error, sel));
07479     }
07480     else
07481     {       
07482         while ((index<UsedSlots) && (FindSelectionLimits(index,&start,&end)))
07483         {
07484             // increase the region by 1 either way and smooth it.
07485             INT32 nstart = start;
07486             INT32 nend = end;
07487 
07488             ExpandRange(&nstart,&nend,1);
07489 
07490             if (nstart != nend)
07491             {
07492                 INT32 sel = 0;
07493                 if (reselect)
07494                 {
07495                     if (nstart<start) sel |=1 ;
07496                     if (nend>end) sel |=2 ;
07497                     if (sel==0) sel=4;
07498                 }
07499                 BOOL ok = Path::SmoothSection(nstart, &nend, error, sel);
07500                 if (!ok) return FALSE;
07501             }
07502             index = nend+1;
07503         }
07504     }
07505     return TRUE;
07506 }

BOOL Path::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].

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/94
Parameters:
index1 = path element index to begin smoothing from. [INPUTS] index2 = path element index to smooth to. -1 then smooth to the end of the path. error = a double describing the max error to use when smoothing selection = 0 then do not reselect the smoothed regions = 1 then reselect all but the first point in the section = 2 then reselect all but the last point in the section a boolean indicating whether the smoothed region should = 3 then reselect all but both end points = 4 reselect all the points in the section
index2 = the new index of the end of the smoothed section [OUTPUTS] this = the altered path, smoothed between index1, index2
Returns:
BOOL = TRUE if the path was smoothed successfully = FALSE then the path remains unchanged

Definition at line 7632 of file paths.cpp.

07633 {
07634     INT32 last = *index2;
07635     if (last==-1)
07636         last = UsedSlots-1;
07637 
07638     // Saftey Checks
07639     ERROR3IF( index1>=last, "Section delimiters are invalid in Path::SmoothSection");
07640     ERROR3IF( last>=UsedSlots, "Section end is off end of path in Path::SmoothSection");
07641     ERROR3IF( index1<0, "Section start is negative in Path::SmoothSection");
07642 
07643     // Release safety checks
07644     if (index1>=last)
07645         return FALSE;
07646     if (last>=UsedSlots)
07647         return FALSE;
07648     if (index1<0)
07649         return FALSE;
07650 
07651     INT32 numtosmooth = last-index1+1;
07652 
07653     // We are smoothing a section of the path so extract a copy from
07654     // the specified section.
07655     Path PathSection;
07656     BOOL ok = PathSection.Initialise(numtosmooth,12);
07657 
07658     if (ok)
07659     {
07660         ok = MakePathFromSection(index1, numtosmooth, &PathSection);
07661         if (ok) 
07662         {
07663             // smooth the section completely
07664             ok = PathSection.Smooth(error);
07665 
07666             if (ok)
07667             {
07668                 // stick the smoothed path back in as a section and return a new
07669                 // index2 value
07670                 ok = RetroReplaceSection(index1, numtosmooth, &PathSection, FALSE);
07671                 if (ok)
07672                 {
07673                     // set up the last coordinate index return param
07674                     *index2 = index1 + PathSection.GetNumCoords() - 1;
07675 
07676                     // if we need to reselect the points then go to it
07677                     if (selection)
07678                     {
07679                         PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle);
07680                         INT32 start = index1;
07681                         INT32 end = *index2;
07682                         if (!(selection & 4))
07683                         {
07684                             if (selection & 1)
07685                                 FindNextEndPoint(&start);
07686                             if (selection & 2)
07687                                 FindPrev(&end);
07688                         }
07689                         for (INT32 i=start; i<=end; i++)
07690                             Flags[i].IsSelected = TRUE;
07691                     }
07692                 }
07693             }
07694         }
07695     }
07696     return ok;
07697 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
SplitPt = DocCoord to use to split the path as close as possible to [INPUTS]
SplitElement = The element index at which the split occured [OUTPUTS] NumElements = The number of elements generated by the split operation Verbs = a list of NumElements path verbs. Coords = a list of NumElements doc coords generated by the split
Returns:
TRUE = if the path could be split, FALSE = if SplitPt was closest to an already existing control vertex and hence is unable to split the element.

Definition at line 7110 of file paths.cpp.

07116 {
07117     double mu;
07118     double dist = SqrDistanceToPoint(SplitPt, SplitElement, &mu);
07119     if (dist < 0.0) return FALSE;
07120 
07121     PathVerb* InVerbs = GetVerbArray();
07122     DocCoord* InCoords = GetCoordArray();
07123 
07124     PathVerb vb = InVerbs[*SplitElement] & ~PT_CLOSEFIGURE;
07125     ENSURE((vb == PT_LINETO) || (vb == PT_BEZIERTO), 
07126             "Unable to find point on path. Index does not specify line or curve");
07127 
07128     switch (vb)
07129     {
07130         case PT_LINETO:
07131             return PathUtil::SplitLine(mu, &InCoords[(*SplitElement)-1], NumElements, Verbs, Coords);
07132             break;
07133         case PT_BEZIERTO:
07134             return PathUtil::SplitCurve(mu, &InCoords[(*SplitElement)-1], NumElements, Verbs, Coords);
07135             break;
07136     }
07137 
07138     return FALSE;
07139 }

BOOL Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> (from Riks routine in OpFreeHand)
Date:
15/06/95
Parameters:
SplitPoint - The coord that we want the split to happen close to [INPUTS]
SplitAt - The Slot number of the new end point [OUTPUTS] NewElements - The number of new elements inserted into the path
Returns:
TRUE if it was able to split the path ok, FALSE if it failed

Definition at line 9719 of file paths.cpp.

09720 {
09721     INT32       SplitElement=0;
09722     UINT32      NumElements;
09723     PathVerb    NewVerbs[6];
09724     DocCoord    NewCoords[6];
09725     PathFlags   NewFlags[6];
09726 
09727     // Try and split the path. This returns FALSE if the path did not need splitting
09728     if (SplitAtPoint(SplitPoint, &SplitElement, &NumElements, NewVerbs, NewCoords))
09729     {
09730         // Make a note of where the new endpoint will be
09731         *SplitAt = (SplitElement+(NumElements/2)-1);
09732         *NewElements = NumElements;
09733 
09734         // The path was split, so we know where, and how, so let's party on the path
09735         PathVerb* Verbs = GetVerbArray();
09736         PathFlags* Flags = GetFlagArray();
09737 //      DocCoord* Coords = GetCoordArray();
09738 //      UINT32 NumCoords = GetNumCoords();  
09739         INT32 NumToChange;
09740 
09741         // We're adding something, either a line or curve - check which
09742         if ((Verbs[SplitElement] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
09743         {
09744             // Adding a curve - number to change = 6
09745             NumToChange = 6;
09746 
09747             // Initialise the flags appropriately
09748             for (INT32 i=0; i<6; i++)
09749             {
09750                 // copy the flags from the old curve (repeat the flag in the first 3 elements)
09751                 NewFlags[i] = Flags[SplitElement+(i%3)];
09752                 NewFlags[i].IsSelected = FALSE;
09753 
09754                 // Want it to be a cusp in the middle
09755                 if ((i>0) && (i<4))
09756                 {
09757                     NewFlags[i].IsSmooth = FALSE;
09758                     NewFlags[i].IsRotate = FALSE;
09759                 }
09760             }
09761 
09762             // If this was happening at the end of a path,
09763             // then make sure the close figure flag is set correctly
09764             if (Verbs[SplitElement+2] & PT_CLOSEFIGURE)
09765                 NewVerbs[5] |= PT_CLOSEFIGURE;
09766         }
09767         else
09768         {
09769             // The slit happened in a straight line section
09770             NumToChange = 2;
09771             NewFlags[0] = NewFlags[1] = Flags[SplitElement];
09772             NewFlags[0].IsSmooth = NewFlags[0].IsRotate = FALSE;
09773             NewFlags[0].IsSelected = FALSE;
09774 
09775             // Make sure that the close figure flag is maintained
09776             if (Verbs[SplitElement] & PT_CLOSEFIGURE)
09777                 NewVerbs[1] |= PT_CLOSEFIGURE;
09778         }
09779 
09780         // Move to the place in the path where the split took place
09781         SetPathPosition(SplitElement);
09782         PathFlags InsertFlags;
09783         BOOL      InsertWorked;
09784 
09785         // insert a curve or a line, depending on where the split happened
09786         if (NumToChange==6)
09787             InsertWorked = InsertCurveTo(NewCoords[0], NewCoords[1], NewCoords[2], &InsertFlags);
09788         else
09789             InsertWorked = InsertLineTo(NewCoords[0], &InsertFlags);
09790 
09791         // see if the insertion worked
09792         if (!InsertWorked)
09793             return FALSE;
09794     }
09795     else
09796     {
09797         // else we tried to split at an existing control point (endpoint)
09798         // That means that there were no new endpoints
09799         *NewElements = 0;
09800         *SplitAt = (SplitElement-1);
09801 
09802         // See if we can find the control point in question
09803         DocCoord* Coords = GetCoordArray();
09804         INT32 NumCoords = GetNumCoords();
09805 
09806         // see if the split point is over the last point on the curve
09807         if (Coords[NumCoords-1]==SplitPoint)
09808             *SplitAt = NumCoords;
09809     }   
09810 
09811     // all worked
09812     return TRUE;
09813 }

double Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/08/94
Parameters:
pt = DocCoord of point of interest (eg MouseCoord) [INPUTS]
NearEl = path index pointer of closest element to be retured [OUTPUTS] mu = element parameter of closest point to be returned
Returns:
a double, being the closest distance on the path or -1 if there are no points in the path, mu being unaffected

Definition at line 6923 of file paths.cpp.

06924 {
06925     // Get the coordinate list and verb list for this path instance
06926 
06927     DocCoord* Coords = GetCoordArray();
06928     PathVerb* Verbs = GetVerbArray();
06929 
06930     // check for the presence of at least some elements
06931 
06932     if (UsedSlots==0)
06933     {
06934         *NearEl = -1;
06935         return -1;
06936     }
06937 
06938     // calculate the distance to the first control point
06939 
06940     double fdist;
06941     double ldist;
06942     double tmu;
06943 
06944     INT32 el=-1;
06945 
06946     fdist = PathUtil::SqrDistance(Coords[0], pt);
06947 
06948     for (INT32 i=0; i<UsedSlots; i++)
06949     {
06950         switch (Verbs[i] & ~PT_CLOSEFIGURE)
06951         {
06952 
06953             case PT_LINETO:
06954                 ldist = PathUtil::SqrDistanceToLine(&Coords[i-1], pt, &tmu);
06955                 if (ldist<=fdist) 
06956                 {
06957                     fdist=ldist;
06958                     el=i;
06959                     *mu=tmu;
06960                 } 
06961                 break;
06962 
06963             case PT_BEZIERTO:
06964                 ldist = PathUtil::SqrDistanceToCurve(MAXPATHDIFFRATE, &Coords[i-1], pt, &tmu);
06965                 if (ldist<=fdist) 
06966                 {
06967                     fdist=ldist;
06968                     el=i;
06969                     *mu=tmu;
06970                 }
06971                 i+=2;                           // skip next two bezierto el.
06972                 break;
06973         }
06974     }
06975 
06976     if (el>-1)                                  // have we an element? 
06977     {
06978         *NearEl = el;
06979         return fdist;
06980     }
06981 
06982     *NearEl = -1;
06983     return -1;
06984 }

double Path::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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/11/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
The squared length of the path defined in the same coordinate system as the paths points.

Definition at line 7912 of file paths.cpp.

07913 {
07914     double Acc = 64;
07915     double Len = 0;
07916     ProcessLength LengthObj(Acc);
07917 
07918 
07919     BOOL ok = LengthObj.PathLength(this, &Len);
07920     if (ok)
07921         return Len;
07922     return 0;
07923 
07924 }

BOOL Path::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.

BOOL Path::StrokePathToPath(MILLIPOINT LineWidth = 250, LineCapType LineCap = LineCapButt, JointType JoinStyle = MitreJoin, DashType *pDash = NULL, Path* pDest = NULL, DWORD Flatness = 200, BOOL Close = FALSE)

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/1/95
Parameters:
LineWidth = line width in millipoints [INPUTS] LineCap = line cap style JoinStyle = join style (what else!) pDash = ptr to dash pattern (NULL means no dash pattern) pDest = ptr to path to place result in (NULL means put result in 'this' path) Flatness = the value used to flatten the path Close = TRUE means the path is closed, FALSE otherwise
- [OUTPUTS]
Returns:
TRUE if OK, FALSE if not enough memory, or the resultant path has no elements
See also:
-

Definition at line 5610 of file paths.cpp.

05617 {
05618     if (pDest == NULL) pDest = this;
05619 
05620     UINT32 NewFlatness = (UINT32)Flatness;
05621 
05622     INT32 NumCoords  = GetNumCoords();
05623     INT32 OutputSize = (NumCoords*40)+1000;
05624     Path OutputPath;
05625     if (!OutputPath.Initialise(OutputSize)) return FALSE;
05626 
05627     DocCoord*   IPoints =           GetCoordArray();
05628     BYTE*       ITypes  = (BYTE*)   GetVerbArray();
05629     DWORD       ILength = (DWORD)   NumCoords;
05630 
05631     DocCoord*   OPoints =           OutputPath.GetCoordArray();
05632     BYTE*       OTypes  = (BYTE*)   OutputPath.GetVerbArray();
05633     DWORD       OLength = (DWORD)   OutputSize;
05634 
05635     // Karim 22/11/2000
05636     // Modified - if line-width is 0, then we don't want dashes.
05637     DashType Dash;
05638     Dash.Length = 0;
05639     if (pDash == NULL || LineWidth == 0) pDash = &Dash;
05640 
05641     INT32 len = -10;
05642 
05643     // keep checking to see if we had an overflow!
05644     while(len < -2)
05645     {
05646         len = GRenderRegion::StrokePathToPath(IPoints,ITypes,ILength,
05647                                     OPoints,OTypes,OLength,
05648                                     Close,LineWidth,NewFlatness,LineCap,JoinStyle,pDash);
05649 
05650         if(len < -2)
05651         {
05652             OLength -= len;
05653             OutputPath.EnsureVolume(OLength);
05654             OPoints =           OutputPath.GetCoordArray();
05655             OTypes  = (BYTE*)   OutputPath.GetVerbArray();
05656         }
05657     }
05658 
05659     OutputPath.UsedSlots    = len;
05660     OutputPath.UnUsedSlots -= len;
05661     OutputPath.IsFilled     = TRUE;
05662 
05663     pDest->ClearPath();
05664     if (len > 0)
05665     {
05666         if (!pDest->MergeTwoPaths(OutputPath)) return FALSE;
05667         pDest->InitialiseFlags();
05668         INT32 n = pDest->GetNumCoords();
05669         PathVerb* pVerbs = pDest->GetVerbArray();
05670         pVerbs[n-1] |= PT_CLOSEFIGURE;
05671     }
05672 
05673     return TRUE;
05674 }

void Path::SyncExtraInfo  ) 
 

Sets the Extra Info Ptr to the current Path Position.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/06/94
Parameters:
- [INPUTS]
Returns:
-

Errors: -

Definition at line 8234 of file paths.cpp.

08235 {
08236     if (ExtraInfo == NULL)
08237         return;
08238 
08239     ExtraInfo->Sync(CurrentPos);
08240 }

void Path::Translate const DocCoord coord  ) 
 

Translate all coordinate within 'this' path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/11/94
Parameters:
x = x coordinate to translate path by [INPUTS] y = y coordinate to translate path by
Returns:

Definition at line 8133 of file paths.cpp.

08134 {
08135     INT32 x=coord.x;
08136     INT32 y=coord.y;
08137     Translate(x,y);
08138 }

void Path::Translate const INT32  x,
const INT32  y
 

Translate all coordinate within 'this' path.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/11/94
Parameters:
x = x coordinate to translate path by [INPUTS] y = y coordinate to translate path by
Returns:

Definition at line 8154 of file paths.cpp.

08155 {
08156     // if there's any translation then apply it
08157     if (x || y)
08158     {
08159         DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle);
08160 
08161         for (INT32 i=0; i<UsedSlots; i++)
08162         {
08163             Coords[i].x += x;
08164             Coords[i].y += y;
08165         }
08166     }
08167 }

void Path::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.

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

Definition at line 5267 of file paths.cpp.

05268 {
05269     // Dereference the pointers to the coords and the verbs
05270     DocCoord*  Coords = (DocCoord*)  DescribeHandle(CoordHandle);
05271     PathVerb*  Verbs  = (PathVerb*)  DescribeHandle(VerbHandle);
05272 
05273     // Need to try all the sub paths, so loop through the whoel path
05274     INT32 EndOfSubPath = UsedSlots-1;
05275     for (INT32 i=UsedSlots-1; i>=0; i--)
05276     {
05277         // Have we found the begining of a sub-path
05278         if (Verbs[i]==PT_MOVETO)
05279         {
05280             // yes - is its start and end coords the same
05281             if (Coords[i] == Coords[EndOfSubPath])
05282             {
05283                 // This path has the same start and end coord
05284                 // so mark it as closed and fill it
05285                 Verbs[EndOfSubPath] |= PT_CLOSEFIGURE;
05286                 IsFilled = TRUE;
05287             }
05288 
05289             // Update the EndOfSubPath variable
05290             EndOfSubPath = i-1;
05291         }
05292     }
05293 }


Member Data Documentation

MHANDLE Path::CoordHandle [private]
 

Definition at line 578 of file paths.h.

INT32 Path::CurrentPos [private]
 

Definition at line 591 of file paths.h.

PathExtraInfo* Path::ExtraInfo [private]
 

Definition at line 582 of file paths.h.

MHANDLE Path::FlagsHandle [private]
 

Definition at line 579 of file paths.h.

BOOL Path::IsFilled
 

Definition at line 570 of file paths.h.

BOOL Path::IsStroked
 

Definition at line 571 of file paths.h.

CapStyles Path::m_ContourCapS [private]
 

Definition at line 559 of file paths.h.

double Path::m_ContourFlatness [private]
 

Definition at line 560 of file paths.h.

JoinStyles Path::m_ContourJoinS [private]
 

Definition at line 558 of file paths.h.

UINT32 Path::m_ContourLength [private]
 

Definition at line 562 of file paths.h.

UINT32 Path::m_ContourMitreLimit [private]
 

Definition at line 561 of file paths.h.

INT32 Path::m_ContourWidth [private]
 

Definition at line 557 of file paths.h.

BOOL Path::m_DoClosePath [private]
 

Definition at line 564 of file paths.h.

BOOL Path::m_IsAnOuterContour [private]
 

Definition at line 563 of file paths.h.

BOOL Path::m_UseContourMode [private]
 

Definition at line 565 of file paths.h.

INT32 Path::SlotAllocSize [private]
 

Definition at line 587 of file paths.h.

INT32 Path::SlotInitSize [private]
 

Definition at line 588 of file paths.h.

INT32 Path::UnUsedSlots [private]
 

Definition at line 585 of file paths.h.

INT32 Path::UsedSlots [private]
 

Definition at line 586 of file paths.h.

MHANDLE Path::VerbHandle [private]
 

Definition at line 577 of file paths.h.


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