#include <moldenv.h>
Inheritance diagram for MouldEnvelope:
Public Member Functions | |
MouldEnvelope () | |
Envelope mould constructor. | |
~MouldEnvelope () | |
Envelope mould destructor. | |
virtual BOOL | Initialise () |
Initialise a mould envelope to contain the correct geometry. | |
virtual BOOL | Validate (Path *const pPath, UINT32 &errorID) |
This function checks whether the path given is suitabile for use as an envelope manifold. Valid paths at present are any set of 5 path elements starting with a moveto followed by line or bezier elements. | |
virtual BOOL | Define (Path *const pPath, DocRect *const pRect) |
This function sets the low level envelope state ready for calls to various envelope path generation functions. It serves simply as a way of informing the low level enveloper of the shape of the current envelope. | |
virtual BOOL | MakeValidFrom (Path **Out, Path *In, INT32 *CornersHint=0) |
creates a valid moulding path from an non-invalid path. | |
virtual MouldSpace | Describe () |
virtual void | Transform (Path *const pPath, DocRect *const pRect, TransformBase &Trans) |
Make sure the envelope mould data is transformed correctly. Note, all we need do here is redefine the low level envelope by calling Define() again with the current NodePath shape. We are ofcourse assuming that the child node path has already been transformed and so is correct. This is the case for NodeMould.Transform() which calls this function. It ensures all children are transformed first before it calls us passing in the transformed path itself. | |
virtual ChangeCode | RecordContext (UndoableOperation *) |
Record our context on the undo. In this overridden function we simply create an action to perform the undo/redo of our envelope shape. | |
virtual UINT32 | GetByteSize () const |
virtual MouldGeometry * | MakeCopy () |
Make a copy of this mould envelope object and return it. | |
Static Public Member Functions | |
static BOOL | WillBeValid (POINT *P) |
Check whether the point array suited for use as a manifold. | |
Protected Member Functions | |
BOOL | CopyContents (MouldEnvelope *pGeom) |
Make a copy of this mouldenvelope class private data. | |
Private Member Functions | |
CC_DECLARE_DYNAMIC (MouldEnvelope) | |
Private Attributes | |
const INT32 | EnvNumCoords |
Definition at line 184 of file moldenv.h.
|
Envelope mould constructor.
Definition at line 924 of file moldenv.cpp. 00924 : EnvNumCoords(ENV_NUMCOORDS) 00925 { 00926 }
|
|
Envelope mould destructor.
Definition at line 939 of file moldenv.cpp.
|
|
|
|
Make a copy of this mouldenvelope class private data.
Definition at line 1457 of file moldenv.cpp. 01458 { 01459 ERROR3IF(pCopyEnvelope==NULL, "MouldEnvelope::CopyContents() passed a null pointer"); 01460 // ask the base class to copy its bits first 01461 if (!MouldGeometry::CopyContents(pCopyEnvelope)) 01462 return FALSE; 01463 01464 // now lets copy data about ourselves 01465 POINT* TempArray = new POINT[EnvNumCoords]; 01466 if (TempArray==NULL) 01467 return FALSE; 01468 01469 RECT TempRect = pEnvelope->GetSourceBBox(); 01470 DocRect Rect = ConvRectToDocRect(TempRect); 01471 pEnvelope->CopyShape(TempArray); 01472 01473 // define this shape with the details 01474 BOOL ok = (pCopyEnvelope->BuildShape(TempArray, &Rect)); 01475 01476 delete [] TempArray; 01477 return ok; 01478 }
|
|
This function sets the low level envelope state ready for calls to various envelope path generation functions. It serves simply as a way of informing the low level enveloper of the shape of the current envelope.
Reimplemented from MouldGeometry. Definition at line 1341 of file moldenv.cpp. 01342 { 01343 ERROR2IF(pPath==NULL,FALSE,"MouldEnvelope::Define() called with NULL path"); 01344 return MouldEnvelopeBase::Define(pPath,pOrigBBox,EnvNumCoords); 01345 }
|
|
Reimplemented from MouldGeometry. Definition at line 197 of file moldenv.h. 00197 {return MOULDSPACE_ENVELOPE;}
|
|
Reimplemented from MouldGeometry. Definition at line 201 of file moldenv.h. 00201 { return sizeof(MouldEnvelope); };
|
|
Initialise a mould envelope to contain the correct geometry.
Definition at line 955 of file moldenv.cpp. 00956 { 00957 ERROR3IF(MouldEnvelopeBase::pEnvelope!=NULL, "MouldEnvelope::Initialise() - pEnvelope not NULL!"); 00958 GEnvelope* pGEnvelope = new GEnvelope; 00959 if (pGEnvelope==NULL) 00960 return FALSE; 00961 MouldEnvelopeBase::pEnvelope = pGEnvelope; 00962 return TRUE; 00963 }
|
|
Make a copy of this mould envelope object and return it.
Reimplemented from MouldGeometry. Definition at line 1420 of file moldenv.cpp. 01421 { 01422 // create a new Geometry 01423 MouldEnvelope* pGeometry = new MouldEnvelope; 01424 if (pGeometry == NULL) 01425 return NULL; 01426 01427 if (!pGeometry->Initialise()) 01428 { 01429 delete pGeometry; 01430 return NULL; 01431 } 01432 01433 if (!CopyContents(pGeometry)) 01434 { 01435 delete pGeometry; 01436 return NULL; 01437 } 01438 01439 return ((MouldGeometry*)pGeometry); 01440 }
|
|
creates a valid moulding path from an non-invalid path.
Reimplemented from MouldGeometry. Definition at line 1049 of file moldenv.cpp. 01050 { 01051 // get the bound rect of the path 01052 DocRect Bounds = In->GetBoundingRect(); 01053 DocCoord TL(Bounds.lo.x, Bounds.hi.y); 01054 DocCoord BR(Bounds.hi.x, Bounds.lo.y); 01055 01056 // run through the path finding points and work out which is closest to each corner 01057 INT32 Corners[4] = {-1, -1, -1, -1}; 01058 01059 INT32 BottomLeftDist=-1; 01060 INT32 BottomRightDist=-1; 01061 INT32 TopLeftDist=-1; 01062 INT32 TopRightDist=-1; 01063 01064 // get the coord arrays 01065 DocCoord *Coords = In->GetCoordArray(); 01066 PathVerb *Verbs = In->GetVerbArray(); 01067 INT32 Entries = In->GetNumCoords(); 01068 if(Entries < 2) 01069 return FALSE; 01070 01071 INT32 Elements = 0; 01072 01073 // run through 01074 for(INT32 Pass = 0; Pass < 4; Pass++) 01075 { 01076 INT32 dy, dx, dist; 01077 INT32 BezCount = 0; 01078 INT32 c; 01079 01080 for(c = 0; c < Entries; c++) 01081 { 01082 BOOL LookAtThis = FALSE; 01083 01084 switch(Verbs[c] & (~PT_CLOSEFIGURE)) 01085 { 01086 case PT_LINETO: 01087 LookAtThis = TRUE; 01088 break; 01089 01090 case PT_BEZIERTO: 01091 BezCount++; 01092 if(BezCount == 3) 01093 { 01094 BezCount = 0; 01095 LookAtThis = TRUE; 01096 } 01097 break; 01098 01099 default: 01100 break; 01101 } 01102 #define CHECKAGAINST(var, vdist, near) { \ 01103 dx = Coords[c].x - near.x; \ 01104 dy = Coords[c].y - near.y; \ 01105 dist = (INT32)sqrt((double)((dx * dx) + (dy * dy))); \ 01106 BOOL notused = TRUE; \ 01107 for(INT32 l = 0; l < 4; l++) \ 01108 { \ 01109 if(Corners[l] == c) \ 01110 notused = FALSE; \ 01111 } \ 01112 if(notused && (var == -1 || dist < vdist)) \ 01113 { \ 01114 vdist = dist; \ 01115 var = c; \ 01116 } \ 01117 } 01118 01119 if(LookAtThis) 01120 { 01121 switch(Pass) 01122 { 01123 case 0: 01124 Elements++; // only count elements on pass 0 01125 CHECKAGAINST(Corners[0], BottomLeftDist, Bounds.lo) 01126 break; 01127 01128 case 1: 01129 CHECKAGAINST(Corners[1], TopLeftDist, TL) 01130 break; 01131 01132 case 2: 01133 CHECKAGAINST(Corners[2], TopRightDist, Bounds.hi) 01134 break; 01135 01136 case 3: 01137 CHECKAGAINST(Corners[3], BottomRightDist, BR) 01138 break; 01139 01140 default: 01141 ERROR3("Unknown pass in MouldEnvelope::MakeValidFrom"); 01142 break; 01143 } 01144 } 01145 01146 if((Verbs[c] & (~PT_CLOSEFIGURE)) == PT_MOVETO && c != 0) 01147 break; // end at end of first sub path 01148 } 01149 } 01150 01151 // got enough elements? 01152 if(Elements < 4) 01153 { 01154 return FALSE; 01155 } 01156 01157 // got a hint about the corners? 01158 if(CornersHint != 0) 01159 { 01160 // yes - copy them in to the corners array we already have 01161 for(INT32 l = 0; l < 4; l++) 01162 { 01163 Corners[l] = CornersHint[l]; 01164 } 01165 } 01166 01167 // sort the points... 01168 INT32 s, l; 01169 for(s = 0; s < 3; s++) 01170 { 01171 for(l = 0; l < 3; l++) 01172 { 01173 if(Corners[l] > Corners[l+1]) 01174 { 01175 INT32 Temp = Corners[l]; 01176 Corners[l] = Corners[l+1]; 01177 Corners[l+1] = Temp; 01178 } 01179 } 01180 } 01181 01182 // make a path object 01183 Path *OutputShape = new Path; 01184 if(OutputShape == 0 || !OutputShape->Initialise()) 01185 { 01186 delete OutputShape; 01187 return FALSE; 01188 } 01189 01190 OutputShape->FindStartOfPath(); 01191 01192 // go through appoximating beziers to each segment 01193 INT32 Side; 01194 for(Side = 0; Side < 4; Side++) 01195 { 01196 // work out which coords to start from 01197 INT32 StartCoord = Corners[Side]; 01198 INT32 EndCoord; 01199 if(Side != 3) 01200 EndCoord = Corners[Side + 1]; 01201 else 01202 EndCoord = Corners[0]; 01203 01204 ERROR2IF(StartCoord == EndCoord, FALSE, "Two corners the same in MakeValidFrom!"); 01205 01206 // generate a path 01207 INT32 CoordsNeeded = EndCoord - StartCoord; 01208 if(CoordsNeeded < 0) 01209 CoordsNeeded = 0 - CoordsNeeded; 01210 01211 Path *SidePath = new Path; 01212 if(SidePath == 0 || !SidePath->Initialise(CoordsNeeded + 8, 12)) 01213 { 01214 delete SidePath; 01215 delete OutputShape; 01216 return FALSE; 01217 } 01218 01219 // OK, we've got a path with plenty of space in it - make the path of the side 01220 SidePath->FindStartOfPath(); 01221 01222 DocCoord StartPoint, EndPoint; 01223 01224 // make a moveto... 01225 if(!SidePath->InsertMoveTo(Coords[StartCoord])) 01226 return FALSE; 01227 01228 StartPoint = Coords[StartCoord]; 01229 01230 // insert the coordinates 01231 BOOL WillWrap = FALSE; 01232 01233 if(StartCoord > EndCoord) 01234 WillWrap = TRUE; 01235 01236 INT32 At = StartCoord + 1; 01237 while((At <= EndCoord) || WillWrap) 01238 { 01239 // check for wrapping round 01240 if(WillWrap && (At >= Entries)) 01241 { 01242 At = 0; 01243 WillWrap = FALSE; 01244 } 01245 else 01246 { 01247 switch(Verbs[At] & (~PT_CLOSEFIGURE)) 01248 { 01249 case PT_LINETO: 01250 if(!SidePath->InsertLineTo(Coords[At])) 01251 return FALSE; 01252 01253 At++; 01254 break; 01255 01256 case PT_BEZIERTO: 01257 if(!SidePath->InsertCurveTo(Coords[At], Coords[At+1], Coords[At+2])) 01258 return FALSE; 01259 01260 At += 3; 01261 break; 01262 01263 default: 01264 At++; 01265 break; 01266 } 01267 } 01268 01269 } 01270 01271 EndPoint = Coords[EndCoord]; 01272 01273 // got it... now approximate a bezier to what we got. 01274 01275 // find the path length 01276 ProcessLength PathLengthProcess(64); 01277 double fPathLength=0; 01278 if(!PathLengthProcess.PathLength(SidePath, &fPathLength)) 01279 return FALSE; 01280 01281 // find coords at 33% and 66% of the path length 01282 ProcessPathDistance PathDistanceProcess(64); 01283 01284 DocCoord Point1; 01285 BOOL Found; 01286 if(!PathDistanceProcess.GetCoordAndTangent(&Point1, 0, &Found, fPathLength / 3, SidePath)) 01287 return FALSE; 01288 01289 DocCoord Point2; 01290 if(!PathDistanceProcess.GetCoordAndTangent(&Point2, 0, &Found, (fPathLength * 2) / 3, SidePath)) 01291 return FALSE; 01292 01293 // do some stuff which Mathematica emitted to find the control points for this segment 01294 DocCoord Control1, Control2; 01295 01296 Control1.x = ((-5 * StartPoint.x) + (2 * EndPoint.x) + (18 * Point1.x) - (9 * Point2.x)) / 6; 01297 Control1.y = ((-5 * StartPoint.y) + (2 * EndPoint.y) + (18 * Point1.y) - (9 * Point2.y)) / 6; 01298 Control2.x = ((2 * StartPoint.x) - (5 * EndPoint.x) - (9 * Point1.x) + (18 * Point2.x)) / 6; 01299 Control2.y = ((2 * StartPoint.y) - (5 * EndPoint.y) - (9 * Point1.y) + (18 * Point2.y)) / 6; 01300 01301 // if this is the first bit coord, we need a move to 01302 if(Side == 0) 01303 { 01304 if(!OutputShape->InsertMoveTo(StartPoint)) 01305 return FALSE; 01306 } 01307 01308 // right then, add the nice curve... 01309 if(!OutputShape->InsertCurveTo(Control1, Control2, EndPoint)) 01310 return FALSE; 01311 } 01312 01313 // close the shape 01314 if(!OutputShape->CloseSubPath()) 01315 return FALSE; 01316 01317 // set the return pointer 01318 (*Out) = OutputShape; 01319 01320 return TRUE; 01321 }
|
|
Record our context on the undo. In this overridden function we simply create an action to perform the undo/redo of our envelope shape.
Reimplemented from MouldGeometry. Definition at line 1388 of file moldenv.cpp. 01389 { 01390 if (pOp!=NULL) 01391 { 01392 RecordEnvelopeAction* EnvAction; 01393 ActionCode Act; 01394 01395 // call the actions static init function to get the action going. 01396 Act = RecordEnvelopeAction::Init(pOp, pOp->GetUndoActionList(), this, (Action**)(&EnvAction)); 01397 01398 if (Act == AC_FAIL) 01399 return CC_FAIL; 01400 if (Act == AC_NORECORD) 01401 return CC_NORECORD; 01402 } 01403 return CC_OK; 01404 }
|
|
Make sure the envelope mould data is transformed correctly. Note, all we need do here is redefine the low level envelope by calling Define() again with the current NodePath shape. We are ofcourse assuming that the child node path has already been transformed and so is correct. This is the case for NodeMould.Transform() which calls this function. It ensures all children are transformed first before it calls us passing in the transformed path itself.
Reimplemented from MouldGeometry. Definition at line 1366 of file moldenv.cpp. 01367 { 01368 ERROR3IF(pPath==NULL,"MouldEnvelope::Transform() passed a NULL path shape"); 01369 Define(pPath,pRect); 01370 }
|
|
This function checks whether the path given is suitabile for use as an envelope manifold. Valid paths at present are any set of 5 path elements starting with a moveto followed by line or bezier elements.
Reimplemented from MouldGeometry. Definition at line 982 of file moldenv.cpp. 00983 { 00984 // check for a reasonable number of coordinates 00985 INT32 numc=pPath->GetNumCoords(); 00986 if ((numc<5) || numc>(EnvNumCoords+1)) 00987 { 00988 errorID = _R(IDE_ENV_NUMCOORDERR); 00989 return FALSE; 00990 } 00991 00992 if (!ValidMouldingPath(numc, 4, pPath, errorID)) 00993 return FALSE; 00994 00995 // Make sure there's no folds either 00996 POINT* p = (POINT*)pPath->GetCoordArray(); 00997 if (!WillBeValid(p)) 00998 { 00999 errorID = _R(IDE_ENV_NOWIDTHHEIGHT); 01000 return FALSE; 01001 } 01002 01003 // Ok, now if necessary do a pseudo conversion 01004 if (numc<(EnvNumCoords+1)) 01005 { 01006 if (!ConvertShape(EnvNumCoords,NULL,pPath,numc)) 01007 { 01008 errorID = _R(IDE_ENV_NUMCOORDERR); 01009 return FALSE; 01010 } 01011 } 01012 01013 // All is well, we should be able to use this shape 01014 return TRUE; 01015 }
|
|
Check whether the point array suited for use as a manifold. static BOOL MouldEnvelope::WillBeValid(POINT* P)
Definition at line 1031 of file moldenv.cpp. 01032 { 01033 return MouldEnvelopeBase::WillBeValid(ENV_NUMCOORDS, P); 01034 }
|
|
|