FreeHandEPSFilter Class Reference

Aldus FreeHand 3.0 filter. More...

#include <freeeps.h>

Inheritance diagram for FreeHandEPSFilter:

EPSFilter VectorFilter Filter ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

 FreeHandEPSFilter ()
 Constructor for an FreeHandEPSFilter object. The object should be initialised before use.
BOOL Init ()
 Initialise an FreeHandEPSFilter object.

Protected Member Functions

BOOL PrepareToImport ()
 prepares to import a freehand EPS file
INT32 EPSHeaderIsOk (ADDR pFileHeader, UINT32 HeaderSize)
 Checks to see if the EPS comment headers specify that this is an FreeHand 3.0 generated EPS file, as required.
void LookUpToken ()
 Compare the current token against the AI keywords to see if it is one of them.
BOOL ProcessToken ()
 Examines the current token and performs whatever actions are necessary to process its meaning. Operands are simply pushed onto the EPS stack, and keywords are either acted upon, or ignored if they describe something that Camelot does not yet support (in the latter case, the operands of the keyword, if any, are simply discarded from the stack).
void CleanUpAfterImport (BOOL Successful)
 clears up after importing a FreeHand 3.0 EPS file
BOOL ValidateGroup (Node *pGroup)
 validates a group created by the filter. As all objects have a group around then, this removes groups which only have one entry.
BOOL MaskedGroupEnding ()
 Restores the graphic state after a masked group ends.
virtual BOOL AddNewNode (Node *pNewNode)
 checks to see if we're in complex path mode before passing on the node to the base class. If we are, it joins it to the last one and fiddles about with the attributes.

Private Member Functions

 CC_DECLARE_DYNAMIC (FreeHandEPSFilter)
BOOL PopColour (DocColour *Col)
 Pops a FreeHand colour off the stack.
BOOL PopNamedColour (DocColour *Col)
 Pops a FreeHand named colour off the stack.
BOOL DiscardFillSubType ()
 discards a fill sub type from the stack ('{}' or '{logtaper}' or something)
BOOL SaveCurrentFill ()
 stores the current fill attribute
BOOL RestoreCurrentFill ()
 restores the current fill attribute from the stored one
BOOL RemoveLastSubPathIfNotUnique (Path *pPath)
 Removes the last subpath from a path if an sub path with it's exact coords already exists.

Private Attributes

BOOL HadhToken
BOOL DoingGradFill
AttributeValueOldFill
BOOL InColours
BOOL InText
ImportedColourspNewColours
IndexedColour ** ColourArray
INT32 ColourArrayEntries
INT32 ColourArraySize
BOOL ComplexPathMode
BOOL HadFirstOfComplexPath
NodePathpLastPathSeen

Static Private Attributes

static CommandMap FHCommands []

Detailed Description

Aldus FreeHand 3.0 filter.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/05/95

Definition at line 121 of file freeeps.h.


Constructor & Destructor Documentation

FreeHandEPSFilter::FreeHandEPSFilter  ) 
 

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

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/05/95
See also:
EPSFilter::Init

Definition at line 213 of file freeeps.cpp.

00214 {
00215     // Set up filter descriptions.
00216     FilterNameID = _R(IDT_FREEHANDEPS_FILTERNAME);
00217     FilterInfoID = _R(IDT_FREEHANDEPS_FILTERINFO);
00218     ImportMsgID  = _R(IDT_IMPORTMSG_FREEHANDEPS);
00219 
00220     FilterID = FILTERID_FREEHAND_EPS;
00221 
00222     Flags.CanImport = TRUE;
00223     Flags.CanExport = FALSE;
00224 
00225     AdjustOrigin = FALSE;
00226 }


Member Function Documentation

BOOL FreeHandEPSFilter::AddNewNode Node pNewNode  )  [protected, virtual]
 

checks to see if we're in complex path mode before passing on the node to the base class. If we are, it joins it to the last one and fiddles about with the attributes.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/06/95
Returns:
error flag

Reimplemented from EPSFilter.

Definition at line 1409 of file freeeps.cpp.

01410 {
01411     if(IS_A(pNewNode, NodePath))
01412         pLastPathSeen = (NodePath *)pNewNode;
01413     
01414     // check to see if we want to handle this
01415     if((ComplexPathMode == FALSE) || (pNewNode == 0) || (pNode == 0) || (!IS_A(pNewNode, NodePath)))
01416         return EPSFilter::AddNewNode(pNewNode);
01417 
01418     // check to see if this is the first...
01419     if(HadFirstOfComplexPath == FALSE)
01420     {
01421         HadFirstOfComplexPath = TRUE;
01422         return EPSFilter::AddNewNode(pNewNode);
01423     }
01424 
01425     // find the last child of the node
01426     Node *pLastChild = pNode->FindLastChild();
01427     if(pLastChild == 0 || !IS_A(pLastChild, NodePath))
01428         return EPSFilter::AddNewNode(pNewNode);
01429 
01430     // we know that both of these things are NodePaths.
01431     Path *pTarget = &((NodePath *)pLastChild)->InkPath;
01432     Path *pAddition = &((NodePath *)pNewNode)->InkPath;
01433 
01434     // work out the new flags for the target
01435     BOOL TargetFilled = pTarget->IsFilled;
01436     BOOL TargetStroked = pTarget->IsStroked;
01437     if(pAddition->IsFilled)     TargetFilled = TRUE;
01438     if(pAddition->IsStroked)    TargetStroked = TRUE;
01439 
01440     // add this new path to the old one...
01441     if(!pTarget->MergeTwoPaths(*pAddition))
01442         return FALSE;
01443 
01444     // check that the thing we just added isn't already there
01445     if(!RemoveLastSubPathIfNotUnique(pTarget))
01446         return FALSE;
01447 
01448     // set it's flags
01449     pTarget->IsFilled = TargetFilled;
01450     pTarget->IsStroked = TargetStroked;
01451 
01452     // vape it's attributes
01453     pLastChild->DeleteChildren(pLastChild->FindFirstChild());
01454 
01455     // apply some new ones
01456     SetPathFilled(TargetFilled);
01457     if(!AddAttributes((NodePath *)pLastChild, TargetStroked, TargetFilled))
01458         return FALSE;
01459 
01460     // hide the nice additional path
01461     //if(!ImportInfo.pOp->DoHideNode(pNewNode, TRUE))
01462     //  return FALSE;
01463     pNewNode->CascadeDelete();
01464     delete pNewNode;
01465 
01466     // set the last seen path bollox
01467     pLastPathSeen = (NodePath *)pLastChild;
01468 
01469     // done!
01470     return TRUE;
01471 }

FreeHandEPSFilter::CC_DECLARE_DYNAMIC FreeHandEPSFilter   )  [private]
 

void FreeHandEPSFilter::CleanUpAfterImport BOOL  Successful  )  [protected, virtual]
 

clears up after importing a FreeHand 3.0 EPS file

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
02/06/95
Returns:
error flag
See also:
EPSFilter

Reimplemented from EPSFilter.

Definition at line 316 of file freeeps.cpp.

00317 {
00318     // ensure that there's no old fill hanging around
00319     if(OldFill != 0)
00320         delete OldFill;
00321 
00322     OldFill = 0;
00323 
00324     // add new colours if successful, destroy them if not
00325     if(Successful)
00326     {
00327         pNewColours->AddColoursToDocument();
00328     }
00329     else
00330     {
00331         pNewColours->DestroyColours();
00332     }
00333 
00334     // delete the colour reference array
00335     if(ColourArray != 0)
00336     {
00337         CCFree(ColourArray);
00338         ColourArray = 0;
00339     }
00340 
00341     // get rid of any stuff in the stack
00342     Stack.DeleteAll ();
00343 
00344     EPSFilter::CleanUpAfterImport(Successful);
00345 }

BOOL FreeHandEPSFilter::DiscardFillSubType  )  [private]
 

discards a fill sub type from the stack ('{}' or '{logtaper}' or something)

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
02/06/95
Returns:
EPS error

Definition at line 1063 of file freeeps.cpp.

01064 {
01065     BOOL Done = FALSE;
01066     EPSType Type;
01067     while(Done == FALSE)
01068     {
01069         Type = Stack.GetType();
01070         if(Type == EPSTYPE_NONE)
01071         {
01072             // not enough stuff on the stack
01073             return FALSE;;
01074         }
01075         else if(Type == EPSTYPE_STRING)
01076         {
01077             // string - is this the ending?
01078             String_64 Str;
01079             if(!Stack.Pop(&Str))
01080                 return FALSE;
01081             if(camStrcmp(Str, _T("{")) == 0)
01082                 Done = TRUE;        // found end of this bit
01083         }
01084         else
01085         {
01086             // just something unimportant - discard it
01087             if(!Stack.Discard())
01088                 return FALSE;
01089         }
01090     }
01091     
01092     return TRUE;
01093 }

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

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

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/06/95
Returns:
TRUE if the header is ok and import should proceed, FALSE if not.

Reimplemented from EPSFilter.

Definition at line 360 of file freeeps.cpp.

00361 {
00362     // Check the first line in EPS file
00363     if (strncmp((char *) pFileHeader, "%!PS-Adobe", 10) != 0)
00364     {
00365         // Incorrect version of EPS header line - we don't want this
00366         return 0;
00367     }
00368 
00369     // !PS-Adobe line is ok - check creator line...
00370     TCHAR *Buffer;
00371     CCMemTextFile HeaderFile((char *)pFileHeader, HeaderSize);
00372     if(HeaderFile.IsMemFileInited() == FALSE || HeaderFile.InitLexer() == FALSE)
00373     {
00374         HeaderFile.close();
00375         return 0;
00376     }
00377 
00378 
00379     BOOL HaveCreatorString = FALSE;
00380     
00381     UINT32 Lines = 0;
00382     while ((Lines < 20) && !HeaderFile.eof())
00383     {
00384         HeaderFile.GetLineToken();
00385         Buffer = (TCHAR *)HeaderFile.GetTokenBuf();
00386         ERROR2IF(Buffer == 0, 0, "Returned buffer from lex file == 0");
00387         Lines++;
00388 
00389         // Return TRUE if this file was created by Illustrator, or has been exported in 
00390         // Illustrator format.
00391         if (camStrncmp( (const TCHAR *)Buffer, _T("%%Creator: "), 11) == 0 && 
00392             camStrstr( (const TCHAR*)Buffer, _T("FreeHand")) != 0)
00393         {
00394             // found a plausible creator string - but it could be any version
00395             // (3.0 for the Mac gives it's version number here, but the PC one doesn't)
00396             HaveCreatorString = TRUE;
00397         }
00398 
00399         if (camStrncmp(Buffer, _T("%%DocumentProcSets: FreeHand_header 3 "), 38) == 0 && HaveCreatorString)
00400         {
00401             // I'll have that then.
00402             HeaderFile.close();
00403             return 10;
00404         }
00405 
00406         // If we find the compression token then stop the search as we don't want to start
00407         // looking in the compressed data!
00408         if (camStrncmp(Buffer, _T("%%Compression:"), 14)==0)
00409             break;
00410     }
00411 
00412     HeaderFile.close();
00413     
00414     return 0;
00415 }

BOOL FreeHandEPSFilter::Init void   )  [virtual]
 

Initialise an FreeHandEPSFilter object.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/05/95
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.

Definition at line 241 of file freeeps.cpp.

00242 {
00243     // Get the OILFilter object
00244     pOILFilter = new FreeHandEPSOILFilter(this);
00245     if (pOILFilter == NULL)
00246         return FALSE;
00247 
00248     // Load the description strings
00249     FilterName.Load(FilterNameID);
00250     FilterInfo.Load(FilterInfoID);
00251 
00252     // All ok
00253     return TRUE;
00254 }

void FreeHandEPSFilter::LookUpToken  )  [protected, virtual]
 

Compare the current token against the AI 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 FreeHand EPS token; FALSE if not.
See also:
EPSFilter::LookUpToken; EPSFilter::DecodeToken

Reimplemented from EPSFilter.

Definition at line 431 of file freeeps.cpp.

00432 {
00433     // Check to see if it is a keyword - cycle through the array of keyword names and
00434     // compare against our token (could use a hash table?)
00435     INT32 i = 0;
00436     while (FHCommands[i].Cmd != EPSC_Invalid)
00437     {
00438         if (camStrcmp(TokenBuf, FHCommands[i].CmdStr) == 0)
00439         {
00440             // Found the token - set the token variable and return success
00441             Token = FHCommands[i].Cmd;
00442             return;
00443         }
00444         // Try next command
00445         i++;
00446     }
00447 
00448     // Did not find this token - pass on to base class.
00449     EPSFilter::LookUpToken();
00450 }

BOOL FreeHandEPSFilter::MaskedGroupEnding  )  [protected, virtual]
 

Restores the graphic state after a masked group ends.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
02/06/95
Returns:
EPS error flag

Reimplemented from EPSFilter.

Definition at line 1322 of file freeeps.cpp.

01323 {
01324     // make the path type normal
01325     if(ThePathType == PATH_DISCARD || ThePathType == PATH_DISCARD_STICKY)
01326     {
01327         ThePathType = PATH_NORMAL;
01328     }
01329     
01330     return TRUE;
01331 }

BOOL FreeHandEPSFilter::PopColour DocColour Col  )  [private]
 

Pops a FreeHand colour off the stack.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/06/95
Returns:
TRUE if colour understood and processed ok, FALSE if not.

Errors: Syntax error in EPS, Out of memory.

See also:
EPSFilter::ProcessToken

Definition at line 1109 of file freeeps.cpp.

01110 {
01111     // OK, we expect an array of four values in the order (of popping) K, Y, M, C
01112 
01113     // check that we've got a array end
01114     EPSCommand Cmd;
01115     if(!Stack.PopCmd(&Cmd))
01116         return FALSE;
01117     if(Cmd != EPSC_ArrayEnd)
01118         return FALSE;
01119 
01120     // pop the colours
01121     double C, M, Y, K;
01122     if(!Stack.Pop(&K) ||
01123             !Stack.Pop(&Y) ||
01124             !Stack.Pop(&M) ||
01125             !Stack.Pop(&C))
01126         return FALSE;
01127 
01128     // check that we've got a array start
01129     if(!Stack.PopCmd(&Cmd))
01130         return FALSE;
01131     if(Cmd != EPSC_ArrayStart)
01132         return FALSE;
01133 
01134     // knock up the colour...
01135     ColourCMYK Colour;
01136     
01137     Colour.Cyan = C;
01138     Colour.Magenta = M;
01139     Colour.Yellow = Y;
01140     Colour.Key = K;
01141     
01142     IndexedColour *NewCol = new IndexedColour(COLOURMODEL_CMYK, (ColourGeneric *)&Colour);
01143 
01144     if(NewCol == 0)
01145         return FALSE;
01146 
01147     pColours->GetColourList()->GetUnnamedColours()->AddTail(NewCol);
01148 
01149     Col->MakeRefToIndexedColour(NewCol);
01150 
01151     return TRUE;
01152 }

BOOL FreeHandEPSFilter::PopNamedColour DocColour Col  )  [private]
 

Pops a FreeHand named colour off the stack.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/06/95
Returns:
TRUE if colour understood and processed ok, FALSE if not.

Errors: Syntax error in EPS, Out of memory.

See also:
EPSFilter::ProcessToken

Definition at line 1168 of file freeeps.cpp.

01169 {
01170     // OK, we expect an array of two values in the order (of popping) random, index
01171     // and we can use the index to look up the indexed colour we should use in our
01172     // nice list in ColourArray.
01173     // 'random'? Maybe it's a tint or something? Which doesn't seem to be used.
01174 
01175     // check that we've got a array end
01176     EPSCommand Cmd;
01177     if(!Stack.PopCmd(&Cmd))
01178         return FALSE;
01179     if(Cmd != EPSC_ArrayEnd)
01180         return FALSE;
01181 
01182     // pop the index
01183     double Random;
01184     INT32 Index;
01185     if(!Stack.Pop(&Index) ||
01186             !Stack.Pop(&Random))
01187         return FALSE;
01188 
01189     // check that we've got a array start
01190     if(!Stack.PopCmd(&Cmd))
01191         return FALSE;
01192     if(Cmd != EPSC_ArrayStart)
01193         return FALSE;
01194 
01195     // check that the index is valid
01196     if(Index < 0 || Index >= ColourArrayEntries)
01197         return FALSE;
01198 
01199     // knock up the colour...
01200     Col->MakeRefToIndexedColour(ColourArray[Index]);
01201 
01202     return TRUE;
01203 }

BOOL FreeHandEPSFilter::PrepareToImport  )  [protected, virtual]
 

prepares to import a freehand EPS file

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
02/06/95
Returns:
error flag
See also:
EPSFilter

Reimplemented from EPSFilter.

Definition at line 268 of file freeeps.cpp.

00269 {
00270     if(!EPSFilter::PrepareToImport())
00271         return FALSE;
00272 
00273     // set some nice variables
00274     HadhToken = FALSE;
00275     DoingGradFill = FALSE;
00276     OldFill = 0;
00277     InColours = FALSE;
00278     InText = FALSE;
00279     ComplexPathMode = FALSE;
00280     pLastPathSeen = 0;
00281     
00282     // set the clipping flags
00283     ClipRegion.SetClippingFlags(2);
00284 
00285     // get an importedcolours object
00286     pNewColours = new ImportedColours(pColours, FALSE);
00287     if(pNewColours == 0 || !pNewColours->Init())
00288         return FALSE;
00289 
00290     // get a colour array
00291     ColourArray = (IndexedColour **)CCMalloc(FHEF_COLOURARRAY_INITIALSIZE * sizeof(IndexedColour *));
00292     if(ColourArray == 0)
00293     {
00294         delete pNewColours;
00295         pNewColours = 0;
00296         return FALSE;
00297     }
00298     ColourArrayEntries = 0;
00299     ColourArraySize = FHEF_COLOURARRAY_INITIALSIZE;
00300 
00301     return TRUE;
00302 }

BOOL FreeHandEPSFilter::ProcessToken  )  [protected, virtual]
 

Examines the current token and performs whatever actions are necessary to process its meaning. Operands are simply pushed onto the EPS stack, and keywords are either acted upon, or ignored if they describe something that Camelot does not yet support (in the latter case, the operands of the keyword, if any, are simply discarded from the stack).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/10/93
Returns:
TRUE if the token was processed ok, FALSE if an error occured.

Errors: Fails (returns FALSE) if a syntax/error is detected in the EPS file, or if there is insufficient memory to complete the operation.

See also:
EPSFilter::GetToken Scope: Private

Reimplemented from EPSFilter.

Definition at line 477 of file freeeps.cpp.

00478 {
00479     // Decode the command, and execute it...
00480     switch (Token)
00481     {
00482         // state saving
00483         case EPSC_vms:
00484             if(!Import_gsave())
00485                 return FALSE;
00486             break;
00487 
00488         case EPSC_vmr:
00489             if(!Import_grestore())
00490                 return FALSE;
00491             break;
00492 
00493         case EPSC_vmrs:
00494             if(!Import_grestore())
00495                 return FALSE;
00496             if(!Import_gsave())
00497                 return FALSE;
00498             break;
00499 
00500         // tokens to ignore
00501         case EPSC_FREEHAND_IGNOREDTOKEN:
00502             break;
00503 
00504         // tokens which should be ignored and one entry discarded
00505         case EPSC_load:         // the load part of a fill - discard the /clipper before it
00506         case EPSC_fhsetspreadallow:
00507             if(!Stack.Discard(1))
00508                 goto EPSError;
00509             break;
00510 
00511         case EPSC_concat:
00512             if(!Stack.DiscardArray())
00513                 goto EPSError;
00514             break;
00515         
00516         // complex paths...
00517         case EPSC_eomode:
00518             {
00519                 INT32 ComplexStart;
00520 
00521                 if(!Stack.Pop(&ComplexStart))
00522                     goto EPSError;
00523 
00524                 // is this a start of a complex path?
00525                 if(ComplexStart != TRUE)
00526                 {
00527                     ComplexPathMode = FALSE;
00528                 }
00529                 else
00530                 {
00531                     HadFirstOfComplexPath = FALSE;
00532                     ComplexPathMode = TRUE;
00533                 }
00534             }
00535             break;
00536 
00537         case EPSC_true:
00538             Stack.Push((INT32)TRUE);
00539             break;
00540 
00541         case EPSC_false:
00542             Stack.Push((INT32)FALSE);
00543             break;
00544 
00545         case EPSC_u:
00546             HadFirstOfComplexPath = FALSE;
00547             return EPSFilter::ProcessToken();
00548             break;
00549 
00550         // colours
00551         case EPSC_Ka:
00552         case EPSC_ka:
00553             {
00554                 DocColour Colour;
00555 
00556                 if(PopColour(&Colour))
00557                 {
00558                     // Remember this colour for future objects
00559                     if (Token == EPSC_ka)
00560                     {
00561                         if (!SetFillColour(Colour))
00562                             goto NoMemory;
00563                     }
00564                     else
00565                     {
00566                         if (!SetLineColour(Colour))
00567                             goto NoMemory;
00568                     }
00569                 }
00570                 else    
00571                     // Invalid colour operands
00572                     goto EPSError;
00573             }
00574             break;
00575 
00576         case EPSC_Xa:
00577         case EPSC_xa:
00578             {
00579                 DocColour Colour;
00580 
00581                 if(PopNamedColour(&Colour))
00582                 {
00583                     // Remember this colour for future objects
00584                     if (Token == EPSC_xa)
00585                     {
00586                         if (!SetFillColour(Colour))
00587                             goto NoMemory;
00588                     }
00589                     else
00590                     {
00591                         if (!SetLineColour(Colour))
00592                             goto NoMemory;
00593                     }
00594                 }
00595                 else    
00596                     // Invalid colour operands
00597                     goto EPSError;
00598             }
00599             break;
00600 
00601         case EPSC_H:
00602             if(ComplexPathMode)
00603             {
00604                 // in complex path mode - make this a filled one, not a discarded one
00605                 Token = EPSC_S; 
00606             }
00607             return EPSFilter::ProcessToken();
00608             break;
00609         
00610         case EPSC_h:
00611             if(ComplexPathMode)
00612             {
00613                 // in complex path mode - modify and process
00614                 Token = EPSC_s;
00615                 return EPSFilter::ProcessToken();
00616                 break;
00617             }
00618             // the hidden path closing operator - a grad fill thingy will follow shortly maybe...
00619             // this will prevent it being processed now, although it may get processed later on.
00620             HadhToken = TRUE;
00621             break;
00622 
00623         // for clipping masks, do some funky stuff
00624         case EPSC_q:
00625             // if there's a pending grad fill...
00626             if(DoingGradFill)
00627             {
00628                 if(pPath != 0)
00629                 {
00630                     // right then, make a copy of the path...
00631                     NodePath *pPathClone;
00632 
00633                     if(!pPath->NodeCopy((Node **)&pPathClone))
00634                     {
00635                         goto NoMemory;
00636                     }
00637 
00638                     // copy the flags
00639                     EPSFlagsDefn EPSFlagsClone = EPSFlags;
00640                 
00641                     // send a token to finish and fill the path...
00642                     Token = (pInkPath->IsFilled)?EPSC_f:EPSC_s;
00643                     if(!EPSFilter::ProcessToken())
00644                         return FALSE;
00645 
00646                     // restore the old fill
00647                     if(!RestoreCurrentFill())
00648                         goto NoMemory;
00649 
00650                     // restore the copy of the path
00651                     pPath = pPathClone;
00652                     pInkPath = &pPath->InkPath;
00653 
00654                     // restore the flags
00655                     EPSFlags = EPSFlagsClone;
00656 
00657                     // definately want to send an h
00658                     HadhToken = TRUE;
00659                 }
00660 
00661                 // done the grad fill
00662                 DoingGradFill = FALSE;
00663 
00664                 // restore the old token
00665                 Token = EPSC_q;
00666             }
00667 
00668             // clipping started - have we got an h token to send?
00669             if(HadhToken)
00670                 FHEF_SENDh
00671 
00672             // process this
00673             return EPSFilter::ProcessToken();
00674             break;
00675 
00676         // for now, if there's no path, don't return a W
00677         case EPSC_W:
00678             if(pPath == 0)
00679             {
00680                 // OK, now we want to get the last path we created, make a copy of it and then install it as the current one
00681                 if(pLastPathSeen == 0)
00682                     goto EPSError;
00683 
00684                 // make a copy of it
00685                 NodePath *pClone;
00686                 
00687                 if(!pLastPathSeen->NodeCopy((Node **)&pClone))
00688                     goto NoMemory;
00689 
00690                 // delete it's attributes
00691                 pClone->DeleteChildren(pClone->FindFirstChild());
00692 
00693                 // make it the current path
00694                 pPath = pClone;
00695                 pInkPath = &pPath->InkPath;
00696                 ThePathType = PATH_NORMAL;
00697                 EPSFlags.NoAttributes = TRUE;
00698             }
00699             if(pPath != 0)
00700                 return EPSFilter::ProcessToken();
00701             break;
00702 
00703         // we may need to modify path closing things if we're doing a grad fill
00704         case EPSC_s:
00705         case EPSC_S:
00706             if(Token == EPSC_S)
00707             {
00708                 // if we've had an h token but no grad fill, send the h now
00709                 if(HadhToken)
00710                     FHEF_SENDh
00711 
00712                 // if we've got a grad fill, modify the token we got
00713                 if(DoingGradFill)
00714                     Token = EPSC_b;
00715             }
00716             
00717             // process the possily modified token normally
00718             HadhToken = FALSE;
00719             return EPSFilter::ProcessToken();
00720             break;
00721 
00722         // modify path closing for grad fills.
00723         case EPSC_n:
00724             if(DoingGradFill)
00725             {
00726                 Token = EPSC_f;         // we want to fill the thing
00727                 HadhToken = FALSE;
00728                 return EPSFilter::ProcessToken();
00729                 break;
00730             }
00731             HadhToken = FALSE;          // ignore h's as this is another end path thingy...
00732 
00733             if(pPath != 0)
00734                 return EPSFilter::ProcessToken();
00735             break;
00736 
00737         // unset the had h token for other path closing things
00738         case EPSC_N:
00739         case EPSC_F:
00740         case EPSC_f:
00741         case EPSC_B:
00742         case EPSC_b:
00743             HadhToken = FALSE;
00744             return EPSFilter::ProcessToken();
00745             break;
00746         
00747         // interested in path element things to switch off grad fills
00748         case EPSC_m:
00749             if(InText)
00750             {
00751                 // if we're doing some text, discard the moveto command
00752                 if(!Stack.Discard(2))
00753                     goto EPSError;
00754 
00755                 break;
00756             }
00757         case EPSC_l:
00758         case EPSC_L:
00759         case EPSC_c:
00760         case EPSC_C:
00761         case EPSC_v:
00762         case EPSC_V:
00763         case EPSC_y:
00764         case EPSC_Y:
00765             // maybe we need an h token to be sent
00766             if(HadhToken)
00767                 FHEF_SENDh
00768             
00769             // stop grad fill
00770             if(DoingGradFill)
00771             {
00772                 // turn the grad fill state off
00773                 DoingGradFill = FALSE;
00774 
00775                 // restore the old fill type
00776                 RestoreCurrentFill();
00777             }
00778             return EPSFilter::ProcessToken();
00779             break;
00780 
00781         
00782         case EPSC_recfill:
00783             {
00784                 // get the colours
00785                 DocColour StartColour, EndColour;
00786 
00787                 if(!PopColour(&EndColour) ||
00788                         !PopColour(&StartColour))
00789                     goto EPSError;
00790 
00791                 // discard the fill type thingy - we can only do colours
00792                 if(!DiscardFillSubType())
00793                     goto EPSError;
00794 
00795                 // OK, now a few coords
00796                 DocCoord Centre;
00797                 double Angle;
00798                 DocRect BBox;
00799                 if(!Stack.PopCoordPair(&BBox.hi) ||
00800                         !Stack.PopCoordPair(&BBox.lo) ||
00801                         !Stack.Pop(&Angle) ||
00802                         !Stack.PopCoordPair(&Centre))
00803                     goto EPSError;
00804 
00805                 // munge the angle a little and get it into radians
00806                 Angle += 225;
00807                 Angle = (Angle * (2 * PI)) / 360;
00808 
00809                 // see if we can get a more accurate BBox
00810                 if(pPath != 0)
00811                 {
00812                     BBox = pPath->GetBoundingRect();
00813                     Centre.x = BBox.lo.x + (BBox.Width() / 2);
00814                     Centre.y = BBox.lo.y + (BBox.Height() / 2);
00815                 }
00816 
00817                 // OK, we've got all the stuff we need to do some niceness on it
00818                 BBox.Translate(0 - Centre.x, 0 - Centre.y);
00819                 DocCoord StartPoint, EndPoint;
00820 
00821                 StartPoint.x = Centre.x + (INT32)(((double)BBox.lo.x * cos(Angle)) - ((double)BBox.lo.y * sin(Angle)));
00822                 StartPoint.y = Centre.y + (INT32)(((double)BBox.lo.x * sin(Angle)) + ((double)BBox.lo.y * cos(Angle)));
00823                 EndPoint.x = Centre.x + (INT32)(((double)BBox.hi.x * cos(Angle)) - ((double)BBox.hi.y * sin(Angle)));
00824                 EndPoint.y = Centre.y + (INT32)(((double)BBox.hi.x * sin(Angle)) + ((double)BBox.hi.y * cos(Angle)));
00825         
00826                 // store current fill attribute
00827                 SaveCurrentFill();
00828 
00829                 // set the fill
00830                 if(!SetLinearFill(StartColour, EndColour, StartPoint, EndPoint))
00831                     goto NoMemory;
00832 
00833                 // say we're doing a grad fill
00834                 DoingGradFill = TRUE;
00835                 HadhToken = FALSE;          // absorb this
00836             }
00837             break;
00838 
00839         case EPSC_radfill:
00840             {
00841                 // get the colours
00842                 DocColour StartColour, EndColour;
00843 
00844                 if(!PopColour(&StartColour) ||
00845                         !PopColour(&EndColour))
00846                     goto EPSError;
00847 
00848                 // get the radius and centre coordinate
00849                 DocCoord Centre;
00850                 INT32 Radius;
00851                 if(!Stack.PopCoord(&Radius) ||
00852                         !Stack.PopCoordPair(&Centre))
00853                     goto EPSError;
00854 
00855                 // store current fill attribute
00856                 SaveCurrentFill();
00857 
00858                 // set the fill
00859                 DocCoord EndPoint(Centre.x + Radius, Centre.y);
00860                 if(!SetRadialFill(StartColour, EndColour, Centre, EndPoint))
00861                     goto NoMemory;
00862 
00863                 // say we're doing a grad fill
00864                 DoingGradFill = TRUE;
00865                 HadhToken = FALSE;
00866             }
00867             break;
00868 
00869         case EPSC_BeginSetup:
00870             // there's probably a colour list or something in that there setup thingy - search for the spots token
00871             {
00872                 BOOL Found = FALSE;
00873                 
00874                 while(Found == FALSE)
00875                 {
00876                     if(!EPSFile->GetToken())
00877                         return FALSE;
00878 
00879                     if(EPSFile->GetTokenType() == TOKEN_NORMAL)
00880                     {
00881                         if(camStrcmp(TokenBuf, _T("spots")) == 0)
00882                         {
00883                             // check to see if the array is about to start
00884                             if(!EPSFile->GetToken())
00885                                 return FALSE;
00886 
00887                             if(TokenBuf[0] == '[')
00888                             {
00889                                 TRACEUSER( "Ben", _T("Found spots\n"));
00890                                 Found = TRUE;
00891                             }
00892                         }
00893                     }
00894                 
00895                     if(camStrncmp(TokenBuf, _T("%%EndSetup"), 10) == 0)
00896                     {
00897                         TRACEUSER( "Ben", _T("Met end of setup without finding spots\n"));
00898                         break;
00899                     }
00900 
00901                     if(EPSFile->eof())
00902                         goto EPSError;
00903                 }
00904 
00905                 if(Found == TRUE)
00906                 {
00907                     InColours = TRUE;
00908                 }
00909             }
00910             break;
00911 
00912         case EPSC_def:
00913             if(InColours)
00914             {
00915                 // finished the colours...
00916                 TRACEUSER( "Ben", _T("Finished spot colours\n"));           
00917                 // scan for the end of the setup section
00918                 BOOL Found = FALSE;
00919                 
00920                 while(Found == FALSE)
00921                 {
00922                     if(!EPSFile->GetToken())
00923                         return FALSE;
00924 
00925                     if(EPSFile->GetTokenType() == TOKEN_COMMENT)
00926                     {
00927                         if(camStrncmp(TokenBuf, _T("%%EndSetup"), 10) == 0)
00928                         {
00929                             TRACEUSER( "Ben", _T("Found end of setup\n"));
00930                             Found = TRUE;
00931                         }
00932                     }
00933 
00934                     if(EPSFile->eof())
00935                         goto EPSError;
00936                 }
00937                 
00938                 // get the ] off the stack
00939                 EPSCommand Ignored;
00940                 Stack.PopCmd(&Ignored);
00941 
00942                 // empty it...
00943                 Stack.DeleteAll ();
00944                 InColours = FALSE;
00945             }
00946             else
00947             {
00948                 // probably a font type thingy - empty the stack including commands
00949                 Stack.DeleteAll ();
00950             }
00951             break;
00952 
00953         case EPSC_newcmykcustomcolor:
00954             // OK, here's a named colour... add it to those known
00955             {
00956                 // discard some random thingy
00957                 if(!Stack.Discard())
00958                     goto EPSError;
00959             
00960                 // get the name
00961                 String_64 ColourName;
00962                 if(!Stack.Pop(&ColourName))
00963                     goto EPSError;
00964 
00965                 // get the components
00966                 double C, M, Y, K;
00967                 if(!Stack.Pop(&K) ||
00968                         !Stack.Pop(&Y) ||
00969                         !Stack.Pop(&M) ||
00970                         !Stack.Pop(&C))
00971                     goto EPSError;
00972 
00973                 // make the new colour
00974                 ColourCMYK Colour;
00975                 Colour.Cyan = C;
00976                 Colour.Magenta = M;
00977                 Colour.Yellow = Y;
00978                 Colour.Key = K;
00979 
00980                 // add it
00981                 if(!pNewColours->AddColour(&ColourName, &Colour))
00982                     goto NoMemory;
00983 
00984                 // add it to the list of colours
00985                 // this is a bit of a bodge, but never mind. Shouldn't be that bad.
00986                 IndexedColour *TheNewColour = pNewColours->GetColour(ColourName);
00987 
00988                 if(TheNewColour == 0)
00989                     goto NoMemory;
00990 
00991                 // add it to the list of colours
00992                 // enough space?
00993                 if((ColourArrayEntries + 1) >= ColourArraySize)
00994                 {
00995                     TRACEUSER( "Ben", _T("Extening colour array\n"));
00996                     IndexedColour **NewPtr = (IndexedColour **)CCRealloc(ColourArray, (ColourArraySize + FHEF_COLOURARRAY_CHUNK) * sizeof(IndexedColour *));
00997 
00998                     if(NewPtr == 0)
00999                         goto NoMemory;
01000 
01001                     ColourArray = NewPtr;
01002                     ColourArraySize += FHEF_COLOURARRAY_CHUNK;
01003                 }
01004 
01005                 // add
01006                 ColourArray[ColourArrayEntries] = TheNewColour;
01007                 ColourArrayEntries++;
01008             }
01009             break;
01010 
01011         // ignore text stuff
01012         case EPSC_makesetfont:
01013             if(!Stack.DiscardArray())
01014                 goto EPSError;
01015             if(!Stack.Discard(1))
01016                 goto EPSError;
01017             InText = TRUE;
01018             break;
01019 
01020         case EPSC_ts:
01021             if(!Stack.Discard(6))
01022                 goto EPSError;
01023             break;
01024 
01025         case EPSC_stob:
01026         case EPSC_sts:
01027             Stack.DeleteAll ();
01028             InText = FALSE;
01029             break;
01030                 
01031         default:
01032             // Token not understood - pass on to base class
01033             return EPSFilter::ProcessToken();
01034     }
01035 
01036 
01037     // No errors encountered while parsing this token and its operands.
01038     return TRUE;
01039     
01040     
01041     // Error handlers:
01042 EPSError:
01043     HandleEPSError();
01044     return FALSE;
01045 
01046 NoMemory:
01047     HandleNoMemory();
01048     return FALSE;
01049 }

BOOL FreeHandEPSFilter::RemoveLastSubPathIfNotUnique Path pIPath  )  [private]
 

Removes the last subpath from a path if an sub path with it's exact coords already exists.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/06/95
Returns:
error flag

Definition at line 1346 of file freeeps.cpp.

01347 {
01348     // get coord arrays
01349     INT32 NCoords = pIPath->GetNumCoords();
01350     DocCoord *Coords = pIPath->GetCoordArray();
01351     PathVerb *Verbs = pIPath->GetVerbArray();
01352 
01353     // find the last moveto
01354     INT32 LastMoveTo = -1;
01355     INT32 c;
01356 
01357     for(c = 0; c < NCoords; c++)
01358     {
01359         if((Verbs[c] & ~PT_CLOSEFIGURE) == PT_MOVETO)
01360         {
01361             LastMoveTo = c;
01362         }
01363     }
01364 
01365     // check that there is a last moveto and it's not the first coord...
01366     if(LastMoveTo == -1 || LastMoveTo == 0)
01367         return TRUE;            // nothing more to do
01368     
01369     // go through the coords matching subpaths...
01370     for(c = 0; c < LastMoveTo; c++)
01371     {
01372         if((Verbs[c] & ~PT_CLOSEFIGURE) == PT_MOVETO)
01373         {
01374             // found a moveto... compare the subpaths
01375             INT32 n = 0;
01376 
01377             while(((Verbs[c+n] & ~PT_CLOSEFIGURE) == (Verbs[LastMoveTo+n] & ~PT_CLOSEFIGURE)) && (Coords[c+n] == Coords[LastMoveTo+n]))
01378             {
01379                 // this was ok... is the next a moveto and the subpath the right length?
01380 
01381                 if((LastMoveTo+n+1) == NCoords)
01382                 {
01383                     // yes, delete and return
01384                     return pIPath->DeleteFromElement(LastMoveTo);
01385                 }
01386                 
01387                 n++;
01388             }
01389         }
01390     }
01391 
01392     return TRUE;
01393 }

BOOL FreeHandEPSFilter::RestoreCurrentFill  )  [private]
 

restores the current fill attribute from the stored one

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
02/06/95
Returns:
error flag
See also:
EPSFilter::ProcessToken

Definition at line 1252 of file freeeps.cpp.

01253 {
01254     if(OldFill == 0)
01255         return TRUE;            // no saved state
01256 
01257     // delete the old attribute
01258     if(CurrentAttrs[ATTR_FILLGEOMETRY].pAttr != 0)
01259         delete CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
01260 
01261     // make the current one the old one
01262     CurrentAttrs[ATTR_FILLGEOMETRY].pAttr = OldFill;
01263 
01264     // mark this as used so it doesn't get deleted
01265     OldFill = 0;
01266     
01267     return TRUE;
01268 }

BOOL FreeHandEPSFilter::SaveCurrentFill  )  [private]
 

stores the current fill attribute

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
02/06/95
Returns:
error flag
See also:
EPSFilter::ProcessToken

Definition at line 1218 of file freeeps.cpp.

01219 {
01220     // get rid of any stored fill
01221     if(OldFill != 0)
01222         delete OldFill;
01223 
01224     // create a copy of the current fill attribute
01225     CCRuntimeClass* ObjectType = CurrentAttrs[ATTR_FILLGEOMETRY].pAttr->GetRuntimeClass();
01226     AttributeValue* AttrClone = (AttributeValue*)ObjectType->CreateObject();
01227 
01228     if(AttrClone == 0)
01229         return FALSE;
01230     
01231     AttrClone->SimpleCopy(CurrentAttrs[ATTR_FILLGEOMETRY].pAttr);
01232 
01233     // set the old fill pointer to the nice clone we've made
01234     OldFill = AttrClone;
01235 
01236     return TRUE;
01237 }

BOOL FreeHandEPSFilter::ValidateGroup Node pGroup  )  [protected, virtual]
 

validates a group created by the filter. As all objects have a group around then, this removes groups which only have one entry.

Author:
Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
Date:
02/06/95
Returns:
error flag

Reimplemented from EPSFilter.

Definition at line 1282 of file freeeps.cpp.

01283 {
01284     ERROR2IF(pGroup == 0, FALSE, "Group passed to validateGroup is null");
01285 
01286     Node *pFirstChild = pGroup->FindFirstChild();
01287 
01288     ERROR2IF(pFirstChild == 0, FALSE, "Group without children passed to ValidateGroup - should have been deleted by EndGroup"); 
01289 
01290     if(pFirstChild->FindNext() == 0)
01291     {
01292         // there was only one object - delete this group.
01293 
01294         // if pFirstNodeInRange is this node, set it to the child
01295         if(pFirstNodeInRange == pGroup)
01296             pFirstNodeInRange = pFirstChild;
01297         
01298         // move the child to the parent of the group
01299         if (!ImportInfo.pOp->DoMoveNode(pFirstChild, pNode, LASTCHILD))
01300             return FALSE;
01301 
01302         // see EPSFilter::EndGroup for the reason why it's hidden rather than deleted
01303         if (!ImportInfo.pOp->DoHideNode(pGroup, TRUE))
01304             return FALSE;
01305 
01306     }
01307 
01308     return TRUE;
01309 }


Member Data Documentation

IndexedColour** FreeHandEPSFilter::ColourArray [private]
 

Definition at line 155 of file freeeps.h.

INT32 FreeHandEPSFilter::ColourArrayEntries [private]
 

Definition at line 156 of file freeeps.h.

INT32 FreeHandEPSFilter::ColourArraySize [private]
 

Definition at line 157 of file freeeps.h.

BOOL FreeHandEPSFilter::ComplexPathMode [private]
 

Definition at line 158 of file freeeps.h.

BOOL FreeHandEPSFilter::DoingGradFill [private]
 

Definition at line 150 of file freeeps.h.

CommandMap FreeHandEPSFilter::FHCommands [static, private]
 

Definition at line 140 of file freeeps.h.

BOOL FreeHandEPSFilter::HadFirstOfComplexPath [private]
 

Definition at line 159 of file freeeps.h.

BOOL FreeHandEPSFilter::HadhToken [private]
 

Definition at line 149 of file freeeps.h.

BOOL FreeHandEPSFilter::InColours [private]
 

Definition at line 152 of file freeeps.h.

BOOL FreeHandEPSFilter::InText [private]
 

Definition at line 153 of file freeeps.h.

AttributeValue* FreeHandEPSFilter::OldFill [private]
 

Definition at line 151 of file freeeps.h.

NodePath* FreeHandEPSFilter::pLastPathSeen [private]
 

Definition at line 160 of file freeeps.h.

ImportedColours* FreeHandEPSFilter::pNewColours [private]
 

Definition at line 154 of file freeeps.h.


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