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 of