ArtWorksEPSFilter Class Reference

A filter that imports EPS files in ArtWorks EPS format. More...

#include <aw_eps.h>

Inheritance diagram for ArtWorksEPSFilter:

EPSFilter VectorFilter Filter ListItem CCObject SimpleCCObject CamelotEPSFilter CamelotNativeEPSFilter List of all members.

Public Member Functions

 ArtWorksEPSFilter ()
 Constructor for an ArtWorksEPSFilter object. The object should be initialised before use.
BOOL Init ()
 Initialise an ArtWorksEPSFilter object.
BOOL PrepareToExport (CCLexFile *, Spread *pSpread)
 Prepare to import EPS data using this filter. This sets up the filter to a sensible state for reading.
TCHARGetEPSCommand (EPSCommand Cmd)
 Given an EPS token, return the string representation of it; mainly for debugging purposes.
virtual BOOL NeedsPrintComponents (void)
 Informs the print components code that no data should be written.
virtual BitmapFilterSupport GetBitmapSupportLevel ()
 Determine how well this filter supports bitmaps when exporting.

Protected Member Functions

virtual void LookUpToken ()
 Compare the current token against the ArtWorks keywords to see if it is one of them.
virtual BOOL ProcessToken ()
 Processes EPS tokens that are not part of the standard Illustrator set, or which need to be handled differently to the standard Illustrator meanings. i.e. this is the function that handles all the ArtWorks EPS operators.
INT32 EPSHeaderIsOk (ADDR pFileHeader, UINT32 HeaderSize)
 Checks to see if the EPS comment headers specify that this is an ArtWorks generated EPS file, as required.
BOOL ProcessBlend ()
 Reads in all the elements of a blend structure in the EPS file.
BOOL ProcessBlender ()
 Reads in all the elements of a blender structure in the EPS file.
BOOL StartBlend ()
 Used when a blend structure needs to be created - after this is called, all new nodes added with AddNewNode() will be added as children of this new blend, until EndBlend is called.
BOOL StartBlender ()
 Used when a blender structure needs to be created - after this is called, all new paths will be discarded, until EndBlender is called.
BOOL EndBlend ()
 Used when a blend has finished being constructed and we want to return to normal node positioning. The blend is added to the document when this function is called (although that depending on the current filter mode, i.e. whether this is a new or existing layer, it may not be added directly to the documnent tree straight away - it may be deferred until the next layer is found, or the import has ended).
BOOL EndBlender ()
 Used when a blender has finished being constructed. Paths are not longer discarded.
BOOL ProcessEnvelope ()
 Reads in all the elements of an envelope structure in the ArtWorksEPS file and builds the camelot envelope tree.
BOOL ProcessPerspective ()
 Reads in all the elements of an perspective structure in the EPS file.
BOOL StartMould (MouldSpace mSpace)
 Used when an mould structure needs to be created - after this is called, all new nodes added with AddNewNode() will be added as children of this new mould, until EndMould is called.
BOOL EndMould ()
 Used when a envelope has finished being constructed and we want to return to normal node positioning.
BOOL ProcessMould ()
 Processes tokens inside a mould object. Tokens specific to mould objects are processed along with some overridding of default tokens such as groups.
BOOL ProcessMouldShape ()
 Reads in all the elements of a mould geometry held in the EPS file. The description of the geometry for this particular file type is that of a path. Depending on the geometry type (perspective or envelope) we will obviously expect a slightly different path. The rules are, that currently perspective geometry is described as {m,l,l,l,l} and envelope geometry is {m,c,c,c,c}. Internally we are not restricted to these but ArtworksEPS certainly is. Input Stack = coord, coord.
BOOL ProcessMangledObjs ()
 On finding a 'apc' token in the input stream, this function is executed. It will process all further tokens in the stream until a path termination has been found. A path terminator is considered any of { s,S,b,B,f,F,h,H } Its purpose is strictly defined. It must place the next set of attributes and single path as children of the last object imported rather than the default action which would be to stick them in as siblings of the object.
BOOL ConvertArtMould (NodeMould *)
 Right here comes the difficult bit. What we have now is a really interresting structure. We should have a complete tree beneath the mould group node containing invisible source objects and visible moulded shapes. So if we were to render this tree, it would look sensible. Now we need to disassemble this tree by placing all the moulded objects and their attributes inside our moulder object. This we will do by copying the entire tree and deleting the right bits. (Isn't it yuk but there you go, its the only sensible and simple way of doing it, without massively duplicating bits of code.
BOOL ConvertMouldStyles (Node *pNode)
 Scan through all moulded objects, copying their fill and stroke styles to the original objects (which are currently their parents).
void DeleteAllMangled (Node *pNode)
 Delete all nodes with their mangled bits set at and below pNode.
BOOL DeleteAllNoneMangled (Node *pNode)
 Delete all renderable parents of mangled objects from pNode onwards. This really is a specialised function and should be used with care. It scans through the tree, hunting for mangled objects. When one is found it will attempt to promote the node to become a sibling of its parent and delete the parent. It will only do so if the parent is renderable. We know or are assuming this is a confined and sensible action. It is only so having loaded an ArtWorksEPS envelope or perspective object.
BOOL PromoteMangled (Node *pNode)
 Promote all mangled child nodes to siblings of their parents.
BOOL HandleMouldedFill ()
 On finding a 'axm' token in the input stream, this function is executed. It will build a graduated fill structure and set it as the current fill style to be applied to future objects. The function has been split off from the main structure for one very important reason. Fills applied to moulds work in a random way. Imagine the senario, you have a rectangle, and you envelope it. You then apply a linear grad fill to it. If this gets exported as AWEPS what you get are two objects, one moulded and one rectangle. Now you also get a moulded and none moulded fill style represented by ax and axm. Unfortunately although ax stands for 'standard fill style' and axm is used as an override describing the coordinates of a moulded fill (hence the m) the coordinates of both fills are reversed. DONT ASK ME WHY, ASK THE AUTHOR OF AWEPS! So we have to perform some brain dead processing here to get the right attributes applied to the right objects.

Static Protected Attributes

static CommandMap ArtWorksCommands []

Private Member Functions

 CC_DECLARE_DYNAMIC (ArtWorksEPSFilter)

Private Attributes

DocRect MouldRect
INT32 LastFillType
GradEndCol LastStartColour
GradEndCol LastEndColour

Detailed Description

A filter that imports EPS files in ArtWorks EPS format.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/03/94
See also:
EPSFilter

Definition at line 130 of file aw_eps.h.


Constructor & Destructor Documentation

ArtWorksEPSFilter::ArtWorksEPSFilter  ) 
 

Constructor for an ArtWorksEPSFilter object. The object should be initialised before use.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/10/93
See also:
EPSFilter::Init

Definition at line 223 of file aw_eps.cpp.

00224 {
00225     // Set up filter descriptions.
00226     FilterNameID = _R(IDT_AWEPS_FILTERNAME);
00227     FilterInfoID = _R(IDT_AWEPS_FILTERINFO);
00228     ImportMsgID  = _R(IDT_IMPORTMSG_ARTWORKS);
00229 
00230     FilterID = FILTERID_ARTWORKS_EPS;
00231 
00232 #ifndef STANDALONE
00233     Flags.CanImport = TRUE;
00234     //WEBSTER-Martin-27/01/97
00235 #ifdef WEBSTER
00236     Flags.CanExport = FALSE;
00237 #else
00238     Flags.CanExport = TRUE;
00239 #endif //WEBSTER
00240 #else
00241     Flags.CanImport = FALSE;
00242     Flags.CanExport = FALSE;
00243 #endif
00244 
00245     LastFillType = 0;
00246 }


Member Function Documentation

ArtWorksEPSFilter::CC_DECLARE_DYNAMIC ArtWorksEPSFilter   )  [private]
 

BOOL ArtWorksEPSFilter::ConvertArtMould NodeMould pNodeMould  )  [protected]
 

Right here comes the difficult bit. What we have now is a really interresting structure. We should have a complete tree beneath the mould group node containing invisible source objects and visible moulded shapes. So if we were to render this tree, it would look sensible. Now we need to disassemble this tree by placing all the moulded objects and their attributes inside our moulder object. This we will do by copying the entire tree and deleting the right bits. (Isn't it yuk but there you go, its the only sensible and simple way of doing it, without massively duplicating bits of code.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/94
Parameters:
pNodeMould - a pointer to the mould object [INPUTS]
Returns:
TRUE if the artworks mould has been converted correctly FALSE if not.

Errors: Syntax error in EPS file, Out of memory

Definition at line 2082 of file aw_eps.cpp.

02084 {
02085     ERROR2IF(pNodeMould==NULL, FALSE, "NULL mould pointer passed to ConvertArtMould()");
02086 
02087     NodeMouldGroup* pNodeMGroup = pNodeMould->FindMouldGroup();
02088     if (pNodeMGroup==NULL)
02089         return FALSE;
02090 
02091     NodeMoulder* pMoulder = pNodeMould->FindFirstMoulder();
02092     if (pMoulder==NULL)
02093         return FALSE;
02094 
02095     Node *pNode;
02096     // Stage 1
02097     // Copy all objects from the mould group to this new moulder object
02098 
02099     pNode = pNodeMGroup->FindFirstChild();
02100     while (pNode)
02101     {
02102         if (!pNode->CopyNode(pMoulder,LASTCHILD))
02103         {
02104             pMoulder->CascadeDelete();
02105             return FALSE;
02106         }
02107         pNode=pNode->FindNext();
02108     }
02109 
02110     // Stage2
02111     // Scan through deleting all mangled objects in the source tree
02112     pNode=pNodeMGroup->FindFirstChild();
02113     DeleteAllMangled(pNode);
02114 
02115     //Stage 3
02116     //Scan through deleting all none mangled objects in the destination tree
02117     //but leaving the mangled versions!
02118     pNode=pMoulder->FindFirstChild();
02119     DeleteAllNoneMangled(pNode);
02120 
02121     return TRUE;
02122 }

BOOL ArtWorksEPSFilter::ConvertMouldStyles Node pNode  )  [protected]
 

Scan through all moulded objects, copying their fill and stroke styles to the original objects (which are currently their parents).

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/94
Parameters:
pNode - a pointer to an object to start scanning from [INPUTS]
Returns:
TRUE if the mould styles have been converted correctly FALSE if not.

Definition at line 2018 of file aw_eps.cpp.

02019 {
02020     Node *qNode, *rNode;
02021     BOOL IsFilled = FALSE, IsStroked = FALSE;
02022 
02023     while (pNode)
02024     {
02025         qNode=pNode;
02026         pNode=pNode->FindNext();
02027 
02028         // if its mangled delete it otherwise scan its kids
02029         if (qNode->IsMangled())
02030         {
02031             rNode = qNode->FindParent();
02032             if (rNode)
02033             {
02034                 // this should be polymorphic but there's no virtual func to
02035                 // do it so I'll have to be explicit.
02036                 if (IS_A(qNode, NodePath))
02037                 {
02038                     IsFilled  = ((NodePath*)qNode)->InkPath.IsFilled;
02039                     IsStroked = ((NodePath*)qNode)->InkPath.IsStroked;
02040 
02041                     if (rNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)))
02042                     {
02043                         ((NodePath*)rNode)->InkPath.IsFilled  = IsFilled;
02044                         ((NodePath*)rNode)->InkPath.IsStroked = IsStroked;
02045                     }
02046                     else if (rNode->IsKindOf(CC_RUNTIME_CLASS(NodeSimpleShape)))
02047                     {
02048                         ((NodePath*)rNode)->InkPath.IsFilled  = IsFilled;
02049                         ((NodePath*)rNode)->InkPath.IsStroked = IsStroked;
02050                     }
02051                 }
02052             }
02053         }
02054         else
02055             ConvertMouldStyles(qNode->FindFirstChild());
02056     }
02057     return TRUE;
02058 }

void ArtWorksEPSFilter::DeleteAllMangled Node pNode  )  [protected]
 

Delete all nodes with their mangled bits set at and below pNode.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
09/03/95
Parameters:
pNode = a pointer to a node to start deleting from [INPUTS]
Returns:
-
See also:

Definition at line 2139 of file aw_eps.cpp.

02140 {
02141     Node *qNode;
02142 
02143     while (pNode)
02144     {
02145         qNode=pNode;
02146         pNode=pNode->FindNext();
02147 
02148         // if its mangled delete it otherwise scan its kids
02149         if (qNode->IsMangled())
02150         {
02151             qNode->CascadeDelete();
02152             delete qNode;
02153         }
02154         else
02155             DeleteAllMangled(qNode->FindFirstChild());
02156     }
02157 }

BOOL ArtWorksEPSFilter::DeleteAllNoneMangled Node pNode  )  [protected]
 

Delete all renderable parents of mangled objects from pNode onwards. This really is a specialised function and should be used with care. It scans through the tree, hunting for mangled objects. When one is found it will attempt to promote the node to become a sibling of its parent and delete the parent. It will only do so if the parent is renderable. We know or are assuming this is a confined and sensible action. It is only so having loaded an ArtWorksEPS envelope or perspective object.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
09/03/95
Parameters:
pNode = a pointer to a node to start deleting from [INPUTS]
Returns:
-
See also:

Definition at line 2178 of file aw_eps.cpp.

02179 {
02180     Node* qNode;
02181     while (pNode)
02182     {
02183         qNode=pNode;
02184         pNode=pNode->FindNext();
02185         if (!PromoteMangled(qNode))
02186             DeleteAllNoneMangled(qNode->FindFirstChild());
02187     }
02188     return TRUE;
02189 }   

BOOL ArtWorksEPSFilter::EndBlend  )  [protected]
 

Used when a blend has finished being constructed and we want to return to normal node positioning. The blend is added to the document when this function is called (although that depending on the current filter mode, i.e. whether this is a new or existing layer, it may not be added directly to the documnent tree straight away - it may be deferred until the next layer is found, or the import has ended).

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/11/94
Returns:
TRUE if the blend was ended ok; FALSE if not.

Errors: Out of memory

See also:
ArtWorksEPSFilter::StartBlend

Reimplemented in CamelotEPSFilter.

Definition at line 1119 of file aw_eps.cpp.

01120 {
01121     // Sanity check
01122     ENSURE(pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBlend)), "No blend in ArtWorksEPSFilter::EndBlend");
01123 
01124     // Keep the blend ptr and find the first child of the node before we reset pNode.
01125     Node* pBlend     = pNode;
01126     Node* pChildNode = pNode->FindFirstChild();
01127 
01128     // Get the parent of the blend node, and use that to add new objects to
01129     pNode = pBlend->FindParent();
01130     ERROR2IF(pNode==NULL, FALSE, "Blend has no parent in EndBlend()");
01131 
01132     // Initialise all the child blender nodes
01133     UINT32 BlenderCount=0;
01134     while (pChildNode != NULL)
01135     {
01136         if (IS_A(pChildNode,NodeBlender))
01137         {
01138             NodeBlender* pNodeBlender = (NodeBlender*)pChildNode;
01139             INT32 PathIndexStart = pNodeBlender->GetPathIndexStart();
01140             INT32 PathIndexEnd   = pNodeBlender->GetPathIndexEnd();
01141 
01142             // Convert the AW path indexes into Camelot path indexes
01143             if (!pNodeBlender->ConvertAWPathIndexesToCamelot(&PathIndexStart,&PathIndexEnd))
01144             {
01145                 ERROR2(FALSE,"Unable to convert artworks path indexes in EndBlend()");
01146             }
01147 
01148             // Init the blender to blend the prev and next ink nodes together
01149             if (!pNodeBlender->Initialise(NULL,NULL,PathIndexStart,PathIndexEnd,ImportInfo.pOp,NULL,TRUE))
01150             {
01151                 ERROR2(FALSE,"Unable to initialise a node blender in EndBlend()");
01152             }
01153 
01154             BlenderCount++;
01155         }
01156         pChildNode = pChildNode->FindNext();
01157     }
01158 
01159     if (BlenderCount == 0)
01160     {
01161         ERROR3("Imported Blend node doesn't contain any blender nodes");
01162         if (!ImportInfo.pOp->DoHideNode(pBlend, TRUE))
01163             return FALSE;
01164     }
01165 
01166     return TRUE;
01167 }

BOOL ArtWorksEPSFilter::EndBlender  )  [protected]
 

Used when a blender has finished being constructed. Paths are not longer discarded.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/11/94
Returns:
TRUE if the blender was ended ok; FALSE if not.

Errors: -

See also:
ArtWorksEPSFilter::StartBlender

Reimplemented in CamelotEPSFilter.

Definition at line 1301 of file aw_eps.cpp.

01302 {
01303     ThePathType = PATH_NORMAL;
01304     return TRUE;
01305 }

BOOL ArtWorksEPSFilter::EndMould  )  [protected]
 

Used when a envelope has finished being constructed and we want to return to normal node positioning.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/95
Returns:
TRUE if the envelope was ended ok; FALSE if not.
See also:
ArtWorksEPSFilter::StartEnvelope()

Reimplemented in CamelotEPSFilter.

Definition at line 1520 of file aw_eps.cpp.

01521 {
01522     // Sanity check
01523     ERROR3IF(!pNode->IsKindOf(CC_RUNTIME_CLASS(NodeMouldGroup)), "No mouldgroup in ArtWorksEPSFilter::EndMould");
01524 //  NodeMouldGroup* pNodeMGroup = (NodeMouldGroup*)pNode;
01525     pNode = pNode->FindParent();
01526     ERROR3IF(!pNode->IsKindOf(CC_RUNTIME_CLASS(NodeMould)), "No MouldParent in ArtWorksEPSFilter::EndMould");
01527     NodeMould* pNodeMould = (NodeMould*)pNode;
01528 
01529     NodeMoulder* pMoulder = pNodeMould->CreateNewMoulder(NULL);
01530     if (!pMoulder)
01531     {
01532         HandleNoMemory();
01533         return FALSE;
01534     }
01535 
01536     // Add it into the tree as the last child of the mould
01537     if (!AddNewNode(pMoulder))
01538     {
01539         HandleNoMemory();
01540         return FALSE;
01541     }
01542 
01543     // Right, now we need to scan through all moulded objects and copy their fill and
01544     // stroke styles to the originals. We need to do this because the original objects
01545     // within the file are terminated by h and H functions. These describe closed and open
01546     // (none filled,none stroked) paths ie invisible paths. Hence to create the correct
01547     // original styles we need to take the definitions from the destination objects
01548     // instead. This means when we edit the imported mould the drawing doesn't suddenly
01549     // take on random fill and stroke styles.
01550 
01551     // Right here comes the difficult bit. What we have now is a really interresting
01552     // structure. We should have a complete tree beneath the mould group node. This tree
01553     // contains invisible source objects and visible moulded shapes. So if we we're to
01554     // render this tree, it would look sensible. Now we need to disassemble this tree
01555     // by placing all the moulded objects and their attributes inside our moulder object.
01556     // This we will do by copying the entire tree and deleting the right bits. (Isn't it
01557     // yuk but there you go, its the only sensible and simple way of doing it, without
01558     // massively duplicating bits of code.
01559 
01560     // go and convert the artworks tree
01561     if (!ConvertArtMould(pNodeMould))
01562     {
01563         HandleNoMemory();
01564         return FALSE;
01565     }
01566 
01567     // and finally move pNode up one level
01568     pNode = pNode->FindParent();
01569     ERROR3IF(pNode==NULL, "No parent of envelope in ArtWorksEPSFilter::EndMould");
01570 
01571     return TRUE;
01572 }

INT32 ArtWorksEPSFilter::EPSHeaderIsOk ADDR  pFileHeader,
UINT32  HeaderSize
[protected, virtual]
 

Checks to see if the EPS comment headers specify that this is an ArtWorks generated EPS file, as required.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/02/94
Returns:
TRUE if the header is ok and import should proceed, FALSE if not.

Reimplemented from EPSFilter.

Reimplemented in CamelotEPSFilter, and CamelotNativeEPSFilter.

Definition at line 289 of file aw_eps.cpp.

00290 {
00291     // this function is not Unicode
00292 
00293     // Check the first line in EPS file
00294     if (strncmp((char *) pFileHeader, "%!PS-Adobe-2.0 EPSF-1.2", 23) != 0)
00295     {
00296         // Incorrect version of EPS header line - we don't want this
00297         return 0;
00298     }
00299 
00300     // !PS-Adobe line is ok - check creator line...
00301     std::istringstream HeaderFile((char *) pFileHeader, ios_base::in /*, HeaderSize*/);
00302     char Buffer[200];
00303 
00304     UINT32 Lines = 0;
00305     while ((Lines < 20) && !HeaderFile.eof())
00306     {
00307         HeaderFile.getline(Buffer, 200);
00308         Lines++;
00309 
00310         // Return TRUE if this file was created by ArtWorks
00311         if (strncmp(Buffer, "%%Creator: ArtWorks", 19) == 0)
00312         {
00313             // ArtWorks is the creator - but has it exported it in an alien format?
00314             // Return 10 if it hasn't, 1 if it has.
00315             if (strstr(Buffer, "exported") == NULL)
00316                 return 10;
00317             else
00318                 // 5 because it *might* be "ArtWorks (exported by Mr. Blobby)", and
00319                 // we don't want to let the user not load this at all...
00320                 return 5;
00321         }
00322 
00323         // If we find the compression token then stop the search as we don't want to start
00324         // looking in the compressed data!
00325         if (strncmp(Buffer, "%%Compression:", 14)==0)
00326             break;
00327     }
00328 
00329     // Didn't find a suitable Creator line, but we did find an EPS line, so indicate
00330     // that we're interested, but not sure.
00331     return 5;
00332 }

BitmapFilterSupport ArtWorksEPSFilter::GetBitmapSupportLevel  )  [virtual]
 

Determine how well this filter supports bitmaps when exporting.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/01/95
Returns:
SimpleBitmapSupport - This filter has simple support for bitmap images; they must be saved into the file whenever they are used.

Reimplemented from Filter.

Reimplemented in CamelotNativeEPSFilter.

Definition at line 2235 of file aw_eps.cpp.

02236 {
02237     // ArtWorks EPS has simple bitmap support
02238     return SimpleBitmapSupport;
02239 }

TCHAR * ArtWorksEPSFilter::GetEPSCommand EPSCommand  Cmd  ) 
 

Given an EPS token, return the string representation of it; mainly for debugging purposes.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/02/94
Parameters:
Cmd - the EPS token, e.g. EPSC_aoa [INPUTS]
Returns:
Pointer to the string representation of the token, e.g. "aoa"

Reimplemented from EPSFilter.

Reimplemented in CamelotEPSFilter.

Definition at line 971 of file aw_eps.cpp.

00972 {
00973     INT32 i = 0;
00974     while (ArtWorksCommands[i].Cmd != EPSC_Invalid)
00975     {
00976         if (ArtWorksCommands[i].Cmd == Cmd)
00977             return ArtWorksCommands[i].CmdStr;
00978 
00979         // Try next command
00980         i++;
00981     }
00982 
00983     // Couldn't find it - default to base class method
00984     return EPSFilter::GetEPSCommand(Cmd);
00985 }

BOOL ArtWorksEPSFilter::HandleMouldedFill  )  [protected]
 

On finding a 'axm' token in the input stream, this function is executed. It will build a graduated fill structure and set it as the current fill style to be applied to future objects. The function has been split off from the main structure for one very important reason. Fills applied to moulds work in a random way. Imagine the senario, you have a rectangle, and you envelope it. You then apply a linear grad fill to it. If this gets exported as AWEPS what you get are two objects, one moulded and one rectangle. Now you also get a moulded and none moulded fill style represented by ax and axm. Unfortunately although ax stands for 'standard fill style' and axm is used as an override describing the coordinates of a moulded fill (hence the m) the coordinates of both fills are reversed. DONT ASK ME WHY, ASK THE AUTHOR OF AWEPS! So we have to perform some brain dead processing here to get the right attributes applied to the right objects.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/94
Parameters:
- [INPUTS]
Returns:
TRUE if the mangled fill has been dealt with correctly FALSE if not.

Errors: Syntax error in EPS file, Out of memory

Definition at line 1949 of file aw_eps.cpp.

01950 {
01951 
01952     BOOL ok;
01953 
01954     DocCoord StartPoint, EndPoint;
01955     DocColour StartColour, EndColour;
01956 
01957     // Get start and end positions for grad-fills
01958     if (!Stack.PopCoordPair(&EndPoint) || !Stack.PopCoordPair(&StartPoint))
01959         return FALSE;
01960 
01961     // read the last definitions of set colours
01962     if (LastFillType>0)
01963     {
01964         GetEPSColour(&StartColour,
01965                      &LastStartColour.Col, 
01966                      LastStartColour.Tint,
01967                      LastStartColour.TintVal,
01968                      &LastStartColour.ColName);
01969 
01970         GetEPSColour(&EndColour,
01971                      &LastEndColour.Col, 
01972                      LastEndColour.Tint,
01973                      LastEndColour.TintVal,
01974                      &LastEndColour.ColName);
01975     }
01976 
01977     switch (LastFillType)
01978     {
01979         // Decode ArtWorks EPS grad fill codes
01980         case 1:
01981             // Check for silly grad fills first...
01982             if (StartPoint==EndPoint)
01983                 ok = SetFillColour(StartColour);
01984             else
01985                 ok = SetLinearFill(StartColour, EndColour, StartPoint, EndPoint);
01986             break;
01987 
01988         case 2:
01989             // Check for silly grad fills first...
01990             if (StartPoint==EndPoint)
01991                 ok=SetFillColour(EndColour);
01992             else
01993                 ok=SetRadialFill(StartColour, EndColour, StartPoint, EndPoint);
01994             break;
01995 
01996         default:
01997             // if there's no fill applied previously then this is rampant so ignore it.
01998             ok=Stack.Discard(4);
01999     }
02000     
02001     return ok;
02002 }

BOOL ArtWorksEPSFilter::Init void   )  [virtual]
 

Initialise an ArtWorksEPSFilter object.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/02/94
Returns:
TRUE if the filter was initialised ok, FALSE otherwise.

Errors: Will fail if not enough memory to initialise the EPS stack.

See also:
EPSStack

Reimplemented from EPSFilter.

Reimplemented in CamelotEPSFilter, and CamelotNativeEPSFilter.

Definition at line 262 of file aw_eps.cpp.

00263 {
00264     // Get the OILFilter object
00265     pOILFilter = new ArtWorksEPSOILFilter(this);
00266     if (pOILFilter == NULL)
00267         return FALSE;
00268 
00269     // Load the description strings
00270     FilterName.Load(FilterNameID);
00271     FilterInfo.Load(FilterInfoID);
00272 
00273     // All ok
00274     return TRUE;
00275 }

void ArtWorksEPSFilter::LookUpToken  )  [protected, virtual]
 

Compare the current token against the ArtWorks keywords to see if it is one of them.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/02/94
Returns:
TRUE if the token is an ArtWorks EPS token; FALSE if not.
See also:
EPSFilter::LookUpToken; EPSFilter::DecodeToken

Reimplemented from EPSFilter.

Reimplemented in CamelotEPSFilter, and CamelotNativeEPSFilter.

Definition at line 413 of file aw_eps.cpp.

00414 {
00415     // Not interested in comments
00416     if (Token == EPSC_Comment)
00417         return;
00418 
00419     // Check to see if it is a keyword - cycle through the array of keyword names and
00420     // compare against our token (could use a hash table?)
00421     INT32 i = 0;
00422     while (ArtWorksCommands[i].Cmd != EPSC_Invalid)
00423     {
00424         if (camStrcmp(TokenBuf, ArtWorksCommands[i].CmdStr) == 0)
00425         {
00426             // Found the token - set the token variable and return success
00427             Token = ArtWorksCommands[i].Cmd;
00428             return;
00429         }
00430         // Try next command
00431         i++;
00432     }
00433 
00434     // Did not find this token - pass on to base class.
00435     EPSFilter::LookUpToken();
00436 }

BOOL ArtWorksEPSFilter::NeedsPrintComponents void   )  [virtual]
 

Informs the print components code that no data should be written.

Author:
Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/5/00
Returns:
FALSE - ArtWorks files don't need print components.

Reimplemented from EPSFilter.

Definition at line 998 of file aw_eps.cpp.

00999 {
01000     // We don't want print components!
01001     return FALSE;
01002 }

BOOL ArtWorksEPSFilter::PrepareToExport CCLexFile pFile,
Spread pSpread
[virtual]
 

Prepare to import EPS data using this filter. This sets up the filter to a sensible state for reading.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/04/94
Parameters:
pFile - The File to export to [INPUTS] pSpread - The spread to export
Returns:
TRUE if succeeded, FALSE if not (e.g. no memory for EPS stack)

Errors: Out of memory.

See also:
EPSFilter::DoImport; EPSFilter::CleanUpAfterImport Scope: Private

Reimplemented from EPSFilter.

Reimplemented in CamelotEPSFilter, and CamelotNativeEPSFilter.

Definition at line 351 of file aw_eps.cpp.

00352 {
00353 #ifdef DO_EXPORT
00354     // Created the 'file' DC for rendering and try to open the specified file.
00355     ExportDCPtr = new EPSExportDC(this);
00356     if (ExportDCPtr == NULL) return FALSE;
00357     
00358     // Tell it about the file
00359     if (!ExportDCPtr->Init(pFile)) return FALSE;
00360 
00361     // Get the position of the first page, and use this to set the origin.
00362     Page *pPage = pSpread->FindFirstPageInSpread(); 
00363     ENSURE(pPage != NULL, "Spread has no pages");
00364     ERRORIF(pPage == NULL, _R(IDT_DOC_BADSTRUCTURE), FALSE);
00365 
00366     // Use bottom left of page as origin
00367     DocRect PageRect = pPage->GetPageRect();
00368     ExportDCPtr->SetOrigin(PageRect.lo);
00369 
00370     // Create a new render region to export to:
00371 
00372     // Don't care about clip regions when exporting - create a null region.
00373     DocRect NullClipRect;
00374     NullClipRect.MakeEmpty();
00375 
00376     if (IS_A(this, ArtWorksEPSFilter))
00377     {
00378         // Don't use rendering matrix when exporting EPS as it uses fractional coordinates.
00379         Matrix Identity;
00380 
00381         // Don't use view scale; set to 1
00382         FIXED16 Scale(1);
00383 
00384         // Create the region
00385         ExportRegion = new ArtWorksEPSRenderRegion(NullClipRect, Identity, Scale);
00386         if (ExportRegion == NULL)
00387             return FALSE;
00388 
00389         // Attach to the right device.
00390         ExportRegion->AttachDevice(DocView::GetSelected(), ExportDCPtr->GetDC(), pSpread);
00391     }
00392 
00393     // All ok
00394     return TRUE;
00395 #else
00396     return FALSE;
00397 #endif
00398 };

BOOL ArtWorksEPSFilter::ProcessBlend  )  [protected]
 

Reads in all the elements of a blend structure in the EPS file.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/11/94
Returns:
TRUE if the blend was processed correctly, FALSE if not.

Errors: Syntax error in EPS file, Out of memory

Reimplemented in CamelotEPSFilter.

Definition at line 1016 of file aw_eps.cpp.

01017 {
01018     if (!StartBlend())
01019         return FALSE;
01020 
01021     // Keep processing tokens until we find the end of the blend
01022     do
01023     {
01024         GetToken();
01025 
01026         // Look for the end of the blend token...
01027         if (Token == EPSC_aebd)
01028         {
01029             return EndBlend();
01030         }
01031     }
01032     // Otherwise keep going until an error or eof is encountered
01033     while (HandleToken() && (!EPSFile->eof()));
01034 
01035     if (EPSFile->eof())
01036     {
01037         // Didn't find end of blend - syntax error; deal with it
01038         HandleEPSError();
01039     }
01040 
01041     // If we're here, something went wrong
01042     return FALSE;
01043 }

BOOL ArtWorksEPSFilter::ProcessBlender  )  [protected]
 

Reads in all the elements of a blender structure in the EPS file.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/11/94
Returns:
TRUE if the blender was processed correctly, FALSE if not.

Errors: Syntax error in EPS file, Out of memory

Reimplemented in CamelotEPSFilter.

Definition at line 1182 of file aw_eps.cpp.

01183 {
01184     if (!StartBlender())
01185         return FALSE;
01186 
01187     // Keep processing tokens until we find the end of the blender
01188     do
01189     {
01190         GetToken();
01191 
01192         // Look for the end of the blender token...
01193         if (Token == EPSC_aebr)
01194         {
01195             return EndBlender();
01196         }
01197     }
01198     // Otherwise keep going until an error or eof is encountered
01199     while (HandleToken() && (!EPSFile->eof()));
01200 
01201     if (EPSFile->eof())
01202     {
01203         // Didn't find end of blender - syntax error; deal with it
01204         HandleEPSError();
01205     }
01206 
01207     // If we're here, something went wrong
01208     return FALSE;
01209 }

BOOL ArtWorksEPSFilter::ProcessEnvelope  )  [protected]
 

Reads in all the elements of an envelope structure in the ArtWorksEPS file and builds the camelot envelope tree.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/94
Returns:
TRUE if the envelope object was processed correctly, FALSE if not.

Errors: Syntax error in EPS file, Out of memory

Notes: This reader is reasonably complex. It is made so soley by the problem of being unable to calculate an inverse transform of an envelope. The crux of the matter is this. If you apply attributes to an already enveloped set of objects (lets call them the Dset), then in some way the attributes need to be applied to the source objects (the Sset). Now when you do this in ArtWorks eg, apply a linear fill to the Dset, the same fill is exported as applied to the Sset. Import the file back in and ArtWorks rebuilds both Sset and Dset from the file applying all necessary attributes there in. This works. But now we have a Dset attribute applied to an Sset object. As soon as you regenerate the Dset from the Sset (by tweeking the envelope shape) the new attributes created are wrong, as it transforms already transformed attributes. Ok, this problem prevents me from simply loading all Sset members from the file and recreating the Dset automatically. The loaded image does not look correct when grad fills are applied. (ie more often than not). Complexity level 1. To combat this problem, I'll do as ArtWorks did and load both Sset & Dset members. However, another problem arrises here.... ArtWorks envelope structure is as follows

line col fill col start env envelope shape fill col invisible path (Sset) mangled path (Dset) fill col invisible path (Sset) mangled path (Dset) end env

and this is saved as such in its EPS structure. Now Camelots structure is slightly different. It creates a source tree for Sset and a destination tree for Dset. Hence we need to disassemble the AW structure into two trees with the correct attributes in each. How do we do this? Complexity level 2. We could do this while importing, keeping two trees on the go, importing the correct bits into the correct tree. However this has many problems associated with it. Globally applied atts will need to be created in both trees. Groups too. We would have to intercept far more than the envelope tokens during import to do it. - no chance. So the only way to do it is to import the structure as is, creating an Artworks envelope inside Camelot. This will be structured as follows

Env | > EnvShape => MouldGroup => Moulder | > { Sset + Dset objects }

Having done this, we will convert this into

Env | > EnvShape => MouldGroup => Moulder | | > Sset > Dset

So long as we can tell the difference between Sset and Dset objects, which we can (all Dset objs are primary children of an Sset obj and Dset objects never contain Sset objs as children) we can use object move technology to build the correct moulder. Attributes will move (via inheritance) correctly with objects.

Reimplemented in CamelotEPSFilter.

Definition at line 1390 of file aw_eps.cpp.

01391 {
01392     // NOT IMPLEMENTED
01393     if (!StartMould(MOULDSPACE_ENVELOPE))
01394         return FALSE;
01395     
01396     if (ProcessMould())
01397         // If we've completed then all is well
01398         return EndMould();
01399 
01400     if (EPSFile->eof())
01401     {
01402         // Didn't find end of envelope - syntax error; deal with it
01403         HandleEPSError();
01404     }
01405 
01406     // if made it here all is not well
01407     return FALSE;
01408 }

BOOL ArtWorksEPSFilter::ProcessMangledObjs  )  [protected]
 

On finding a 'apc' token in the input stream, this function is executed. It will process all further tokens in the stream until a path termination has been found. A path terminator is considered any of { s,S,b,B,f,F,h,H } Its purpose is strictly defined. It must place the next set of attributes and single path as children of the last object imported rather than the default action which would be to stick them in as siblings of the object.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/94
Returns:
TRUE if the mangled object has been dealt with correctly FALSE if not.

Errors: Syntax error in EPS file, Out of memory

Definition at line 1866 of file aw_eps.cpp.

01867 {
01868     // Set the new position of pNode, our insert indicator
01869     Node *pOldPos = pNode;
01870     pNode=pNode->FindLastChild();
01871     if (pNode==NULL)
01872     {
01873         pNode=pOldPos;
01874         return FALSE;
01875     }
01876 
01877     BOOL ok = TRUE, end = FALSE;
01878 
01879     // The next path we create should be mangled
01880     ThePathType = PATH_MANGLED;
01881 
01882     while ((!end) && (!EPSFile->eof()) && (ok))
01883     {
01884         GetToken();
01885 
01886         switch (Token)
01887         {
01888             case EPSC_axm:
01889                 // ignore axm in this context
01890                 // See notes on func HandleMouldedFill below
01891                 ok = Stack.Discard(4);
01892                 break;
01893                 
01894             case EPSC_s: case EPSC_f: case EPSC_b: case EPSC_h:
01895             case EPSC_S: case EPSC_F: case EPSC_B: case EPSC_H:
01896                 // We've finished so set term flag
01897                 end = TRUE;
01898                 ok = HandleToken();
01899                 break;
01900 
01901             default:
01902                 // try to handle whatever token it was.
01903                 ok = HandleToken();
01904                 break;
01905         }
01906     }
01907 
01908     // Set the path back to something sensible
01909     ThePathType=PATH_NORMAL;
01910     pNode=pOldPos;
01911 
01912     if (ok && !(EPSFile->eof())) 
01913         return TRUE;
01914 
01915     // Arrgh didn't find an end-of-path token - syntax error; deal with it
01916     HandleEPSError();
01917     return FALSE;
01918 }

BOOL ArtWorksEPSFilter::ProcessMould  )  [protected]
 

Processes tokens inside a mould object. Tokens specific to mould objects are processed along with some overridding of default tokens such as groups.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/95
Returns:
TRUE if the mould was processed ok; FALSE if not.
See also:

Reimplemented in CamelotEPSFilter.

Definition at line 1589 of file aw_eps.cpp.

01590 {
01591     // Keep processing tokens until we find the end of the envelope
01592     while (!EPSFile->eof())
01593     {
01594         GetToken();
01595 
01596         // Look for the end of the envelope token...
01597         switch (Token)
01598         {
01599             case EPSC_aeev:
01600             case EPSC_aepr:
01601                 // if we've found the envelope/perspective end then
01602                 // all is well.
01603                 return TRUE;
01604                 break;
01605 
01606             case EPSC_apc:
01607                 // Create next object as a child
01608                 if (!ProcessMangledObjs())
01609                     return FALSE;
01610                 break;
01611 
01612             case EPSC_u:
01613                 // NOT IMPLEMENTED INSIDE MOULDS
01614                 break;
01615 
01616             case EPSC_U:
01617                 // NOT IMPLEMENTED INSIDE MOULDS
01618                 break;
01619 
01620             case EPSC_aof:
01621                 // don't need this token
01622                 if (!Stack.Discard(2))
01623                 {
01624                     HandleEPSError();
01625                     return FALSE;
01626                 }
01627                 break;
01628 
01629             case EPSC_h:
01630                 Token = EPSC_b;
01631                 if (!HandleToken())
01632                     return FALSE;
01633                 break;
01634 
01635             case EPSC_H:
01636                 Token = EPSC_B;
01637                 if (!HandleToken())
01638                     return FALSE;
01639                 break;
01640 
01641             default:
01642                 // try to handle whatever token this is.
01643                 if (!HandleToken()) 
01644                     return FALSE;
01645                 break;
01646         }
01647     }
01648 
01649     HandleEPSError();
01650     return FALSE;
01651 }

BOOL ArtWorksEPSFilter::ProcessMouldShape  )  [protected]
 

Reads in all the elements of a mould geometry held in the EPS file. The description of the geometry for this particular file type is that of a path. Depending on the geometry type (perspective or envelope) we will obviously expect a slightly different path. The rules are, that currently perspective geometry is described as {m,l,l,l,l} and envelope geometry is {m,c,c,c,c}. Internally we are not restricted to these but ArtworksEPS certainly is. Input Stack = coord, coord.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/94
Returns:
TRUE if the shape has been read correctly, FALSE if not.

Errors: Syntax error in EPS file, Out of memory

Reimplemented in CamelotEPSFilter.

Definition at line 1677 of file aw_eps.cpp.

01678 {
01679     // We really should be inside a mould object at this stage
01680     if (!IS_A(pNode,NodeMould)) 
01681     {
01682         ERROR3("Mould shape found outside a mould object");
01683         return FALSE;
01684     }
01685 
01686     NodeMould* pNodeMould = (NodeMould*)pNode;
01687 
01688     // Create a path object to read the mould geometry into
01689     Path TempPath;
01690     if (!TempPath.Initialise(24,12))
01691     {
01692         HandleNoMemory();
01693         return FALSE;
01694     }
01695 
01696     // Set the current used slots to none
01697     INT32 numt = 0;
01698     DocCoord Ta,Tb,Tc;
01699     PathFlags flags;
01700     flags.IsSelected = FALSE;
01701 
01702     // ok, pop off the move stacked coordinate
01703     BOOL ok = Stack.PopCoordPair(&Ta);
01704     if (!ok)
01705     {
01706         HandleEPSError();
01707         return FALSE;
01708     }
01709 
01710     // Add this first element as a move to
01711     if (!TempPath.AddMoveTo(Ta, &flags))
01712     {
01713         HandleNoMemory();
01714         return FALSE;
01715     }
01716 
01717     // increase the number of tokens read
01718     numt++;
01719     BOOL done = FALSE;
01720 
01721     // Keep processing tokens until we find the end of the mould path
01722     while (!done && (!EPSFile->eof()))
01723     {
01724         GetToken();
01725 
01726         // {m,c,c,c,c,c,c,c,c,e} is current maximum
01727         // if more complex, then illegal
01728         if ((numt++)>60)
01729         {
01730             HandleEPSError();
01731             return FALSE;
01732         }
01733 
01734         switch (Token)
01735         {
01736             case EPSC_aml:
01737                 // lineto (x,y) found
01738                         ok = Stack.PopCoordPair(&Ta);
01739                 if (ok) ok = TempPath.AddLineTo(Ta, &flags);
01740                 break;
01741                                                 
01742             case EPSC_amc:
01743                 // curveto (x0,y0,x1,y1,x2,y2) found
01744                         ok = Stack.PopCoordPair(&Tc);
01745                 if (ok) ok = Stack.PopCoordPair(&Tb);
01746                 if (ok) ok = Stack.PopCoordPair(&Ta);
01747                 if (ok) ok = TempPath.AddCurveTo(Ta,Tb,Tc,&flags);
01748                 break;
01749 
01750             case EPSC_amcp:
01751                 // found a close path. That should be it for path elements
01752                 ok = TempPath.CloseSubPath();
01753                 break;
01754 
01755             case EPSC_amep:
01756                 // end path drawfile parameter completes the path
01757                 // it contains a single 'length' parameter which seems
01758                 // to be zero always
01759                 ok = Stack.Discard();
01760                 done = TRUE;
01761                 break;
01762 
01763             default:
01764                 // try to handle whatever token this is.
01765                 ok = HandleToken();
01766                 break;
01767         }
01768 
01769         if (!ok)
01770         {
01771             HandleNoMemory();
01772             return FALSE;
01773         }
01774     }
01775 
01776     // We have read the path so now lets try and build the geometry
01777     // check the shape we've been given is fine and lovely  
01778     UINT32 errID;
01779     if (!pNodeMould->GetGeometry()->Validate(&TempPath,errID))
01780     {
01781         // ok the path we read is invalid so lets try to build a valid one
01782         Path* pPath = NULL;
01783         INT32 Corners[4] = {0, 3, 6, 9}; 
01784 
01785         if (!pNodeMould->GetGeometry()->MakeValidFrom(&pPath, &TempPath, Corners))
01786         {
01787             ERROR2(FALSE,"Unable to rectify invalid mould path in ProcessMouldShape()");
01788         }
01789  
01790         if (!TempPath.CloneFrom(*pPath))
01791         {
01792             delete pPath;
01793             HandleNoMemory();
01794             return FALSE;
01795         }
01796 
01797         delete pPath;
01798     }
01799 
01800     // Build and if necessary fit the geometry
01801     NodeMouldPath* pNodeMPath = pNodeMould->CreateNewMouldShape(&TempPath,NULL,NULL);
01802     if (pNodeMPath==NULL) 
01803     {
01804         HandleNoMemory();   
01805         return FALSE;
01806     }
01807 
01808     // set the geometry using this new mould shape
01809     if (!pNodeMould->GetGeometry()->Define(&(pNodeMPath->InkPath), &MouldRect))
01810     {
01811         HandleNoMemory();
01812         return FALSE;
01813     }
01814 
01815     // having created the shape bung it in the tree.
01816     if (!AddNewNode(pNodeMPath))
01817     {
01818         delete pNodeMPath;
01819         HandleNoMemory();
01820         return FALSE;
01821     }
01822 
01823     // Create a mould group object
01824     NodeMouldGroup* pMouldGroup = pNodeMould->CreateNewMouldGroup(NULL);
01825     if (pMouldGroup==NULL)
01826     {
01827         HandleNoMemory();
01828         return FALSE;
01829     }
01830 
01831     if (!AddNewNode(pMouldGroup))
01832     {
01833         delete pMouldGroup;
01834         HandleNoMemory();
01835         return FALSE;
01836     }
01837 
01838     // finally leave the insert pointer on the MouldGroup object
01839     pNode = pMouldGroup;
01840 
01841     return TRUE;
01842 
01843 }

BOOL ArtWorksEPSFilter::ProcessPerspective  )  [protected]
 

Reads in all the elements of an perspective structure in the EPS file.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/03/94
Returns:
TRUE if the perspective object was processed correctly, FALSE if not.

Errors: Syntax error in EPS file, Out of memory

See also:
ProcessEnvelope() for furher details

Reimplemented in CamelotEPSFilter.

Definition at line 1424 of file aw_eps.cpp.

01425 {
01426     // NOT IMPLEMENTED
01427     if (!StartMould(MOULDSPACE_PERSPECTIVE))
01428         return FALSE;
01429 
01430     // If we've completed then all is well
01431     if (ProcessMould())
01432         return EndMould();
01433 
01434     if (EPSFile->eof())
01435     {
01436         // Didn't find end of perspective - syntax error; deal with it
01437         HandleEPSError();
01438     }
01439 
01440     // if made it here all is not well
01441     return FALSE;
01442 }

BOOL ArtWorksEPSFilter::ProcessToken  )  [protected, virtual]
 

Processes EPS tokens that are not part of the standard Illustrator set, or which need to be handled differently to the standard Illustrator meanings. i.e. this is the function that handles all the ArtWorks EPS operators.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/02/94
Returns:
TRUE if token understood and processed ok, FALSE if not.

Errors: Syntax error in EPS, Out of memory.

See also:
EPSFilter::ProcessToken

Reimplemented from EPSFilter.

Reimplemented in CamelotEPSFilter, and CamelotNativeEPSFilter.

Definition at line 453 of file aw_eps.cpp.

00454 {
00455     // Variables used to extract operands from the stack
00456     DocCoord    Coords[3];
00457     String_64   ColName;
00458     PColourCMYK Col;
00459     TintType    Tint = TINT_NONE;
00460     FIXEDPOINT  TintVal;
00461     INT32       Long;
00462     DocCoord    StartPoint, 
00463                 EndPoint;
00464     PathFlags   Flags;
00465 
00466     // Decode the command, and execute it...
00467     switch (Token)
00468     {
00469         // LineTo - overridden to overcome ArtWorks EPS incompatibility with AI EPS.
00470         case EPSC_l:
00471             if (ThePathType == PATH_DISCARD || ThePathType == PATH_DISCARD_STICKY)
00472             {
00473                 if (!Stack.PopCoordPair(&Coords[0]))
00474                     goto EPSError;
00475                 break;
00476             }
00477 
00478             if (pInkPath == NULL)
00479                 // Paths must start with a moveto
00480                 goto EPSError;
00481             
00482             // Get the co-ordinate from the stack
00483             if (Stack.PopCoordPair(&Coords[0]))
00484             {
00485                 // ArtWorks doesn't save smoothing bit of the point, so default to
00486                 // no smoothing (it's the logical default).
00487                 Flags.IsSmooth = FALSE;
00488 
00489                 if (!pInkPath->InsertLineTo(Coords[0], &Flags))
00490                     // Not enough dynamic heap to insert the lineto command
00491                     goto NoMemory;
00492             }
00493             else
00494                 // Invalid number/type of coordinate operands
00495                 goto EPSError;
00496             break;
00497 
00498         // Curveto - overridden to overcome ArtWorks EPS incompatibility with AI EPS.
00499         case EPSC_c:
00500             if (ThePathType == PATH_DISCARD || ThePathType == PATH_DISCARD_STICKY)
00501             {
00502                 if (!Stack.PopCoordPair(&Coords[2]) ||
00503                     !Stack.PopCoordPair(&Coords[1]) ||
00504                     !Stack.PopCoordPair(&Coords[0]))
00505                     goto EPSError;
00506 
00507                 break;
00508             }
00509 
00510             if (pInkPath == NULL)
00511                 // Paths must start with a moveto
00512                 goto EPSError;
00513             
00514             // Get the co-ordinate from the stack
00515             if (Stack.PopCoordPair(&Coords[2]) &&
00516                 Stack.PopCoordPair(&Coords[1]) &&
00517                 Stack.PopCoordPair(&Coords[0]))
00518             {
00519                 // ArtWorks doesn't save smoothing bit of the point, so default to
00520                 // no smoothing (it's the logical default).
00521                 Flags.IsSmooth = FALSE;
00522 
00523                 if (!pInkPath->InsertCurveTo(Coords[0], Coords[1], Coords[2], &Flags))
00524                     // Not enough dynamic heap to insert the curveto command
00525                     goto NoMemory;
00526             }
00527             else
00528                 // Invalid number/type of coordinate operands
00529                 goto EPSError;
00530             break;
00531             
00532         case EPSC_aoa:
00533             // NOT IMPLEMENTED
00534             if (!Stack.Discard())
00535                 goto EPSError;
00536             break;
00537             
00538         case EPSC_aafs:
00539             // NOT IMPLEMENTED
00540             if (!Stack.Discard(3))
00541                 goto EPSError;
00542             break;
00543             
00544         
00545         // Path related procedures
00546         case EPSC_ar:
00547             // ArtWorks rectangle
00548             ThePathType = PATH_RECT;
00549             break;
00550         
00551         case EPSC_arr:
00552             // NOT IMPLEMENTED
00553             if (!Stack.Discard(7))
00554                 goto EPSError;
00555             break;
00556             
00557         case EPSC_ae:
00558         {
00559             // ArtWorks ellipse
00560             ThePathType = PATH_ELLIPSE;
00561 
00562             // Read in parallelogram bounding box.
00563             if (!Stack.PopCoordPair(&ShapeBBox[0]) ||
00564                 !Stack.PopCoordPair(&ShapeBBox[1]) ||
00565                 !Stack.PopCoordPair(&ShapeBBox[2]))
00566                 goto EPSError;
00567 
00568             // Fill in the 4th co-ordinate
00569             ShapeBBox[3].x = ShapeBBox[0].x + (ShapeBBox[2].x - ShapeBBox[1].x);
00570             ShapeBBox[3].y = ShapeBBox[0].y + (ShapeBBox[2].y - ShapeBBox[1].y);
00571 
00572             break;
00573         }
00574             
00575         case EPSC_apl:
00576             // NOT IMPLEMENTED
00577             if (!Stack.Discard())
00578                 goto EPSError;
00579             break;
00580             
00581         case EPSC_apc:
00582             // NOT IMPLEMENTED
00583             break;
00584             
00585         case EPSC_aof:
00586             // NOT IMPLEMENTED
00587             if (!Stack.Discard(2))
00588                 goto EPSError;
00589             break;
00590             
00591         
00592         // Text related procedures
00593         case EPSC_asto:
00594             // NOT IMPLEMENTED
00595             break;
00596             
00597         case EPSC_aeto:
00598             // NOT IMPLEMENTED
00599             break;
00600             
00601         case EPSC_aco:
00602             // NOT IMPLEMENTED
00603             if (!Stack.Discard(2))
00604                 goto EPSError;
00605             break;
00606             
00607         case EPSC_atc:
00608             // NOT IMPLEMENTED
00609             if (!Stack.Discard())
00610                 goto EPSError;
00611             break;
00612             
00613         case EPSC_atph:
00614             // NOT IMPLEMENTED
00615             if (!Stack.Discard())
00616                 goto EPSError;
00617             break;
00618             
00619         case EPSC_atof:
00620             // NOT IMPLEMENTED
00621             if (!Stack.Discard(2))
00622                 goto EPSError;
00623             break;
00624             
00625         
00626         // Blend related procedures
00627         case EPSC_asbd:
00628             return ProcessBlend();
00629             
00630         case EPSC_aebd:
00631             goto EPSError;
00632             
00633         case EPSC_asbr:
00634             return ProcessBlender();
00635             
00636         case EPSC_aebr:
00637             goto EPSError;
00638             
00639         
00640         // Mould related procedures
00641         case EPSC_asev:
00642             return ProcessEnvelope();
00643             
00644         case EPSC_aeev:
00645             goto EPSError;
00646             
00647         case EPSC_aspr:
00648             return ProcessPerspective();
00649             
00650         case EPSC_aepr:
00651             goto EPSError;
00652             
00653         case EPSC_amm:
00654             return ProcessMouldShape();
00655 
00656         case EPSC_aml:
00657         case EPSC_amc:
00658         case EPSC_amcp:
00659         case EPSC_amep:
00660             // all these tokens are mould path related and are
00661             // delt with inside ProcessMouldShape(). If they are found
00662             // on their own elsewhere then we obviously have an error
00663             goto EPSError;
00664                         
00665         
00666         // Group related procedures
00667         
00668         case EPSC_anu:
00669             // Discard the name - we don't do named groups.
00670             if (!Stack.Discard())
00671                 goto EPSError;
00672 
00673             // Process as a normal EPS group.
00674             GroupNesting++;
00675             return ProcessGroup();
00676             
00677         // Linear/radial fills
00678         case EPSC_ax:
00679             // Colours are described using a name and tint as well as CMYK.
00680             Tint = TINT_ILLUSTRATOR;
00681         case EPSC_az:
00682         {
00683             DocColour StartColour, EndColour;
00684             DocCoord StartPoint, EndPoint;
00685 
00686             // Get start and end positions for grad-fills
00687             if (!Stack.PopCoordPair(&EndPoint) || !Stack.PopCoordPair(&StartPoint))
00688                 goto EPSError;
00689             
00690             // Get start and end colours for grad-fills
00691             if (!Stack.PopColour(&Col, Tint, &TintVal, &ColName))
00692                 // Invalid colour operands
00693                 goto EPSError;
00694 
00695             // Keep hold of this colour definition 
00696             LastEndColour.Col = Col;
00697             LastEndColour.Tint = Tint;
00698             LastEndColour.TintVal = TintVal;
00699             LastEndColour.ColName = ColName;
00700 
00701             GetEPSColour(&EndColour, &Col, Tint, TintVal, &ColName);
00702 
00703             if (!Stack.PopColour(&Col, Tint, &TintVal, &ColName))
00704                 // Invalid colour operands
00705                 goto EPSError;
00706 
00707             // Keep hold of this colour definition 
00708             LastStartColour.Col = Col;
00709             LastStartColour.Tint = Tint;
00710             LastStartColour.TintVal = TintVal;
00711             LastStartColour.ColName = ColName;
00712 
00713             GetEPSColour(&StartColour, &Col, Tint, TintVal, &ColName);
00714                 
00715             // Get fill type
00716             if (!Stack.Pop(&Long))
00717                 goto EPSError;
00718 
00719             // Also save the last fill style
00720             LastFillType = Long;
00721 
00722             switch (Long)
00723             {
00724                 // Decode ArtWorks EPS grad fill codes
00725                 case 1:
00726                     // Check for silly grad fills first...
00727                     if (StartPoint == EndPoint)
00728                     {
00729                         // Zero length grad fill line!
00730                         // Just set a flat fill  using the first colour, cos that is
00731                         // how Arc GDraw renders such fills.
00732                         if (!SetFillColour(StartColour))
00733                             goto NoMemory;
00734                     }
00735                     else
00736                     {
00737                         if (!SetLinearFill(StartColour, EndColour, StartPoint, EndPoint))
00738                             goto NoMemory;
00739                     }
00740                     break;
00741 
00742                 case 2:
00743                     // Check for silly grad fills first...
00744                     if (StartPoint == EndPoint)
00745                     {
00746                         // Zero length grad fill line!
00747                         // Just set a flat fill  using the second colour, cos that is
00748                         // how Arc GDraw renders such fills.
00749                         //
00750                         // NB. This is different to linear fills above, which use the first 
00751                         // colour - that is how the GDraw cookie crumbles, cos that's
00752                         // the kind of guys we are! :-)
00753                         if (!SetFillColour(EndColour))
00754                             goto NoMemory;
00755                     }
00756                     else
00757                     {
00758                         if (!SetRadialFill(StartColour, EndColour, StartPoint, EndPoint))
00759                             goto NoMemory;
00760                     }
00761                     break;
00762 
00763                 default:
00764                     ENSURE(FALSE, "Unknown fill type found!");
00765                     break;  // Don't know this fill type
00766             }
00767             break;
00768         }
00769             
00770         case EPSC_axm:
00771         {
00772             // ignore axm in this context
00773             if (!HandleMouldedFill())
00774                 goto EPSError;
00775             break;
00776         }
00777 
00778         case EPSC_axop:
00779             // NOT IMPLEMENTED
00780             if (!Stack.Discard(4))
00781                 goto EPSError;
00782             break;
00783             
00784         
00785         // Others(!)
00786         case EPSC_awr:
00787             if (!Stack.Pop(&Long))
00788                 goto EPSError;
00789             // Decode winding rule
00790             ENSURE((Long == 0) || (Long == 1), "Bad winding rule found in Artworks EPS");
00791             if (Long == 0)
00792             {
00793                 if (!SetWindingRule(NonZeroWinding))
00794                     goto NoMemory;
00795             }
00796             else if (Long == 1)
00797             {
00798                 if (!SetWindingRule(EvenOddWinding))
00799                     goto NoMemory;
00800             }
00801             break;
00802             
00803         case EPSC_asc:
00804             // NOT IMPLEMENTED
00805             if (!Stack.Discard(3))
00806                 goto EPSError;
00807             break;
00808             
00809         case EPSC_aec:
00810             // NOT IMPLEMENTED
00811             if (!Stack.Discard(3))
00812                 goto EPSError;
00813             break;
00814             
00815         case EPSC_aca:
00816             // NOT IMPLEMENTED
00817             break;
00818             
00819         case EPSC_asah:
00820             // NOT IMPLEMENTED
00821             if (!Stack.Discard(3))
00822                 goto EPSError;
00823             break;
00824             
00825         case EPSC_aeah:
00826             // NOT IMPLEMENTED
00827             if (!Stack.Discard(3))
00828                 goto EPSError;
00829             break;
00830             
00831         case EPSC_asat:
00832             // NOT IMPLEMENTED
00833             if (!Stack.Discard(6))
00834                 goto EPSError;
00835             break;
00836             
00837         case EPSC_aeat:
00838             // NOT IMPLEMENTED
00839             if (!Stack.Discard(6))
00840                 goto EPSError;
00841             break;
00842             
00843         // Procedures that define a text object
00844         case EPSC_atp:
00845             // NOT IMPLEMENTED
00846             if (!Stack.Discard(2))
00847                 goto EPSError;
00848             break;
00849             
00850         case EPSC_atf:
00851             // NOT IMPLEMENTED
00852             if (!Stack.Discard())
00853                 goto EPSError;
00854             break;
00855             
00856         case EPSC_atxy:
00857             // NOT IMPLEMENTED
00858             if (!Stack.Discard(2))
00859                 goto EPSError;
00860             break;
00861             
00862         case EPSC_atrk:
00863             // NOT IMPLEMENTED
00864             if (!Stack.Discard(4))
00865                 goto EPSError;
00866             break;
00867             
00868         case EPSC_akrn:
00869             // NOT IMPLEMENTED
00870             if (!Stack.Discard(2))
00871                 goto EPSError;
00872             break;
00873             
00874         
00875         // Layer procedure
00876         case EPSC_alyr:
00877         {
00878             String_256 LayerName;
00879             INT32 Visible;
00880             INT32 Locked;
00881             INT32 Foreground;
00882             INT32 Printable;
00883 
00884             // We ignore the layer type and print over-ride flag (for now)
00885             if (!Stack.Pop(&Locked)     || 
00886                 !Stack.Pop(&Printable)  || 
00887                 !Stack.Pop(&Visible)    || 
00888                 !Stack.Pop(&Foreground) || 
00889                 !Stack.Pop(&LayerName))
00890                 goto EPSError;
00891 
00892             if (Filter::ImportWithLayers)
00893             {
00894                 // We are importing layers, so put all new nodes on this layer.
00895                 UseLayer(LayerName);
00896 
00897                 // Try to set the visible/locked flags on this layer, but only if
00898                 // we created a new one (i.e. don't change the flags of existing layers.
00899                 if (EPSFlags.AddToNewLayer)
00900                 {
00901                     // Here we force layers to be printable if they are in the foreground - just in case
00902                     // This will have to change if the UI allows Printable & Foreground to be specified
00903                     // independantly.
00904                     Printable = Foreground;
00905 
00906                     // Visible flag
00907                     pLayer->SetVisible(!(Visible == 0));
00908 
00909                     // Locked flag
00910                     pLayer->SetLocked(!(Locked == 0));
00911 
00912                     // Printable flag
00913                     pLayer->SetPrintable(!(Printable == 0));
00914 
00915                     // Background flag
00916                     pLayer->SetBackground(Foreground == 0);
00917                 }
00918             }
00919             break;
00920         }
00921             
00922         
00923         // Sprite procedure
00924         case EPSC_ass:
00925             // NOT IMPLEMENTED
00926             ERROR2RAW("EPS reader cannot handle Acorn sprites - Dream On!");
00927             goto EPSError;
00928             break;
00929             
00930         case EPSC_aes:
00931             // NOT IMPLEMENTED
00932             ERROR2RAW("EPS reader cannot handle Acorn sprites! - Dream On!");
00933             goto EPSError;
00934             break;
00935             
00936         default:
00937             // Token not understood - pass on to base class
00938             return EPSFilter::ProcessToken();
00939     }
00940 
00941 
00942     // No errors encountered while parsing this token and its operands.
00943     return TRUE;
00944     
00945     
00946     // Error handlers:
00947     
00948 EPSError:
00949     HandleEPSError();
00950     return FALSE;
00951 
00952 NoMemory:
00953     HandleNoMemory();
00954     return FALSE;
00955 }

BOOL ArtWorksEPSFilter::PromoteMangled Node rNode  )  [protected]
 

Promote all mangled child nodes to siblings of their parents.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
09/03/95
Parameters:
rNode = a pointer to a mangled node to promote [INPUTS]
Returns:
-

Definition at line 2203 of file aw_eps.cpp.

02204 {
02205     Node* sNode;
02206     sNode=rNode->FindFirstChild();
02207     while (sNode)
02208     {
02209         if (sNode->IsMangled())
02210         {
02211             sNode->SetMangled(FALSE);
02212             sNode->MoveNode(rNode,NEXT);
02213             rNode->CascadeDelete();
02214             delete rNode;
02215             return TRUE;
02216         }
02217         sNode=sNode->FindNext();
02218     }
02219     return FALSE;
02220 }

BOOL ArtWorksEPSFilter::StartBlend  )  [protected]
 

Used when a blend structure needs to be created - after this is called, all new nodes added with AddNewNode() will be added as children of this new blend, until EndBlend is called.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/11/94
Returns:
TRUE if the new blend was created ok; FALSE if not.

Errors: Out of memory

See also:
ArtWorksEPSFilter::EndBlend

Reimplemented in CamelotEPSFilter.

Definition at line 1061 of file aw_eps.cpp.

01062 {
01063     INT32 NumBlendShapes,Version,Expanded;
01064     
01065     // Read in the params
01066     BOOL    ok = Stack.Pop(&NumBlendShapes);
01067     if (ok) ok = Stack.Pop(&Expanded);
01068     if (ok) ok = Stack.Pop(&Version);
01069     if (!ok) 
01070     {
01071         HandleEPSError();
01072         return FALSE;
01073     }
01074 
01075     // If the version isn;t one we know, go b-b-b-bang!
01076     ERROR1IF(Version != 1,FALSE,_R(IDT_EPS_BADSYNTAX));
01077 
01078     // Make a new blend node for this blend
01079     NodeBlend *pBlend = new NodeBlend;
01080     if (pBlend==NULL)
01081     {
01082         HandleNoMemory();
01083         return FALSE;
01084     }
01085 
01086     // Add it into the tree
01087     if (!AddNewNode(pBlend))
01088     {
01089         HandleNoMemory();
01090         return FALSE;
01091     }
01092 
01093     // Make sure new objects are added as children of the node
01094     pNode = pBlend;
01095 
01096     // All ok
01097     return TRUE;
01098 }

BOOL ArtWorksEPSFilter::StartBlender  )  [protected]
 

Used when a blender structure needs to be created - after this is called, all new paths will be discarded, until EndBlender is called.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/11/94
Returns:
TRUE if the new blender was created ok; FALSE if not.

Errors: Out of memory

See also:
ArtWorksEPSFilter::EndBlender

Reimplemented in CamelotEPSFilter.

Definition at line 1226 of file aw_eps.cpp.

01227 {
01228     UINT32 NumBlendSteps;
01229     INT32 Expanded,OneToOne,Complex;
01230     INT32 PathIndexStart,PathIndexEnd;
01231     
01232     // Get the blender params
01233     BOOL    ok = Stack.Pop(&PathIndexEnd);
01234     if (ok) ok = Stack.Pop(&PathIndexStart);
01235     if (ok) ok = Stack.Pop(&NumBlendSteps);
01236     if (ok) ok = Stack.Pop(&OneToOne);
01237     if (ok) ok = Stack.Pop(&Complex);
01238     if (ok) ok = Stack.Pop(&Expanded);
01239     if (!ok)
01240     {
01241         HandleEPSError();
01242         return FALSE;
01243     }
01244 
01245     // Make a new blender node for this blender
01246     NodeBlender *pNodeBlender = new NodeBlender;
01247     if (pNodeBlender == NULL)
01248     {
01249         HandleNoMemory();
01250         return FALSE;
01251     }
01252 
01253     // Add it into the tree
01254     if (!AddNewNode(pNodeBlender))
01255     {
01256         delete pNodeBlender;
01257         HandleNoMemory();
01258         return FALSE;
01259     }
01260 
01261     // If both indexes are -ve, don't change the start points of the paths when blending
01262     if (PathIndexEnd < 0 && PathIndexEnd < 0)
01263         PathIndexStart = PathIndexEnd = 0;
01264 
01265     // Set the AW path indexes to be used when we get an "aebd" (end blend) token
01266     pNodeBlender->SetPathIndexStart(PathIndexStart);
01267     pNodeBlender->SetPathIndexEnd  (PathIndexEnd);
01268 
01269     // Some of these flags are stored in the parent blend node in Camelot - so set them!
01270     if (!IS_A(pNode,NodeBlend))
01271     {
01272         ERROR2(FALSE,"Found a blender token without finding a blend");
01273     }
01274 
01275     NodeBlend* pNodeBlend = (NodeBlend*)pNode;
01276     pNodeBlend->SetNumBlendSteps(NumBlendSteps-1);
01277     pNodeBlend->SetOneToOne(OneToOne);
01278 
01279     // Discard all paths between this and the aebr tokens
01280     ThePathType = PATH_DISCARD_STICKY;
01281 
01282     // All ok
01283     return TRUE;
01284 }

BOOL ArtWorksEPSFilter::StartMould MouldSpace  mSpace  )  [protected]
 

Used when an mould structure needs to be created - after this is called, all new nodes added with AddNewNode() will be added as children of this new mould, until EndMould is called.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> (from MarkN's)
Date:
06/03/95
Parameters:
mSpace = Mould geometry to define, either envelope or perspective [INPUTS]
Returns:
TRUE if the new mould object was created ok; FALSE if not.

Errors: Out of memory

See also:
ArtWorksEPSFilter::EndMould

Reimplemented in CamelotEPSFilter.

Definition at line 1464 of file aw_eps.cpp.

01465 {
01466     // Read in the bounding box of the original objects
01467     if (!Stack.PopCoordPair(&MouldRect.hi) || 
01468         !Stack.PopCoordPair(&MouldRect.lo))
01469     {
01470         HandleEPSError();
01471         return FALSE;
01472     }
01473 
01474     // create a mould parent and insert it in the tree
01475     NodeMould* pMouldParent = new NodeMould;
01476     if (pMouldParent==NULL)
01477     {
01478         HandleNoMemory();
01479         return FALSE;
01480     }
01481 
01482     // give the parent mould object a shape and mould space to work with and stick it
01483     // in the tree
01484     if (!pMouldParent->CreateGeometry(mSpace))
01485     {
01486         delete pMouldParent;
01487         HandleNoMemory();
01488         return FALSE;
01489     }
01490 
01491     if (!AddNewNode(pMouldParent))
01492     {
01493         HandleNoMemory();
01494         return FALSE;
01495     }
01496             
01497     // Make sure new objects are added as children of the mould
01498     pNode = pMouldParent;
01499 
01500     // All ok
01501     return TRUE;
01502 }


Member Data Documentation

CommandMap ArtWorksEPSFilter::ArtWorksCommands [static, protected]
 

Definition at line 149 of file aw_eps.h.

GradEndCol ArtWorksEPSFilter::LastEndColour [private]
 

Definition at line 179 of file aw_eps.h.

INT32 ArtWorksEPSFilter::LastFillType [private]
 

Definition at line 177 of file aw_eps.h.

GradEndCol ArtWorksEPSFilter::LastStartColour [private]
 

Definition at line 178 of file aw_eps.h.

DocRect ArtWorksEPSFilter::MouldRect [private]
 

Definition at line 176 of file aw_eps.h.


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