MouldEnvelope Class Reference

The envelope mould node. Provides control over a coons patch shape made from 4 connected 3rd order bezier splines. More...

#include <moldenv.h>

Inheritance diagram for MouldEnvelope:

MouldEnvelopeBase MouldGeometry CCObject SimpleCCObject List of all members.

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 MouldGeometryMakeCopy ()
 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

Detailed Description

The envelope mould node. Provides control over a coons patch shape made from 4 connected 3rd order bezier splines.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/12/94

Definition at line 184 of file moldenv.h.


Constructor & Destructor Documentation

MouldEnvelope::MouldEnvelope  ) 
 

Envelope mould constructor.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/12/94
Parameters:
[INPUTS] 

Definition at line 924 of file moldenv.cpp.

00924                              : EnvNumCoords(ENV_NUMCOORDS)
00925 {
00926 }

MouldEnvelope::~MouldEnvelope  ) 
 

Envelope mould destructor.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/12/94
Parameters:
[INPUTS] 

Definition at line 939 of file moldenv.cpp.

00940 {
00941 }


Member Function Documentation

MouldEnvelope::CC_DECLARE_DYNAMIC MouldEnvelope   )  [private]
 

BOOL MouldEnvelope::CopyContents MouldEnvelope pCopyEnvelope  )  [protected]
 

Make a copy of this mouldenvelope class private data.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/01/95
Parameters:
pEnvelope = a pointer to a copy of a mould envelope. [INPUTS]
[OUTPUTS] 
Returns:
TRUE if the data has been copied correctly FALSE if failed

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 }

BOOL MouldEnvelope::Define Path *const   pPath,
DocRect *const   pOrigBBox
[virtual]
 

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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/12/94
Parameters:
pPath = the path to use for enveloping [INPUTS] pOrigBBox = a pointer to the bounding box of the objects to be enveloped = NULL then the old bounding box will be assumed. returns: TRUE - then SetUp has succeded FALSE - then setup has failed to initialise itself

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 }

virtual MouldSpace MouldEnvelope::Describe  )  [inline, virtual]
 

Reimplemented from MouldGeometry.

Definition at line 197 of file moldenv.h.

00197 {return MOULDSPACE_ENVELOPE;}

virtual UINT32 MouldEnvelope::GetByteSize  )  const [inline, virtual]
 

Reimplemented from MouldGeometry.

Definition at line 201 of file moldenv.h.

00201 { return sizeof(MouldEnvelope); };

BOOL MouldEnvelope::Initialise  )  [virtual]
 

Initialise a mould envelope to contain the correct geometry.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/12/94
Parameters:
[INPUTS] 

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 }

MouldGeometry * MouldEnvelope::MakeCopy  )  [virtual]
 

Make a copy of this mould envelope object and return it.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/01/95
Parameters:
- [INPUTS]
a pointer to a new mould envelope object. [OUTPUTS] NULL if unable to create the object.

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 }

BOOL MouldEnvelope::MakeValidFrom Path **  Out,
Path In,
INT32 *  CornersHint = 0
[virtual]
 

creates a valid moulding path from an non-invalid path.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/05/95
Parameters:
Out = variable to output the new Path in. In = path to create a valid one from. [INPUTS]
Returns:
whether it managed to create one or not

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 }

ChangeCode MouldEnvelope::RecordContext UndoableOperation pOp  )  [virtual]
 

Record our context on the undo. In this overridden function we simply create an action to perform the undo/redo of our envelope shape.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/01/95
Parameters:
pOp = pointer to a running undoable operation [INPUTS]
- [OUTPUTS]

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 }

void MouldEnvelope::Transform Path *const   pPath,
DocRect *const   pRect,
TransformBase Trans
[virtual]
 

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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/01/95
Parameters:
pMould = A pointer to the node mould object associated with this envelope [INPUTS] Trans = A transformation object

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 }

BOOL MouldEnvelope::Validate Path *const   pPath,
UINT32 errorID
[virtual]
 

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.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/02/95
Parameters:
pPath = the path to use for enveloping [INPUTS]
errorID = an id of an error string reporting the problem when failed. [OUTPUTS]
Returns:
TRUE - then the path can be used as an envelope FALSE - then the path is not suitable for use as an envelope

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 }

BOOL MouldEnvelope::WillBeValid POINT P  )  [static]
 

Check whether the point array suited for use as a manifold.

static BOOL MouldEnvelope::WillBeValid(POINT* P)

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/12/94
Parameters:
P a pointer to a POINT array of coordinates [INPUTS]
Returns:
TRUE if the point set is valid

Definition at line 1031 of file moldenv.cpp.

01032 {
01033     return MouldEnvelopeBase::WillBeValid(ENV_NUMCOORDS, P);
01034 }


Member Data Documentation

const INT32 MouldEnvelope::EnvNumCoords [private]
 

Definition at line 213 of file moldenv.h.


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