#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.
Definition at line 1715 of file paths.cpp. 01716 { 01717 // If the path is empty, then return an empty rectangle 01718 if (UsedSlots==0) 01719 return DocRect(0,0,0,0); 01720 01721 // de-reference the coord array 01722 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 01723 DocRect BlobRect; 01724 01725 for (INT32 i=0; i<UsedSlots; i++) 01726 { 01727 DocRect TempRect; 01728 GetApplication()->GetBlobManager()->GetBlobRect(Coords[i],&TempRect); 01729 01730 if (i==0) 01731 BlobRect = TempRect; // For first coord, set BlobRect = rect of blob 01732 else 01733 BlobRect = BlobRect.Union(TempRect); // for other coords, find the union 01734 } 01735 01736 // return the completed rectangle 01737 return BlobRect; 01738 }
|
|
Calculates the bounding rectangle of the paths coordinates. This is calculated on the fly, so don't over use it.
Definition at line 1549 of file paths.cpp. 01550 { 01551 // If the path is empty, then return an empty rectangle 01552 if (UsedSlots==0) 01553 return DocRect(0,0,0,0); 01554 01555 // de-reference the coord array 01556 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 01557 DocRect BoundingRect(Coords[0], Coords[0]); 01558 01559 // include each point in the path to the bounding rectangle 01560 for (INT32 i=1; i<UsedSlots; i++) 01561 BoundingRect.IncludePoint(Coords[i]); 01562 01563 // return the completed rectangle 01564 return BoundingRect; 01565 }
|
|
Definition at line 5725 of file paths.cpp. 05726 { 05727 // First Check to see if the Path pasted in is valid! 05728 ERROR2IF(pDest==NULL,0,"Init GenPathContour Recieved a NULL Pointer!"); 05729 05730 PPOINT SPoints = (PPOINT)GetCoordArray(); 05731 PBYTE STypes = (PBYTE)GetVerbArray(); 05732 INT32 SLength = GetNumCoords(); 05733 05734 PPOINT OPoints = NULL; 05735 PBYTE OTypes = NULL; 05736 PPOINT INPoints = NULL; 05737 PBYTE INTypes = NULL; 05738 05739 ERROR3IF(SLength < 0,"We`ve got a problem got a path with negative length!"); 05740 05741 Path CopyPath; 05742 CopyPath.Initialise(); 05743 05744 Path StrokedPath; 05745 StrokedPath.Initialise(); 05746 05747 INT32 PathLength = -1; 05748 INT32 Width = 100; 05749 Width = (INT32)(StepValue * m_ContourWidth); 05750 05751 JointType JoinS = (m_ContourJoinS==JOIN_MITER) ? MitreJoin : (m_ContourJoinS==JOIN_ROUND) ? RoundJoin : BevelledJoin; 05752 LineCapType CapS = (m_ContourCapS==CAPS_BUTT) ? LineCapButt : (m_ContourCapS==CAPS_ROUND) ? LineCapRound : LineCapSquare; 05753 05754 TRACEUSER( "MarkH", _T("Contouring with flatness %lf\n"),m_ContourFlatness); 05755 INT32 NewPathLength = -2; 05756 INT32 Passes = 0; 05757 05758 // If we`re not using the contouring mode and we want to use the StrokePathToPAth function then do it here! 05759 if(!m_UseContourMode) 05760 PathLength = StrokePathToPath(Width, CapS, JoinS, NULL, &StrokedPath, m_ContourFlatness, m_DoClosePath); 05761 05762 if(pDest->GetNumCoords() > 0) 05763 { 05764 // Now copy the Destination path as it needs to be clipped with the intermediate Path! 05765 CopyPath.CloneFrom(*pDest); 05766 pDest->ClearPath(); 05767 } 05768 else 05769 { 05770 pDest->SetPathPosition(0); 05771 } 05772 05773 // Check again to see if we`re doing the contour mode or the stroke path to path mode 05774 if(m_UseContourMode) 05775 { 05776 // now initialize and get the Points and Type pointers from a tempary path 05777 // that holds the intermediate step 05778 GenPathContour GStroke; 05779 // [Phil, 18/08/2005] Should this be assigning to NewPathLength? The test marked !!! below will always fail... 05780 PathLength = GStroke.ContourPath(SPoints, STypes, SLength, &OPoints, &OTypes, 05781 Width, m_ContourMitreLimit, m_ContourFlatness, 05782 m_ContourJoinS, (m_IsAnOuterContour == TRUE)); 05783 05784 INT32 OLength = (PathLength * 4)+1000; 05785 05786 if ( PathLength > 0 && OPoints && OTypes) 05787 { 05788 if ( !m_IsAnOuterContour ) 05789 { 05790 // Create two new Arrays which are larger than the current OPoints and OTypes 05791 // as gavin allocates his own memory for these points! 05792 INPoints = new POINT[OLength]; 05793 INTypes = new BYTE[OLength]; 05794 05795 if(INPoints && INTypes) 05796 { 05797 memcpy(INPoints,OPoints,sizeof(POINT) * PathLength); 05798 memcpy(INTypes,OTypes,PathLength); 05799 delete OPoints; 05800 OPoints = INPoints; 05801 delete OTypes; 05802 OTypes = INTypes; 05803 } 05804 else 05805 { 05806 delete OTypes; 05807 delete OPoints; 05808 05809 // If the NewPathLength is 0 then there`s no point continueing so 05810 // make sure the destination path contains the data it came in with 05811 // and return! 05812 if(NewPathLength == 0) // !!! 05813 pDest->CloneFrom(CopyPath); 05814 05815 return NewPathLength; 05816 } 05817 05818 RECT obbox ; 05819 XaDraw_CalcSimpleBBox( OPoints,PathLength,&obbox ) ; 05820 OPoints[PathLength+0].x = obbox.right +0x1000 ; 05821 OPoints[PathLength+0].y = obbox.top -0x1000 ; 05822 OPoints[PathLength+1].x = obbox.right +0x1000 ; 05823 OPoints[PathLength+1].y = obbox.bottom+0x1000 ; 05824 OPoints[PathLength+2].x = obbox.left -0x1000 ; 05825 OPoints[PathLength+2].y = obbox.bottom+0x1000 ; 05826 OPoints[PathLength+3].x = obbox.left -0x1000 ; 05827 OPoints[PathLength+3].y = obbox.top -0x1000 ; 05828 OTypes[PathLength+0] = PT_MOVETO ; 05829 OTypes[PathLength+1] = PT_LINETO ; 05830 OTypes[PathLength+2] = PT_LINETO ; 05831 OTypes[PathLength+3] = PT_LINETO|PT_CLOSEFIGURE ; 05832 05833 while(NewPathLength == -2 && Passes++ < 6) 05834 { 05835 NewPathLength = ::ClipPathToPath(OPoints, OTypes, PathLength+4, m_ContourFlatness, 05836 OPoints+PathLength, OTypes+PathLength, 4, m_ContourFlatness, 05837 4 | 1<<4 | 1<<5, 30, 05838 OPoints, OTypes, OLength); 05839 } 05840 05841 PathLength = NewPathLength; 05842 05843 if(NewPathLength <= 0) 05844 { 05845 delete OTypes; 05846 delete OPoints; 05847 05848 // If the NewPathLength is 0 then there`s no point continueing so 05849 // make sure the destination path contains the data it came in with 05850 // and return! 05851 if(NewPathLength == 0) 05852 pDest->CloneFrom(CopyPath); 05853 05854 return NewPathLength; 05855 } 05856 } 05857 05858 pDest->EnsureVolume(OLength); 05859 05860 PPOINT DPoints = (PPOINT)pDest->GetCoordArray(); 05861 PBYTE DTypes = (PBYTE)pDest->GetVerbArray(); 05862 // INT32 DLength = pDest->GetNumCoords(); 05863 05864 PPOINT CPoints = (PPOINT)CopyPath.GetCoordArray(); 05865 PBYTE CTypes = (PBYTE)CopyPath.GetVerbArray(); 05866 INT32 CLength = CopyPath.GetNumCoords(); 05867 05868 NewPathLength = -2; 05869 05870 while(NewPathLength == -2 && Passes++ < 6) 05871 { 05872 NewPathLength = ::ClipPathToPath( OPoints, OTypes, PathLength, m_ContourFlatness, 05873 CPoints, CTypes, CLength, m_ContourFlatness, 05874 7 | 1<<4, 30, 05875 DPoints, DTypes, OLength); 05876 05877 if(NewPathLength == -2) 05878 { 05879 OLength <<= 1; 05880 pDest->EnsureVolume(OLength); 05881 pDest->SetPathPosition(0); 05882 DPoints = (PPOINT)pDest->GetCoordArray(); 05883 DTypes = (PBYTE)pDest->GetVerbArray(); 05884 TRACEUSER( "MarkH", _T("Path to short so using new length %d\n"),OLength); 05885 } 05886 } 05887 05888 if(NewPathLength <= 0) 05889 { 05890 delete OTypes; 05891 delete OPoints; 05892 05893 // If the NewPathLength is 0 then there`s no point continueing so 05894 // make sure the destination path contains the data it came in with 05895 // and return! 05896 if(NewPathLength == 0) 05897 pDest->CloneFrom(CopyPath); 05898 05899 return NewPathLength; 05900 } 05901 05902 pDest->UsedSlots += NewPathLength; 05903 pDest->UnUsedSlots -= NewPathLength; 05904 05905 delete OTypes; 05906 delete OPoints; 05907 05908 // Now try to close the destination path and tidyup the slot allocations! 05909 pDest->TryToClose(); 05910 } 05911 else 05912 { 05913 delete OTypes; 05914 delete OPoints; 05915 05916 // If the NewPathLength is 0 then there`s no point continueing so 05917 // make sure the destination path contains the data it came in with 05918 // and return! 05919 // if(NewPathLength == 0) 05920 if (NewPathLength <=0) 05921 { 05922 pDest->CloneFrom(CopyPath); 05923 return 0; 05924 } 05925 } 05926 } 05927 else 05928 { 05929 // With the stroke path to path method we need to clean up the resultant path! 05930 PathLength = CopyPath.ClipPathToPath(StrokedPath, pDest, 7|(1<<4), 30, m_ContourFlatness, m_ContourFlatness); 05931 05932 if(PathLength <= 0) 05933 { 05934 // If the NewPathLength is 0 then there`s no point continueing so 05935 // make sure the destination path contains the data it came in with 05936 // and return! 05937 if(PathLength == 0) 05938 pDest->CloneFrom(CopyPath); 05939 05940 TRACEUSER( "MarkH", _T("ClipFailed so copying path! PATHS\n")); 05941 } 05942 } 05943 05944 // Return the New Path Length 05945 return PathLength; 05946 }
|
|
Finds the first control point of a bezier.
Definition at line 1785 of file paths.cpp. 01786 { 01787 ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetEndPoint" ); 01788 01789 // de-reference the coord array 01790 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 01791 01792 ENSURE((((PathVerb*) DescribeHandle(VerbHandle)) [CurrentPos] & (~PT_CLOSEFIGURE))==PT_BEZIERTO, "Not a Bezier in Path::GetControl1()"); 01793 01794 return Coords[CurrentPos]; 01795 }
|
|
Finds the second control point of a Bezier.
Definition at line 1809 of file paths.cpp. 01810 { 01811 ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetEndPoint" ); 01812 01813 // de-reference the arrays 01814 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 01815 01816 ENSURE((((PathVerb*) DescribeHandle(VerbHandle))[CurrentPos+1] & (~PT_CLOSEFIGURE))==PT_BEZIERTO, "Not a Bezier in Path::GetControl2()"); 01817 01818 return Coords[CurrentPos+1]; 01819 }
|
|
finds the DocCoord associated with the path position
Definition at line 1146 of file paths.cpp. 01147 { 01148 ENSURE( CurrentPos<UsedSlots, "Index out of bounds in Path::GetCoord" ); 01149 01150 // de-reference the coord array 01151 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 01152 01153 return Coords[CurrentPos]; 01154 }
|
|
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.
Definition at line 1837 of file paths.cpp. 01838 { 01839 // de-reference the coord array 01840 return (DocCoord*) DescribeHandle(CoordHandle); 01841 }
|
|
Dumps the whole path out during tree display debugging.
Info returned: Number of handles and bytes used by the path data. Whether the path is filled or not. Each handle's verbs, coords and flags Verbs - L - LineTo C - CurveTo M - MoveTo S - ClosePath Notes: For example of use, see NodeClipViewController::GetDebugDetails(). Definition at line 2912 of file paths.cpp. 02913 { 02914 #ifdef _DEBUG 02915 String_256 TempStr; 02916 02917 // output number of handles and space used by the path. 02918 INT32 nSlots = GetNumCoords(); 02919 TempStr._MakeMsg( TEXT("#1%ld handles, #2%ld bytes used\r\n"), nSlots, 02920 GetPathByteLength() ); 02921 (*Str) += TempStr; 02922 02923 // output whether or not the path is filled. 02924 TempStr._MakeMsg( TEXT("Path is#1%s Filled and is#2%s Stroked\r\n"), 02925 IsFilled ? "" : " not", 02926 IsStroked ? "" : " not" ); 02927 (*Str) += TempStr; 02928 02929 // output the path's handle information. 02930 (*Str) += TEXT( "Num\tType\tX Coord\tY Coord\r\n" ); 02931 PathVerb * Verbs = GetVerbArray(); 02932 DocCoord * Coords = GetCoordArray(); 02933 PathFlags * Flags = GetFlagArray(); 02934 for (INT32 i=0; i < nSlots; i ++) 02935 { 02936 String_32 VerbStr; 02937 VerbStr._MakeMsg(TEXT("#1%d ("), Verbs[i]); 02938 if (Verbs[i] & PT_CLOSEFIGURE) VerbStr += TEXT("S"); 02939 if (Verbs[i] & PT_LINETO) VerbStr += TEXT("L"); 02940 if (Verbs[i] & PT_BEZIERTO) VerbStr += TEXT("C"); 02941 if (Verbs[i] & PT_MOVETO) VerbStr += TEXT("M"); 02942 VerbStr += TEXT(")"); 02943 02944 TempStr._MakeMsg( TEXT("#1%d.\t#2%S\t#3%ld,\t#4%ld\t"), 02945 i, &VerbStr, Coords[i].x, Coords[i].y ); 02946 02947 if (Flags[i].IsSmooth) TempStr += TEXT("S"); 02948 if (Flags[i].IsRotate) TempStr += TEXT("R"); 02949 if (Flags[i].IsEndPoint) TempStr += TEXT("E"); 02950 if (Flags[i].IsSelected) TempStr += TEXT("(sel)"); 02951 02952 TempStr += TEXT("\r\n"); 02953 (*Str) += TempStr; 02954 } 02955 #endif 02956 }
|
|
Gets the distance along the path for a given point.
Definition at line 9852 of file paths.cpp. 09853 { 09854 ERROR2IF(Distance==NULL, FALSE, "NULL output parameter"); 09855 09856 INT32 NextEndpoint = 0; 09857 double dDistance = 0.0; 09858 double mu = 0.0; 09859 BOOL ok = (SqrDistanceToPoint(Point, &NextEndpoint, &mu) != -1); 09860 ERROR3IF(!ok, "SqrDistanceToPoint failed"); 09861 if (ok) 09862 { 09863 ok = DistanceTo(NextEndpoint, mu, &dDistance); 09864 ERROR3IF(!ok, "Path::DistanceTo failed"); 09865 } 09866 09867 *Distance = (MILLIPOINT)dDistance; 09868 09869 return ok; 09870 }
|
|
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.
Definition at line 1756 of file paths.cpp. 01757 { 01758 ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetEndPoint" ); 01759 01760 // de-reference the verb array 01761 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 01762 01763 // de-reference the coord array 01764 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 01765 01766 if ((Verbs[CurrentPos] & (~PT_CLOSEFIGURE))==PT_BEZIERTO) 01767 return Coords[CurrentPos+2]; 01768 else 01769 return Coords[CurrentPos]; 01770 }
|
|
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.
Definition at line 1881 of file paths.cpp. 01882 { 01883 // de-reference the Flag array 01884 return (PathFlags*) DescribeHandle(FlagsHandle); 01885 }
|
|
returns all the flags for the current path position
Definition at line 2689 of file paths.cpp. 02690 { 02691 ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsEndPoint" ); 02692 02693 // Get the flags array 02694 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02695 02696 // and return the selected flag 02697 *NewFlags = Flags[CurrentPos]; 02698 }
|
|
finds the flags associated with the path position
Definition at line 1168 of file paths.cpp. 01169 { 01170 ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetFlags" ); 01171 01172 // de-reference the flag array 01173 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 01174 01175 return Flags[CurrentPos]; 01176 }
|
|
This returns the number of coordinates that make the path up.
Definition at line 1391 of file paths.cpp. 01392 { 01393 return UsedSlots; 01394 }
|
|
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).
Definition at line 1326 of file paths.cpp. 01327 { 01328 // The routine relies on the path beginning with a MoveTo 01329 PathVerb* pVerbs = (PathVerb*) DescribeHandle(VerbHandle); 01330 INT32 Index=0,Count=0; 01331 while (FindNextEndPoint(&Index)) 01332 { 01333 if ((pVerbs[Index] & ~PT_CLOSEFIGURE) != PT_MOVETO) 01334 Count++; 01335 } 01336 01337 return Count; 01338 }
|
|
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.
Definition at line 1444 of file paths.cpp. 01445 { 01446 // de-reference the verb array 01447 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 01448 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 01449 01450 INT32 Count = 0; 01451 for (INT32 i=0; i<UsedSlots; i++) 01452 { 01453 if (Flags[i].IsEndPoint) 01454 Count++; 01455 01456 if ((i>0) && (Verbs[i]==PT_MOVETO) && (Verbs[i-1] & PT_CLOSEFIGURE)) 01457 Count--; 01458 } 01459 01460 // return the number of 'on the path' end points 01461 return Count; 01462 }
|
|
determine how many selected endpoints there are within this path. Useful indirectly for finding whether there's a subselection.
Definition at line 1411 of file paths.cpp. 01412 { 01413 // We need to find all the selected control points in the path 01414 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 01415 INT32 count = 0; 01416 01417 // look for selected coords 01418 for (INT32 i=0; i<UsedSlots; i++) 01419 { 01420 if ((Flags[i].IsSelected) && (Flags[i].IsEndPoint)) 01421 count++; 01422 } 01423 return count; 01424 }
|
|
Gets the number of subpaths in this path.
Definition at line 1351 of file paths.cpp. 01352 { 01353 //This variable will tell us our current position in the path 01354 INT32 lCurPos=0; 01355 01356 //And this will keep a count of the subpaths we find 01357 INT32 lSubpaths=0; 01358 01359 //Now, while we are still in the path 01360 while (lCurPos<GetNumCoords()) 01361 { 01362 //Set lCurPos to the end of the subpath we are in 01363 FindEndElOfSubPath(&lCurPos); 01364 01365 //Add one to the number of subpaths found 01366 lSubpaths++; 01367 01368 //And move the current position on by one place, to move it 01369 //either into the next subpath or off the end of the path 01370 lCurPos++; 01371 } 01372 01373 //And return the number of subpaths we found 01374 return lSubpaths; 01375 01376 }
|
|
Easy way of getting the path pointers into variables. Combines three function calls into one.
Definition at line 1907 of file paths.cpp. 01908 { 01909 if (VerbArray != NULL) 01910 *VerbArray = (PathVerb*) DescribeHandle(VerbHandle); 01911 if (CoordArray != NULL) 01912 *CoordArray = (DocCoord*) DescribeHandle(CoordHandle); 01913 if (FlagsArray != NULL) 01914 *FlagsArray = (PathFlags*) DescribeHandle(FlagsHandle); 01915 }
|
|
Calculates the length of the path in bytes. This figures includes the size of the 3 arrays (Coordinates, Verbs and Flags) only.
Definition at line 1300 of file paths.cpp. 01301 { 01302 INT32 Total; 01303 01304 // Add up the size of each of the Arrays 01305 Total = UsedSlots * sizeof(DocCoord); 01306 Total += UsedSlots * sizeof(PathVerb); 01307 Total += UsedSlots * sizeof(PathFlags); 01308 01309 return Total; 01310 }
|
|
Find the length of a path in millipoints.
Definition at line 7938 of file paths.cpp. 07939 { 07940 double TotalLength = 0.0; 07941 INT32 LastEndPoint = GetNumCoords()-1; 07942 07943 if (LastEndPoint==-1) 07944 return 0.0; 07945 07946 BOOL ok = DistanceTo(LastEndPoint, 1.0, &TotalLength, dFlatness); 07947 ERROR3IF(!ok, "Path.DistanceTo failed"); 07948 07949 if (ok) 07950 return TotalLength; 07951 else 07952 return 0.0; 07953 }
|
|
Find out where in the path we are.
Definition at line 999 of file paths.cpp. 01000 { 01001 return CurrentPos; 01002 }
|
|
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.
Definition at line 1195 of file paths.cpp. 01196 { 01197 PathVerb* pVerbs = GetVerbArray(); 01198 01199 if (pVerbs[UsedSlots-1] & PT_CLOSEFIGURE) 01200 return (PATHTYPE_SHAPE); 01201 else 01202 return (PATHTYPE_LINE); 01203 }
|
|
Gets the coordinate of a point a certain distance along this path.
Definition at line 9828 of file paths.cpp. 09829 { 09830 ERROR2IF(pPoint==NULL, FALSE, "NULL output parameter"); 09831 ERROR2IF(Distance<0, FALSE, "-ve distance"); 09832 09833 ProcessPathDistance PathProc(64); 09834 BOOL Found = FALSE; 09835 BOOL ok = PathProc.GetCoordAndTangent(pPoint, pTangent, &Found, Distance, this, pPressure); 09836 09837 return ok && Found; 09838 }
|
|
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.
Definition at line 693 of file paths.cpp. 00694 { 00695 DocCoord temp1; 00696 00697 FindStartOfSubPath(); 00698 temp1 = GetCoord(); 00699 FindEndOfSubPath(); 00700 00701 // Find out if this path is really closed. If the PT_CLOSEFIGURE flag is set in the end 00702 // verb, the path is closed, so return FALSE, otherwise return TRUE, with *start and *end 00703 // set up accordingly. 00704 00705 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 00706 if (Verbs[CurrentPos] & PT_CLOSEFIGURE) 00707 { 00708 return FALSE; 00709 } 00710 else 00711 { 00712 *end = GetEndPoint(); 00713 *start = temp1; 00714 return TRUE; 00715 } 00716 }
|
|
Calculate the bounding rectangle of a path using GDraw. Added by Diccon 22/5/2000 LineWidth - the width of the path, note that this defaults to zero so you don't have to supply anything unless you want to. pAttrMap ptr to an attrmap, from which to take modification info. note that if we can extract a LineWidth value from it, then the attrmap's value will override that passed in directly.
By using one or other of the extra parameters to this method, you can find out the bounds for thick lines, or lines with arrow-heads/tails.
Definition at line 1603 of file paths.cpp. 01604 { 01605 // validate inputs. 01606 if (pRect == NULL) 01607 { 01608 ERROR3("Path::GetTrueBoundingRect; NULL input rectangle!"); 01609 return FALSE; 01610 } 01611 if (LineWidth < 0) 01612 { 01613 //ERROR3("Negative line width supplied to Path::GetTrueBoundingRect"); 01614 LineWidth = 0; // we can recover from this 01615 } 01616 01617 // check the attr map for any attrs which we think may alter 01618 // the bounds of the path, eg line width, arrow heads. 01619 ArrowRec* pArrow1 = NULL; 01620 ArrowRec* pArrow2 = NULL; 01621 JoinStyles JoinStyle = JOIN_ROUND; 01622 if (pAttrMap != NULL) 01623 { 01624 AttrLineWidth* pLineWidth = NULL; 01625 AttrStrokeColour* pLineColour = NULL; 01626 AttrStartArrow* pStartArrow = NULL; 01627 AttrEndArrow* pEndArrow = NULL; 01628 AttrJoinType* pJoinType = NULL; 01629 01630 // note that we only use the path's LineWidth if its outline is not transparent. 01631 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrLineWidth), (void*&)pLineWidth); 01632 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeColour), (void*&)pLineColour); 01633 01634 if (pLineColour != NULL && pLineWidth != NULL) 01635 { 01636 LineWidth = 0; 01637 DocColour* pCol = pLineColour->GetStartColour(); 01638 if (pCol != NULL && !pCol->IsTransparent()) 01639 LineWidth = pLineWidth->Value.LineWidth; 01640 } 01641 01642 // ok, if we have a line width then we'll need to look for stuff like 01643 // arrowheads and join-style (esp. Mitre joins). 01644 if (LineWidth > 0) 01645 { 01646 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartArrow), (void*&)pStartArrow); 01647 if (pStartArrow != NULL) 01648 pArrow1 = &(pStartArrow->Value.StartArrow); 01649 01650 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrEndArrow), (void*&)pEndArrow); 01651 if (pEndArrow != NULL) 01652 pArrow2 = &(pEndArrow->Value.EndArrow); 01653 01654 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrJoinType), (void*&)pJoinType); 01655 if (pJoinType != NULL) 01656 { 01657 JointType jt = pJoinType->Value.JoinType; 01658 01659 JoinStyle = (jt == MitreJoin) ? JOIN_MITER : 01660 (jt == RoundJoin) ? JOIN_ROUND : 01661 JOIN_BEVEL; 01662 } 01663 } 01664 } 01665 01666 // ok, let's get the path's bounds! 01667 pRect->MakeEmpty(); 01668 BOOL fSuccess = FALSE; 01669 DocRect drBounds; 01670 GDrawContext *GD = GRenderRegion::GetStaticDrawContext(); 01671 01672 if (GD == NULL) 01673 return FALSE; 01674 01675 fSuccess = GD->CalcStrokeBBox( (POINT*)GetCoordArray(), GetVerbArray(), GetNumCoords(), 01676 (RECT *)(&drBounds), IsFilled, (DWORD)LineWidth, 01677 CAPS_ROUND, JoinStyle, NULL ) != -1; 01678 01679 // if the bounds are invalid then make sure that we flag a failure. 01680 if (!drBounds.IsValid()) 01681 fSuccess = FALSE; 01682 01683 // ok so far - if we need to account for any arrowheads, do so now. 01684 if (fSuccess) 01685 { 01686 if (pArrow1 != NULL) 01687 drBounds = drBounds.Union(pArrow1->GetArrowBoundingRect(this, LineWidth, TRUE)); 01688 01689 if (pArrow2 != NULL) 01690 drBounds = drBounds.Union(pArrow2->GetArrowBoundingRect(this, LineWidth, FALSE)); 01691 } 01692 01693 // ok, if we're a success then record the bounds. 01694 if (fSuccess) 01695 *pRect = drBounds; 01696 01697 return fSuccess; 01698 }
|
|
Definition at line 573 of file paths.h. 00573 { return (UsedSlots); }
|
|
finds the verb associated with the path position
Definition at line 1122 of file paths.cpp. 01123 { 01124 ENSURE( CurrentPos<UsedSlots, "Index out of bounds in GetVerb" ); 01125 01126 // de-reference the verb array 01127 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 01128 01129 // return the verb with the close path bit removed 01130 return ((Verbs[CurrentPos]) & (~PT_CLOSEFIGURE)); 01131 }
|
|
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.
Definition at line 1859 of file paths.cpp. 01860 { 01861 // de-reference the Verb array 01862 return (PathVerb*) DescribeHandle(VerbHandle); 01863 }
|
|
Fetches width values from the path.
Definition at line 8255 of file paths.cpp. 08256 { 08257 if (ExtraInfo == NULL) 08258 return 0; 08259 08260 return ExtraInfo->GetWidthInfo(); 08261 }
|
|
The array holds the width of all the points in the path. DO NOT MODIFY THE CONTENTS OF THE ARRAY.
Definition at line 8275 of file paths.cpp. 08276 { 08277 if (ExtraInfo == NULL) 08278 return NULL; 08279 08280 return ExtraInfo->GetWidthArray(); 08281 }
|
|
To determine if the path has any width information.
Definition at line 8294 of file paths.cpp. 08295 { 08296 if (ExtraInfo == NULL) 08297 return FALSE; 08298 08299 return ExtraInfo->HasWidthInfo(); 08300 }
|
|
Allocates memory in the path for the extra info arrays.
Definition at line 8184 of file paths.cpp. 08185 { 08186 TRACEUSER( "Will", _T("InitExtraInfo, Index=%d\n"), Index ); 08187 ENSURE(Index <= NUMEXTRACHANNELS, "Index out of range in InitExtraInfo"); 08188 08189 // If we haven't any extra info yet then we need to create some 08190 if (ExtraInfo == NULL) 08191 { 08192 ExtraInfo = new PathExtraInfo(); 08193 if (ExtraInfo == NULL) 08194 return FALSE; 08195 } 08196 08197 // Now we can initialise the channel. 08198 // We use the same initial slot size as was used for the main path data. 08199 return ExtraInfo->Init(Index, SlotInitSize); 08200 }
|
|
Allocates memory in the path for the three arrays - The Verbs, Coordinates and the Flags.
Definition at line 284 of file paths.cpp. 00285 { 00286 // CGS (19/6/2000) A few of camelots programmers seem to be assuming that calling initialise 00287 // on an already initialised path will clear out all previous pointers. This is NOT the case 00288 // (or at least wasn't). It is not unreasonable for the programmer to expect this to happen 00289 // (being viewed as a reinitialise), so I have added code to handle deletion automatically. 00290 // This should fix a considerable amount of camelots memory leaks! 00291 00292 if (VerbHandle != BAD_MHANDLE) 00293 ReleaseBlock(VerbHandle); 00294 00295 if (CoordHandle != BAD_MHANDLE) 00296 ReleaseBlock(CoordHandle); 00297 00298 if (FlagsHandle != BAD_MHANDLE) 00299 ReleaseBlock(FlagsHandle); 00300 00301 // The memory manager will not allocate blocks of less that 12 bytes and have to be multiples of 4! 00302 if (InitialSize<12) 00303 { 00304 InitialSize = 12; 00305 } 00306 else 00307 { 00308 // Make sure it is a multiple of 4, by shifting left 2 and then shifting it back again! 00309 InitialSize = (InitialSize+3) >> 2; 00310 InitialSize = InitialSize << 2; 00311 } 00312 00313 if (BlockSize<12) 00314 { 00315 BlockSize = 12; 00316 } 00317 else 00318 { 00319 // Make sure it is a multiple of 4, by shifting left 2 and then shifting it back again! 00320 BlockSize = (BlockSize+3) >> 2; 00321 BlockSize = BlockSize << 2; 00322 } 00323 00324 // try and get memory for the verbs 00325 VerbHandle = ClaimBlock(sizeof(PathVerb)*InitialSize); 00326 if (VerbHandle!=BAD_MHANDLE) 00327 { 00328 // try and get memory for the coords 00329 CoordHandle = ClaimBlock(sizeof(DocCoord)*InitialSize); 00330 if (CoordHandle != BAD_MHANDLE) 00331 { 00332 // try and get memory for the flags 00333 FlagsHandle = ClaimBlock(sizeof(PathFlags)*InitialSize); 00334 if (FlagsHandle != BAD_MHANDLE) 00335 { 00336 // everything worked 00337 UsedSlots = 0; 00338 UnUsedSlots = InitialSize; 00339 SlotInitSize = InitialSize; 00340 SlotAllocSize = BlockSize; 00341 } 00342 else 00343 { 00344 // failed to get the flag block, so release the other blocks and fail 00345 ReleaseBlock( CoordHandle ); 00346 ReleaseBlock( VerbHandle ); 00347 return FALSE; 00348 } 00349 } 00350 else 00351 { 00352 // failed to get the coords block, so release the block we already have and fail 00353 ReleaseBlock( VerbHandle ); 00354 return FALSE; 00355 } 00356 } 00357 else 00358 { 00359 // failed to get any memory, so fail 00360 return FALSE; 00361 } 00362 00363 // a total success, so say so. 00364 return TRUE; 00365 }
|
|
This generates a legal path flags array based on the path verbs in pVerbs within the specified region. It sets all flags in pFlags to default values and then scans all end points setting their end point flag to TRUE. void Path::InitialiseFlags(PathVerb* pVerbs, PathFlags* pFlags, const INT32 Len)
Definition at line 2796 of file paths.cpp. 02797 { 02798 INT32 n; 02799 02800 // Reset all the path flags to default values 02801 PathFlags DefaultPathFlags; 02802 for (n=0; n < Len; n++) 02803 pFlags[n] = DefaultPathFlags; 02804 02805 // Scan the verbs, so that the end point flags can be set correctly 02806 for (n=0; n < Len; n++) 02807 { 02808 PathVerb Verb = pVerbs[n] & ~PT_CLOSEFIGURE; 02809 switch (Verb) 02810 { 02811 case PT_LINETO: 02812 case PT_MOVETO: 02813 pFlags[n].IsEndPoint = TRUE; 02814 break; 02815 02816 case PT_BEZIERTO: 02817 n += 2; 02818 ERROR3IF(n>=Len,"Found a PT_BEZIERTO, but third pt is off the end of the array"); 02819 pFlags[n].IsEndPoint = TRUE; 02820 break; 02821 02822 default: 02823 ERROR3_PF(("Illegal path verb found : %c",Verb)); 02824 break; 02825 } 02826 } 02827 }
|
|
This generates a legal path flags array based on the path verbs within the specified region. It sets all flags to default values and then scans all end points setting their end point flag to TRUE. void Path::InitialiseFlags( const UINT32 Startindex, const INT32 Len)
Definition at line 2763 of file paths.cpp. 02765 { 02766 ERROR3IF(Startindex<0,"startindex off start of path in Path::SetPathFlags()"); 02767 ERROR3IF(Startindex+Len>UsedSlots,"(startindex+len) of end of path in Path::SetPathFlags()"); 02768 02769 // Get the flags array 02770 PathFlags* pFlags = (PathFlags*) DescribeHandle(FlagsHandle); 02771 PathVerb* pVerbs = (PathVerb*) DescribeHandle(VerbHandle); 02772 02773 InitialiseFlags(pVerbs+Startindex,pFlags+Startindex,Len); 02774 }
|
|
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.
Definition at line 2740 of file paths.cpp. 02741 { 02742 InitialiseFlags(0,UsedSlots); 02743 }
|
|
Definition at line 5698 of file paths.cpp. 05700 { 05701 m_ContourWidth = Width; 05702 m_ContourJoinS = JoinS; 05703 m_ContourCapS = CapS; 05704 m_IsAnOuterContour = IsAnOuterContour; 05705 m_DoClosePath = ClosePath; 05706 m_UseContourMode = UseContourMode; 05707 m_ContourFlatness = Flatness; 05708 m_ContourMitreLimit = MitreLimit; 05709 05710 return GetNumCoords(); 05711 }
|
|
Inserts a Curve into the path at the Current Path Position.
Definition at line 2154 of file paths.cpp. 02155 { 02156 // We need 3 empty slot to add a CurveTo 02157 if (!MakeSpaceInPath(3)) 02158 { 02159 ERROR( _R(IDS_PATH_MEM_ERROR), FALSE ); 02160 } 02161 02162 // get all the pointers 02163 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 02164 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 02165 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02166 02167 // Prepare the flags 02168 PathFlags UseFlags; 02169 if (NewFlags!=NULL) 02170 UseFlags = *NewFlags; 02171 02172 UseFlags.IsEndPoint = FALSE; 02173 02174 // There is now a hole in the middle of the path. 02175 // We can fill in the appropriate details for the first control point 02176 Verbs[CurrentPos] = PT_BEZIERTO; 02177 Coords[CurrentPos] = p1; 02178 Flags[CurrentPos] = UseFlags; 02179 02180 SyncExtraInfo(); 02181 CurrentPos++; 02182 02183 // and the second control point 02184 Verbs[CurrentPos] = PT_BEZIERTO; 02185 Coords[CurrentPos] = p2; 02186 Flags[CurrentPos] = UseFlags; 02187 CurrentPos++; 02188 02189 // and the endpoint 02190 UseFlags.IsEndPoint = TRUE; 02191 Verbs[CurrentPos] = PT_BEZIERTO; 02192 Coords[CurrentPos] = p3; 02193 Flags[CurrentPos] = UseFlags; 02194 CurrentPos++; 02195 02196 // Update the memory usage vars 02197 UsedSlots += 3; 02198 UnUsedSlots -= 3; 02199 02200 // The Current Path Position has already been updated and now points to the item 02201 // after the curveto (or off the end of the path, if this is the last element in the path 02202 02203 return TRUE; 02204 }
|
|
Inserts a LineTo into the path at the Current Path Position.
Definition at line 2098 of file paths.cpp. 02099 { 02100 // We need only 1 empty slot to add a LineTo 02101 if (!MakeSpaceInPath(1)) 02102 { 02103 ERROR( _R(IDS_PATH_MEM_ERROR), FALSE ); 02104 } 02105 02106 // get all the pointers 02107 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 02108 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 02109 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02110 02111 // Prepare the flags 02112 PathFlags UseFlags; 02113 if (NewFlags!=NULL) 02114 UseFlags = *NewFlags; 02115 02116 UseFlags.IsEndPoint = TRUE; 02117 02118 // There is now a hole in the middle of the path. We can fill in the appropriate details 02119 // and call it a day 02120 Verbs[CurrentPos] = PT_LINETO; 02121 Coords[CurrentPos] = p1; 02122 Flags[CurrentPos] = UseFlags; 02123 02124 // Update the memory usage vars 02125 UsedSlots++; 02126 UnUsedSlots--; 02127 02128 // move the position indicator to point to the thing after our new item 02129 SyncExtraInfo(); 02130 CurrentPos++; 02131 02132 return TRUE; 02133 }
|
|
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.
Definition at line 2046 of file paths.cpp. 02047 { 02048 // We need only 1 empty slot to add a MoveTo 02049 if (!MakeSpaceInPath(1)) 02050 { 02051 ERROR( _R(IDS_PATH_MEM_ERROR), FALSE ); 02052 } 02053 02054 // get all the pointers 02055 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 02056 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 02057 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02058 02059 // Prepare the flags 02060 PathFlags UseFlags; 02061 if (NewFlags!=NULL) 02062 UseFlags = *NewFlags; 02063 02064 UseFlags.IsEndPoint = TRUE; 02065 02066 // There is now a hole in the middle of the path. We can fill in the appropriate details 02067 // and call it a day 02068 Verbs[CurrentPos] = PT_MOVETO; 02069 Coords[CurrentPos] = p1; 02070 Flags[CurrentPos] = UseFlags; 02071 02072 // Update the memory usage vars 02073 UsedSlots++; 02074 UnUsedSlots--; 02075 02076 // move the position indicator to point to the thing after our new item 02077 SyncExtraInfo(); 02078 CurrentPos++; 02079 02080 return TRUE; 02081 }
|
|
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.
Definition at line 4071 of file paths.cpp. 04072 { 04073 INT32 OldPosition = CurrentPos; 04074 CurrentPos = StartSlot; 04075 if (!MakeSpaceInPath(NumSlots)) 04076 { 04077 CurrentPos = OldPosition; 04078 return FALSE; 04079 } 04080 CurrentPos = OldPosition; 04081 UsedSlots+=NumSlots; 04082 UnUsedSlots -= NumSlots; 04083 return TRUE; 04084 }
|
|
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.
Definition at line 6679 of file paths.cpp. 06680 { 06681 // Make sure that there is room in the path to store this extra info 06682 if (UnUsedSlots<NumSlots) 06683 { 06684 TRACE( _T("There was not enough room in this path to copy data into")); 06685 return FALSE; 06686 } 06687 06688 // We need to know about the path arrays 06689 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 06690 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 06691 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 06692 06693 // and the new path 06694 DocCoord* OtherCoords = (DocCoord*) DescribeHandle(Other->CoordHandle); 06695 PathFlags* OtherFlags = (PathFlags*) DescribeHandle(Other->FlagsHandle); 06696 PathVerb* OtherVerbs = (PathVerb*) DescribeHandle(Other->VerbHandle); 06697 06698 // Go though and copy all the element from one path to the other 06699 for (INT32 i=StartSlot; i<StartSlot+NumSlots; i++) 06700 { 06701 ENSURE(UnUsedSlots>0, "Ran out of space in a path that should have enough space in it" ); 06702 if (UnUsedSlots<=0) 06703 return FALSE; 06704 06705 // Copy the coords 06706 Coords[UsedSlots] = OtherCoords[i]; 06707 Flags[UsedSlots] = OtherFlags[i]; 06708 Verbs[UsedSlots] = OtherVerbs[i]; 06709 06710 // Move on to the next slots 06711 UsedSlots++; 06712 UnUsedSlots--; 06713 } 06714 06715 return TRUE; 06716 }
|
|
Tells you whether all subpaths of this path are closed.
See also: IsSubPathClosed Definition at line 4758 of file paths.cpp. 04759 { 04760 INT32 StartIndex = 0; 04761 INT32 EndIndex = 0; 04762 04763 // test each subpath for closure. 04764 while (StartIndex < UsedSlots) 04765 { 04766 EndIndex = StartIndex; 04767 FindEndElOfSubPath(&EndIndex); 04768 04769 if (!IsSubPathClosed(StartIndex)) 04770 return FALSE; 04771 04772 StartIndex = EndIndex + 1; 04773 } 04774 04775 return TRUE; 04776 }
|
|
Tests to see if the path is a complex path (ie it has multiple sub-paths).
Definition at line 2654 of file paths.cpp. 02655 { 02656 // Get the path verbs 02657 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 02658 02659 INT32 SubPaths = 0; 02660 for (INT32 i=0; i<UsedSlots; i++) 02661 { 02662 // Count all the MoveTos in the path 02663 if (Verbs[i] == PT_MOVETO) 02664 SubPaths++; 02665 } 02666 02667 // Make sure that there was a moveto in this path. This should not happen 02668 ENSURE( SubPaths>0, "Path::IsComplexPath() - Found a Path with no MoveTo in it!" ); 02669 02670 // If there was only one SubPath then it is simple, otherwise it is complex 02671 if (SubPaths==1) 02672 return FALSE; 02673 else 02674 return TRUE; 02675 }
|
|
return the IsEndPoint flag for the coordinate
Definition at line 2488 of file paths.cpp. 02489 { 02490 ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsEndPoint" ); 02491 02492 // Get the flags array 02493 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02494 02495 // and return the selected flag 02496 return Flags[CurrentPos].IsEndPoint; 02497 }
|
|
Determine if the path current position is still inside the path.
Definition at line 1045 of file paths.cpp. 01046 { 01047 // We are still in the path if the current position has not gone past the last valid 01048 // item in the path 01049 return ((CurrentPos>=0) && (CurrentPos<UsedSlots)); 01050 }
|
|
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.
Definition at line 10039 of file paths.cpp. 10040 { 10041 // Check path lengths for equality 10042 if (GetNumCoords() != OtherPath.GetNumCoords()) 10043 { 10044 // If not equal can't possibly be the same 10045 return FALSE; 10046 } 10047 10048 // Determine the transformation matrix from the first three coords 10049 DocCoord* ThisCoordArray = GetCoordArray(); 10050 DocCoord* OtherCoordArray = OtherPath.GetCoordArray(); 10051 10052 double a, b, c, d, e, f = Tolerance; // Matrix components 10053 10054 // Find First Non-Colinear points 10055 INT32 First = FindNonColinear(ThisCoordArray, GetNumCoords()); 10056 if (First == -1) 10057 { 10058 // this path was a straight line. 10059 // If the other one is we might be in with a chance 10060 First = FindNonColinear(OtherCoordArray, OtherPath.GetNumCoords()); 10061 if (First != -1) 10062 { 10063 // Unfortunately it had a kink so it can't match 10064 return FALSE; 10065 } 10066 // Shears don't work with the following. But then I doubt they're that common 10067 DocCoord ef(- ThisCoordArray[0].x, - ThisCoordArray[0].y); 10068 10069 DocCoord v1(ThisCoordArray[1].x - ThisCoordArray[0].x, ThisCoordArray[1].y - ThisCoordArray[0].y); 10070 DocCoord v2(OtherCoordArray[1].x - OtherCoordArray[0].x, OtherCoordArray[1].y - OtherCoordArray[0].y); 10071 double v1dotv2 = v1.x * v2.x + v1.y * v2.y; 10072 double modv1sqrd = v1.x * v1.x + v1.y * v1.y; 10073 double v1crossv2 = v1.x * v2.y - v1.y * v2.x; 10074 a = v1dotv2 / modv1sqrd; 10075 b = v1crossv2 / modv1sqrd; 10076 c = -b; 10077 d = a; 10078 e = a * (double)ef.x - b * (double)ef.y + OtherCoordArray[0].x; 10079 f = b * (double)ef.x + a * (double)ef.y + OtherCoordArray[0].y; 10080 } 10081 else 10082 { 10083 // We have three non-colinear points: 10084 10085 /* 10086 In fact, we have: 10087 ax00 + cy00 + e = x10 10088 bx00 + dy00 + f = y10 10089 & 10090 ax01 + cy01 + e = x11 10091 bx01 + dy01 + f = y11 10092 & 10093 ax02 + cy02 + e = x12 10094 bx02 + dy02 + f = y12 10095 10096 Hence need to solve 2 sets of simultaneous equations for (a,c,e) & (b,d,f) 10097 */ 10098 10099 // Try to find a solution for the a,b,e part 10100 CCVector3 x0s(ThisCoordArray[First].x, ThisCoordArray[First + 1].x, ThisCoordArray[First + 2].x); 10101 CCVector3 y0s(ThisCoordArray[First].y, ThisCoordArray[First + 1].y, ThisCoordArray[First + 2].y); 10102 CCVector3 x1s(OtherCoordArray[First].x, OtherCoordArray[First + 1].x, OtherCoordArray[First + 2].x); 10103 10104 if (!Solve3Simultaneous(x0s, x1s, y0s, a, c, e)) 10105 { 10106 return FALSE; 10107 } 10108 10109 // Try to find a solution for the (b,d,f) part 10110 CCVector3 y1s(OtherCoordArray[First].y, OtherCoordArray[First + 1].y, OtherCoordArray[First + 2].y); 10111 10112 if (!Solve3Simultaneous(x0s, y1s, y0s, b, d, f)) 10113 { 10114 return FALSE; 10115 } 10116 } 10117 10118 // Determine the transformation matrix from the first three coords 10119 Matrix Solution(a, b, c, d, INT32(e), INT32(f)); 10120 10121 // Check the flags & bits 10122 PathVerb* ThisVerbArray = GetVerbArray(); 10123 PathVerb* OtherVerbArray = OtherPath.GetVerbArray(); 10124 10125 INT32 lTolerance = (INT32)Tolerance; 10126 // For each remaining coordinate in this path, check we can transform to the otherPath 10127 DocCoord CurrentCoord; 10128 for (INT32 i = 0; i < GetNumCoords(); ++i) 10129 { 10130 // Transform(ThisCoordArray[i], a, b, c, d, e, f, CurrentCoord); 10131 10132 // Compare the flags & bits (unlikely to be different if coords same though) 10133 if (ThisVerbArray[i] != OtherVerbArray[i]) 10134 { 10135 return FALSE; 10136 } 10137 CurrentCoord = ThisCoordArray[i]; 10138 Solution.transform(&CurrentCoord); 10139 if (!IsNear(CurrentCoord.x, OtherCoordArray[i].x, lTolerance) || 10140 !IsNear(CurrentCoord.y, OtherCoordArray[i].y, lTolerance)) 10141 { 10142 return FALSE; 10143 } 10144 } 10145 10146 *pTransform = Solution; 10147 10148 return TRUE; 10149 }
|
|
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.
Definition at line 2563 of file paths.cpp. 02564 { 02565 #if !defined(EXCLUDE_FROM_RALPH) 02566 // Dereference a few pointers 02567 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 02568 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 02569 02570 // Start searching all the coords for EndPoints 02571 INT32 EndSlot = UsedSlots-1; 02572 for (INT32 i=UsedSlots-1; i>=0; i--) 02573 { 02574 // Are we at the start of a sub-path yet 02575 if (Verbs[i] == PT_MOVETO) 02576 { 02577 // Is this sub path open? 02578 if ((Verbs[EndSlot] & PT_CLOSEFIGURE) == 0) 02579 { 02580 // This is an open sub path, so test if they are close to the TestCoord 02581 if (BlobRect.ContainsCoord(Coords[i])) 02582 { 02583 *SlotNum = i; 02584 return TRUE; 02585 } 02586 02587 if (BlobRect.ContainsCoord(Coords[EndSlot])) 02588 { 02589 *SlotNum = EndSlot; 02590 return TRUE; 02591 } 02592 } 02593 02594 // That sub path did not intersect the rect, so carry on 02595 EndSlot = i-1; 02596 } 02597 } 02598 #endif 02599 // No luck, so fail 02600 return FALSE; 02601 }
|
|
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.
Definition at line 2617 of file paths.cpp. 02618 { 02619 // Do a quick sanity check 02620 if (index<0 || index>=UsedSlots || UsedSlots==0) 02621 return FALSE; 02622 02623 // 0<=index<=UsedSlots-1 02624 // Dereference the verbs 02625 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 02626 02627 // Check its not the end index 02628 INT32 end = index; 02629 FindEndElOfSubPath(&end); 02630 if (Verbs[end] & PT_CLOSEFIGURE) 02631 return FALSE; 02632 02633 if (end==index) 02634 return TRUE; 02635 02636 // Check for a start point 02637 return (Verbs[index]==PT_MOVETO); 02638 02639 }
|
|
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.
Definition at line 7065 of file paths.cpp. 07069 { 07070 double dist = SqrDistanceToPoint(ICoord, NearElement, mu); 07071 // if (IsUserName("Jim")) TRACE( _T("Distance from path = %f\n"),dist); 07072 if (dist<0) return FALSE; // return false (not close to path) 07073 return (dist<range); 07074 }
|
|
returns the Rotate flag for the coordinate
Definition at line 2536 of file paths.cpp. 02537 { 02538 ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsRotate" ); 02539 02540 // Get the flags array 02541 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02542 02543 // and return the selected flag 02544 return Flags[CurrentPos].IsRotate; 02545 }
|
|
return the Selected flag for the coordinate
Definition at line 2465 of file paths.cpp. 02466 { 02467 ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsSelected" ); 02468 02469 // Get the flags array 02470 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02471 02472 // and return the selected flag 02473 return Flags[CurrentPos].IsSelected; 02474 }
|
|
returns the Smooth flag for the Current Path Position
Definition at line 2512 of file paths.cpp. 02513 { 02514 ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsSmooth" ); 02515 02516 // Get the flags array 02517 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02518 02519 // and return the selected flag 02520 return Flags[CurrentPos].IsSmooth; 02521 }
|
|
Scans to the end of this subpath to see if it has the PT_CLOSEFIGURE flag set.
Definition at line 4722 of file paths.cpp. 04723 { 04724 INT32 i = Index; 04725 PathVerb* Verbs = GetVerbArray(); 04726 04727 // skip through until we hit the end or a MoveTo 04728 do 04729 { 04730 i++; 04731 } while (i<UsedSlots && Verbs[i] != PT_MOVETO); 04732 04733 // i points to the firsy element after this subpath (i.e. the top of the subpath) 04734 // Check the CloseFigure flag on the previous element to see if the subpath is closed 04735 if (Verbs[i-1] & PT_CLOSEFIGURE) 04736 return TRUE; 04737 return FALSE; 04738 }
|
|
determine if the path has a subselection
Definition at line 3684 of file paths.cpp. 03685 { 03686 // We need to find all the selected control points in the path and de-select them 03687 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 03688 03689 // look for a selected coord 03690 for (INT32 i=0; i<UsedSlots; i++) 03691 { 03692 // if we find one then return TRUE 03693 if (Flags[i].IsSelected) 03694 return TRUE; 03695 } 03696 03697 // we did not find one, so return FALSE 03698 return FALSE; 03699 }
|
|
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.
Definition at line 6164 of file paths.cpp. 06165 { 06166 // First, get some indices pointing at the start and end of these subpaths 06167 INT32 MainSubStart; // Start of subpath in main path (this) 06168 INT32 MainSubEnd; // End of subpath in this path 06169 INT32 OtherSubStart; // Start of subpath in other path 06170 INT32 OtherSubEnd; // End of subpath in other path 06171 06172 MainSubStart = MainSubEnd = MainIndex; 06173 FindStartOfSubPath(&MainSubStart); 06174 FindEndElOfSubPath(&MainSubEnd); 06175 06176 OtherSubStart = OtherSubEnd = OtherIndex; 06177 OtherPath->FindStartOfSubPath(&OtherSubStart); 06178 OtherPath->FindEndElOfSubPath(&OtherSubEnd); 06179 06180 ERROR2IF(((this == OtherPath) && (MainSubStart == OtherSubStart)), FALSE, "Attempted to join this subpath with itself"); 06181 06182 // Because we'll be messing around with the path, it's easier if we make the 06183 // two indices relative to the starts of their respective subpaths 06184 MainIndex = MainIndex - MainSubStart; 06185 OtherIndex = OtherIndex - OtherSubStart; 06186 06187 // Now that we know which subpaths we're interested in, let's see if we have to join the two paths 06188 06189 if (this != OtherPath) 06190 { 06191 // OtherPath is not the same, so copy it into this one and adjust the subpath indices 06192 OtherSubStart += UsedSlots; 06193 OtherSubEnd += UsedSlots; 06194 //OtherIndex += UsedSlots; 06195 if (!MergeTwoPaths(*OtherPath)) 06196 return FALSE; 06197 } 06198 06199 // Now this path contains both subpaths (and others, maybe) 06200 // If the subpaths were originally in the same path, it's possible that the other subpath 06201 // is below the main subpath. We don't want that possibility, so swap them if that's the case 06202 if (OtherSubStart < MainSubStart) 06203 { 06204 INT32 temp = OtherSubStart; 06205 OtherSubStart = MainSubStart; 06206 MainSubStart = temp; 06207 temp = OtherSubEnd; 06208 OtherSubEnd = MainSubEnd; 06209 MainSubEnd = temp; 06210 temp = OtherIndex; 06211 OtherIndex = MainIndex; 06212 MainIndex = temp; 06213 } 06214 06215 // See if the two subpaths are adjacent now 06216 if (OtherSubStart - MainSubEnd >1) 06217 { 06218 // The two subpaths are not adjacent, so let's shuffle the path around... 06219 // It's just possible that the Othersection might be at the top of the path so move the 06220 // main section to the top. 06221 CurrentPos = UsedSlots; 06222 if (!MakeSpaceInPath(MainSubEnd-MainSubStart+1)) 06223 return FALSE; 06224 if (!InsertSectionAtEnd(this, MainSubStart, MainSubEnd-MainSubStart+1)) 06225 return FALSE; 06226 DeleteSection( MainSubStart, MainSubEnd-MainSubStart+1); 06227 06228 // Recalculate the subpath indices 06229 MainSubEnd = MainSubEnd-MainSubStart+1; // Change into length 06230 MainSubStart = UsedSlots - MainSubEnd; 06231 OtherSubStart -= MainSubEnd; 06232 OtherSubEnd -= MainSubEnd; 06233 MainSubEnd = UsedSlots-1; 06234 06235 // Now, are the subpaths adjacent? Main is now above Other 06236 if (MainSubStart - OtherSubEnd > 1) 06237 { 06238 // Do the same as above, but with Other instead of Main 06239 CurrentPos = UsedSlots; 06240 if (!MakeSpaceInPath(OtherSubEnd-OtherSubStart+1)) 06241 return FALSE; 06242 if (!InsertSectionAtEnd(this, OtherSubStart, OtherSubEnd-OtherSubStart+1)) 06243 return FALSE; 06244 DeleteSection( OtherSubStart, OtherSubEnd-OtherSubStart+1); 06245 06246 // Recalculate the subpath indices 06247 OtherSubEnd = OtherSubEnd-OtherSubStart+1; // Change into length 06248 OtherSubStart = UsedSlots - OtherSubEnd; 06249 MainSubStart -= OtherSubEnd; 06250 MainSubEnd -= OtherSubEnd; 06251 OtherSubEnd = UsedSlots-1; 06252 06253 06254 } 06255 06256 if (OtherSubStart < MainSubStart) 06257 { 06258 // Swap Main and Other indices 06259 INT32 temp = MainSubStart; 06260 MainSubStart = OtherSubStart; 06261 OtherSubStart = temp; 06262 temp = MainSubEnd; 06263 MainSubEnd = OtherSubEnd; 06264 OtherSubEnd = temp; 06265 temp = OtherIndex; 06266 OtherIndex = MainIndex; 06267 MainIndex = temp; 06268 } 06269 } 06270 06271 // Now we are guaranteed that the two subpaths are adjacent and that Main is below Other 06272 // Let's see if we have to reverse anything 06273 MainIndex+=MainSubStart; 06274 OtherIndex+=OtherSubStart; 06275 06276 if (MainIndex == MainSubStart) 06277 { 06278 // Because Main is below Other, this means we have to reverse this subpath... 06279 ReverseSection(MainSubStart, MainSubEnd-MainSubStart+1); 06280 MainIndex = MainSubEnd; 06281 } 06282 06283 if (OtherIndex == OtherSubEnd) 06284 { 06285 // We have to reverse the other subpath 06286 ReverseSection(OtherSubStart, OtherSubEnd-OtherSubStart+1); 06287 OtherIndex = OtherSubStart; 06288 } 06289 06290 // At INT32 last, it's possible just to join the subpaths - we do this by deleting the 06291 // MoveTo between them. 06292 DeleteSection(OtherSubStart,1); 06293 06294 // And clear selection, then select just the point we want 06295 ClearSubSelection(); 06296 PathVerb* Verbs = GetVerbArray(); 06297 PathFlags* Flags = GetFlagArray(); 06298 Flags[MainSubEnd].IsSelected = TRUE; 06299 if (Verbs[MainSubEnd] == PT_BEZIERTO) 06300 Flags[MainSubEnd-1].IsSelected = TRUE; 06301 if (Verbs[MainSubEnd+1] == PT_BEZIERTO) 06302 Flags[MainSubEnd+1].IsSelected = TRUE; 06303 06304 return TRUE; 06305 }
|
|
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.
Definition at line 7716 of file paths.cpp. 07717 { 07718 // Validate the input params 07719 ERROR3IF(Start>(UsedSlots-1),"MakePathFromSection given an illegal start index"); 07720 if (Start > (UsedSlots-1)) 07721 return FALSE; 07722 07723 ERROR3IF((Start+Length)>UsedSlots,"MakePathFromSection given an illegal Length"); 07724 if ((Start+Length) > UsedSlots) 07725 return FALSE; 07726 07727 // PathVerb* SourceVerbs = GetVerbArray(); 07728 07729 BOOL ok = MergeSectionTo(Start, Length, pDestin, 0); 07730 if (ok) 07731 { 07732 PathVerb* pDestinVerbs = pDestin->GetVerbArray(); 07733 pDestinVerbs[0] = PT_MOVETO; 07734 } 07735 return ok; 07736 }
|
|
Makes a subpath into a path in its own right. > BOOL Path::MakePathFromSubPath(const INT32 lSubpathIndex, Path* ppthToFill)
Definition at line 10230 of file paths.cpp. 10231 { 10232 //Check our variables 10233 ERROR2IF(ppthToFill==NULL,FALSE, "Path::MakePathFromSubPath - null parameter"); 10234 ERROR2IF(lSubpathIndex>(GetNumSubpaths()-1),FALSE, "Path::MakePathFromSubPath - null parameter"); 10235 10236 //First we must find the start and end of the subpath 10237 10238 //This variable will find the start of the subpath 10239 INT32 lStart=0; 10240 10241 //For each subpath we must skip over 10242 for (INT32 l=0; l<lSubpathIndex; l++) 10243 { 10244 //Move to the end of the current subpath 10245 FindEndElOfSubPath(&lStart); 10246 10247 //Move on one place to take us into the next subpath 10248 lStart++; 10249 10250 //And if we haven't overshot the end of the path 10251 if (lStart<GetNumCoords()) 10252 { 10253 //Move to the beginning of that subpath 10254 FindStartOfSubPath(&lStart); 10255 } 10256 } 10257 10258 //If we have overshot the end of the path, return FALSE 10259 ERROR2IF(lStart>GetNumCoords(),FALSE, "Path::MakePathFromSubPath failed"); 10260 10261 //lLookPos is now pointing to the start of the subpath we want to copy 10262 //This variable will find the end of that subpath 10263 INT32 lEnd=lStart; 10264 10265 //And move it to the end of the subpath 10266 FindEndElOfSubPath(&lEnd); 10267 10268 //Now, copy the subpath into the path 10269 MakePathFromSection(lStart, (lEnd-lStart+1), ppthToFill); 10270 10271 //And return TRUE 10272 return TRUE; 10273 }
|
|
Will make enough room for NumSlots unused slots at the end of the path.
Definition at line 3907 of file paths.cpp. 03908 { 03909 ERROR2IF(SlotAllocSize <= 0,FALSE,"MakeSpaceAtEnd has ZERO Slot Allocation Size!"); 03910 if (UnUsedSlots<NumSlots) 03911 { 03912 // Find out how many slots to ask for and make sure it is a multiple of 4 03913 INT32 SlotsNeeded = NumSlots-UnUsedSlots; 03914 SlotsNeeded = ((INT32)(SlotsNeeded/SlotAllocSize))*SlotAllocSize+SlotAllocSize; 03915 SlotsNeeded = ((SlotsNeeded+3) >> 2) << 2; 03916 03917 // we are out of spare slots, so try to alloc some extra ones 03918 if (!IncreaseBlock(VerbHandle, sizeof(PathVerb)*SlotsNeeded)) 03919 return FALSE; 03920 03921 if (!IncreaseBlock(CoordHandle, sizeof(DocCoord)*SlotsNeeded)) 03922 return FALSE; 03923 03924 if (!IncreaseBlock(FlagsHandle, sizeof(PathFlags)*SlotsNeeded)) 03925 return FALSE; 03926 03927 if (ExtraInfo != NULL) 03928 if (!ExtraInfo->IncreaseExtraBlocks(SlotsNeeded)) 03929 return FALSE; 03930 03931 // Got the memory back that we asked for, so update a few vars 03932 UnUsedSlots += SlotsNeeded; 03933 } 03934 return TRUE; 03935 }
|
|
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.
Definition at line 3883 of file paths.cpp. 03884 { 03885 if (!MakeSpaceAtEnd(NumSlots)) 03886 return FALSE; 03887 03888 return OpenGap(NumSlots,Position); 03889 }
|
|
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.
Definition at line 3857 of file paths.cpp. 03858 { 03859 if (!MakeSpaceAtEnd(NumSlots)) 03860 return FALSE; 03861 03862 return OpenGap(NumSlots,CurrentPos); 03863 }
|
|
Alters the mapping of the Width Information to one of the ExtraInfo channels.
Definition at line 8313 of file paths.cpp. 08314 { 08315 ENSURE(Index <= NUMEXTRACHANNELS, "Index out of range in MapWidth()"); 08316 08317 ExtraInfo->MapWidthInfo(Index); 08318 }
|
|
Copies a specified section from a source path to a specified position in this path.
Definition at line 6061 of file paths.cpp. 06062 { 06063 06064 // Make space to copy all the data from the other path into this one 06065 CurrentPos = DestinPos; 06066 if (!MakeSpaceInPath(Length)) 06067 // Failed to get extra memory 06068 return FALSE; 06069 06070 // We will need all the arrays for both paths 06071 DocCoord* DCoords = (DocCoord*) DescribeHandle(CoordHandle); 06072 PathFlags* DFlags = (PathFlags*) DescribeHandle(FlagsHandle); 06073 PathVerb* DVerbs = (PathVerb*) DescribeHandle(VerbHandle); 06074 06075 DocCoord* SCoords = (DocCoord*) DescribeHandle(Source.CoordHandle); 06076 PathFlags* SFlags = (PathFlags*) DescribeHandle(Source.FlagsHandle); 06077 PathVerb* SVerbs = (PathVerb*) DescribeHandle(Source.VerbHandle); 06078 06079 // Copy all the data 06080 memmove((void*)(DCoords+DestinPos), (void*)(SCoords+SourcePos), Length*sizeof(DocCoord)); 06081 memmove((void*)(DVerbs+DestinPos), (void*)(SVerbs+SourcePos), Length*sizeof(PathVerb)); 06082 memmove((void*)(DFlags+DestinPos), (void*)(SFlags+SourcePos), Length*sizeof(PathFlags)); 06083 06084 UsedSlots+=Length; 06085 UnUsedSlots-=Length; 06086 06087 // and say that it worked 06088 return TRUE; 06089 }
|
|
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.
Definition at line 6110 of file paths.cpp. 06111 { 06112 // Make space to copy all the data this path to the destination 06113 06114 Destin->CurrentPos = DestinPos; 06115 if (!Destin->MakeSpaceInPath(Length)) 06116 // Failed to get extra memory 06117 return FALSE; 06118 06119 // We will need all the arrays for both paths 06120 DocCoord* SCoords = (DocCoord*) DescribeHandle(CoordHandle); 06121 PathFlags* SFlags = (PathFlags*) DescribeHandle(FlagsHandle); 06122 PathVerb* SVerbs = (PathVerb*) DescribeHandle(VerbHandle); 06123 06124 DocCoord* DCoords = (DocCoord*) DescribeHandle(Destin->CoordHandle); 06125 PathFlags* DFlags = (PathFlags*) DescribeHandle(Destin->FlagsHandle); 06126 PathVerb* DVerbs = (PathVerb*) DescribeHandle(Destin->VerbHandle); 06127 06128 // Copy all the data 06129 memmove((void*)(DCoords+DestinPos), (void*)(SCoords+SourcePos), Length*sizeof(DocCoord)); 06130 memmove((void*)(DVerbs+DestinPos), (void*)(SVerbs+SourcePos), Length*sizeof(PathVerb)); 06131 memmove((void*)(DFlags+DestinPos), (void*)(SFlags+SourcePos), Length*sizeof(PathFlags)); 06132 06133 Destin->UsedSlots+=Length; 06134 Destin->UnUsedSlots-=Length; 06135 06136 // and say that it worked 06137 return TRUE; 06138 }
|
|
Appends the data in the three given arrays to the arrays in this path.
Definition at line 5340 of file paths.cpp. 05341 { 05342 // Do we have enough room? 05343 if (UnUsedSlots < Length) 05344 return FALSE; 05345 05346 // We will need all the arrays for both paths 05347 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 05348 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 05349 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 05350 05351 // Copy all the data 05352 INT32 DestPos = UsedSlots; 05353 for (INT32 i=0; i<Length; i++) 05354 { 05355 // Copy this coord and its associated data 05356 Coords[DestPos] = OtherCoords[i]; 05357 Flags[DestPos] = OtherFlags[i]; 05358 Verbs[DestPos] = OtherVerbs[i]; 05359 05360 // move to the next position 05361 DestPos++; 05362 UsedSlots++; 05363 UnUsedSlots--; 05364 } 05365 05366 // If the other path was closed and marked as filled, then 05367 // the new path should also be filled 05368 if (Filled) 05369 IsFilled = TRUE; 05370 05371 // Put current pos to the end of the used slots 05372 CurrentPos = UsedSlots; 05373 05374 // and say that it worked 05375 return TRUE; 05376 }
|
|
Combines the two paths into a single complex path.
Definition at line 5309 of file paths.cpp. 05310 { 05311 // Make space to copy all the data from the other path into this one 05312 CurrentPos = UsedSlots; 05313 if (!MakeSpaceInPath(Other.UsedSlots)) 05314 return FALSE; 05315 05316 DocCoord* OtherCoords = (DocCoord*) DescribeHandle(Other.CoordHandle); 05317 PathVerb* OtherVerbs = (PathVerb*) DescribeHandle(Other.VerbHandle); 05318 PathFlags* OtherFlags = (PathFlags*) DescribeHandle(Other.FlagsHandle); 05319 05320 return MergeTwoPaths(OtherCoords,OtherVerbs,OtherFlags,Other.UsedSlots,Other.IsFilled); 05321 }
|
|
Definition at line 525 of file paths.h.
|
|
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.
Definition at line 9268 of file paths.cpp. 09269 { 09270 // New implementation by Markn 15/2/95 09271 // This version will return 2 when there's a selected point in the middle of a line. The old code 09272 // returned 1 in this case 09273 09274 INT32 Index = -1; 09275 INT32 EndIndex = -1; 09276 INT32 LastEndIndex = -1; 09277 INT32 NumSplinters = 0; 09278 BOOL SubPathOpen; 09279 09280 PathVerb* pVerbs = GetVerbArray(); 09281 09282 while (Index++, FindNextSelected(&Index)) 09283 { 09284 PathVerb Verb = pVerbs[Index] & ~PT_CLOSEFIGURE; 09285 09286 // Ignore selected moveto elements 09287 if (Verb == PT_MOVETO) 09288 continue; 09289 09290 EndIndex = Index; 09291 FindEndElOfSubPath(&EndIndex); // returns index of last element in this subpath/path 09292 SubPathOpen = !(pVerbs[EndIndex] & PT_CLOSEFIGURE); 09293 09294 // ignore selected end points when the subpath is open 09295 if (Index == EndIndex && SubPathOpen) 09296 continue; 09297 09298 NumSplinters++; 09299 09300 if (EndIndex != LastEndIndex) 09301 { 09302 LastEndIndex = EndIndex; 09303 09304 // if we have found a selected point in the middle of an open subpath 09305 // an extra splinter will be produced. 09306 if (SubPathOpen) 09307 NumSplinters++; 09308 } 09309 } 09310 09311 return NumSplinters; 09312 09313 /* 09314 // Get array of verbs 09315 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 09316 09317 // p,q indexes to selected point and endof(sub)path 09318 // vp,vq local verb holders 09319 09320 INT32 p = -1; 09321 INT32 q = -1; 09322 PathVerb vp; 09323 PathVerb vq; 09324 09325 INT32 splinters = 0; 09326 while (p++, FindNextSelected(&p)) 09327 { 09328 q = p; 09329 09330 FindEndElOfSubPath(&q); // returns index of last element in this subpath/path 09331 if (p>q) break; // just a quick check on sanity. 09332 09333 if (p==q) 09334 { 09335 if (!(Verbs[p] & PT_CLOSEFIGURE)) continue; // ignore selected points at end of open subpaths 09336 } 09337 09338 vp = (Verbs[p] & ~PT_CLOSEFIGURE); 09339 vq = (Verbs[q]); 09340 09341 if (vp==PT_MOVETO) 09342 { 09343 if (!(vq & PT_CLOSEFIGURE)) // is this sub path already open? 09344 { 09345 p++; // move forward past moveto 09346 continue; // continue do loop 09347 } 09348 } 09349 09350 if ((vp == PT_MOVETO) || (vp == PT_LINETO) || (vp == PT_BEZIERTO)) 09351 splinters++; 09352 } 09353 09354 return splinters; 09355 */ 09356 }
|
|
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.
Definition at line 3976 of file paths.cpp. 03977 { 03978 if (UnUsedSlots<NumSlots) 03979 { 03980 ERROR3("Path::OpenGap() overflow: Gap request is too large"); 03981 return FALSE; 03982 } 03983 03984 if (Position<0 || Position>UsedSlots) 03985 { 03986 ERROR3("Path::OpenGap() called with an illegal gap position"); 03987 return FALSE; 03988 } 03989 03990 INT32 SlotsToMove = UsedSlots-Position; 03991 03992 if (SlotsToMove>0) 03993 { 03994 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 03995 memmove( (void*)(&Verbs[Position+NumSlots]), (void*)(&Verbs[Position]), SlotsToMove*sizeof(PathVerb) ); 03996 03997 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 03998 memmove( (void*)&Coords[Position+NumSlots], (void*)&Coords[Position], SlotsToMove*sizeof(DocCoord) ); 03999 04000 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 04001 memmove( (void*)&Flags[Position+NumSlots], (void*)&Flags[Position], SlotsToMove*sizeof(PathFlags) ); 04002 04003 if (ExtraInfo != NULL) 04004 ExtraInfo->ShiftUpExtraInfo(Position, NumSlots, SlotsToMove); 04005 } 04006 04007 return TRUE; 04008 }
|
|
Will open a gap of NumSlots size in this path. The gap is positioned at CurrentPos (A path class variable).
Definition at line 3951 of file paths.cpp. 03952 { 03953 return OpenGap(NumSlots, CurrentPos); 03954 }
|
|
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.
Definition at line 7163 of file paths.cpp. 07164 { 07165 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARLIB) 07166 /* 07167 double d; 07168 INT32 Near; 07169 double Param; 07170 07171 d = SqrDistanceToPoint(pos, &Near, &Param); 07172 07173 TRACE( _T("Index=%d\n"),Near); 07174 07175 DocCoord coord; 07176 coord = ClosestPointTo(Param, Near); 07177 07178 TRACE( _T("x=%d, y=%d\n"),coord.x,coord.y); 07179 07180 */ 07181 07182 DocRect temp; 07183 GetApplication()->GetBlobManager()->GetBlobRect(DocCoord(0,0),&temp); 07184 double mu; 07185 INT32 width = (temp.Width())/2; 07186 return (IsPointCloseTo(pos, width*width, position, &mu)); 07187 07188 // return(FALSE); 07189 #else 07190 return FALSE; 07191 #endif 07192 }
|
|
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.
Definition at line 7827 of file paths.cpp. 07828 { 07829 // when flattening, flatten curves but dont quantise lines 07830 ProcessFlags QuantFlags(TRUE,TRUE); 07831 return CreateFlatPath(QuantFlags, threshold, pOutput); 07832 }
|
|
Draws all the selection blobs for a path. Useful for putting the blobs on or taking them back off again.
Definition at line 3001 of file paths.cpp. 03002 { 03003 #if !defined(EXCLUDE_FROM_RALPH) 03004 // Dereference the pointers 03005 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 03006 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 03007 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 03008 03009 BOOL PrevIsEndPoint; 03010 DocCoord StartCoord = Coords[0]; 03011 03012 // loop through the path and render each of the blobs 03013 INT32 endcount = 0; // Count the number of selected endpoints 03014 INT32 EndPtIndex = 0; // Index of only selected endpoint 03015 for (INT32 i=0; i<UsedSlots; i++) 03016 { 03017 if (Flags[i].IsEndPoint) 03018 { 03019 // Render a blob 03020 if (!((Verbs[i] & PT_CLOSEFIGURE) && Coords[i]==StartCoord)) 03021 { 03022 DrawBlob(pRender, Coords[i], Flags[i].IsSelected); 03023 // count the number of selected endpoints 03024 if (Flags[i].IsSelected) 03025 { 03026 EndPtIndex = i; 03027 endcount++; 03028 } 03029 } 03030 //GdiFlush(); 03031 PrevIsEndPoint = TRUE; 03032 if (Verbs[i] == PT_MOVETO) 03033 StartCoord = Coords[i]; 03034 } 03035 } 03036 // Now render the control point blobs if there was just one selected endpoint 03037 if (endcount == 1) 03038 { 03039 RenderPathControlBlobs(pRender, EndPtIndex); 03040 } 03041 #endif 03042 }
|
|
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).
Definition at line 2974 of file paths.cpp. 02975 { 02976 #if !defined(EXCLUDE_FROM_RALPH) 02977 // Go into a RenderOnTop loop 02978 RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR); 02979 while (pRender!=NULL) 02980 { 02981 RenderPathBlobs(pRender); 02982 pRender = DocView::GetNextOnTop(NULL); 02983 } 02984 #endif 02985 }
|
|
Draws all the control points selection blobs for a path. Used by RenderPathBlobs and also the Bezier tool.
Definition at line 3216 of file paths.cpp. 03217 { 03218 #if !defined(EXCLUDE_FROM_RALPH) 03219 // Dereference the pointers 03220 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 03221 // PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 03222 03223 // Render the appropriate control points 03224 // We render the two control points adjacent to the only 03225 // selected endpoint, but we also render the two control points beyond 03226 // those, because their positions might affect the curve. 03227 // A special case is when we have a closed path containing 03228 // only a moveto and a curveto (it could happen) in which case 03229 // we'll have to spot that, and only render two controls instead 03230 // of four 03231 03232 // find the index of the previous ctrl point of this endpoint 03233 INT32 i = FindPrevControlPoint(EndPtIndex); 03234 if (i>=0) 03235 { 03236 DrawControlBlob(pRender, Coords[i]); 03237 DrawControlLine(pRender, Coords[i], Coords[EndPtIndex]); 03238 DrawControlBlob(pRender, Coords[i-1]); 03239 DrawControlLine(pRender, Coords[i-1], Coords[i-2]); 03240 } 03241 03242 // now do the next control point. Don't render if the next 03243 // is still part of the same path 03244 INT32 j = FindNextControlPoint(EndPtIndex); 03245 if (j>=0 && j!=i-1) 03246 { 03247 DrawControlBlob(pRender, Coords[j]); 03248 DrawControlLine(pRender, Coords[j], Coords[EndPtIndex]); 03249 03250 DrawControlBlob(pRender, Coords[j+1]); 03251 DrawControlLine(pRender, Coords[j+1], Coords[j+2]); 03252 } 03253 #endif 03254 }
|
|
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.
Definition at line 3187 of file paths.cpp. 03188 { 03189 #if !defined(EXCLUDE_FROM_RALPH) 03190 // Go into a RenderOnTop loop 03191 RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR); 03192 while (pRender!=NULL) 03193 { 03194 RenderPathControlBlobs(pRender,EndPtIndex); 03195 pRender = DocView::GetNextOnTop(NULL); 03196 } 03197 #endif 03198 }
|
|
Draws all the selection blobs and pen blobs for a path. Useful for putting the blobs on or taking them back off again.
Definition at line 3298 of file paths.cpp. 03299 { 03300 #if !defined(EXCLUDE_FROM_RALPH) 03301 // Dereference the pointers 03302 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 03303 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 03304 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 03305 03306 DocCoord StartCoord = Coords[0]; 03307 INT32 SelEndPts = 0; 03308 03309 // loop through the path and render each of the blobs 03310 INT32 EndPtIndex = 0; // Index of only selected endpoint 03311 INT32 i; 03312 for (i=0; i<UsedSlots; i++) 03313 { 03314 if (Flags[i].IsEndPoint) 03315 { 03316 // Render a blob 03317 if (!((Verbs[i] & PT_CLOSEFIGURE) && Coords[i]==StartCoord)) 03318 { 03319 DrawBlob(pRegion, Coords[i], Flags[i].IsSelected); 03320 // count the number of selected endpoints 03321 if (Flags[i].IsSelected) 03322 { 03323 EndPtIndex = i; 03324 SelEndPts++; 03325 } 03326 } 03327 if (Verbs[i] == PT_MOVETO) 03328 StartCoord = Coords[i]; 03329 } 03330 } 03331 03332 // now make sure the correct control handles are drawn 03333 if (SelEndPts == 1) 03334 { 03335 if (Flags[EndPtIndex].IsRotate && IsOpenEnd(EndPtIndex)) 03336 { 03337 if (Verbs[EndPtIndex] == PT_MOVETO) 03338 i = FindNextControlPoint(EndPtIndex); 03339 else 03340 i = FindPrevControlPoint(EndPtIndex); 03341 03342 if (i>=0) 03343 { 03344 DocCoord GhostPt; 03345 GhostPt.x = Coords[EndPtIndex].x - (Coords[i].x - Coords[EndPtIndex].x); 03346 GhostPt.y = Coords[EndPtIndex].y - (Coords[i].y - Coords[EndPtIndex].y); 03347 03348 pRegion -> SetLineColour(COLOUR_BEZIERLINE); 03349 pRegion -> SetFillColour(COLOUR_TRANS); 03350 pRegion -> DrawLine(GhostPt, Coords[i]); 03351 03352 pRegion -> SetLineColour(COLOUR_TRANS); 03353 pRegion -> SetFillColour(COLOUR_UNSELECTEDBLOB); 03354 pRegion -> DrawBlob(GhostPt, BT_UNSELECTED); 03355 pRegion -> DrawBlob(Coords[i], BT_UNSELECTED); 03356 } 03357 } 03358 } 03359 #endif 03360 }
|
|
Draws all the selection blobs and pen blobs for a path. Useful for putting the blobs on or taking them back off again.
Definition at line 3272 of file paths.cpp. 03273 { 03274 #if !defined(EXCLUDE_FROM_RALPH) 03275 // Go into a RenderOnTop loop 03276 RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR); 03277 while (pRender!=NULL) 03278 { 03279 RenderPathPenBlobs(pRender); 03280 pRender = DocView::GetNextOnTop(NULL); 03281 } 03282 #endif 03283 }
|
|
Draws all the control points selection blobs for an entire path into a specified render region. Called by the above function.
Definition at line 3097 of file paths.cpp. 03098 { 03099 #if !defined(EXCLUDE_FROM_RALPH) 03100 ERROR3IF(pSpread == NULL, "pSpread was NULL"); 03101 ERROR3IF(pRender == NULL, "pRender was NULL"); 03102 if ((pRender == NULL) || (pSpread == NULL)) 03103 return ; 03104 03105 // loop through the path and count the selected blobs 03106 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 03107 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 03108 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 03109 const INT32 NumCoords = GetNumCoords(); 03110 INT32 endcount = 0; // Count the number of selected endpoints 03111 INT32 EndPtIndex = 0; // Index of only selected endpoint 03112 for (INT32 i=0; i<NumCoords; i++) 03113 { 03114 if (Flags[i].IsEndPoint && Flags[i].IsSelected) 03115 { 03116 if (!(Verbs[i] & PT_CLOSEFIGURE)) 03117 { 03118 EndPtIndex = i; 03119 endcount++; 03120 DrawBlob(pRender, Coords[i], TRUE); 03121 DrawBlob(pRender, Coords[i], FALSE); 03122 } 03123 } 03124 } 03125 if (endcount == 1) 03126 { 03127 // Remove the control points and lines 03128 RenderPathControlBlobs(pRender, EndPtIndex); 03129 } 03130 #endif 03131 }
|
|
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.
Definition at line 3061 of file paths.cpp. 03062 { 03063 #if !defined(EXCLUDE_FROM_RALPH) 03064 // If removing then render on into pending render regions first 03065 // if (Removing) 03066 // RenderSelectedControlBlobsToPendingRegions(pSpread); 03067 03068 // Render the blobs on the path 03069 RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR); 03070 while (pRender!=NULL) 03071 { 03072 RenderPathSelectedControlBlobs(pSpread, pRender); 03073 pRender = DocView::GetNextOnTop(NULL); 03074 } 03075 03076 // If putting back on then render back off in pender render regions 03077 // if (!Removing) 03078 // RenderSelectedControlBlobsToPendingRegions(pSpread); 03079 #endif 03080 }
|
|
Draws all the control points selection blobs for an entire path into all the pending render regions.
Definition at line 3147 of file paths.cpp. 03148 { 03149 #if !defined(EXCLUDE_FROM_RALPH) 03150 RenderRegionList* pRegionList = GetApplication()->GetRegionList(); 03151 if (!pRegionList->IsEmpty()) 03152 { 03153 RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead(); 03154 03155 while (pRegion != NULL) 03156 { 03157 // Check the RenderRegion is for the same spread. 03158 if (pRegion->GetRenderSpread() == pSpread) 03159 { 03160 // Render the blobs into this Render Region. 03161 RenderPathSelectedControlBlobs(pSpread, pRegion); 03162 } 03163 03164 // Get the Next render region 03165 pRegion = (RenderRegion*)pRegionList->GetNext(pRegion); 03166 } 03167 } 03168 #endif 03169 }
|
|
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.
Definition at line 7339 of file paths.cpp. 07340 { 07341 // Saftey Checks 07342 ENSURE( StartSlot<UsedSlots, "PathPosition is off end of path in Path::RetroReplaceSection" ); 07343 ENSURE( StartSlot>=0, "PathPosition is off beginning of path in Path::RetroReplaceSection" ); 07344 07345 // Make enough space in the path to copy the new path in after the marked section has been removed 07346 INT32 SlotsToAdd = NewPath->UsedSlots - Len; 07347 if (SlotsToAdd>0) 07348 { 07349 // We need more space as the new path is bigger than the gap 07350 CurrentPos = StartSlot+1; 07351 if (!MakeSpaceInPath(SlotsToAdd)) 07352 // Failed to get the memory, so fail 07353 return FALSE; 07354 07355 // Update the usage counters 07356 UsedSlots += SlotsToAdd; 07357 UnUsedSlots -= SlotsToAdd; 07358 } 07359 07360 // Dereference the pointers 07361 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 07362 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 07363 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 07364 07365 // If the section to be replaced is bigger than the new path, then we should move the end of 07366 // the path down a bit 07367 if (SlotsToAdd<0) 07368 { 07369 // Find out how much memory to move about 07370 INT32 SlotToMoveFrom = StartSlot+Len; 07371 INT32 SlotToMoveTo = StartSlot+NewPath->UsedSlots; 07372 INT32 SlotsToMove = UsedSlots-SlotToMoveFrom; 07373 07374 // Does it need moving 07375 if (SlotsToMove>0) 07376 { 07377 // yep, move it 07378 memmove((void*)(&Verbs[SlotToMoveTo]), (void*)(&Verbs[SlotToMoveFrom]), SlotsToMove*sizeof(PathVerb)); 07379 memmove((void*)(&Flags[SlotToMoveTo]), (void*)(&Flags[SlotToMoveFrom]), SlotsToMove*sizeof(PathFlags)); 07380 memmove((void*)(&Coords[SlotToMoveTo]), (void*)(&Coords[SlotToMoveFrom]), SlotsToMove*sizeof(DocCoord)); 07381 } 07382 07383 // Change the path flags (SlotsToAdd is negative in here) 07384 UsedSlots += SlotsToAdd; 07385 UnUsedSlots -= SlotsToAdd; 07386 } 07387 07388 // Find out about the pointers to the new path 07389 PathVerb* NewVerbs = (PathVerb*) DescribeHandle(NewPath->VerbHandle); 07390 DocCoord* NewCoords = (DocCoord*) DescribeHandle(NewPath->CoordHandle); 07391 PathFlags* NewFlags = (PathFlags*) DescribeHandle(NewPath->FlagsHandle); 07392 07393 // Now we have to copy NewPath into the hole 07394 INT32 ReadStart, ReadLen, WriteStart; 07395 07396 // Work out which section we are copying 07397 if (KeepStart) 07398 { 07399 // Here we are keeping the initial moveto in the replacement path 07400 ReadStart = 0; 07401 ReadLen = NewPath->UsedSlots; 07402 WriteStart = StartSlot; 07403 } 07404 else 07405 { 07406 // Here we are throwing away the Moveto in the replacement path 07407 ReadStart = 1; 07408 ReadLen = NewPath->UsedSlots-1; 07409 WriteStart = StartSlot+1; 07410 } 07411 07412 // Go though the path replacing all the relavent sections 07413 for (INT32 i=ReadStart; i<ReadStart+ReadLen; i++) 07414 { 07415 // Copy the data from the new path into the old path 07416 Verbs[WriteStart] = NewVerbs[i]; 07417 Flags[WriteStart] = NewFlags[i]; 07418 Coords[WriteStart] = NewCoords[i]; 07419 07420 // increment the destination slot 07421 WriteStart++; 07422 } 07423 07424 // See if this is a closed shape 07425 TryToClose(); 07426 07427 // All worked, so return happy 07428 return TRUE; 07429 }
|
|
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.
Definition at line 5080 of file paths.cpp. 05081 { 05082 ReverseSection(0, UsedSlots); 05083 }
|
|
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.
Definition at line 5100 of file paths.cpp. 05101 { 05102 // We will need to change all the arrays 05103 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 05104 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 05105 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 05106 05107 // First we will reverse all the Coords and their flags 05108 INT32 LastPos = FirstPos+SubPathLen-1; 05109 INT32 Start = FirstPos; 05110 DocCoord SwapCoord; 05111 PathFlags SwapFlag; 05112 while (FirstPos<LastPos) 05113 { 05114 // change the order of the coords in the array 05115 SwapCoord = Coords[FirstPos]; 05116 Coords[FirstPos] = Coords[LastPos]; 05117 Coords[LastPos] = SwapCoord; 05118 05119 // Change the order of the flags associated with the coord 05120 SwapFlag = Flags[FirstPos]; 05121 Flags[FirstPos] = Flags[LastPos]; 05122 Flags[LastPos] = SwapFlag; 05123 05124 // find the next two coords/flags to swap 05125 FirstPos++; 05126 LastPos--; 05127 } 05128 05129 // Now reverse the verbs. 05130 // The first verb always stays as a MoveTo and everything else gets sorted around it 05131 FirstPos = Start+1; 05132 LastPos = Start+SubPathLen-1; 05133 PathVerb SwapVerb; 05134 while (FirstPos<LastPos) 05135 { 05136 SwapVerb = Verbs[FirstPos]; 05137 Verbs[FirstPos] = Verbs[LastPos]; 05138 Verbs[LastPos] = SwapVerb; 05139 05140 // Find the next two verbs to swap 05141 FirstPos++; 05142 LastPos--; 05143 } 05144 05145 // added by Ed 23/5/95 - fix up screwed up closed paths! 05146 // ie first element of subpath has PT_CLOSEFIGURE rather than last! 05147 INT32 StartOfSubPath = Start; 05148 INT32 EndElOfLastSubPath = Start+SubPathLen-1; 05149 05150 #ifdef _DEBUG 05151 // check assumption that we are reversing a set of complete subpaths 05152 INT32 temp=StartOfSubPath; 05153 FindStartOfSubPath(&temp); 05154 ERROR3IF(StartOfSubPath!=temp,"Path::ReverseSection() - section does not start at the start of a subpath"); 05155 temp=EndElOfLastSubPath-1; 05156 FindEndElOfSubPath(&temp); 05157 ERROR3IF(EndElOfLastSubPath!=temp,"Path::ReverseSection() - section does not end at the end of a subpath"); 05158 #endif 05159 05160 // for each subpath, if the second element has an erroneous PT_CLOSEFIGURE, 05161 // move it to the end element of the subpath 05162 while (StartOfSubPath<=EndElOfLastSubPath) 05163 { 05164 INT32 EndElOfSubPath=StartOfSubPath; 05165 FindEndElOfSubPath(&EndElOfSubPath); 05166 if (Verbs[StartOfSubPath+1] & PT_CLOSEFIGURE) 05167 { 05168 Verbs[StartOfSubPath+1]&=~PT_CLOSEFIGURE; 05169 Verbs[EndElOfSubPath] |= PT_CLOSEFIGURE; 05170 } 05171 StartOfSubPath=EndElOfSubPath+1; 05172 } 05173 05174 return; 05175 }
|
|
Rotates the specified elements in a path by the number of positions indicated. Elements will be rotated from right to left.
Definition at line 8997 of file paths.cpp. 08998 { 08999 // just make sure the start and end positions are sensible 09000 09001 INT32 Width = End-Start+1; 09002 if (Width<2) return; 09003 Rotate = Rotate % Width; 09004 if (Rotate==0) return; 09005 if (Start<0) return; 09006 if (End>=UsedSlots) return; 09007 09008 // make a rotate right into a rotate left 09009 if (Rotate<0) Rotate=Width-Rotate; 09010 09011 INT32 Shift = 64; 09012 INT32 Step = Rotate/Shift; 09013 INT32 Residual = Rotate % Shift; 09014 09015 UINT32 Size = sizeof(PathVerb); 09016 if (Size<sizeof(PathFlags)) Size=sizeof(PathFlags); 09017 if (Size<sizeof(DocCoord)) Size=sizeof(DocCoord); 09018 09019 void* TempBuff = (void*)CCMalloc(Shift*Size); 09020 09021 // Get arrays of flags,verbs and points. 09022 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 09023 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 09024 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 09025 09026 if (TempBuff!=NULL) 09027 { 09028 void* Destin; 09029 void* Source; 09030 while (Step>0) 09031 { 09032 Destin = TempBuff; 09033 Source = (void*)&Flags[Start]; 09034 memmove(Destin, Source, Shift*sizeof(PathFlags)); 09035 Destin = (void*)&Flags[Start]; 09036 Source = (void*)&Flags[Start+Shift]; 09037 memmove(Destin, Source, (Width-Shift)*sizeof(PathFlags)); 09038 Destin = (void*)&Flags[End-Shift+1]; 09039 Source = TempBuff; 09040 memmove(Destin, Source, Shift*sizeof(PathFlags)); 09041 09042 Destin = TempBuff; 09043 Source = (void*)&Verbs[Start]; 09044 memmove(Destin, Source, Shift*sizeof(PathVerb)); 09045 Destin = (void*)&Verbs[Start]; 09046 Source = (void*)&Verbs[Start+Shift]; 09047 memmove(Destin, Source, (Width-Shift)*sizeof(PathVerb)); 09048 Destin = (void*)&Verbs[End-Shift+1]; 09049 Source = TempBuff; 09050 memmove(Destin, Source, Shift*sizeof(PathVerb)); 09051 09052 Destin = TempBuff; 09053 Source = (void*)&Coords[Start]; 09054 memmove(Destin, Source, Shift*sizeof(DocCoord)); 09055 Destin = (void*)&Coords[Start]; 09056 Source = (void*)&Coords[Start+Shift]; 09057 memmove(Destin, Source, (Width-Shift)*sizeof(DocCoord)); 09058 Destin = (void*)&Coords[End-Shift+1]; 09059 Source = TempBuff; 09060 memmove(Destin, Source, Shift*sizeof(DocCoord)); 09061 09062 Step--; 09063 } 09064 if (Residual>0) 09065 { 09066 09067 Destin = TempBuff; 09068 Source = (void*)&Flags[Start]; 09069 memmove(Destin, Source, Residual*sizeof(PathFlags)); 09070 Destin = (void*)&Flags[Start]; 09071 Source = (void*)&Flags[Start+Residual]; 09072 memmove(Destin, Source, (Width-Residual)*sizeof(PathFlags)); 09073 Destin = (void*)&Flags[End-Residual+1]; 09074 Source = TempBuff; 09075 memmove(Destin, Source, Residual*sizeof(PathFlags)); 09076 09077 Destin = TempBuff; 09078 Source = (void*)&Verbs[Start]; 09079 memmove(Destin, Source, Residual*sizeof(PathVerb)); 09080 Destin = (void*)&Verbs[Start]; 09081 Source = (void*)&Verbs[Start+Residual]; 09082 memmove(Destin, Source, (Width-Residual)*sizeof(PathVerb)); 09083 Destin = (void*)&Verbs[End-Residual+1]; 09084 Source = TempBuff; 09085 memmove(Destin, Source, Residual*sizeof(PathVerb)); 09086 09087 Destin = TempBuff; 09088 Source = (void*)&Coords[Start]; 09089 memmove(Destin, Source, Residual*sizeof(DocCoord)); 09090 Destin = (void*)&Coords[Start]; 09091 Source = (void*)&Coords[Start+Residual]; 09092 memmove(Destin, Source, (Width-Residual)*sizeof(DocCoord)); 09093 Destin = (void*)&Coords[End-Residual+1]; 09094 Source = TempBuff; 09095 memmove(Destin, Source, Residual*sizeof(DocCoord)); 09096 09097 } 09098 CCFree(TempBuff); 09099 } 09100 else 09101 { 09102 PathFlags TempFlags; 09103 PathVerb TempVerb; 09104 DocCoord TempCoord; 09105 09106 while (Rotate>0) 09107 { 09108 TempFlags = Flags[Start]; 09109 TempVerb = Verbs[Start]; 09110 TempCoord = Coords[Start]; 09111 for (INT32 i=Start; i<End; i++) 09112 { 09113 Flags[i] = Flags[i+1]; 09114 Verbs[i] = Verbs[i+1]; 09115 Coords[i] = Coords[i+1]; 09116 } 09117 Flags[End]=TempFlags; 09118 Verbs[End]=TempVerb; 09119 Coords[End]=TempCoord; 09120 Rotate--; 09121 } 09122 } 09123 }
|
|
This function is called on a path specified in DocCoords, to convert it into pixel coordinates. > void Path::Scale(const DocCoord dcOrigin, const double dDPI=96.0)
This is used in imagemaps, to convert a path specified in the document to a polygon to specify an imagemap clickable area over a bitmap. This function does the following to all the coordinates in the path a. Subtracts the origin dcOrigin b. Inverts the y-axis c. Multiplies the coordinates to convert them to the number of DPI specified.
Definition at line 10184 of file paths.cpp. 10185 { 10186 //First find out how many coordinates we have to process 10187 INT32 lNumCoords=GetNumCoords(); 10188 10189 //And get a pointer to the array 10190 DocCoord* pdcArray=GetCoordArray(); 10191 10192 //For every coord in the array 10193 for (INT32 l=0; l<lNumCoords; l++) 10194 { 10195 //Get a pointer to the coordinate we are changing 10196 DocCoord* pdcThisCoord=&pdcArray[l]; 10197 10198 if (pdcThisCoord==NULL) 10199 { 10200 ERROR2RAW("Path::Scale - coord error"); 10201 return; 10202 } 10203 10204 //And scale it 10205 pdcThisCoord->Scale(dcOrigin, (float)dDPI); 10206 } 10207 }
|
|
Goes through the path and sets all the IsSelected flags to TRUE, also selecting all control points in the path.
Definition at line 3663 of file paths.cpp. 03664 { 03665 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 03666 03667 for (INT32 i=0; i<UsedSlots; i++) 03668 Flags[i].IsSelected = TRUE; 03669 }
|
|
Sets the flags at the current path position to the flags provided.
Definition at line 2712 of file paths.cpp. 02713 { 02714 ENSURE( CurrentPos<UsedSlots, "PathPosition is out of Bounds in Path::IsEndPoint" ); 02715 02716 // Get the flags array 02717 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 02718 02719 // and set the flags 02720 Flags[CurrentPos] = NewFlags; 02721 }
|
|
Sets the current path position to the value supplied. This represents the Coord number in the path.
Definition at line 1018 of file paths.cpp. 01019 { 01020 // Set the pos to the position supplied 01021 CurrentPos = NewPos; 01022 01023 // make sure it was in bounds 01024 if (CurrentPos>=UsedSlots) 01025 CurrentPos = UsedSlots-1; 01026 01027 if (CurrentPos<0) 01028 CurrentPos = 0; 01029 }
|
|
Joins two paths to form a new, longer path. Both the paths invloved are simple (ie not complex).
Definition at line 6325 of file paths.cpp. 06326 { 06327 // We have not reversed the other path yet 06328 *IsOtherReversed = FALSE; 06329 06330 // Make a note of where the new path will start after the merge 06331 INT32 PathStart = UsedSlots; 06332 06333 if (ThisReversed != NULL) 06334 *ThisReversed = FALSE; 06335 // Do we need to reverse any elements of this path 06336 INT32 StartSlot, NumSlots; 06337 BOOL JoinedAtStart; 06338 DocCoord* OtherCoords = (DocCoord*) DescribeHandle(Other->CoordHandle); 06339 06340 // Find out if we need to reverse this path to help with the joining 06341 if (FindJoinedSubPathInfo(OtherCoords[0], &StartSlot, &NumSlots, &JoinedAtStart)) 06342 { 06343 // Maybe need to reverse this path 06344 if (JoinedAtStart) 06345 { 06346 Reverse(); 06347 if (ThisReversed != NULL) 06348 *ThisReversed = TRUE; 06349 } 06350 } 06351 06352 // And check to see if the other end needs checking as well. 06353 if (FindJoinedSubPathInfo(OtherCoords[Other->UsedSlots-1], &StartSlot, &NumSlots, &JoinedAtStart)) 06354 { 06355 // Reverse the joining path always 06356 Other->Reverse(); 06357 06358 // We have reversed the other path 06359 *IsOtherReversed = TRUE; 06360 06361 // and maybe reverse this path 06362 if (JoinedAtStart) 06363 { 06364 Reverse(); 06365 if (ThisReversed != NULL) 06366 *ThisReversed = TRUE; 06367 } 06368 } 06369 06370 // merge the paths 06371 if (MergeTwoPaths(*Other)==FALSE) 06372 return FALSE; 06373 06374 // Make sure that the new path starts with a MoveTo 06375 #ifdef _DEBUG 06376 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 06377 ENSURE( Verbs[PathStart]==PT_MOVETO, "Start of SubPath is not a MoveTo in SimpleJoin()" ); 06378 #endif 06379 06380 // The merge must have worked, so remove the initial MoveTo 06381 CurrentPos = PathStart; 06382 DeleteElement(); 06383 06384 // See if we can make it a closed path 06385 TryToClose(); 06386 06387 // report that it all worked 06388 CurrentPos = UsedSlots; 06389 *OtherStartSlot = PathStart-1; 06390 return TRUE; 06391 }
|
|
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.
Definition at line 7768 of file paths.cpp. 07769 { 07770 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARLIB) 07771 double QuantOrder = 1024; 07772 07773 INT32 orignumcoords = UsedSlots; 07774 07775 // create a path and quantise to it 07776 Path QuantPath; 07777 QuantPath.Initialise(24,12); 07778 07779 // quantise original path to QuantPath 07780 Quantise(QuantOrder, &QuantPath); 07781 07782 // create and fit a smooth curve to the data points. 07783 CurveFitObject Smoothed(&QuantPath, error); 07784 BOOL ok = Smoothed.Initialise(&QuantPath,QuantPath.GetNumCoords()); 07785 07786 if (ok) 07787 { 07788 Smoothed.FitCurve(); 07789 07790 // now that we've smoothed the curve lets check on the number 07791 // of coordinates we've generated. If its more, then we should 07792 // leave the original path as it was. If its less then replace 07793 if (QuantPath.GetNumCoords()<orignumcoords) 07794 ok = CloneFrom(QuantPath); 07795 07796 } 07797 return ok; 07798 #else 07799 return FALSE; 07800 #endif 07801 }
|
|
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.
Definition at line 4347 of file paths.cpp. 04352 { 04353 #if !defined(EXCLUDE_FROM_RALPH) 04354 PathVerb* Verbs = GetVerbArray(); 04355 DocCoord* Coords = GetCoordArray(); 04356 PathFlags* Flags = GetFlagArray(); 04357 04358 // temp vars for calculating smoothness 04359 04360 DocCoord p; // Endpoint opposite the control point 04361 DocCoord q; // Endpoint directly adjacent to control point 04362 DocCoord r; // Endpoint on same side of control point but not adjacent 04363 DocCoord ret; // Temp for returning value 04364 04365 // We get the parameters for the calculation from different places depending on whether we're 04366 // at the first or second control point. We know this by looking at the EndPoint flags 04367 04368 if (Flags[Index-1].IsEndPoint) 04369 { 04370 // This is the first control point of a curve 04371 04372 /* 04373 04374 These are the possibilities with the control point as the first one in the curve: 04375 04376 1: Curve/Curve 04377 ... 04378 m/l/c p 04379 c a 04380 c b 04381 c q <- endpoint to which point is attached 04382 c c <- Control point we're smoothing 04383 c d 04384 c r 04385 ... 04386 04387 2: Line/Curve 04388 ... 04389 m/l/c p 04390 l q 04391 c a <- Control point we're smoothing 04392 c b 04393 c r 04394 ... 04395 04396 3: Curve/Open line 04397 m q 04398 c a <- control point we're smoothing 04399 c b 04400 c r 04401 ... 04402 04403 4: Curve/snapping to curve at end 04404 m q 04405 c a <- control point we're snapping 04406 c b 04407 c r 04408 ... 04409 l/c p 04410 c c 04411 c d 04412 c q 04413 04414 5: Curve/snapping to line at end 04415 m q 04416 c a <- control point we're snapping to 04417 c b 04418 c r 04419 ... 04420 l/c p 04421 l q 04422 04423 6: Curve/snapping to curve in another path 04424 7: Curve/snapping to line in another path 04425 m q 04426 c a <- control point we're smoothing 04427 c b 04428 c r 04429 ... 04430 04431 point p = OtherCoord 04432 */ 04433 04434 // The position of this point depends on: The previous endpoint (which is the point 04435 // to which this control point is 'attached'), the endpoint before that one, and the 04436 // endpoint of the bezier segment containing the control point. 04437 // point q is the endpoint of the previous element (which always exists where we want it) 04438 04439 q = Coords[Index-1]; 04440 04441 // point r is the endpoint of this curve element - again, always there 04442 04443 r = Coords[Index+2]; 04444 04445 // point p, on the other hand, is problematical. It might not exist at all (if the 04446 // previous element was a MoveTo and the path is open). It might be a lineto. It 04447 // might be a CurveTo element, which is the simplest case. Or, it might be any of 04448 // those three elements on a completely different path. Or it might be a curve or 04449 // a line at the opposite end of the path (if the CLOSEFIGURE flag is set or the 04450 // StartAndEndSnapped flag is TRUE). 04451 04452 if (Verbs[Index-1] == PT_BEZIERTO) 04453 { 04454 // Simple - p = the start of this curve (case 1) 04455 p = Coords[Index-4]; 04456 CalcPointCurve(p,q,r,&ret); 04457 04458 // Bodge inserted by Peter to fix the problem that occurs when you have a closed path 04459 // consisting of just two Bezier segments. In this case the returned position is wrong 04460 // - it positions the control point over the opposite one - so we will just flip it around 04461 /* Commented out by Markn 17/1/95 - replaced by new bodge written by Peter 04462 if ((GetNumCoords() == 7) && StartAndEndSnapped) 04463 { 04464 ret = q - (ret - q); 04465 } 04466 */ 04467 04468 // New version of above bodge also by Peter (put in by Markn - 17/1/95) 04469 if ((GetNumCoords() == 7) && ((Verbs[GetNumCoords()-1] & PT_CLOSEFIGURE) || StartAndEndSnapped)) 04470 { 04471 ret = q - (ret - q); 04472 } 04473 return ret; 04474 } 04475 else if (Verbs[Index-1] == PT_LINETO) 04476 { 04477 // Simple - previous is a lineto, so get its start point and calculate (case 2) 04478 p = Coords[Index-2]; 04479 CalcPointLine(p,q,r,&ret); 04480 return ret; 04481 } 04482 else 04483 { 04484 04485 // Scan along to find the end element. This we find by scanning forward until 04486 // we find a MoveTo or we go off the end. Either way, the previous element is 04487 // the one we want. 04488 04489 INT32 i = Index; 04490 while (i<UsedSlots && Verbs[i] != PT_MOVETO) 04491 i++; 04492 04493 // i either points after the end of the path, or at the next MoveTo. Move to the 04494 // previous element (could be the endpoint of a curve). 04495 04496 i--; 04497 04498 if (StartAndEndSnapped || (Verbs[i] & PT_CLOSEFIGURE) ) 04499 { 04500 // We have to get p from the end of the subpath (cases 4 & 5) 04501 if ((Verbs[i] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) 04502 { 04503 // Case 4 04504 p = Coords[i-3]; 04505 CalcPointCurve(p,q,r,&ret); 04506 04507 // Bodge inserted by Peter to fix the problem that occurs when you have a path consisting 04508 // of just two Bezier segments. In this case the returned position is wrong - it 04509 // positions the control point over the opposite one - so we will just flip it around 04510 if (GetNumCoords() == 7) 04511 { 04512 ret = q - (ret - q); 04513 } 04514 04515 return ret; 04516 } 04517 else 04518 { 04519 // Case 5 04520 p = Coords[i-1]; 04521 CalcPointLine(p,q,r,&ret); 04522 return ret; 04523 } 04524 } 04525 else 04526 { 04527 // This path hasn't snapped, and isn't closed. Check if it snaps with another 04528 if (JoinedToAnother) 04529 { 04530 // Cases 6 & 7 04531 p = OtherCoord; 04532 if (OtherIsCurve) 04533 { 04534 // Case 6 04535 CalcPointCurve(p,q,r,&ret); 04536 } 04537 else 04538 { 04539 // Case 7 04540 CalcPointLine(p,q,r,&ret); 04541 } 04542 return ret; 04543 } 04544 else 04545 { 04546 // There's no snapping at all, so this point has to be calculated as an endpoint 04547 CalcPointEnd(q,r,&ret); 04548 return ret; 04549 } 04550 } 04551 } 04552 } 04553 else 04554 { 04555 // This is the second control point of a curve 04556 04557 /* 04558 These are the possible situations, with sections of path data 04559 04560 1: Curve/Curve 04561 ... 04562 m/l/c r 04563 c a 04564 c b <- Control point pointed to by Index 04565 c q <- this is the endpoint to which the control point is connected 04566 c c 04567 c d 04568 c p 04569 ... 04570 04571 2: Curve/Line 04572 ... 04573 m/l/c r 04574 c a 04575 c b <- Control point pointed to by Index 04576 c q <- this is the endpoint to which the control point is connected 04577 l p 04578 ... 04579 04580 3: Curve/open line 04581 ... 04582 m/l/c r 04583 c a 04584 c b <- Control point pointed to by Index 04585 c q <- this is the endpoint to which the control point is connected 04586 either nothing or a moveto 04587 ... 04588 04589 4: Curve/snapping to curve at start 04590 m q 04591 c c 04592 c d 04593 c p 04594 ... 04595 l/c r 04596 c a 04597 c b <- Control point pointed to by index 04598 c q <- Enpoint to which control is connected 04599 either nothing or moveto, CLOSEFIGURE or SnapToEnd set 04600 ... 04601 04602 5: Curve/snapping to line at start 04603 m q 04604 l p 04605 ... 04606 l/c r 04607 c a 04608 c b <- Control point pointed to by index 04609 c q <- Enpoint to which control is connected 04610 either nothing or moveto, CLOSEFIGURE or SnapToEnd set 04611 ... 04612 04613 6: Curve/snapping to curve in another path 04614 7: Curve/snapping to line in another path 04615 ... 04616 m/l/c r 04617 c a 04618 c b <- Control point pointed to by index 04619 c q <- Enpoint to which control is connected 04620 nothing/moveto 04621 04622 point p = OtherCoord 04623 04624 */ 04625 04626 // Point q is the endpoint of this curve 04627 04628 q = Coords[Index+1]; 04629 04630 // Point r is the start point of this curve (always guaranteed to be there) 04631 04632 r = Coords[Index-2]; 04633 04634 // Point p (as before) is difficult. It ight be a curve element. it might be a line 04635 // element. It might not exist at all (i.e. this might be the end point of an open subpath). 04636 // It also might be the start point of this subpath, either because this path is closed 04637 // or because we've been told to snap. Or even, it might be an element at the start or end 04638 // of another path. My God, what a choice! 04639 04640 // First check for the simple cases of curve/curve or curve/line (1 & 2) 04641 if (Index+2<UsedSlots && Verbs[Index+2] != PT_MOVETO) 04642 { 04643 // The next element is either a curve or a line 04644 if (Verbs[Index+2] == PT_BEZIERTO) 04645 { 04646 // It's a curve, so point p is its endpoint 04647 p = Coords[Index+4]; 04648 CalcPointCurve(p,q,r,&ret); 04649 return ret; 04650 } 04651 { 04652 // It's a line, so point p is the endpoint of that 04653 p = Coords[Index+2]; 04654 CalcPointLine(p,q,r,&ret); 04655 return ret; 04656 } 04657 } 04658 // Now we know there's nothing after this curve, so check snapping and stuff 04659 else if (StartAndEndSnapped || (Verbs[Index+1] & PT_CLOSEFIGURE)) 04660 { 04661 // We're snapping to the start of this path (4 & 5) , so we have to find 04662 // the start of this subpath 04663 INT32 i = Index; 04664 FindStartOfSubPath(&i); // i returned pointing at start element 04665 i++; // Point at first element in path 04666 if (Verbs[i] == PT_BEZIERTO) 04667 { 04668 p = Coords[i+2]; 04669 CalcPointCurve(p,q,r,&ret); 04670 return ret; 04671 } 04672 else 04673 { 04674 p = Coords[i]; 04675 CalcPointLine(p,q,r,&ret); 04676 return ret; 04677 } 04678 04679 } 04680 else if (JoinedToAnother) 04681 { 04682 // Joined to another path (6 & 7) 04683 p = OtherCoord; 04684 if (OtherIsCurve) 04685 { 04686 CalcPointCurve(p,q,r,&ret); 04687 } 04688 else 04689 { 04690 CalcPointLine(p,q,r,&ret); 04691 } 04692 return ret; 04693 } 04694 else 04695 { 04696 // The only thing left is a curve at the end of the path (3) 04697 CalcPointEnd(q,r,&ret); 04698 return ret; 04699 } 04700 } 04701 #else 04702 return DocCoord(0,0); 04703 #endif 04704 }
|
|
Smooths the path on the areas that have the IsSmooth flag set to TRUE. This can change any or all of the path.
Definition at line 4130 of file paths.cpp. 04131 { 04132 04133 // This is a less efficient (slightly) version of this routine (in that there is a 04134 // certain amount of moving backward and forward in the path, but only for the start 04135 // and end points) but it copes with end snapping 04136 04137 DocCoord* Coords = GetCoordArray(); 04138 PathVerb* Verbs = GetVerbArray(); 04139 PathFlags* Flags = GetFlagArray(); 04140 INT32 StartSnapSub = 0; 04141 INT32 EndSnapSub = 0; // Start and end of the subpath we're snapping 04142 DocCoord tempcoord(0,0); 04143 04144 // Find the start and end of the subpath we're snapping 04145 if (SnapEnds) 04146 { 04147 StartSnapSub = EndSnapSub = SnapIndex; 04148 FindStartOfSubPath(&StartSnapSub); 04149 FindEndElOfSubPath(&EndSnapSub); 04150 } 04151 04152 if (SetRenderFlags) 04153 { 04154 // As well as smoothing, we also set the NeedToRender flag on any path that's changed. 04155 // Notice that we never clear the NeedToRender flags - if they're rendered once, they're 04156 // rendered forever. 04157 04158 for (INT32 i = 0; i < UsedSlots; i++) 04159 { 04160 if (Verbs[i] == PT_BEZIERTO && !(Flags[i].IsEndPoint) && Flags[i].IsSmooth) 04161 { 04162 tempcoord = SmoothControlPoint(i, (SnapEnds && (i>=StartSnapSub && i<=EndSnapSub))); 04163 if (Coords[i] != tempcoord) 04164 { 04165 if (Flags[i+1].IsEndPoint) 04166 Flags[i+1].NeedToRender = TRUE; 04167 else 04168 Flags[i+2].NeedToRender = TRUE; 04169 } 04170 Coords[i] = tempcoord; 04171 } 04172 } 04173 04174 } 04175 else 04176 { 04177 for (INT32 i = 0; i < UsedSlots; i++) 04178 { 04179 if (Verbs[i] == PT_BEZIERTO && !(Flags[i].IsEndPoint) && Flags[i].IsSmooth) 04180 Coords[i] = SmoothControlPoint(i, (SnapEnds && (i>=StartSnapSub && i<=EndSnapSub))); 04181 } 04182 } 04183 }
|
|
Given a path, search for regions of interest and smooth these regions. Regions are defined by sequences of connected selected points ie.
If smoothall is true the whole path is smoothed. You should call this function with a path which you do not mind being corrupted, ie changed in an unpredictable way. The function may successfully smooth a number of regions within the path, then fail on one particular region. The result will be a path with m out of n regions smoothed. Definition at line 7468 of file paths.cpp. 07469 { 07470 INT32 index = 0; 07471 INT32 start = 0; 07472 INT32 end = UsedSlots-1; 07473 07474 if (smoothall) 07475 { 07476 INT32 sel; 07477 (reselect) ? sel=4 : sel=0; 07478 return (Path::SmoothSection(start,&end,error, sel)); 07479 } 07480 else 07481 { 07482 while ((index<UsedSlots) && (FindSelectionLimits(index,&start,&end))) 07483 { 07484 // increase the region by 1 either way and smooth it. 07485 INT32 nstart = start; 07486 INT32 nend = end; 07487 07488 ExpandRange(&nstart,&nend,1); 07489 07490 if (nstart != nend) 07491 { 07492 INT32 sel = 0; 07493 if (reselect) 07494 { 07495 if (nstart<start) sel |=1 ; 07496 if (nend>end) sel |=2 ; 07497 if (sel==0) sel=4; 07498 } 07499 BOOL ok = Path::SmoothSection(nstart, &nend, error, sel); 07500 if (!ok) return FALSE; 07501 } 07502 index = nend+1; 07503 } 07504 } 07505 return TRUE; 07506 }
|
|
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].
Definition at line 7632 of file paths.cpp. 07633 { 07634 INT32 last = *index2; 07635 if (last==-1) 07636 last = UsedSlots-1; 07637 07638 // Saftey Checks 07639 ERROR3IF( index1>=last, "Section delimiters are invalid in Path::SmoothSection"); 07640 ERROR3IF( last>=UsedSlots, "Section end is off end of path in Path::SmoothSection"); 07641 ERROR3IF( index1<0, "Section start is negative in Path::SmoothSection"); 07642 07643 // Release safety checks 07644 if (index1>=last) 07645 return FALSE; 07646 if (last>=UsedSlots) 07647 return FALSE; 07648 if (index1<0) 07649 return FALSE; 07650 07651 INT32 numtosmooth = last-index1+1; 07652 07653 // We are smoothing a section of the path so extract a copy from 07654 // the specified section. 07655 Path PathSection; 07656 BOOL ok = PathSection.Initialise(numtosmooth,12); 07657 07658 if (ok) 07659 { 07660 ok = MakePathFromSection(index1, numtosmooth, &PathSection); 07661 if (ok) 07662 { 07663 // smooth the section completely 07664 ok = PathSection.Smooth(error); 07665 07666 if (ok) 07667 { 07668 // stick the smoothed path back in as a section and return a new 07669 // index2 value 07670 ok = RetroReplaceSection(index1, numtosmooth, &PathSection, FALSE); 07671 if (ok) 07672 { 07673 // set up the last coordinate index return param 07674 *index2 = index1 + PathSection.GetNumCoords() - 1; 07675 07676 // if we need to reselect the points then go to it 07677 if (selection) 07678 { 07679 PathFlags* Flags = (PathFlags*) DescribeHandle(FlagsHandle); 07680 INT32 start = index1; 07681 INT32 end = *index2; 07682 if (!(selection & 4)) 07683 { 07684 if (selection & 1) 07685 FindNextEndPoint(&start); 07686 if (selection & 2) 07687 FindPrev(&end); 07688 } 07689 for (INT32 i=start; i<=end; i++) 07690 Flags[i].IsSelected = TRUE; 07691 } 07692 } 07693 } 07694 } 07695 } 07696 return ok; 07697 }
|
|
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.
Definition at line 7110 of file paths.cpp. 07116 { 07117 double mu; 07118 double dist = SqrDistanceToPoint(SplitPt, SplitElement, &mu); 07119 if (dist < 0.0) return FALSE; 07120 07121 PathVerb* InVerbs = GetVerbArray(); 07122 DocCoord* InCoords = GetCoordArray(); 07123 07124 PathVerb vb = InVerbs[*SplitElement] & ~PT_CLOSEFIGURE; 07125 ENSURE((vb == PT_LINETO) || (vb == PT_BEZIERTO), 07126 "Unable to find point on path. Index does not specify line or curve"); 07127 07128 switch (vb) 07129 { 07130 case PT_LINETO: 07131 return PathUtil::SplitLine(mu, &InCoords[(*SplitElement)-1], NumElements, Verbs, Coords); 07132 break; 07133 case PT_BEZIERTO: 07134 return PathUtil::SplitCurve(mu, &InCoords[(*SplitElement)-1], NumElements, Verbs, Coords); 07135 break; 07136 } 07137 07138 return FALSE; 07139 }
|
|
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.
Definition at line 9719 of file paths.cpp. 09720 { 09721 INT32 SplitElement=0; 09722 UINT32 NumElements; 09723 PathVerb NewVerbs[6]; 09724 DocCoord NewCoords[6]; 09725 PathFlags NewFlags[6]; 09726 09727 // Try and split the path. This returns FALSE if the path did not need splitting 09728 if (SplitAtPoint(SplitPoint, &SplitElement, &NumElements, NewVerbs, NewCoords)) 09729 { 09730 // Make a note of where the new endpoint will be 09731 *SplitAt = (SplitElement+(NumElements/2)-1); 09732 *NewElements = NumElements; 09733 09734 // The path was split, so we know where, and how, so let's party on the path 09735 PathVerb* Verbs = GetVerbArray(); 09736 PathFlags* Flags = GetFlagArray(); 09737 // DocCoord* Coords = GetCoordArray(); 09738 // UINT32 NumCoords = GetNumCoords(); 09739 INT32 NumToChange; 09740 09741 // We're adding something, either a line or curve - check which 09742 if ((Verbs[SplitElement] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) 09743 { 09744 // Adding a curve - number to change = 6 09745 NumToChange = 6; 09746 09747 // Initialise the flags appropriately 09748 for (INT32 i=0; i<6; i++) 09749 { 09750 // copy the flags from the old curve (repeat the flag in the first 3 elements) 09751 NewFlags[i] = Flags[SplitElement+(i%3)]; 09752 NewFlags[i].IsSelected = FALSE; 09753 09754 // Want it to be a cusp in the middle 09755 if ((i>0) && (i<4)) 09756 { 09757 NewFlags[i].IsSmooth = FALSE; 09758 NewFlags[i].IsRotate = FALSE; 09759 } 09760 } 09761 09762 // If this was happening at the end of a path, 09763 // then make sure the close figure flag is set correctly 09764 if (Verbs[SplitElement+2] & PT_CLOSEFIGURE) 09765 NewVerbs[5] |= PT_CLOSEFIGURE; 09766 } 09767 else 09768 { 09769 // The slit happened in a straight line section 09770 NumToChange = 2; 09771 NewFlags[0] = NewFlags[1] = Flags[SplitElement]; 09772 NewFlags[0].IsSmooth = NewFlags[0].IsRotate = FALSE; 09773 NewFlags[0].IsSelected = FALSE; 09774 09775 // Make sure that the close figure flag is maintained 09776 if (Verbs[SplitElement] & PT_CLOSEFIGURE) 09777 NewVerbs[1] |= PT_CLOSEFIGURE; 09778 } 09779 09780 // Move to the place in the path where the split took place 09781 SetPathPosition(SplitElement); 09782 PathFlags InsertFlags; 09783 BOOL InsertWorked; 09784 09785 // insert a curve or a line, depending on where the split happened 09786 if (NumToChange==6) 09787 InsertWorked = InsertCurveTo(NewCoords[0], NewCoords[1], NewCoords[2], &InsertFlags); 09788 else 09789 InsertWorked = InsertLineTo(NewCoords[0], &InsertFlags); 09790 09791 // see if the insertion worked 09792 if (!InsertWorked) 09793 return FALSE; 09794 } 09795 else 09796 { 09797 // else we tried to split at an existing control point (endpoint) 09798 // That means that there were no new endpoints 09799 *NewElements = 0; 09800 *SplitAt = (SplitElement-1); 09801 09802 // See if we can find the control point in question 09803 DocCoord* Coords = GetCoordArray(); 09804 INT32 NumCoords = GetNumCoords(); 09805 09806 // see if the split point is over the last point on the curve 09807 if (Coords[NumCoords-1]==SplitPoint) 09808 *SplitAt = NumCoords; 09809 } 09810 09811 // all worked 09812 return TRUE; 09813 }
|
|
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.
Definition at line 6923 of file paths.cpp. 06924 { 06925 // Get the coordinate list and verb list for this path instance 06926 06927 DocCoord* Coords = GetCoordArray(); 06928 PathVerb* Verbs = GetVerbArray(); 06929 06930 // check for the presence of at least some elements 06931 06932 if (UsedSlots==0) 06933 { 06934 *NearEl = -1; 06935 return -1; 06936 } 06937 06938 // calculate the distance to the first control point 06939 06940 double fdist; 06941 double ldist; 06942 double tmu; 06943 06944 INT32 el=-1; 06945 06946 fdist = PathUtil::SqrDistance(Coords[0], pt); 06947 06948 for (INT32 i=0; i<UsedSlots; i++) 06949 { 06950 switch (Verbs[i] & ~PT_CLOSEFIGURE) 06951 { 06952 06953 case PT_LINETO: 06954 ldist = PathUtil::SqrDistanceToLine(&Coords[i-1], pt, &tmu); 06955 if (ldist<=fdist) 06956 { 06957 fdist=ldist; 06958 el=i; 06959 *mu=tmu; 06960 } 06961 break; 06962 06963 case PT_BEZIERTO: 06964 ldist = PathUtil::SqrDistanceToCurve(MAXPATHDIFFRATE, &Coords[i-1], pt, &tmu); 06965 if (ldist<=fdist) 06966 { 06967 fdist=ldist; 06968 el=i; 06969 *mu=tmu; 06970 } 06971 i+=2; // skip next two bezierto el. 06972 break; 06973 } 06974 } 06975 06976 if (el>-1) // have we an element? 06977 { 06978 *NearEl = el; 06979 return fdist; 06980 } 06981 06982 *NearEl = -1; 06983 return -1; 06984 }
|
|
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.
Definition at line 7912 of file paths.cpp. 07913 { 07914 double Acc = 64; 07915 double Len = 0; 07916 ProcessLength LengthObj(Acc); 07917 07918 07919 BOOL ok = LengthObj.PathLength(this, &Len); 07920 if (ok) 07921 return Len; 07922 return 0; 07923 07924 }
|
|
Strokes the path, and places result in pDest. If pDest == NULL, the result is placed back in this path. BOOL Path::StrokePathToPath(MILLIPOINT LineWidth = 250, LineCapType LineCap = LineCapButt, JointType JoinStyle = MitreJoin, DashType *pDash = NULL, Path* pDest = NULL, DWORD Flatness = 200, BOOL Close = FALSE)
Definition at line 5610 of file paths.cpp. 05617 { 05618 if (pDest == NULL) pDest = this; 05619 05620 UINT32 NewFlatness = (UINT32)Flatness; 05621 05622 INT32 NumCoords = GetNumCoords(); 05623 INT32 OutputSize = (NumCoords*40)+1000; 05624 Path OutputPath; 05625 if (!OutputPath.Initialise(OutputSize)) return FALSE; 05626 05627 DocCoord* IPoints = GetCoordArray(); 05628 BYTE* ITypes = (BYTE*) GetVerbArray(); 05629 DWORD ILength = (DWORD) NumCoords; 05630 05631 DocCoord* OPoints = OutputPath.GetCoordArray(); 05632 BYTE* OTypes = (BYTE*) OutputPath.GetVerbArray(); 05633 DWORD OLength = (DWORD) OutputSize; 05634 05635 // Karim 22/11/2000 05636 // Modified - if line-width is 0, then we don't want dashes. 05637 DashType Dash; 05638 Dash.Length = 0; 05639 if (pDash == NULL || LineWidth == 0) pDash = &Dash; 05640 05641 INT32 len = -10; 05642 05643 // keep checking to see if we had an overflow! 05644 while(len < -2) 05645 { 05646 len = GRenderRegion::StrokePathToPath(IPoints,ITypes,ILength, 05647 OPoints,OTypes,OLength, 05648 Close,LineWidth,NewFlatness,LineCap,JoinStyle,pDash); 05649 05650 if(len < -2) 05651 { 05652 OLength -= len; 05653 OutputPath.EnsureVolume(OLength); 05654 OPoints = OutputPath.GetCoordArray(); 05655 OTypes = (BYTE*) OutputPath.GetVerbArray(); 05656 } 05657 } 05658 05659 OutputPath.UsedSlots = len; 05660 OutputPath.UnUsedSlots -= len; 05661 OutputPath.IsFilled = TRUE; 05662 05663 pDest->ClearPath(); 05664 if (len > 0) 05665 { 05666 if (!pDest->MergeTwoPaths(OutputPath)) return FALSE; 05667 pDest->InitialiseFlags(); 05668 INT32 n = pDest->GetNumCoords(); 05669 PathVerb* pVerbs = pDest->GetVerbArray(); 05670 pVerbs[n-1] |= PT_CLOSEFIGURE; 05671 } 05672 05673 return TRUE; 05674 }
|
|
Sets the Extra Info Ptr to the current Path Position.
Definition at line 8234 of file paths.cpp. 08235 { 08236 if (ExtraInfo == NULL) 08237 return; 08238 08239 ExtraInfo->Sync(CurrentPos); 08240 }
|
|
Translate all coordinate within 'this' path.
Definition at line 8133 of file paths.cpp.
|
|
Translate all coordinate within 'this' path.
Definition at line 8154 of file paths.cpp. 08155 { 08156 // if there's any translation then apply it 08157 if (x || y) 08158 { 08159 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 08160 08161 for (INT32 i=0; i<UsedSlots; i++) 08162 { 08163 Coords[i].x += x; 08164 Coords[i].y += y; 08165 } 08166 } 08167 }
|
|
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.
Definition at line 5267 of file paths.cpp. 05268 { 05269 // Dereference the pointers to the coords and the verbs 05270 DocCoord* Coords = (DocCoord*) DescribeHandle(CoordHandle); 05271 PathVerb* Verbs = (PathVerb*) DescribeHandle(VerbHandle); 05272 05273 // Need to try all the sub paths, so loop through the whoel path 05274 INT32 EndOfSubPath = UsedSlots-1; 05275 for (INT32 i=UsedSlots-1; i>=0; i--) 05276 { 05277 // Have we found the begining of a sub-path 05278 if (Verbs[i]==PT_MOVETO) 05279 { 05280 // yes - is its start and end coords the same 05281 if (Coords[i] == Coords[EndOfSubPath]) 05282 { 05283 // This path has the same start and end coord 05284 // so mark it as closed and fill it 05285 Verbs[EndOfSubPath] |= PT_CLOSEFIGURE; 05286 IsFilled = TRUE; 05287 } 05288 05289 // Update the EndOfSubPath variable 05290 EndOfSubPath = i-1; 05291 } 05292 } 05293 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|