TraceRegion Class Reference

#include <tracergn.h>

Inheritance diagram for TraceRegion:

CCObject SimpleCCObject List of all members.

Public Member Functions

 TraceRegion ()
 Sets intial values up.
 ~TraceRegion ()
 Destructs object.
BOOL UseBitmap (KernelBitmap *pBitmap)
 Points the TraceRegion at a particular bitmap and claims the relevant size buffers.
BOOL UsePath (Path *pPath)
 Specifies we should use a particular path. The path is initialised, cleared etc.
BOOL Trace (INT32 InitialX, INT32 InitialY, BfxPixelOp *thepBfxPixelOp)
 Does a single boundary trace.
BOOL SetParams (double *pPixelError=NULL)
 Sets the tracing parameters.
BOOL GetParams (double *pPixelError=NULL)
 Sets the tracing parameters.

Static Public Member Functions

static void Test (UndoableOperation *Op)
 Internal test routine.

Protected Member Functions

BOOL TraceBoundary (DocCoord Origin, DocCoord Point1, DocCoord Point2)
 Does a single boundary trace.
BOOL FillBoundaryBuffer (BOOL *End)
 Fills up the boundary buffer.
BOOL ProcessBoundaryBuffer (BOOL Done=FALSE)
 Empties the boundary buffer.
BOOL FindInitialPoint (BOOL *End)
 Finds an initial point to start at.
void FitCubic (INT32 FirstPoint, INT32 LastPoint, TraceBoundaryPoint Tangent1, TraceBoundaryPoint Tangent2, BOOL IsStartCusp, BOOL IsEndCusp)
 This function is recursive. It tries to fit a cubic function to the coordinates in the path between FirstPoint and LastPoint. It then compares this function with the actual coordinates to determine how good a fit it has found. If the fit is good it is added to the path object. If the fit is bad then it is split at the point where the fit is at its worst and FitCubic is called again for the left and right halves. Scope: private.
void GenerateBezier (INT32 FirstPoint, INT32 LastPoint, TraceBoundaryPoint Tangent1, TraceBoundaryPoint Tangent2, TraceBoundaryPoint *Bezier)
 This function supplies the maths to try and fit a cubic function to a set of points. It spends its time trying to come up with good lengths for the two tangents passed in to maximise the closeness of the fit. If it fails to come up with realistic results it simply sets the tangent lengths to be 1/3 of the distance between the start point and the end point. Scope: private.
TraceBoundaryPoint BezierPoint (TraceBoundaryPoint *Bez, double u)
 This function simply evaluates the bezier function for a given position and is used to help when determining how good a fit we have obtained Scope: private.
BOOL CalcMaxError (INT32 LeftPoint, INT32 RightPoint, TraceBoundaryPoint *Bezier, INT32 *SplitPoint, double *MaxDist, INT32 Level)
 Finds out how good a fit the bezier curve we have created is when compared with the data points Scope: private.
void Parameterize (INT32 FirstPoint, INT32 LastPoint)
 This function determines the TPoints which will be fitted (i.e. the trace boundary points we use) and the TValues which will be assigned to them (i.e. the t values along the chord length to which the points correspond). Scope: private.
TraceBoundaryPoint LeftTangent (INT32 Start, INT32 Points)
 Finds the Left tangent at the given point in the path Scope: private.
TraceBoundaryPoint RightTangent (INT32 End, INT32 Points)
 Finds the Right tangent at the given point in the path Scope: private.
TraceBoundaryPoint CentreTangent (INT32 Centre, INT32 Points)
 Finds the tangent at the centre of the path Scope: private.
void InsertBezier (TraceBoundaryPoint *Bezier, BOOL IsStartCusp, BOOL IsEndCusp)
 Adds the bezier curve to the path. If it is that last curve in the fitting (ie Depth is 0) then the rotate flag will not be set Scope: private.
void InsertLine (const DocCoord &Start, const DocCoord &End, BOOL IsStartCusp, BOOL IsEndCusp)
 Inserts a straight curve into the path. It keeps it as a curve so that the path will continue to look smooth after it is edited. If this is the last Path element in the fit, (ie Depth is zero) then the rotate flag will not be set. Scope: private.
void InsertStraightLine (const DocCoord &End)
 Inserts a straight Line into the path. This is used in cases where the Line segment must be kept as a straight line (ie by using Straight Line Mode of the FreeHand tool) Scope: private.
double Bezier0 (double u)
double Bezier1 (double u)
double Bezier2 (double u)
double Bezier3 (double u)
BOOL IsCuspDirectionChange (INT32 dir1, INT32 dir2)

Protected Attributes

TraceBoundaryPointBoundaryBuffer
BfxPixelOppBfxPixelOp
KernelBitmapBitmap
INT32 xsize
INT32 ysize
TraceBoundaryPoint InitialPoint
TraceBoundaryPoint HeadPoint
INT32 InitialDirection
INT32 TailDirection
INT32 HeadDirection
TraceBoundaryPoint FirstBufferPoint
INT32 BoundaryTail
INT32 BoundaryHead
INT32 BoundaryRingMask
INT32 BoundaryRingSize
double Error
double PixelError
BOOL VirginBuffer
BOOL VirginPath
BOOL AtCusp
BOOL TailCusp
PathThePath
TraceBoundaryPoint Directions [(0x7)+1]
TraceBoundaryPoint DirectionPoint [(0x7)+1][(0x7)+1][4]
double TValues [10+1]
INT32 TPoints [10+1]
TraceBoundaryPoint Q1 [3]
TraceBoundaryPoint Q2 [2]
INT32 NumTPoints

Private Member Functions

 CC_DECLARE_DYNCREATE (TraceRegion)

Detailed Description

Definition at line 318 of file tracergn.h.


Constructor & Destructor Documentation

TraceRegion::TraceRegion  ) 
 

Sets intial values up.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
none [INPUTS]
(constructs object) [OUTPUTS]
Returns:
none

Errors: None Scope: Public

See also:
-

Definition at line 165 of file tracergn.cpp.

00166 {
00167     pBfxPixelOp = NULL;
00168     BoundaryBuffer = NULL;
00169     BoundaryRingSize = 0;
00170     BoundaryRingMask =0;
00171     Bitmap = NULL;
00172     xsize = 1;
00173     ysize = 1;
00174     VirginBuffer = TRUE;
00175     AtCusp = FALSE;
00176     TailCusp = FALSE;
00177     TailDirection = -1;
00178     ThePath = NULL;
00179 
00180     double TheError = 1.00;
00181     SetParams(&TheError);
00182 
00183 /*
00184     In each direction of travel we always leave with a particular corner of the pixel set. In some directinos
00185     of travel, we have to set 2 edges. Here goes:
00186 
00187      ->1-X
00188     |    |  This is how an east going trace is represented. The top edge is the one we need to fill in.
00189     |    |
00190      ----
00191 
00192      ->1- 
00193     |    V  This is how a SE going trace is represented. We have 2 edges to fill in this time.
00194     |    2
00195      ----
00196     
00197     When there is a change in direction, things become more complex. Let us assume that the current
00198     direction is east, then note (for the following new directions) how will fill be buffer in:
00199 
00200     Current direction East                                   Current direction south east:           
00201                                                                                                      
00202      ->1-X                                                    ->1-X                                 
00203     |    |  E                                                |    |  E                               
00204     |    |                                                   |    |                                  
00205      ----                                                     ----                                   
00206                                                                                                      
00207      ->1-                                                     ->1-                                   
00208     |    V  SE                                               |    V  SE                              
00209     |    2                                                   |    2                                  
00210      ----X                                                    ----X                                  
00211                                                                                                      
00212      ->1-C                                                    ->1-                                   
00213     |    V  S                                                |    V  S                               
00214     |    2                                                   |    2                                  
00215      ----X                                                    ----X                                  
00216                                                                                                      
00217      ->1-C                                                    ->1-                                   
00218     |    V  SW                                               |    V  SW                              
00219     |    2                                                   |    2                                  
00220     X-<3-                                                    X-<3-C                                  
00221                                                                                                      
00222      ->1-C                                                    ->1-                                   
00223     |    V  W                                                |    V  W                               
00224     |    2                                                   |    2                                  
00225     X-<3-(C)                                                 X-<3-C                                   
00226                                                                                                      
00227     X----                                                     ->1-                                   
00228     |    |  NW  (theoretically impossible - no edges)        4    V  NW                              
00229     |    |                                                   ^    2                                  
00230      ----                                                     -<3-C                                   
00231                                                                                                      
00232     C----                                                    X----                                   
00233     |    |  N   (no edges (correct place))                   |    |  N   (theoretically impossible)  
00234     |    |                                                   |    |                                  
00235      ----                                                     ----                                   
00236                                                                                                      
00237      ->1-                                                     ->1-X                                  
00238     |    |  NE                                               |    |  NE                              
00239     |    |                                                   |    |                                  
00240      ----                                                     ----                                   
00241 
00242 
00243  Note how strikingly similar these are! We use the RH column one as that's generic for both sides.
00244 
00245 */
00246     
00247 
00248 
00249 
00250     // Grrr... This should be static but lovely C++ wont let me compile it. Thanks a lot C++
00251     // Heh what's 128 bytes when you have a bitmap to trace
00252     Directions[0].Init( (1<<8), (0<<8));    // East
00253     Directions[1].Init( (1<<8),-(1<<8));    // South East
00254     Directions[2].Init( (0<<8),-(1<<8));    // South
00255     Directions[3].Init(-(1<<8),-(1<<8));    // South West
00256     Directions[4].Init(-(1<<8), (0<<8));    // West
00257     Directions[5].Init(-(1<<8), (1<<8));    // North West
00258     Directions[6].Init( (0<<8), (1<<8));    // North
00259     Directions[7].Init( (1<<8), (1<<8));    // North East
00260 
00261     // First sort out the non-diagonal table
00262     DirectionPoint[0][0][0].Init( (1<<7), (1<<7));              // East to East
00263     DirectionPoint[0][0][1].Init( -1, -1);                      // No point 2
00264     DirectionPoint[0][0][2].Init( -1, -1);                      // No point 3
00265     DirectionPoint[0][0][3].Init( -1, -1);                      // No point 4
00266 
00267     DirectionPoint[0][1][0].Init( (1<<7), (1<<7));              // East to SE
00268     DirectionPoint[0][1][1].Init( (1<<7),-(1<<7));              // point 2
00269     DirectionPoint[0][1][2].Init( -1, -1);                      // No point 3
00270     DirectionPoint[0][1][3].Init( -1, -1);                      // No point 4
00271     
00272     DirectionPoint[0][2][0].Init( (1<<7), (1<<7));              // East to S
00273     DirectionPoint[0][2][1].Init( -1, 2);                       // No point 2, go south
00274     DirectionPoint[0][2][2].Init( -1, -1);                      // No point 3
00275     DirectionPoint[0][2][3].Init( -1, -1);                      // No point 4
00276     
00277     DirectionPoint[0][3][0].Init( (1<<7), (1<<7));              // East to SW
00278     DirectionPoint[0][3][1].Init( -1, 3);                       // No point 2, go SW
00279     DirectionPoint[0][3][2].Init( -1, -1);                      // point 3
00280     DirectionPoint[0][3][3].Init( -1, -1);                      // No point 4
00281 
00282     DirectionPoint[0][4][0].Init( (1<<7), (1<<7));              // East to W
00283     DirectionPoint[0][4][1].Init( -1, 2);                       // No point 2, go S
00284     DirectionPoint[0][4][2].Init( -1, -1);                      // point 3
00285     DirectionPoint[0][4][3].Init( -1, -1);                      // No point 4
00286 
00287     DirectionPoint[0][5][0].Init( (1<<7), (1<<7));              // South East to NW
00288     DirectionPoint[0][5][1].Init( (1<<7),-(1<<7));              // point 2
00289     DirectionPoint[0][5][2].Init( -1, 5);                       // No point 3, go NW
00290     DirectionPoint[0][5][3].Init( -1, -1);                      // No point 4
00291 
00292     DirectionPoint[0][6][0].Init( -1, 6);                       // No point 1, go N
00293     DirectionPoint[0][6][1].Init( -1, -1);                      // No point 2
00294     DirectionPoint[0][6][2].Init( -1, -1);                      // No point 3
00295     DirectionPoint[0][6][3].Init( -1, -1);                      // No point 4
00296 
00297     DirectionPoint[0][7][0].Init( (1<<7), (1<<7));              // East to NE
00298     DirectionPoint[0][7][1].Init( -1, -1);                      // No point 2
00299     DirectionPoint[0][7][2].Init( -1, -1);                      // No point 3
00300     DirectionPoint[0][7][3].Init( -1, -1);                      // No point 4
00301 
00302 
00303 
00304     DirectionPoint[1][0][0].Init( (1<<7), (1<<7));              // South East to East
00305     DirectionPoint[1][0][1].Init( -1, -1);                      // No point 2
00306     DirectionPoint[1][0][2].Init( -1, -1);                      // No point 3
00307     DirectionPoint[1][0][3].Init( -1, -1);                      // No point 4
00308 
00309     DirectionPoint[1][1][0].Init( (1<<7), (1<<7));              // South East to SE
00310     DirectionPoint[1][1][1].Init( (1<<7),-(1<<7));              // point 2
00311     DirectionPoint[1][1][2].Init( -1, -1);                      // No point 3
00312     DirectionPoint[1][1][3].Init( -1, -1);                      // No point 4
00313     
00314     DirectionPoint[1][2][0].Init( (1<<7), (1<<7));              // South East to S
00315     DirectionPoint[1][2][1].Init( (1<<7),-(1<<7));              // point 2
00316     DirectionPoint[1][2][2].Init( -1, -1);                      // No point 3
00317     DirectionPoint[1][2][3].Init( -1, -1);                      // No point 4
00318                     
00319     DirectionPoint[1][3][0].Init( (1<<7), (1<<7));              // South East to SW
00320     DirectionPoint[1][3][1].Init( (1<<7), (0<<7));              // point 3
00321     DirectionPoint[1][3][2].Init( -1, 3);                       // No point 4, go SW
00322     DirectionPoint[1][3][3].Init( -1, -1);                      // No point 4
00323 
00324     DirectionPoint[1][4][0].Init( (1<<7), (1<<7));              // South East to W
00325     DirectionPoint[1][4][1].Init( (1<<7),-(1<<7));              // point 2
00326     DirectionPoint[1][4][2].Init( -1, 4);                       // No point 3, go W
00327     DirectionPoint[1][4][3].Init( -1, -1);                      // No point 4
00328     
00329     DirectionPoint[1][5][0].Init( (1<<7), (1<<7));              // South East to NW
00330     DirectionPoint[1][5][1].Init( (1<<7),-(1<<7));              // point 2
00331     DirectionPoint[1][5][2].Init( -1, 5);                       // No point 3, go NW
00332     DirectionPoint[1][5][3].Init( -1, -1);                      // No point 4
00333 
00334     DirectionPoint[1][6][0].Init( -1, 6);                       // No point 1, go N
00335     DirectionPoint[1][6][1].Init( -1, -1);                      // No point 2
00336     DirectionPoint[1][6][2].Init( -1, -1);                      // No point 3
00337     DirectionPoint[1][6][3].Init( -1, -1);                      // No point 4
00338                 
00339     DirectionPoint[1][7][0].Init( (0<<7), (1<<7));              // South East to NE
00340     DirectionPoint[1][7][1].Init( -1, 7);                       // No point 2, go NE
00341     DirectionPoint[1][7][2].Init( -1, -1);                      // No point 3
00342     DirectionPoint[1][7][3].Init( -1, -1);                      // No point 4
00343     
00344     INT32 i;
00345     INT32 j;
00346     INT32 k;
00347     for (i=2; i<=7; i+=1) for (j=0; j<=7; j++) for (k=0; k<=3; k++)
00348     {
00349         // Go from direction i to direction j, i even
00350         INT32 j2 = (j-(i & 0x6)) & TR_NUMDIRECTIONMASK;
00351         DirectionPoint[i][j][k]=DirectionPoint[i & 0x1][j2][k];
00352         
00353         if (DirectionPoint[i][j][k].x != -1)
00354         {
00355             DirectionPoint[i][j][k].RotateDirection(Directions[(i & 0x6)]);
00356         }
00357         else
00358         {
00359             if (DirectionPoint[i][j][k].y != -1)
00360                 DirectionPoint[i][j][k].y = (((INT32)(DirectionPoint[(i & 0x1)][j2][k].y) + (i & 0x6)) & TR_NUMDIRECTIONMASK);
00361         }
00362     }
00363     
00364     TraceBoundaryPoint Centre;
00365     Centre.Init((1<<7),(1<<7));
00366     for (i=0; i<=7; i+=1) for (j=0; j<=7; j++) for (k=0; k<=3; k++)
00367     {
00368         if (DirectionPoint[i][j][k].x != -1)
00369         {
00370             DirectionPoint[i][j][k].translate(Centre);
00371         }
00372     }
00373     
00374 }

TraceRegion::~TraceRegion  ) 
 

Destructs object.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
none [INPUTS]
(destructs object) [OUTPUTS]
Returns:
none

Errors: None Scope: Public

See also:
-
This frees the boundary buffer it is is present.

Definition at line 505 of file tracergn.cpp.

00506 {
00507     if (BoundaryBuffer) CCFree(BoundaryBuffer);
00508     // Clear some hanging pointers
00509     BoundaryBuffer = NULL;
00510     Bitmap = NULL;
00511     ThePath = NULL;
00512 }


Member Function Documentation

double TraceRegion::Bezier0 double  u  )  [inline, protected]
 

Definition at line 373 of file tracergn.h.

00373 { double t=1.0-u; return (t*t*t); }

double TraceRegion::Bezier1 double  u  )  [inline, protected]
 

Definition at line 374 of file tracergn.h.

00374 { double t=1.0-u; return (3*u*t*t); }

double TraceRegion::Bezier2 double  u  )  [inline, protected]
 

Definition at line 375 of file tracergn.h.

00375 { double t=1.0-u; return (3*u*u*t); }

double TraceRegion::Bezier3 double  u  )  [inline, protected]
 

Definition at line 376 of file tracergn.h.

00376 { return (u*u*u); }

TraceBoundaryPoint TraceRegion::BezierPoint TraceBoundaryPoint Bez,
double  u
[protected]
 

This function simply evaluates the bezier function for a given position and is used to help when determining how good a fit we have obtained Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex
Date:
7/3/94
Parameters:
Bez - The control points of a bezier curve [INPUTS] u - the normalised distance along the bezier that we are interested in
Returns:
The coord of the point that is a distance u into the bezier. for example, if u = 0.5 then the coord of the point half way along the bezier will be returned
See also:
TraceRegion::CalcMaxError

Definition at line 1383 of file tracergn.cpp.

01384 {
01385     double OneMinus = 1.0-u;
01386     double uSquared = u*u;
01387     double OneMinusSquared = OneMinus*OneMinus;
01388 
01389     TraceBoundaryPoint Coord;
01390     Coord = Bez[0]*(OneMinusSquared*OneMinus);
01391     Coord = Coord + Bez[1]*(3.0*u*OneMinusSquared);
01392     Coord = Coord + Bez[2]*(3.0*uSquared*OneMinus);
01393     Coord = Coord + Bez[3]*(uSquared*u);
01394 
01395     return Coord;
01396 }

BOOL TraceRegion::CalcMaxError INT32  LeftPoint,
INT32  RightPoint,
TraceBoundaryPoint Bezier,
INT32 *  SplitPoint,
double *  MaxDist,
INT32  Level
[protected]
 

Finds out how good a fit the bezier curve we have created is when compared with the data points Scope: private.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/12/94
Parameters:
LeftPoint,RightPoint - the index of the start and send of the section - note these are indexes [INPUTS] into the T Array Bezier - the control points of the bezier we have fitted to the points Level - a recursion level counter
SplitPoint - the point to split the curve at if the error is too great [OUTPUTS] MaxDist - The biggest distance
Returns:
TRUE if the bezier should be split
This is done by recursive splitting of the line (as the largest error terms are likely to be in the middle we are extremely likely to only do one split). However, in order to find the maximum error point we force 3 levels of recursion.

Cunningly we move the TValues about if we think they are salvageable.

Definition at line 1426 of file tracergn.cpp.

01428 {
01429     TraceBoundaryPoint Q_t, Q1_t, Q2_t; // t evaluated at Q, Q' & Q''
01430     INT32 MidPoint = (LeftPoint + RightPoint+1)/2;  // where we are going to evaluate it
01431     double Distance;
01432     
01433     if (!((MidPoint == LeftPoint) || (MidPoint==RightPoint)))
01434     {
01435     
01436         for (INT32 iterations=1; iterations<=3; iterations++)
01437         {       
01438             double t = TValues[MidPoint];
01439             TraceBoundaryPoint pt = BoundaryBuffer[TPoints[MidPoint]];
01440 
01441             // Calculate where the curve actually is and find the distance from where we want it
01442             Distance = (BezierPoint(Bezier, t) - pt).SquaredLength();
01443 
01444             if ((Distance > *MaxDist) && (Distance < Error * 2.0))
01445             // If this is would be the new winner, and it's salvageable (less than twice as far away as we
01446             // we want), recalculate a better TValue
01447             {
01448 
01449                 // Evaluate Q, Q' & Q''
01450                 double OneMinus = 1.0-t;
01451                 double tSquared = t*t;
01452                 double OneMinusSquared = OneMinus*OneMinus;
01453 
01454                 Q_t = Bezier[0] *(OneMinusSquared*OneMinus) + Bezier[1]*(3.0*t*OneMinusSquared)
01455                      +Bezier[2] *(3.0*tSquared*OneMinus) + Bezier[3]*(tSquared*t);
01456                 Q1_t = Q1[0]*(OneMinusSquared) + Q1[1]*(2.0*t*OneMinus) + Q1[2]*(tSquared);
01457                 Q2_t = Q2[0]*(OneMinus) + Q2[1]*(t);
01458 
01459                 // Now Newton Raphson tprime = t - f(t)/f'(t)
01460                 TraceBoundaryPoint QtMinuspt = Q_t - pt;
01461 
01462 //  changed by Ed Cornes 31/10/95 in an attempt to remove an itermittent floating point exception in the tracer
01463 //              t = t - (  (QtMinuspt.x)*(Q1_t.x) + (QtMinuspt.y) * (Q1_t.y) ) /
01464 //                      (  Q1_t.SquaredLength() + ((QtMinuspt.x) * (Q2_t.x) + (QtMinuspt.y) * (Q2_t.y)) );
01465                 double denom = Q1_t.SquaredLength() + ((QtMinuspt.x) * (Q2_t.x) + (QtMinuspt.y) * (Q2_t.y));
01466                 if (fabs(denom)<1e-50)
01467                     denom = (denom<0) ? -1e-50 : 1e-50;
01468 
01469                 t = t - (  (QtMinuspt.x)*(Q1_t.x) + (QtMinuspt.y) * (Q1_t.y) ) / denom;
01470                 if (t<0) t=0;
01471                 if (t>1) t=1;
01472                 //TRACEUSER( "Alex", _T("Point %f moves to %f\n"),TValues[MidPoint],t);
01473                 TValues[MidPoint] = t;
01474             }
01475             else break; // Leave 'for' loop - point OK or point not salvageable
01476         }
01477 
01478         if ( Distance >= *MaxDist)
01479         {
01480             *MaxDist = Distance;
01481             *SplitPoint = MidPoint;
01482         }
01483 
01484         // If we haven't got a point to split at yet, or if we're in the 4 first points,
01485         // recurse down. This ensures we do 8 points.
01486         if ((*MaxDist<=Error) || (Level<3)) CalcMaxError(LeftPoint, MidPoint,
01487                                                          Bezier, SplitPoint, MaxDist, Level+1); 
01488         if ((*MaxDist<=Error) || (Level<3)) CalcMaxError(MidPoint, RightPoint,
01489                                                          Bezier, SplitPoint, MaxDist, Level+1); 
01490         
01491     }   
01492     return(*MaxDist>Error);
01493 }

TraceRegion::CC_DECLARE_DYNCREATE TraceRegion   )  [private]
 

TraceBoundaryPoint TraceRegion::CentreTangent INT32  Centre,
INT32  Points
[protected]
 

Finds the tangent at the centre of the path Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex
Date:
7/3/94
Parameters:
Centre - the index of the split point in the path [INPUTS] Points - the max number of points that can be scanned
Returns:
The tangent at the point Centre

Definition at line 1595 of file tracergn.cpp.

01596 {
01597     TraceBoundaryPoint Left, Right;
01598     TraceBoundaryPoint Tangent(0,0);
01599 
01600     Points = 1+MIN (Points/2,MAXTANGENTPOINTS);
01601     if (Points<2) Points=2;
01602 
01603     // Make sure that is not of zero length
01604     while ((Tangent.x==0) && (Tangent.y==0))
01605     {
01606         if ((--Points)>0)
01607         {
01608             // Calc right tangent
01609             Left.x = BoundaryBuffer[Centre-Points].x - BoundaryBuffer[Centre].x;
01610             Left.y = BoundaryBuffer[Centre-Points].y - BoundaryBuffer[Centre].y;
01611 
01612             // Calc left tangent
01613             Right.x = BoundaryBuffer[Centre].x - BoundaryBuffer[Centre+Points].x;
01614             Right.y = BoundaryBuffer[Centre].y - BoundaryBuffer[Centre+Points].y;
01615 
01616             // Average to get the centre tangent
01617             Tangent.x = (Left.x + Right.x) / 2;
01618             Tangent.y = (Left.y + Right.y) / 2;
01619 
01620         }
01621         else
01622         {
01623             ERROR3("Tangent was a zero length vector in the curve fitter (Centre)");
01624             Tangent.x = -1;
01625         }
01626     }
01627 
01628     return Tangent;
01629 }

BOOL TraceRegion::FillBoundaryBuffer BOOL *  End  )  [protected]
 

Fills up the boundary buffer.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
End ptr to BOOL to return in [INPUTS]
End set TRUE if last point else set FALSE [OUTPUTS]
Returns:
TRUE if worked, FALSE & error set if failed

Errors: Error2 & Error3 (various) Scope: Protected

See also:
TraceRegion::ProcessBoundaryBuffer
This routine fills the boundary buffer up with some more points. It stops if the buffer becomes nearly full.

It also stops if it meets a cusp, or the intial point in the initial direction.

Definition at line 824 of file tracergn.cpp.

00825 {
00826     INT32 NewDirection;
00827     INT32 Turns;
00828 
00829     ERROR2IF((!Bitmap),FALSE,"TraceRegion incorrectly initialised");
00830 
00831     *End=FALSE; 
00832     while (BoundaryHead<BoundaryRingSize - 6)   // there is enough room in buffer
00833     {
00834         // Calculate the new direction. We start looking at direction-2 but as we add one before we start
00835         // we have -3. If we're at a cusp we know the NewDirection set to HeadDirection is the correct place,
00836         // i.e. we want +0, but because we add one before we start, we want -1.
00837         NewDirection = (HeadDirection-(AtCusp?1:3)) & TR_NUMDIRECTIONMASK;
00838         //NewDirection = (HeadDirection-3) & TR_NUMDIRECTIONMASK;
00839         Turns=0;
00840         TraceBoundaryPoint NewPoint=HeadPoint; // Initialisation unnecessary but quiets the compiler
00841         
00842         
00843         do
00844         {
00845             // This should only return(TRUE) if asked to trace a
00846             // one pixel shape - else we must have got to this pixel some how.
00847             if ((Turns++)==8)
00848             {
00849                 *End=TRUE;
00850                 // We want to force it to be the 4 corner case
00851                 NewDirection=((HeadDirection & 0x6) + 6) & TR_NUMDIRECTIONMASK;
00852                 ERROR3("One pixel regions NYI");
00853                 // The above won't work properly because it's not properly entered. I think we need a horrible
00854                 // goto here.
00855                 break;
00856             }
00857             // Find next direction
00858             NewDirection = (NewDirection + 1) & TR_NUMDIRECTIONMASK;            
00859             NewPoint = HeadPoint;       // Calculate the new point
00860             NewPoint.translate(Directions[NewDirection]);
00861         } while (!pBfxPixelOp->IsInRegion(((INT32)(NewPoint.x))>>8, ((INT32)(NewPoint.y))>>8)); 
00862 
00863         if (VirginBuffer) InitialDirection = TailDirection = NewDirection;
00864 
00865 
00866         // stick point in ring buffer
00867         // Limit is such that we know we can fit the maximum of 4 points in
00868         INT32 HintPoint=0;
00869         if (!VirginBuffer)
00870         {
00871             if (AtCusp)
00872             {
00873                 // Only put the last point in if at a cusp
00874                 while ((DirectionPoint[HeadDirection][NewDirection][HintPoint].x != -1) // sufficient check
00875                       && (HintPoint<4)) {HintPoint++;}  // Don't inc at final point
00876                 BoundaryBuffer[BoundaryHead] = HeadPoint;
00877                 BoundaryBuffer[BoundaryHead++].translate(DirectionPoint[HeadDirection][NewDirection][HintPoint-1]);
00878                 // HintPoint still points at terminator
00879             }
00880             else
00881             {
00882                 // Put all points in
00883                 while ((DirectionPoint[HeadDirection][NewDirection][HintPoint].x != -1) // sufficient check
00884                       && (HintPoint<4))
00885                 {
00886                     BoundaryBuffer[BoundaryHead] = HeadPoint;
00887                     BoundaryBuffer[BoundaryHead++].translate(DirectionPoint[HeadDirection][NewDirection][HintPoint++]);
00888                 }
00889             }
00890         } else while ((DirectionPoint[HeadDirection][NewDirection][HintPoint].x != -1) // sufficient check
00891                       && (HintPoint<4)) {HintPoint++;}  // Don't inc at final point
00892 
00893 
00894         if (DirectionPoint[HeadDirection][NewDirection][HintPoint].y !=-1)
00895         {
00896             HeadDirection = (INT32)(DirectionPoint[HeadDirection][NewDirection][HintPoint].y);
00897 //          HeadPoint = NewPoint;
00898             AtCusp = TRUE;
00899             if (TailDirection == -1) TailDirection = HeadDirection;
00900 //          VirginBuffer = FALSE;
00901             return (TRUE);
00902         }
00903 
00904         // check for cusp a with dirty unsigned arithmetic and return NOW if we are there.
00905         // AtCusp =  ( ( ((unsigned)(Turns-2)) >=3) && (!AtCusp));
00906         AtCusp = FALSE;
00907 
00908         //if (AtCusp) return (TRUE); // cusp return 
00909     
00910 
00911         if ( (HeadPoint == InitialPoint) && (NewDirection == InitialDirection) && !VirginBuffer )
00912         {
00913             *End = TRUE;
00914             VirginBuffer = FALSE;
00915             return (TRUE);
00916         }
00917 
00918         VirginBuffer = FALSE;
00919  
00920         if (TailDirection == -1) TailDirection = NewDirection;
00921 
00922         // Set up member vars
00923         HeadPoint = NewPoint;
00924         HeadDirection = NewDirection;
00925 
00926     }
00927 
00928     return(TRUE); // Out of buffer space, go process some & come back
00929 }

BOOL TraceRegion::FindInitialPoint BOOL *  End  )  [protected]
 

Finds an initial point to start at.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
None [INPUTS]
End set if no points [OUTPUTS]
Returns:
TRUE if succeeded else FALSE and error set

Errors: Various Scope: Protected

See also:
-
This routine is currently a horrible bodge creature.

The boundary buffer is cleared. An initial point will be found if possible and End cleared. If one is not found, End will be set.

Definition at line 650 of file tracergn.cpp.

00651 {
00652     INT32 x;
00653     INT32 y;
00654 
00655     ERROR2IF((!Bitmap),FALSE,"How about giving us a bitmap first then?");
00656 
00657     InitialDirection = 0; // East
00658     VirginBuffer = TRUE;
00659     BoundaryHead =0;
00660     BoundaryTail =0;
00661     TailDirection = -1;
00662     HeadDirection = 0;
00663     AtCusp=FALSE;
00664     TailCusp = FALSE;
00665     *End = FALSE;
00666 
00667     for (y = ysize-1; y>=0; y--) for (x = 0; x < xsize; x++) if (pBfxPixelOp->IsInRegion(x,y))
00668     {
00669         InitialPoint.x = x<<8;
00670         InitialPoint.y = y<<8;
00671         HeadPoint = InitialPoint;
00672         return (TRUE);
00673     }
00674 
00675     *End = TRUE;    // Oh dear, no initial point
00676         
00677     return(TRUE);
00678 }

void TraceRegion::FitCubic INT32  FirstPoint,
INT32  LastPoint,
TraceBoundaryPoint  Tangent1,
TraceBoundaryPoint  Tangent2,
BOOL  IsStartCusp,
BOOL  IsEndCusp
[protected]
 

This function is recursive. It tries to fit a cubic function to the coordinates in the path between FirstPoint and LastPoint. It then compares this function with the actual coordinates to determine how good a fit it has found. If the fit is good it is added to the path object. If the fit is bad then it is split at the point where the fit is at its worst and FitCubic is called again for the left and right halves. Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex
Date:
7/3/94
Parameters:
FirstPoint - the index of the coordinate in the path to start fitting from [INPUTS] LastPoint - the index of the coordinate in the path to stop fitting at Tangent1 - The tangent of the curve at the first point Tangent2 - the tangent of the curve at the last point IsStartCusp - TRUE if FirstPoint is next to a cusp IsEndCusp - TRUE of EndPoint is next to a cusp
See also:
TraceRegion::GenerateBezier; TraceRegion::CalcMaxError

Definition at line 1029 of file tracergn.cpp.

01031 {
01032     // Will need space for a Bezier curve
01033     TraceBoundaryPoint Bezier[4];
01034     TraceBoundaryPoint CentTangent;
01035     INT32 NumPoints = LastPoint - FirstPoint + 1;
01036     INT32 SplitPoint, Split;
01037 
01038 
01039     // If we have the flexibility, recalculate the tangents to the left and right
01040     if (IsStartCusp) Tangent1 = LeftTangent(FirstPoint, NumPoints);
01041     if (IsEndCusp) Tangent2 = RightTangent(LastPoint, NumPoints);
01042 
01043 // The following is actually legal if we start on a cusp
01044 //  ERROR3IF(NumPoints<2,"Too few points to fit a cubic");
01045     if (NumPoints<2) return;
01046 #if 0
01047     // if this segment only has 2 points in it then do the special case
01048     if ( NumPoints == 2 )
01049     {
01050         InsertLine( DocCoord((INT32)(BoundaryBuffer[FirstPoint].x), (INT32)(BoundaryBuffer[FirstPoint].y)),
01051                     DocCoord((INT32)(BoundaryBuffer[LastPoint].x), (INT32)(BoundaryBuffer[FirstPoint].y)),
01052                     IsStartCusp, IsEndCusp);
01053         return;
01054     }
01055 #endif
01056     /* Due to a bug in the algorithm we also have to consider 3 points a special case.
01057 
01058     Here's what Mathematica reckons is the formula for a bezier A B C D that passes through a point Q
01059     with tangents tx & ty
01060 
01061                   4 t1x (Ay t2x + Dy t2x - 2 Qy t2x - Ax t2y - Dx t2y + 2 Qx t2y)
01062      {{Bx -> Ax - ---------------------------------------------------------------, 
01063                                        3 (t1y t2x - t1x t2y)
01064                   4 t1y (Ay t2x + Dy t2x - 2 Qy t2x - Ax t2y - Dx t2y + 2 Qx t2y)
01065        By -> Ay - ---------------------------------------------------------------, 
01066                                        3 (t1y t2x - t1x t2y)
01067                   (12 (Ay + Dy - 2 Qy) t1x - 12 (Ax + Dx - 2 Qx) t1y) t2x
01068        Cx -> Dx - -------------------------------------------------------, 
01069                                  9 (-(t1y t2x) + t1x t2y)
01070                   4 (Ay t1x + Dy t1x - 2 Qy t1x - Ax t1y - Dx t1y + 2 Qx t1y) t2y
01071        Cy -> Dy + ---------------------------------------------------------------, 
01072                                        3 (t1y t2x - t1x t2y)
01073 
01074     I reckon I can rewrite this better:
01075 
01076 
01077        F  -> (4/3) (A + D - 2 Q) / (t2x t1y - t2y t1x)
01078 
01079        B  -> Fy t2x - Fx t2y
01080          
01081        C  -> Fx t1y - Fy t1x
01082               
01083        Bx -> Ax - B t1x
01084    
01085        By -> Ay - B t1y
01086 
01087        Cx -> Dx - C t2x
01088               
01089        Cy -> Dy - C t2y
01090 
01091     This is all very well and good, but when does it occur? Here's an example:
01092 
01093 
01094     A     B
01095      ....
01096          ....
01097              ...T1
01098 
01099     T2....C
01100 
01101   
01102     Here A is is the FistPoint with tangent T1, and C is the last point with tangent T2. The only bezier that
01103     fits through B as well with tangents specified is a loop that goes left from C, back under it and up through T1.
01104     Though all the maths is fine, and we can even detect this case, it's just not worth it. We just miss out point B.
01105 
01106     Oh well, so much for the beaury of mathematics. (PS - the real soln is to introduce 1 or more extra points. But that's
01107     getting silly).
01108 
01109     */
01110     
01111     #if 0
01112     // Never appears to run to completion anyway :-(
01113     if (NumPoints == 3)
01114     {
01115         INT32 MidPoint = FirstPoint+1;
01116         double Bottom = 0.75 * (Tangent2.x * Tangent1.y - Tangent2.y * Tangent1.x);
01117         if (Abs(Bottom)>0.001) // Else ignore middle point - this happens if the tangents are nearly parallel
01118         {
01119             TraceBoundaryPoint F = (BoundaryBuffer[FirstPoint]+BoundaryBuffer[LastPoint]-BoundaryBuffer[MidPoint]*2.0)/Bottom;
01120             double B = F.y * Tangent2.x - F.x * Tangent2.y;
01121             double C = F.x * Tangent1.y - F.y * Tangent1.x;
01122             if ((B<0.0) && (C<0.0)) // Not generating a loop
01123             {
01124                 Tangent1 = -(Tangent1 * B);
01125                 Tangent2 = -(Tangent2 * C); // Don't worry - we just need their directions for the fallback case
01126                 // Max distance is ((1<<8)/2)^2 = (1<<14)
01127                 if ((Tangent1.SquaredLength()<(1<<14)) && (Tangent2.SquaredLength()<(1<<14)))
01128                 {
01129                     Bezier[0] = BoundaryBuffer[FirstPoint];
01130                     Bezier[3] = BoundaryBuffer[LastPoint];
01131                     Bezier[1] = BoundaryBuffer[FirstPoint] + Tangent1;
01132                     Bezier[2] = BoundaryBuffer[LastPoint] + Tangent2;
01133                     InsertBezier(Bezier, IsStartCusp, IsEndCusp);
01134                     return;
01135                 }
01136             }
01137         }   
01138     }
01139     #endif
01140 
01141     // We must consider 2 points (or unhandled 3 point cases) as a special case
01142     if ( NumPoints <=2)
01143     {
01144         // With 3 points the distance is always 2.
01145         INT32 Distance = (1<<8)*2/3;
01146         
01147         // store the end points
01148         Bezier[0] = BoundaryBuffer[FirstPoint];
01149         Bezier[3] = BoundaryBuffer[LastPoint];
01150         
01151         // calc the control points
01152         Bezier[1] = Bezier[0] + Tangent1.SetLength(Distance);
01153         Bezier[2] = Bezier[3] + Tangent2.SetLength(Distance);
01154 
01155         // add it to the path
01156         InsertBezier(Bezier, IsStartCusp, IsEndCusp);
01157         return;
01158     }
01159 
01160     
01161     if (NumPoints ==3)
01162     {
01163         Split = FirstPoint + 1; // Midpoint 
01164     }
01165     else
01166     {
01167         // Create a Bezier curve from the segemnt and see if it is a good fit
01168         Parameterize(FirstPoint, LastPoint);
01169 
01170         GenerateBezier(FirstPoint, LastPoint, Tangent1, Tangent2, Bezier);
01171     
01172         SplitPoint=NumTPoints-1;
01173         double MaxError = 0;    
01174         if (!CalcMaxError(0, NumTPoints, Bezier, &SplitPoint, &MaxError, 0))
01175         {
01176             // The mapping was good, so output the curve segment
01177             //TRACEUSER( "Alex", _T("  OK FP=%d, LP=%d, ME=%f\n"),FirstPoint,LastPoint,MaxError);
01178             InsertBezier(Bezier, IsStartCusp, IsEndCusp);
01179             return;
01180         }
01181 
01182         Split = TPoints[SplitPoint];
01183     }   
01184     
01185     //TRACEUSER( "Alex", _T("Split FP=%d, SP=%d, LP=%d\n"),FirstPoint,Split,LastPoint);
01186     // fitting failed -- split at max error point and fit recursively
01187     CentTangent = CentreTangent(Split, MIN(Split-FirstPoint+1,LastPoint-Split+1));
01188     //Tangent1=LeftTangent(FirstPoint,SplitPoint-FirstPoint+1);
01189     FitCubic(FirstPoint, Split, Tangent1, CentTangent, IsStartCusp, FALSE);
01190 
01191     CentTangent = -CentTangent;
01192     //Tangent2=RightTangent(LastPoint,LastPoint-SplitPoint+1);
01193     FitCubic(Split, LastPoint, CentTangent, Tangent2, FALSE, IsEndCusp);
01194     
01195 }

void TraceRegion::GenerateBezier INT32  FirstPoint,
INT32  LastPoint,
TraceBoundaryPoint  Tangent1,
TraceBoundaryPoint  Tangent2,
TraceBoundaryPoint Bezier
[protected]
 

This function supplies the maths to try and fit a cubic function to a set of points. It spends its time trying to come up with good lengths for the two tangents passed in to maximise the closeness of the fit. If it fails to come up with realistic results it simply sets the tangent lengths to be 1/3 of the distance between the start point and the end point. Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex
Date:
7/3/94
Parameters:
FirstPoint - the index of the coordinate in the path to start fitting from [INPUTS] LastPoint - the index of the coordinate in the path to stop fitting at Tangent1 - The tangent of the curve at the first point Tangent2 - the tangent of the curve at the last point
Bezier - A pointer to a Bezier Curve [OUTPUTS]
Note the differential & 2nd differential are also generated

Definition at line 1261 of file tracergn.cpp.

01263 {
01264     INT32 pos;
01265     INT32 i;
01266 //  INT32 NumPoints = LastPoint - FirstPoint + 1;
01267     
01268     // Build a matrix type of thing that contains the tangents scaled by the offsets
01269     TraceBoundaryPoint A[FIT_STEPS+1][2];           //  Vector2 (*A)[2] = new Vector2[NumPoints+1][2];
01270     
01271     // Chord length parameterisation
01272     for (pos=0; pos<=NumTPoints; pos++)
01273     {
01274         // Fill the matrix A
01275         A[pos][0] = Tangent1.SetLength( Bezier1(TValues[pos]) );
01276         A[pos][1] = Tangent2.SetLength( Bezier2(TValues[pos]) );
01277     }
01278 
01279     // For a detailed description of the maths used here, please see Graphics Gems I
01280     // I have made some changes to the basic algorithm used there - the main one is
01281     // that this block of maths is only performed on a small selection of the points
01282     // in the data set, where-as the one in the book uses all the points
01283     double  C[2][2];
01284     double  X[2];
01285     
01286     C[0][0] = 0.0;
01287     C[0][1] = 0.0;
01288     C[1][0] = 0.0;
01289     C[1][1] = 0.0;
01290     X[0]    = 0.0;
01291     X[1]    = 0.0;
01292     
01293     TraceBoundaryPoint FirstCoord = BoundaryBuffer[FirstPoint];
01294     TraceBoundaryPoint LastCoord  = BoundaryBuffer[LastPoint];
01295     TraceBoundaryPoint ThisCoord, Combo;
01296 
01297     for (pos=0; pos<=NumTPoints; pos++)
01298     {
01299         C[0][0] += A[pos][0].SquaredLength();
01300         C[0][1] += A[pos][0].Dot(A[pos][1]);
01301         // Point C[1][0] is the same as C[0][1] and is set outside the loop below
01302         C[1][1] += A[pos][1].SquaredLength();
01303         
01304         // Go ahead and build a vector based on the bezier functions
01305         ThisCoord = BoundaryBuffer[TPoints[pos]];
01306         Combo = ThisCoord - ((FirstCoord * Bezier0(TValues[pos]))
01307                             + (FirstCoord * Bezier1(TValues[pos]))
01308                             + (LastCoord  * Bezier2(TValues[pos]))
01309                             + (LastCoord  * Bezier3(TValues[pos])));
01310 
01311         // Combine it with the other points
01312         X[0] += A[pos][0].Dot( Combo );
01313         X[1] += A[pos][1].Dot( Combo );
01314 
01315     }
01316 
01317     // This point in the matrix is the same, so we do not need to do it in the loop
01318     C[1][0] = C[0][1];
01319     
01320     // calc the determinants of C and X
01321     double det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
01322     double det_C0_X  = C[0][0] * X[1]    - C[0][1] * X[0];
01323     double det_X_C1  = X[0]    * C[1][1] - X[1]    * C[0][1];
01324     
01325     // finally, derive the length of the ideal tangents
01326     if (det_C0_C1 == 0.0)
01327         det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;   // oh err, whats it up to here then!
01328     
01329     double AlphaLeft  = det_X_C1 / det_C0_C1;
01330     double AlphaRight = det_C0_X / det_C0_C1;
01331     
01332     Bezier[0] = BoundaryBuffer[FirstPoint];
01333     Bezier[3] = BoundaryBuffer[LastPoint];
01334 
01335     // if alpha negative, the set the tangent length to a third of the distance between
01336     // the start and the end points of the curve segment    
01337     if ( AlphaLeft < 0.0 || AlphaRight < 0.0)
01338     {
01339         INT32 Distance = ((LastPoint - FirstPoint)<<8) / 3;
01340         
01341         Bezier[1] = Bezier[0] + Tangent1.SetLength(Distance);
01342         Bezier[2] = Bezier[3] + Tangent2.SetLength(Distance);
01343     }
01344     else
01345     {   
01346         Bezier[1] = Bezier[0] + Tangent1.SetLength(AlphaLeft);
01347         Bezier[2] = Bezier[3] + Tangent2.SetLength(AlphaRight);
01348     }
01349 
01350     // Calculate Q1 (differential)
01351     for (i = 0; i<=2; i++)
01352     {
01353         Q1[i]= (Bezier[i+1]-Bezier[i]) * 3.0;
01354     }
01355 
01356     // Calculate Q2 (2nd differential)
01357     for (i = 0; i<=1; i++)
01358     {
01359         Q2[i] = (Q1[i+1]-Q1[i]) * 2.0;
01360     }
01361 
01362 }

BOOL TraceRegion::GetParams double *  pPixelError = NULL  ) 
 

Sets the tracing parameters.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/1/95
Parameters:
None [INPUTS]
^double values of parameters to read May be set to NULL to not read them [OUTPUTS]
Returns:
TRUE on success, FALSE (& error set) on failure

Errors: mainly memory. Scope: Public

See also:
-

Definition at line 419 of file tracergn.cpp.

00420 {
00421     if (pPixelError) *pPixelError = PixelError;
00422     return TRUE;
00423 }

void TraceRegion::InsertBezier TraceBoundaryPoint Bezier,
BOOL  IsStartCusp,
BOOL  IsEndCusp
[protected]
 

Adds the bezier curve to the path. If it is that last curve in the fitting (ie Depth is 0) then the rotate flag will not be set Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex
Date:
7/3/94
Parameters:
Bezier - the control points of the bezier curve to add to the path [INPUTS] IsStartCusp - TRUE if the start of this bezier is at a cusp IsEndCusp - TRUE if the End of this bezier is at a cusp

Definition at line 1648 of file tracergn.cpp.

01649 {
01650     // Prepare some flags
01651     PathFlags Flags;
01652     Flags.IsSelected = FALSE;
01653     Flags.IsSmooth = FALSE;
01654     Flags.IsRotate = TRUE;
01655 
01656     // Add this Bezier curve into the path
01657     ThePath->InsertCurveTo( DocCoord( (INT32)Bezier[1].x, (INT32)Bezier[1].y),
01658                              DocCoord( (INT32)Bezier[2].x, (INT32)Bezier[2].y),
01659                              DocCoord( (INT32)Bezier[3].x, (INT32)Bezier[3].y), &Flags);
01660 
01661     // Deal with cusps
01662     if (IsStartCusp || IsEndCusp)
01663     {
01664         // Go find out about the path
01665         PathFlags* AllFlags = ThePath->GetFlagArray();
01666         INT32 NumCoords = ThePath->GetNumCoords();
01667 
01668         if (IsStartCusp)
01669         {
01670             // Patch up the flags of the bits near that start
01671             AllFlags[NumCoords-3].IsRotate = FALSE;
01672         }
01673     
01674         if (IsEndCusp)
01675         {
01676             // Patch up the flags of the bits near that end
01677             AllFlags[NumCoords-2].IsRotate = FALSE;
01678             AllFlags[NumCoords-1].IsRotate = FALSE;
01679         }
01680     }
01681 }

void TraceRegion::InsertLine const DocCoord Start,
const DocCoord End,
BOOL  IsStartCusp,
BOOL  IsEndCusp
[protected]
 

Inserts a straight curve into the path. It keeps it as a curve so that the path will continue to look smooth after it is edited. If this is the last Path element in the fit, (ie Depth is zero) then the rotate flag will not be set. Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex
Date:
7/3/94
Parameters:
Start - the coord of the start point of the line [INPUTS] End - the coord of the end point of the line IsStartCusp - TRUE if the start of this bezier is at a cusp IsEndCusp - TRUE if the End of this bezier is at a cusp
I've simplified the maths in this somewhat since over the FitCurve implementation.

Definition at line 1706 of file tracergn.cpp.

01708 {
01709     // Prepare some flags
01710     PathFlags Flags;
01711     Flags.IsSelected = FALSE;
01712     Flags.IsSmooth = FALSE;
01713     Flags.IsRotate = TRUE;
01714 
01715     // Find out a third of the distance between the two points
01716     DocCoord StartPos;
01717     DocCoord EndPos;
01718 
01719     StartPos.x = (2 * Start.x + End.x) /3;
01720     StartPos.y = (2 * Start.y + End.y) /3;
01721     EndPos.x = (Start.x + 2 * End.x) /3;
01722     EndPos.y = (Start.y + 2 * End.y) /3;
01723 
01724     // Add the line to the curve
01725     ThePath->InsertCurveTo( (DocCoord) StartPos, (DocCoord) EndPos, (DocCoord) End, &Flags);    
01726     
01727     // Patch up the path
01728     PathVerb * AllVerbs = ThePath->GetVerbArray();
01729     PathFlags* AllFlags = ThePath->GetFlagArray();
01730     INT32 NumCoords = ThePath->GetNumCoords();
01731     ERROR3IF(NumCoords<4,"No initial moveto ?!");
01732 
01733     AllFlags[NumCoords-1].IsRotate = !IsEndCusp;    // Endpoint
01734     AllFlags[NumCoords-2].IsRotate = !IsEndCusp; // 2nd ctl
01735 
01736     if (AllVerbs[NumCoords-4] == PT_MOVETO)
01737     {
01738         AllFlags[NumCoords-3].IsRotate = FALSE;
01739         AllFlags[NumCoords-4].IsRotate = FALSE;
01740     }
01741     else
01742     {
01743         //BOOL IsStartCusp = AllFlags[NumCoords-5].IsRotate;
01744 
01745         AllFlags[NumCoords-3].IsRotate = !IsStartCusp;
01746         AllFlags[NumCoords-4].IsRotate = !IsStartCusp;
01747 
01748         
01749     }
01750 
01751 }

void TraceRegion::InsertStraightLine const DocCoord End  )  [protected]
 

Inserts a straight Line into the path. This is used in cases where the Line segment must be kept as a straight line (ie by using Straight Line Mode of the FreeHand tool) Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex & Alex
Date:
25/4/94
Parameters:
End - the coord of the end point of the line [INPUTS]

Definition at line 1770 of file tracergn.cpp.

01771 {
01772     // Prepare some flags
01773     PathFlags Flags;
01774     Flags.IsSelected = FALSE;
01775     Flags.IsRotate = FALSE;
01776     Flags.IsSmooth = FALSE;
01777 
01778     // Insert the line
01779     ThePath->InsertLineTo((DocCoord) End, &Flags);  
01780 }

BOOL TraceRegion::IsCuspDirectionChange INT32  dir1,
INT32  dir2
[inline, protected]
 

Definition at line 423 of file tracergn.h.

00424         { return (((dir1-dir2+TR_NUMDIRECTIONMASK+2) & TR_NUMDIRECTIONMASK)>2); }

TraceBoundaryPoint TraceRegion::LeftTangent INT32  Start,
INT32  Points
[protected]
 

Finds the Left tangent at the given point in the path Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex
Date:
7/3/94
Parameters:
Start - the index of the point at the start of the segment to fit [INPUTS] Points - the max number of points that can be scanned
Returns:
The tangent at the point Start

Definition at line 1514 of file tracergn.cpp.

01515 {
01516     TraceBoundaryPoint Tangent(0,0);
01517 
01518     Points = 1+MIN (Points/2,MAXTANGENTPOINTS);
01519     if (Points<2) Points=2;
01520 
01521     // Make sure that is not of zero length
01522     while ((Tangent.x==0) && (Tangent.y==0))
01523     {
01524         if ((--Points)>0)
01525         {
01526             Tangent.x = BoundaryBuffer[Start+Points].x - BoundaryBuffer[Start].x;
01527             Tangent.y = BoundaryBuffer[Start+Points].y - BoundaryBuffer[Start].y;
01528         }
01529         else
01530         {
01531             ERROR3("Tangent was a zero length vector in the curve fitter (Left)");
01532             Tangent.x = -1;
01533         }
01534     }
01535 
01536     return Tangent;
01537 }

void TraceRegion::Parameterize INT32  FirstPoint,
INT32  LastPoint
[protected]
 

This function determines the TPoints which will be fitted (i.e. the trace boundary points we use) and the TValues which will be assigned to them (i.e. the t values along the chord length to which the points correspond). Scope: private.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/12/94
Parameters:
FirstPoint - the index of the coordinate in the path to start fitting from [INPUTS] LastPoint - the index of the coordinate in the path to stop fitting at
Fills up TValues & TPoints array [OUTPUTS]

Definition at line 1215 of file tracergn.cpp.

01216 {
01217     INT32 pos, i;
01218     
01219     INT32 NumPoints = LastPoint-FirstPoint;
01220     // Chord length parameterisation
01221 
01222     NumTPoints = MIN(NumPoints, FIT_STEPS);
01223 
01224     for (pos=0; pos<=NumTPoints; pos++)
01225     {
01226         i = (INT32)(((double)pos/(double)NumTPoints*(double)(NumPoints))+0.5);
01227         // In this loop, 
01228         TValues[pos] = ((double)i)/((double)NumPoints);
01229         TPoints[pos] = (i+FirstPoint);
01230     }
01231     
01232     // These should algorithmically never happen
01233     ERROR3IF(TPoints[0]!=FirstPoint,"TraceRegion::Parameterize fouled up first point");
01234     ERROR3IF(TPoints[NumTPoints]!=LastPoint,"TraceRegion::Parameterize fouled up last point");
01235     return;
01236 }

BOOL TraceRegion::ProcessBoundaryBuffer BOOL  Done = FALSE  )  [protected]
 

Empties the boundary buffer.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
Done TRUE to set last point to FirstBufferPoint [INPUTS]
none [OUTPUTS]
Returns:
TRUE if worked, FALSE & error set if failed

Errors: Error2 & Error3 (various) Scope: Protected

See also:
TraceRegion::ProcessBoundaryBuffer
This routine empties the boundary buffer. It leaves exactly one coordinate in it. The buffer must be non-empty.

Definition at line 951 of file tracergn.cpp.

00952 {
00953     BoundaryTail = 0;
00954 //  ERROR3IF( (((BoundaryHead - BoundaryTail) & BoundaryRingMask) <=0 ),
00955 //          "Boundary ring buffer is empty");
00956     if (((BoundaryHead - BoundaryTail) & BoundaryRingMask) <=0 ) return TRUE;
00957 
00958     if (VirginPath)
00959     {
00960         ThePath->FindStartOfPath();
00961         ThePath->InsertMoveTo(DocCoord((INT32)(BoundaryBuffer[BoundaryTail].x), (INT32)(BoundaryBuffer[BoundaryTail].y)));
00962         VirginPath = FALSE;
00963         FirstBufferPoint=BoundaryBuffer[BoundaryTail];
00964     }
00965 
00966     // Patch up initial hinting (done on inadequate information)
00967     if (Done)
00968     {
00969         BoundaryBuffer[BoundaryHead-1]=FirstBufferPoint;
00970         if (BoundaryBuffer[BoundaryHead-2]==FirstBufferPoint) BoundaryHead=(BoundaryHead-1)&BoundaryRingMask;
00971         if (((BoundaryHead - BoundaryTail) & BoundaryRingMask) <=0 ) return TRUE;
00972     }
00973 
00974 #if 0   
00975     while (BoundaryTail != (BoundaryHead-1))
00976     {
00977         InsertLine(DocCoord((INT32)(BoundaryBuffer[BoundaryTail].x),(INT32)(BoundaryBuffer[BoundaryTail].y)),
00978                    DocCoord((INT32)(BoundaryBuffer[BoundaryTail=(BoundaryTail + 1) & BoundaryRingMask].x),
00979                             (INT32)(BoundaryBuffer[BoundaryTail].y)), TRUE, TRUE);
00980     }
00981 #else
00982     // This case should never occur, but does very very occasionally - not sure why (Alex)
00983     // we ignore buffers with only one point in
00984     if (((BoundaryHead-1) & BoundaryRingMask)==BoundaryTail) return TRUE;
00985 
00986     // Just have to fit a curve from the last cusp to the end of the path
00987     TraceBoundaryPoint Tangent1 = LeftTangent(BoundaryTail,BoundaryHead-BoundaryTail);
00988     TraceBoundaryPoint Tangent2 = RightTangent(BoundaryHead-1,BoundaryHead-BoundaryTail);
00989     
00990     // and do a load of maths that will hopefully fit a nice curve on it
00991     FitCubic(BoundaryTail, BoundaryHead-1, Tangent1, Tangent2, TailCusp, AtCusp);
00992 #endif
00993     
00994     BoundaryBuffer[0]=BoundaryBuffer[BoundaryHead-1];
00995     BoundaryTail = 0;
00996     BoundaryHead = 1;
00997 
00998     TailDirection = -1;
00999     TailCusp = AtCusp;
01000     return (TRUE);
01001 }

TraceBoundaryPoint TraceRegion::RightTangent INT32  End,
INT32  Points
[protected]
 

Finds the Right tangent at the given point in the path Scope: private.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> & Alex
Date:
7/3/94
Parameters:
End - the index of the point at the end of the segment to fit [INPUTS] Points - the max number of points that can be scanned
Returns:
The tangent at the point End

Definition at line 1554 of file tracergn.cpp.

01555 {
01556     TraceBoundaryPoint Tangent(0,0);
01557 
01558     Points = 1+MIN (Points/2,MAXTANGENTPOINTS);
01559     if (Points<2) Points=2;
01560 
01561     // Make sure that is not of zero length
01562     while ((Tangent.x==0) && (Tangent.y==0))
01563     {
01564         if ((--Points)>0)
01565         {
01566             Tangent.x = BoundaryBuffer[End-Points].x - BoundaryBuffer[End].x;
01567             Tangent.y = BoundaryBuffer[End-Points].y - BoundaryBuffer[End].y;
01568         }
01569         else
01570         {
01571             ERROR3("Tangent was a zero length vector in the curve fitter (Right)");
01572             Tangent.x = -1;
01573         }
01574     }
01575 
01576     return Tangent;
01577 }

BOOL TraceRegion::SetParams double *  pPixelError = NULL  ) 
 

Sets the tracing parameters.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/1/95
Parameters:
^double values of parameters to set. May be set to NULL to not change them [INPUTS]
None [OUTPUTS]
Returns:
TRUE on success, FALSE (& error set) on failure

Errors: mainly memory. Scope: Public

See also:
-

Definition at line 393 of file tracergn.cpp.

00394 {
00395     if (pPixelError) PixelError = *pPixelError;
00396     Error = PixelError;
00397     Error *= 256.0; // For shift
00398     Error *= Error; // Squared
00399 
00400     return TRUE;
00401 }

void TraceRegion::Test UndoableOperation Op  )  [static]
 

Internal test routine.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
^Op [INPUTS]
none [OUTPUTS]
Returns:
nothing

Errors: none

See also:
-
A test routine

Definition at line 1802 of file tracergn.cpp.

01803 {
01804      
01805     BOOL CarryOn=TRUE;
01806     Range Sel(*(GetApplication()->FindSelection()));
01807 
01808     Node* FirstSelectedNode = Sel.FindFirst(); 
01809     if (FirstSelectedNode != NULL) // No nodes selected so End
01810     {
01811         Node* CurrentNode = FirstSelectedNode;       
01812         Node* NextCurrent; 
01813         
01814         // Do all bitmaps
01815         while ((CurrentNode != NULL) && CarryOn)
01816         {
01817             NextCurrent = Sel.FindNext(CurrentNode);
01818             if  ( (CurrentNode->IsSelected()) && (CurrentNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeBitmap)) ) 
01819             {         
01820                 KernelBitmap * pBitmap = ((NodeBitmap *)(CurrentNode))->GetBitmap();
01821                 BitmapInfo BMInfo;
01822                 UINT32 bpp;
01823                 pBitmap->ActualBitmap->GetInfo(&BMInfo);
01824                 bpp=BMInfo.PixelDepth;
01825                 
01826                 TRACEUSER( "Alex", _T("Bitmap found %d bpp\n"),bpp);
01827 
01828                 if ((bpp==32) || TRUE)
01829                 {
01830                     CarryOn = FALSE;
01831 //                  NodeBitmap *pNodeBitmap = new NodeBitmap;
01832 //                  if ((pNodeBitmap == NULL) || (!pNodeBitmap->SetUpPath(12,12)))
01833 //                      return;
01834 
01835                     Spread *pSpread;
01836                     DocCoord Origin;
01837 
01838                     // For now, position Draw objects on 1st page of spread 1
01839                     Node *pNode = (Document::GetSelected())->GetFirstNode()->FindNext()->FindFirstChild();
01840                     while ((pNode != NULL) && (!pNode->IsKindOf(CC_RUNTIME_CLASS(Chapter))))
01841                         pNode = pNode->FindNext();
01842         
01843                     ENSURE(pNode->IsKindOf(CC_RUNTIME_CLASS(Chapter)), 
01844                            "Filter::GetFirstSpread(): Could not find Chapter");
01845                     Chapter *pChapter = (Chapter *) pNode;
01846     
01847                     // pSpread is a child of pChapter
01848                     pSpread = (Spread *) pChapter->FindFirstChild();
01849                     ENSURE(pSpread->IsKindOf(CC_RUNTIME_CLASS(Spread)),
01850                            "Filter::GetFirstSpread(): Could not find Spread");
01851 
01852                     Page *pPage = (Page *) pSpread->FindFirstPageInSpread();
01853                     ENSURE(pPage->IsKindOf(CC_RUNTIME_CLASS(Page)),
01854                            "BaseBitmapFilter::DoImport(): Could not find first Page");
01855         
01856                     // Use bottom left of page as origin
01857                     DocRect PageRect = pPage->GetPageRect();
01858                     Origin = PageRect.lo;
01859     
01860                     NodePath * pNewNode;
01861                     pNewNode = new NodePath;
01862 
01863                     TraceRegion TR;
01864 
01865 //                  if ((pNode = TR->Trace(pBitmap,((NodeBitmap *)(CurrentNode))->Parallel)) == NULL) {return;}
01866 
01867                     TR.UseBitmap(pBitmap);
01868                     TR.UsePath(&(pNewNode->InkPath));
01869                     TR.TraceBoundary(((NodeBitmap * )CurrentNode)->Parallel[3],
01870                                      ((NodeBitmap * )CurrentNode)->Parallel[2],
01871                                      ((NodeBitmap * )CurrentNode)->Parallel[0]);
01872 
01873                     // Insert the node, but don't invalidate its region
01874                     if (!Op->DoInsertNewNode(pNewNode, pSpread, FALSE))
01875                     {
01876                         // It didn't work - delete the sub-tree we just created, and report error.
01877                         delete pNewNode;
01878                         return;
01879                     }
01880                                                         
01881                     // Invalidate the region
01882                     Op->DoInvalidateNodeRegion(pNewNode, TRUE, FALSE);
01883                 
01884                 }
01885             }
01886             CurrentNode = NextCurrent; 
01887         }
01888 
01889     } 
01890 
01891 //  if (CarryOn) BitmapEffectSILT::RunA();
01892 
01893     return;
01894 }

BOOL TraceRegion::Trace INT32  InitialX,
INT32  InitialY,
BfxPixelOp thepBfxPixelOp
 

Does a single boundary trace.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
Initial coordinates and pixel contour to trace [INPUTS]
None [OUTPUTS]
Returns:
TRUE if succeeded else FALSE and error set

Errors: Various Scope: Protected

See also:
-

Definition at line 743 of file tracergn.cpp.

00744 {
00745     BOOL Done=FALSE;
00746     ERROR2IF((!Bitmap),FALSE,"How about giving us a bitmap first then?");
00747 
00748     pBfxPixelOp = thepBfxPixelOp;
00749     
00750     ERROR2IF( ((!pBfxPixelOp->IsInRegion(InitialX,InitialY))), FALSE, "Initial point not in region" );
00751 
00752     BOOL Bottom=FALSE;
00753     while (!Bottom)
00754     {
00755         Bottom=TRUE;
00756         if (pBfxPixelOp->IsInRegion(InitialX-1,InitialY-1))
00757         {
00758             InitialY--;
00759             InitialX--;
00760             Bottom=FALSE;
00761         }
00762         if (pBfxPixelOp->IsInRegion(InitialX,InitialY-1))
00763         {
00764             InitialY--;
00765             Bottom=FALSE;
00766         }
00767         if (pBfxPixelOp->IsInRegion(InitialX-1,InitialY))
00768         {
00769             InitialX--;
00770             Bottom=FALSE;
00771         }
00772     }
00773 
00774     InitialDirection = 4; // West
00775     VirginBuffer = TRUE;
00776     BoundaryHead =0;
00777     BoundaryTail =0;
00778     TailDirection = -1;
00779     HeadDirection = 4;
00780     AtCusp=FALSE;
00781     TailCusp = FALSE;
00782 
00783     InitialPoint.x = InitialX<<8;
00784     InitialPoint.y = InitialY<<8;
00785     HeadPoint = FirstBufferPoint = InitialPoint;
00786 
00787     do
00788     {
00789         if (!FillBoundaryBuffer(&Done)) return (FALSE);
00790         if (!VirginBuffer) { if (!ProcessBoundaryBuffer(Done)) return (FALSE); } else BoundaryHead=0;
00791     } while (!Done);
00792 
00793     ERROR2IF(VirginPath, FALSE, "We've just traced a path that wasn't a path. Very odd");
00794 
00795     ThePath->CloseSubPath();
00796     ThePath->IsFilled = TRUE; // What lovely encapsulation & abstraction...
00797 
00798     return (TRUE);
00799 }

BOOL TraceRegion::TraceBoundary DocCoord  Origin,
DocCoord  Point1,
DocCoord  Point2
[protected]
 

Does a single boundary trace.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
3 points describing parallelogram [INPUTS]
None [OUTPUTS]
Returns:
TRUE if succeeded else FALSE and error set

Errors: Various Scope: Protected

See also:
-
This function is now defunct and is used to test porpoises only

Definition at line 699 of file tracergn.cpp.

00700 {
00701     BOOL Done;
00702     ERROR2IF((!Bitmap),FALSE,"How about giving us a bitmap first then?");
00703 
00704     // First find the initial point
00705     if (!(FindInitialPoint(&Done))) return (FALSE);
00706     if (Done) return (TRUE);
00707 
00708     do
00709     {
00710         if (!FillBoundaryBuffer(&Done)) return (FALSE);
00711         if (!ProcessBoundaryBuffer(Done)) return (FALSE);
00712     } while (!Done);
00713 
00714     ThePath->CloseSubPath();
00715     ThePath->IsFilled = TRUE; // What lovely encapsulation & abstraction...
00716 
00717     Matrix tMatrix(Div32By32(Point1.x-Origin.x,xsize<<8),Div32By32(Point2.x-Origin.x,xsize<<8),
00718                    Div32By32(Point1.y-Origin.y,ysize<<8),Div32By32(Point2.y-Origin.y,ysize<<8),
00719                    Origin.x,Origin.y);
00720     Trans2DMatrix Trans(tMatrix);
00721     Trans.Transform( (DocCoord*)ThePath->GetCoordArray(), ThePath->GetNumCoords() );
00722 
00723     return (TRUE);
00724 }

BOOL TraceRegion::UseBitmap KernelBitmap pBitmap  ) 
 

Points the TraceRegion at a particular bitmap and claims the relevant size buffers.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
pBitmap = pointer to bitmap object to use or NULL for none [INPUTS]
(sets object up) [OUTPUTS]
Returns:
TRUE if succeeded else FALSE and error set

Errors: None Scope: Public

See also:
-
The TraceRegion is set up with a new boundary buffer of an appropriate size. If NULL is passed in the buffers are removed.

Note (surprisingly, perhaps) we don't actually ever refer to pixels within this bitmap. Only its size is used. The BfxPixelOp does all the poking around and it may be referencing a different (but same sized) bitmap elsewhere.

Definition at line 538 of file tracergn.cpp.

00539 {
00540     if (BoundaryBuffer)
00541     {
00542         CCFree(BoundaryBuffer);
00543         BoundaryBuffer = NULL;
00544     }
00545                                                            
00546     xsize=1;
00547     ysize=1;
00548     Bitmap = NULL;
00549     
00550     if (pBitmap)
00551     {
00552         INT32 MaxDimension;
00553         BitmapInfo BMInfo;
00554         pBitmap->ActualBitmap->GetInfo(&BMInfo);
00555         
00556         // Max dimension is 8 times the largest of the width and height (enough to fit a bezier
00557         // curve of maximal usefulness into half the buffer)
00558         MaxDimension = ((BMInfo.PixelWidth>BMInfo.PixelHeight)?BMInfo.PixelWidth:BMInfo.PixelHeight)*8;
00559         ERROR2IF(MaxDimension<=0, FALSE, "Bitmap info structure is dead");
00560         BoundaryRingSize = 1;
00561         
00562         if (MaxDimension<80) MaxDimension=80;
00563 
00564         // Get next highest power of 2 & mask
00565         while (BoundaryRingSize < MaxDimension) BoundaryRingSize = BoundaryRingSize<<1;
00566         BoundaryRingMask = BoundaryRingSize -1;
00567         
00568         // Allocate memory (CCMalloc sets error)
00569         if (NULL== (BoundaryBuffer=(TraceBoundaryPoint *)CCMalloc(sizeof(TraceBoundaryPoint) * BoundaryRingSize)) )
00570             return FALSE;
00571 //      // fill the memory up with +S-NAN
00572 //      for (INT32 i=0; i<BoundaryRingSize; i++)
00573 //      {
00574 //          INT32* p = (INT32*)&(BoundaryBuffer[i].x);
00575 //          *p++ = 0xFFFFFFFF;
00576 //          *p++ = 0x7FF7FFFF;
00577 //          p = (INT32*)&(BoundaryBuffer[i].y);
00578 //          *p++ = 0xFFFFFFFF;
00579 //          *p++ = 0x7FF7FFFF;
00580 //      }
00581 
00582         xsize = BMInfo.PixelWidth;
00583         ysize = BMInfo.PixelHeight;
00584         Bitmap=pBitmap;
00585         VirginBuffer = TRUE;
00586         TailDirection = -1;
00587         BoundaryHead =0;
00588         BoundaryTail =0;
00589         TailDirection = 0;
00590         HeadDirection = 0;
00591         InitialDirection = 0;
00592         AtCusp = FALSE;
00593         TailCusp = FALSE;
00594     }
00595     return (TRUE);
00596 }

BOOL TraceRegion::UsePath Path pPath  ) 
 

Specifies we should use a particular path. The path is initialised, cleared etc.

Author:
Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
pPath = pointer to Path object to use or NULL for none [INPUTS]
(sets object up) [OUTPUTS]
Returns:
TRUE if succeeded else FALSE and error set

Errors: None Scope: Public

See also:
-

Definition at line 615 of file tracergn.cpp.

00616 {
00617     ThePath = NULL;
00618     VirginPath = TRUE;
00619     
00620     if (pPath)
00621     {
00622 //      if (!pPath->Initialise()) return FALSE;
00623         if (!pPath->ClearPath()) return FALSE;
00624         ThePath = pPath;
00625     }
00626     return (TRUE);
00627 }


Member Data Documentation

BOOL TraceRegion::AtCusp [protected]
 

Definition at line 408 of file tracergn.h.

KernelBitmap* TraceRegion::Bitmap [protected]
 

Definition at line 386 of file tracergn.h.

TraceBoundaryPoint* TraceRegion::BoundaryBuffer [protected]
 

Definition at line 383 of file tracergn.h.

INT32 TraceRegion::BoundaryHead [protected]
 

Definition at line 399 of file tracergn.h.

INT32 TraceRegion::BoundaryRingMask [protected]
 

Definition at line 400 of file tracergn.h.

INT32 TraceRegion::BoundaryRingSize [protected]
 

Definition at line 401 of file tracergn.h.

INT32 TraceRegion::BoundaryTail [protected]
 

Definition at line 398 of file tracergn.h.

TraceBoundaryPoint TraceRegion::DirectionPoint[(0x7)+1][(0x7)+1][4] [protected]
 

Definition at line 414 of file tracergn.h.

TraceBoundaryPoint TraceRegion::Directions[(0x7)+1] [protected]
 

Definition at line 413 of file tracergn.h.

double TraceRegion::Error [protected]
 

Definition at line 403 of file tracergn.h.

TraceBoundaryPoint TraceRegion::FirstBufferPoint [protected]
 

Definition at line 396 of file tracergn.h.

INT32 TraceRegion::HeadDirection [protected]
 

Definition at line 394 of file tracergn.h.

TraceBoundaryPoint TraceRegion::HeadPoint [protected]
 

Definition at line 391 of file tracergn.h.

INT32 TraceRegion::InitialDirection [protected]
 

Definition at line 392 of file tracergn.h.

TraceBoundaryPoint TraceRegion::InitialPoint [protected]
 

Definition at line 390 of file tracergn.h.

INT32 TraceRegion::NumTPoints [protected]
 

Definition at line 419 of file tracergn.h.

BfxPixelOp* TraceRegion::pBfxPixelOp [protected]
 

Definition at line 384 of file tracergn.h.

double TraceRegion::PixelError [protected]
 

Definition at line 404 of file tracergn.h.

TraceBoundaryPoint TraceRegion::Q1[3] [protected]
 

Definition at line 418 of file tracergn.h.

TraceBoundaryPoint TraceRegion::Q2[2] [protected]
 

Definition at line 418 of file tracergn.h.

BOOL TraceRegion::TailCusp [protected]
 

Definition at line 409 of file tracergn.h.

INT32 TraceRegion::TailDirection [protected]
 

Definition at line 393 of file tracergn.h.

Path* TraceRegion::ThePath [protected]
 

Definition at line 411 of file tracergn.h.

INT32 TraceRegion::TPoints[10+1] [protected]
 

Definition at line 417 of file tracergn.h.

double TraceRegion::TValues[10+1] [protected]
 

Definition at line 416 of file tracergn.h.

BOOL TraceRegion::VirginBuffer [protected]
 

Definition at line 406 of file tracergn.h.

BOOL TraceRegion::VirginPath [protected]
 

Definition at line 407 of file tracergn.h.

INT32 TraceRegion::xsize [protected]
 

Definition at line 387 of file tracergn.h.

INT32 TraceRegion::ysize [protected]
 

Definition at line 388 of file tracergn.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 04:02:11 2007 for Camelot by  doxygen 1.4.4