#include <paths.h>
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. | |
| DocCoord * | 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. | |
| PathVerb * | 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. | |
| PathFlags * | 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. | |
| PathWidth * | GetWidthArray () |
| 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 |
| PathExtraInfo * | ExtraInfo |
| INT32 | UnUsedSlots |
| INT32 | UsedSlots |
| INT32 | SlotAllocSize |
| INT32 | SlotInitSize |
| INT32 | CurrentPos |
Definition at line 253 of file paths.h.
|
|
constructor - just sets a few things to sensible values
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 }
|
|
|
Destructor - releases the memory that the path has been using to store coords in.
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 }
|
|
||||||||||||
|
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.
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 }
|
|
||||||||||||||||||||
|
Adds a Curve to the end of the path.
Definition at line 1986 of file paths.cpp. 01987 { 01988 CurrentPos = UsedSlots; 01989 return InsertCurveTo(p1,p2,p3,NewFlags); 01990 }
|
|
||||||||||||
|
Adds an extra Info Value at the current path position.
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 }
|
|
||||||||||||
|
Adds a new LineTo to the end of the path.
Definition at line 1961 of file paths.cpp. 01962 { 01963 CurrentPos = UsedSlots; 01964 return InsertLineTo(p1, NewFlags); 01965 }
|
|
||||||||||||
|
Adds a new MoveTo to the end of the path.
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 }
|
|
|
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.
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 }
|
|
|
Calculate the area of this path.
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 }
|
|
|
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.
Definition at line 8024 of file paths.cpp. 08025 { 08026 return CalcRegionCRC(0,UsedSlots-1); 08027 }
|
|
||||||||||||||||||||||||
|
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).
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 }
|
|
||||||||||||||||||||
|
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).
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 }
|
|
||||||||||||||||
|
Calculates the position of the last control point in the sub-path.
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 }
|
|
||||||||||||||||||||
|
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!
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 }
|
|
||||||||||||
|
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.
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
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.
Definition at line 8081 of file paths.cpp. 08082 { 08083 return CalcSelPointsCRC(0,UsedSlots-1); 08084 }
|
|
||||||||||||
|
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.
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 }
|
|
||||||||||||||||
|
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.
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 }
|
|
|
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.
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 }
|
|
|
Sets the NeedToRender flags on all of the path elements to FALSE.
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 }
|
|
|
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.
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 }
|
|
|
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.
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 }
|
|
|
Goes through the path and sets all the IsSelected flags to FALSE, clearing any selected control points in the path.
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 }
|
|
||||||||||||||||||||||||||||
|
This is an interface to Gavin's ClipPathToPath.
'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)
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 }
|
|
|
Replace the data within this path with that of Other path.
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 }
|
|
||||||||||||
|
This function returns the point at which the closest distance on the path occurs.
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 }
|
|
||||||||||||||||
|
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.
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 }
|
|
|
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.
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 }
|
|
|
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).
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 }
|
|
||||||||||||
|
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.
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 }
|
|
||||||||||||||||
|
Tries to Join the New Path (must be simple) to a complex path.
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 }
|
|
||||||||||||||||
|
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.
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 }
|
|
|
Finds the coordinate which is dist units along 'this' 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 }
|
|
||||||||||||||||||||||||
|
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)
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 }
|
|
|
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.
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 }
|
|
||||||||||||||||
|
Copies a specified section from a path to the end of this one.
Definition at line 6017 of file paths.cpp. 06018 { 06019 return MergeSectionFrom(UsedSlots, Other, StartIndex, NumToCopy); 06020 }
|
|
||||||||||||||||
|
Copies a specified section from this path to the end of another path.
Definition at line 6035 of file paths.cpp. 06036 { 06037 return MergeSectionTo(StartIndex, NumToCopy, Dest, Dest->UsedSlots); 06038 }
|
|
||||||||||||||||
|
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.
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 }
|
|
|
Creates a filled path from a given DocRect.
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 }
|
|
|
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.
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 }
|
|
|
Deletes all the elements in the path from ElementNum to the end of the path.
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 }
|
|
||||||||||||
|
Deletes sections out of the middle of the path. Used by DeleteElement and for Deleting sub paths etc.
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 }
|
|
||||||||||||||||
|
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.
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 }
|
|
||||||||||||||||||||
|
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.
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
Draws a single blob, either selected or un-selected.
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 }
|
|
||||||||||||
|
Draws a blob for a Bezier control point.
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 }
|
|
||||||||||||||||
|
Draws a line from the Bezier control point to its endpoint.
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 }
|
|
|
Dumps the whole path out to the debug terminal.
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 }
|
|
|
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.
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 }
|
|
|
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.
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 }
|
|
|
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.
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 }
|
|
||||||||||||||||
|
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}.
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 }
|
|
|
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)
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 }
|
|
|
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)
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 }
|
|
|
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).
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 }
|
|
|
Searches forwards until it finds the end of the current sub-path. ie Index will point at the last element in the sub path.
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 }
|
|
|
Searches forwards until it finds the end of the current sub-path. ie pos will point at the last element in the sub path.
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 }
|
|
||||||||||||||||||||
|
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.
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 }
|
|
||||||||||||||||
|
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.
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 }
|
|
|
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.
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 }
|
|
|
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.
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 }
|
|
|
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.
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 }
|
|
|
Finds the next path endpoint in this path.
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 }
|
|
|
Searches the point set {*index, usedslots-1} for a selected end point and returns its index if found.
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 }
|
|
|
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.
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 }
|
|
|
Finds the previous path element in this path starting from the value (index).
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 }
|
|
|
Finds the prev path element in this path starting the search from CurrentPos.
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 }
|
|
|
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.
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 }
|
|
|
Finds the previous path endpoint in this path.
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 }
|
|
||||||||||||||||
|
Finds the next connected region of selected control handles.
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 }
|
|
|
Sets Pos to the first element in the path.
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 }
|
|
|
Searches backwards from the current position from Index until it find the start of the subpath (always 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 }
|
|
|
Searches backwards from the current position until it finds the start of the sub path that the current position is in.
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 }
|
|
||||||||||||
|
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.
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 }
|
|
||||||||||||
|
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.
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 }
|
|
|
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.
|