ai5_eps.cpp

Go to the documentation of this file.
00001 // $Id: ai5_eps.cpp 1314 2006-06-14 08:58:56Z builder1 $
00002 // Implementation of Adobe Illustrator 5 EPS filter.
00003 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00004 ================================XARAHEADERSTART===========================
00005  
00006                Xara LX, a vector drawing and manipulation program.
00007                     Copyright (C) 1993-2006 Xara Group Ltd.
00008        Copyright on certain contributions may be held in joint with their
00009               respective authors. See AUTHORS file for details.
00010 
00011 LICENSE TO USE AND MODIFY SOFTWARE
00012 ----------------------------------
00013 
00014 This file is part of Xara LX.
00015 
00016 Xara LX is free software; you can redistribute it and/or modify it
00017 under the terms of the GNU General Public License version 2 as published
00018 by the Free Software Foundation.
00019 
00020 Xara LX and its component source files are distributed in the hope
00021 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00022 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00023 See the GNU General Public License for more details.
00024 
00025 You should have received a copy of the GNU General Public License along
00026 with Xara LX (see the file GPL in the root directory of the
00027 distribution); if not, write to the Free Software Foundation, Inc., 51
00028 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00029 
00030 
00031 ADDITIONAL RIGHTS
00032 -----------------
00033 
00034 Conditional upon your continuing compliance with the GNU General Public
00035 License described above, Xara Group Ltd grants to you certain additional
00036 rights. 
00037 
00038 The additional rights are to use, modify, and distribute the software
00039 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00040 library and any other such library that any version of Xara LX relased
00041 by Xara Group Ltd requires in order to compile and execute, including
00042 the static linking of that library to XaraLX. In the case of the
00043 "CDraw" library, you may satisfy obligation under the GNU General Public
00044 License to provide source code by providing a binary copy of the library
00045 concerned and a copy of the license accompanying it.
00046 
00047 Nothing in this section restricts any of the rights you have under
00048 the GNU General Public License.
00049 
00050 
00051 SCOPE OF LICENSE
00052 ----------------
00053 
00054 This license applies to this program (XaraLX) and its constituent source
00055 files only, and does not necessarily apply to other Xara products which may
00056 in part share the same code base, and are subject to their own licensing
00057 terms.
00058 
00059 This license does not apply to files in the wxXtra directory, which
00060 are built into a separate library, and are subject to the wxWindows
00061 license contained within that directory in the file "WXXTRA-LICENSE".
00062 
00063 This license does not apply to the binary libraries (if any) within
00064 the "libs" directory, which are subject to a separate license contained
00065 within that directory in the file "LIBS-LICENSE".
00066 
00067 
00068 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00069 ----------------------------------------------
00070 
00071 Subject to the terms of the GNU Public License (see above), you are
00072 free to do whatever you like with your modifications. However, you may
00073 (at your option) wish contribute them to Xara's source tree. You can
00074 find details of how to do this at:
00075   http://www.xaraxtreme.org/developers/
00076 
00077 Prior to contributing your modifications, you will need to complete our
00078 contributor agreement. This can be found at:
00079   http://www.xaraxtreme.org/developers/contribute/
00080 
00081 Please note that Xara will not accept modifications which modify any of
00082 the text between the start and end of this header (marked
00083 XARAHEADERSTART and XARAHEADEREND).
00084 
00085 
00086 MARKS
00087 -----
00088 
00089 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00090 designs are registered or unregistered trademarks, design-marks, and/or
00091 service marks of Xara Group Ltd. All rights in these marks are reserved.
00092 
00093 
00094       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00095                         http://www.xara.com/
00096 
00097 =================================XARAHEADEREND============================
00098  */
00099 
00100 #include "camtypes.h"
00101 
00102 #include "ai_eps.h"
00103 #include "ai5_eps.h"
00104 #include "ai_epsrr.h"
00105 #include <sstream>
00106 #include <stdio.h>
00107 
00108 #include "nodepath.h"
00109 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "tim.h"
00111 //#include "nev.h"
00112 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "ccdc.h"
00114 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "page.h"
00116 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 #include "opbevel.h"
00119 #include "progress.h"        
00120 #include "ai_grad.h"        
00121 #include "ai_bmp.h"
00122 #include "ai_layer.h"  
00123 #include "swffiltr.h"
00124 #include "layer.h"
00125 
00126 DECLARE_SOURCE("$Revision");
00127 
00128 #define new CAM_DEBUG_NEW
00129 
00130 CC_IMPLEMENT_DYNAMIC(AI5EPSFilter, AIEPSFilter)
00131 
00132 // This is the array of AI EPS command/keyword names.
00133 CommandMap AI5EPSFilter::AI5Commands[] =
00134 {
00135     // Graduated fills
00136     { EPSC_Bd,      _T("Bd")},
00137     { EPSC_Bm,      _T("Bm")},
00138     { EPSC_Bc,      _T("Bc")},
00139     { EPSC__Bs,     _T("%_Bs")},
00140     { EPSC__BS,     _T("%_BS")},
00141     { EPSC__Br,     _T("%_Br")},
00142     { EPSC_BD,      _T("BD")},
00143     { EPSC_Bg,      _T("Bg")},
00144     { EPSC_Bb,      _T("Bb")},
00145     { EPSC_BB,      _T("BB")},
00146     { EPSC_Bh,      _T("Bh")},
00147     { EPSC_HexStart,    _T("<")},
00148     { EPSC_HexEnd,  _T(">")},
00149 
00150     // Layer stuff
00151     { EPSC_Lb,      _T("Lb")},
00152     { EPSC_LB,      _T("LB")},
00153     { EPSC_Ln,      _T("Ln")},
00154 
00155     // Path tweaks
00156     { EPSC_Ap,      _T("Ap")},
00157     { EPSC_Ar,      _T("Ar")},
00158     { EPSC_XR,      _T("XR")},
00159     
00160     // bitmaps
00161     { EPSC_XI,      _T("XI")},
00162     { EPSC_XF,      _T("XF")},
00163     { EPSC_XG,      _T("XG")},
00164     { EPSC_Xh,      _T("Xh")},
00165     { EPSC_XH,      _T("XH")},
00166 
00167     // unknown
00168     { EPSC_XP,      _T("XP")},
00169 
00170     // object tags
00171     { EPSC_XT,      _T("XT")},
00172 
00173     // spurious
00174     { EPSC_Xm,      _T("Xm")},
00175 
00176     // RGB Colours
00177     { EPSC_Xa,      _T("Xa")},
00178     { EPSC_XA,      _T("XA")},
00179     { EPSC_Xx,      _T("Xx")},
00180     { EPSC_XX,      _T("XX")},
00181 
00182     // Sentinel
00183     { EPSC_Invalid, _T("Invalid")}
00184 };
00185 
00186 /********************************************************************************************
00187 
00188 >   AI5EPSFilter::AI5EPSFilter()
00189 
00190     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00191     Created:    28/10/93
00192     Purpose:    Constructor for an AI5EPSFilter object.  The object should be 
00193                 initialised before use.
00194     SeeAlso:    EPSFilter::Init
00195 
00196 ********************************************************************************************/
00197 
00198 AI5EPSFilter::AI5EPSFilter() :
00199     mpGradientProc(0),
00200     mpBitmapProc(0),
00201     mpLayerProc ( 0 ),
00202     mbReadingGradFill(FALSE),
00203     mbReadingBitmap(FALSE)
00204 {
00205     // Set up filter descriptions.
00206     FilterNameID = _R(IDT_AI5EPS_FILTERNAME);
00207     FilterInfoID = _R(IDT_AI5EPS_FILTERINFO);
00208     ImportMsgID  = _R(IDT_IMPORTMSG_AI5);
00209 
00210     FilterID = FILTERID_AI5EPS;
00211 
00212     // Import only for Illustrator 5.
00213     Flags.CanImport = TRUE;
00214     Flags.CanExport = FALSE;
00215 }
00216 
00217 /********************************************************************************************
00218 
00219 >   BOOL AI5EPSFilter::Init()
00220 
00221     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00222     Created:    28/02/94
00223     Returns:    TRUE if the filter was initialised ok, FALSE otherwise.
00224     Purpose:    Initialise an AI5EPSFilter object.
00225     Errors:     Will fail if not enough memory to initialise the EPS stack.
00226     SeeAlso:    EPSStack
00227 
00228 ********************************************************************************************/
00229 
00230 BOOL AI5EPSFilter::Init()
00231 {
00232     // Get the OILFilter object
00233     pOILFilter = new AI5EPSOILFilter(this);
00234     if (pOILFilter == NULL)
00235         return FALSE;
00236 
00237     // Load the description strings
00238     FilterName.Load(FilterNameID);
00239     FilterInfo.Load(FilterInfoID);
00240 
00241     // All ok
00242     return TRUE;
00243 }
00244 
00245 /********************************************************************************************
00246 
00247 >   INT32 AI5EPSFilter::EPSHeaderIsOk(ADDR pFileHeader, UINT32 HeaderSize)
00248 
00249     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00250     Created:    28/02/94
00251     Returns:    TRUE if the header is ok and import should proceed, FALSE if not.
00252     Purpose:    Checks to see if the EPS comment headers specify that this is an AI
00253                 generated EPS file, as required.
00254 
00255 ********************************************************************************************/
00256 
00257 INT32 AI5EPSFilter::EPSHeaderIsOk(ADDR pFileHeader, UINT32 HeaderSize)
00258 {
00259     UINT32  Lines   = 0;
00260     TCHAR   *Buffer = NULL;
00261 
00262     // !PS-Adobe line is ok - check creator line...
00263     CCMemTextFile HeaderFile ( reinterpret_cast<char *> ( pFileHeader ), HeaderSize );
00264 
00265     if( HeaderFile.IsMemFileInited () == FALSE || HeaderFile.InitLexer () == FALSE )
00266     {
00267         HeaderFile.close();
00268         return 0;
00269     }
00270 
00271     // Graeme (28/6/00) - Adobe have changed their file format, and so the first line can
00272     // now be a %PDF directive. Therefore look for this directive in the first twenty
00273     // lines.
00274     while ( ( Lines < 100 ) && !HeaderFile.eof () )
00275     {
00276         // Get the current line from the file.
00277         HeaderFile.GetLineToken();
00278         Buffer = const_cast<TCHAR *> ( HeaderFile.GetTokenBuf () );
00279 
00280         // Ensure that it's OK.
00281         ERROR2IF(Buffer == 0, 0, "Returned buffer from lex file == 0");
00282 
00283         // Increment the line counter.
00284         Lines++;
00285 
00286         if (camStrncmp(Buffer, _T("%!PS-Adobe"), 10) == 0)
00287         {
00288             // Now find the %%Creator string.
00289             while ((Lines < 100) && !HeaderFile.eof())
00290             {
00291                 HeaderFile.GetLineToken();
00292                 Buffer = const_cast<TCHAR *> ( HeaderFile.GetTokenBuf() );
00293                 ERROR2IF(Buffer == 0, 0, "Returned buffer from lex file == 0");
00294                 Lines++;
00295 
00296                 // Return TRUE if this file was created by Illustrator, or has been exported
00297                 // in Illustrator format.
00298                 if (camStrncmp(Buffer, _T("%%Creator: Adobe Illustrator(TM) 5"), 34) == 0)
00299                 {
00300                     // We definitely want this.
00301                     HeaderFile.close();
00302                     return 10;
00303                 }
00304 
00305                 if (camStrncmp(Buffer, _T("%%Creator:"), 10) == 0)
00306                 {
00307                     // Found the creator line - does it contain the word Illustrator?
00308                     if (camStrstr( (const TCHAR*)Buffer, _T("Illustrator(TM) 5")) != NULL)
00309                     {
00310                         HeaderFile.close();
00311                         return 10;
00312                     }
00313                     // we'll accept version 7.0 as well
00314                     else if ((camStrstr( (const TCHAR*)Buffer, _T("Illustrator(TM) 7")) != NULL) ||
00315                              (camStrstr( (const TCHAR*)Buffer, _T("Illustrator(R) 7")) != NULL))
00316                     {
00317                         HeaderFile.close();
00318                         return 10;
00319                     }
00320                     // Catch FreeHand generated EPS files.
00321                     else if (camStrstr( (const TCHAR*)Buffer, _T("FreeHand")) != NULL)
00322                     {
00323                         HeaderFile.close();
00324                         return 8;
00325                     }
00326                     else
00327                         break;
00328                 }
00329 
00330                 // If we find the compression token then stop the search as we don't want to
00331                 // start looking in the compressed data!
00332                 if (camStrncmp(Buffer, _T("%%Compression:"), 14)==0)
00333                     break;
00334             }
00335 
00336             // Remember to close the file before returning.
00337             HeaderFile.close();
00338 
00339             // Didn't find a suitable Creator line, but the EPS line was ok, so return
00340             // that we're interested, but not sure.
00341             return 5;
00342         }
00343 
00344         // If we find the compression token then stop the search as we don't want to start
00345         // looking in the compressed data!
00346         if (camStrncmp(Buffer, _T("%%Compression:"), 14)==0)
00347             break;
00348     }
00349 
00350     // Remember to close the file before returning.
00351     HeaderFile.close();
00352     
00353     // This file type isn't suitable.
00354     return 0;
00355 }
00356 
00357 /********************************************************************************************
00358 
00359 >   BOOL AI5EPSFilter::PrepareToImport()
00360 
00361     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00362     Created:    12/08/94
00363     Returns:    TRUE if successfully prepared to import;
00364                 FALSE if not.
00365     Purpose:    Set up the stuff ready for adding gradient fills from AI 5 files.
00366     SeeAlso:    EPSFilter::PrepareToImport
00367 
00368 ********************************************************************************************/
00369 
00370 BOOL AI5EPSFilter::PrepareToImport()
00371 {
00372     mbReadingGradFill   = FALSE;
00373     mbReadingBitmap     = FALSE;
00374 
00375     return AIEPSFilter::PrepareToImport();
00376 }
00377 
00378 
00379 /********************************************************************************************
00380 
00381 >   void AI5EPSFilter::CleanUpAfterImport(BOOL Successful)
00382 
00383     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00384     Created:    12/08/94
00385     Inputs:     Successful - TRUE if the import was successful.
00386     Purpose:    Cleans up our list of AI5 gradient fill definitions, and then calls the base
00387                 class to perform usual clean up.
00388     SeeAlso:    EPSFilter::CleanUpAfterImport
00389 
00390 ********************************************************************************************/
00391 
00392 void AI5EPSFilter::CleanUpAfterImport(BOOL Successful)
00393 {
00395     //  free the space occupied by the processors
00397     delete mpGradientProc;
00398     mpGradientProc = NULL;
00399 
00400     delete mpBitmapProc;
00401     mpBitmapProc = NULL;
00402 
00403     // Call base class to tidy up
00404     AIEPSFilter::CleanUpAfterImport(Successful);
00405 }
00406 
00407 /********************************************************************************************
00408 
00409 >   void AI5EPSFilter::LookUpToken()
00410 
00411     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00412     Created:    25/02/94
00413     Returns:    TRUE if the token is an AI EPS token; FALSE if not.
00414     Purpose:    Compare the current token against the AI keywords to see if it is
00415                 one of them.
00416     SeeAlso:    EPSFilter::LookUpToken; EPSFilter::DecodeToken
00417 
00418 ********************************************************************************************/
00419 
00420 void AI5EPSFilter::LookUpToken()
00421 {
00422     // Check to see if it is a keyword - cycle through the array of keyword names and
00423     // compare against our token (could use a hash table?)
00424     INT32 i = 0;
00425     while (AI5Commands[i].Cmd != EPSC_Invalid)
00426     {
00427         if (camStrcmp(TokenBuf, AI5Commands[i].CmdStr) == 0)
00428         {
00429             // Found the token - set the token variable and return success
00430             Token = AI5Commands[i].Cmd;
00431             return;
00432         }
00433         // Try next command
00434         i++;
00435     }
00436 
00437     // Did not find this token - pass on to base class.
00438     AIEPSFilter::LookUpToken();
00439 }
00440 
00441 /********************************************************************************************
00442 
00443 >   BOOL AI5EPSFilter::ProcessToken()
00444 
00445     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00446     Created:    25/02/94
00447     Returns:    TRUE if token understood and processed ok, FALSE if not.
00448     Purpose:    Processes EPS tokens that are not part of the standard Illustrator set, or
00449                 which need to be handled differently to the standard Illustrator meanings.
00450                 i.e. this is the function that handles all the AI EPS operators.
00451     Errors:     Syntax error in EPS, Out of memory.
00452     SeeAlso:    EPSFilter::ProcessToken
00453 
00454 ********************************************************************************************/
00455 
00456 BOOL AI5EPSFilter::ProcessToken()
00457 {
00458     // Variables used to extract operands from the stack
00459     // (ChrisG 12/12/00) these variables are used when processing the RGB colour commands (Xa, 
00460     //  XA, Xx and XX)
00461     INT32       red = 0;
00462     INT32       green = 0;
00463     INT32       blue = 0;
00464     DocColour   DocCol;
00465     TintType    Tint = TINT_NONE;
00466     FIXEDPOINT  TintVal;
00467     String_64   ColName;
00468 
00469     // Decode the command, and execute it...
00470     switch (Token)
00471     {
00472         case EPSC_Bd:
00473         {
00474             if ( !mpGradientProc || !mpGradientProc->DecodeBd( *this ) )
00475             {
00476                 goto EPSError;
00477             }
00478             break;
00479         }
00480 
00481         case EPSC_Bm:
00482         case EPSC_Bc:
00483             // "The two imaging operators specific to gradients are Bm (gradient matrix) and
00484             // Bc (gradient cap). Although required for imaging, these operators are not
00485             // essential to Adobe Illustrator file formats."
00486             if (!Stack.Discard(6))
00487                 goto EPSError;
00488             break;
00489 
00490         case EPSC__Bs:
00491         case EPSC__BS:
00492         {
00493             if ( !mpGradientProc || !mpGradientProc->DecodeBS( *this ) )
00494             {
00495                 goto EPSError;
00496             }
00497             break;
00498         }
00499 
00500         case EPSC_BD:
00501         {
00502             // The end of the definition - lose the rampant '[' from the input stream.
00503             EPSCommand Cmd;
00504             if (!Stack.PopCmd(&Cmd) || (Cmd != EPSC_ArrayStart))
00505                 goto EPSError;
00506             break;
00507         }
00508 
00509         case EPSC_Bg:
00510         {
00511             // A grad fill attribute is being used...
00512 
00513             // First get rid of the strange "1 0 0 1 0 0" bit wot I don't understand yet.
00514             if (!Stack.Discard(6))
00515                 goto EPSError;
00516 
00517             // Get the Start point, angle, and length of the gradient fill line.
00518             DocCoord StartPoint;
00519             double Angle, Length;
00520             if (!Stack.Pop(&Length) || 
00521                 !Stack.Pop(&Angle)  ||
00522                 !Stack.PopCoordPair(&StartPoint))
00523                 goto EPSError;
00524 
00525             // Get the fillname - we need this to get the rest of the fill details.
00526             // (Also lose the random number before it that I don't understand yet)
00527             String_64 FillName;
00528             if (!Stack.Pop(&FillName) || !Stack.Discard())
00529                 goto EPSError;
00530 
00531             // Work out what all this means!
00532             DecodeAI5GradFill(StartPoint, Angle, Length, FillName);
00533 
00534             break;
00535         }
00536 
00537         case EPSC_Bb:
00538             // begin gradient instance
00539             TRACE(_T("Ignoring token Bb\n"));
00540             break;
00541 
00542         case EPSC__Br:
00543         {
00544             // gradient ramp
00545             TRACE(_T("Ignoring token %%_Br\n"));
00546             //  determine the number of tokens we can discard
00547             INT32 rampType = 0;
00548             if (!Stack.Pop(&rampType))
00549                 goto EPSError;
00550 
00551             static const UINT32 sNumToDiscard[] =
00552             {
00553                 1, 4, 5, 6, 7, 8, 9
00554             };
00555 
00556             if ( rampType < 0 || rampType > 6 )
00557                 goto EPSError;
00558 
00559             if (!Stack.Discard(sNumToDiscard[rampType]))
00560                 goto EPSError;
00561 
00562             break;
00563         }
00564 
00565         case EPSC_Lb:
00566             // Process the layer.
00567             if ( !DecodeLayer () )
00568             {
00569                 TRACE( _T("There's been a problem with a layer!") );
00570             }
00571 
00572             break;
00573 
00574         case EPSC_Ln:
00575             // Decode the layer's name.
00576             if ( mpLayerProc == NULL || !mpLayerProc->DecodeLn ( *this ) )
00577             {
00578                 goto EPSError;
00579             }
00580 
00581             break;
00582 
00583         case EPSC_LB:
00584             // End layer
00585             if ( mpLayerProc == NULL || !mpLayerProc->DecodeLB ( *this ) )
00586             {
00587                 goto EPSError;
00588             }
00589             else
00590             {
00591                 delete mpLayerProc;
00592                 mpLayerProc = NULL;
00593             }
00594             break;
00595 
00596         case EPSC_Bh:
00597             // gradient highlights
00598             if ( !mpGradientProc || !mpGradientProc->DecodeBh( *this ) )
00599             {
00600                 goto EPSError;
00601             }
00602             break;
00603 
00604         case EPSC_Ap:
00605             // path centre point
00606             TRACE(_T("Ignoring token Ap\n"));
00607             if (!Stack.Discard())
00608                 goto EPSError;
00609             break;
00610 
00611         case EPSC_Ar:
00612             // path resolution
00613             TRACE(_T("Ignoring token Ar\n"));
00614             if (!Stack.Discard())
00615                 goto EPSError;
00616             break;
00617 
00618         case EPSC_XR:
00619             //  fill rule
00620             //  0 = use non-zero winding number fill rule
00621             //  1 = use even-odd fill rule
00622             TRACE(_T("Ignoring token XR\n"));
00623             if (!Stack.Discard())
00624                 goto EPSError;
00625             break;
00626 
00627 
00628         case EPSC_BB:
00629             // end gradient instance
00630             TRACE(_T("Ignoring token BB\n"));
00631             if (!Stack.Discard())
00632                 goto EPSError;
00633             break;
00634 
00635         case EPSC_Xm:
00636             // a b c d x y Xm 
00637             //  The Xm operator and its parameters are additional information written out as
00638             // part of a linear gradient definition. 
00639             TRACE(_T("Ignoring token Xm\n"));
00640             if (!Stack.Discard(6))
00641                 goto EPSError;
00642             break;
00643 
00644         case EPSC_XT:
00645             // object tag
00646             // potential tags to process include /AdobeURL
00647             TRACE(_T("Ignoring token XT\n"));
00648             if (!Stack.Discard(2))
00649                 goto EPSError;
00650             break;
00651 
00652         case EPSC_XI:
00653             // image definition
00654             if ( !mpBitmapProc || !mpBitmapProc->DecodeXI( *this ) )
00655                 goto EPSError;
00656             break;
00657 
00658         case EPSC_XG:
00659             // image (via path) operator
00660             // we can ignore this
00661             if (!Stack.Discard(2))
00662                 goto EPSError;
00663             break;
00664 
00665         case EPSC_HexStart:
00666             //  the lexical analyzer of lexfile doesn't process this so we have to
00667             //  it's the start of a hex string. 
00668             //  if we're reading a %_Br token we can ignore it
00669             if ( mbReadingGradFill )
00670                 //  push a bogus hex value onto the stack so that %_Br can read it
00671                 if ( !Stack.Push( INT32(0xffffffff) ) )
00672                     goto EPSError;
00673                 IgnoreHexData();
00674             break;
00675 
00676         case EPSC_HexEnd:
00677             //  the lexical analyzer of lexfile doesn't process this so we have to
00678             if ( mbReadingGradFill )
00679                 break;
00680 
00681         case EPSC_Xh:
00682             // The Xh token re-iterates information from the XI image definition.
00683             // As a result, we can ignore it.
00684             TRACE(_T("Ignoring token Xh\n"));
00685             if (!Stack.Discard(2))
00686             {
00687                 goto EPSError;
00688             }
00689             else
00690             {
00691                 // Graeme (13/6/00) - Reduced the strength of the error checking. It
00692                 // shouldn't really matter for this operator since it's ignored.
00693                 Stack.DiscardArray();
00694             }
00695         break;
00696 
00697         case EPSC_XH:
00698             // End of bitmap declaration, but this token is unused by Camelot.
00699             TRACE(_T("Ignoring token XH\n"));
00700             break;
00701 
00702         case EPSC_XP:
00703             // don't know what this is but we can ignore it
00704             TRACE(_T("Ignoring unknown token XP\n"));
00705             if (!Stack.Discard(4))
00706                 goto EPSError;
00707             break;
00708 
00709 
00710             // RGB Custom colours (fill, stroke)
00711         case EPSC_Xx:
00712         case EPSC_XX:
00713             Tint = TINT_ILLUSTRATOR;
00714 
00715             // remove 'type' info - we only support RGB versions.
00716             if (!Stack.Discard (1))
00717                 goto EPSError;
00718 
00719             // RGB standard colours (fill, stroke)
00720         case EPSC_Xa:
00721         case EPSC_XA:
00722 
00723             // Set current line/fill colour (CMYK)
00724             if (Stack.PopColourRGB(&red, &green, &blue, Tint, &TintVal, &ColName))
00725             {
00726                 GetEPSColourRGB(&DocCol, red, green, blue, Tint, TintVal, &ColName);
00727 
00728                 // Remember this colour for future objects
00729                 if ((Token == EPSC_Xa) || (Token == EPSC_Xx))
00730                 {
00731                     if (!SetFillColour(DocCol))
00732                         goto EPSError;
00733                 }
00734                 else
00735                 {
00736                     if (!SetLineColour(DocCol))
00737                         goto EPSError;
00738                 }
00739             }
00740             else    
00741                 // Invalid colour operands
00742                 goto EPSError;
00743 
00744             break;
00745 
00746         default:
00747             // Token not understood - pass on to base class
00748             return AIEPSFilter::ProcessToken();
00749     }
00750 
00751 
00752     // No errors encountered while parsing this token and its operands.
00753     return TRUE;
00754     
00755     
00756     // Error handlers:
00757 EPSError:
00758     HandleEPSError();
00759     return FALSE;
00760 }
00761 
00762 
00763 /********************************************************************************************
00764 
00765 >   void AI5EPSFilter::IgnoreHexData()
00766 
00767     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00768     Created:    24/03/00
00769     Purpose:    Skips hex data in the import stream (used for %_Br)
00770 
00771 ********************************************************************************************/
00772 
00773 BOOL AI5EPSFilter::IgnoreHexData()
00774 {
00775     while (!EPSFile->eof())
00776     {
00777         // Get the next token from the file
00778         if (!EPSFile->GetHexToken())
00779             return TRUE;
00780 
00781         INT32 CharsRead = EPSFile->GetCharsRead();
00782 
00783         if (CharsRead > (LastProgressUpdate + 2048))
00784         {
00785             if (!ContinueSlowJob(CharsRead))
00786             {
00787                 // Abort operation - make sure nodes are deleted and not added to the tree.
00788                 ERROR(_R(IDT_IMPORT_USERABORT), FALSE);
00789             }
00790             else
00791             {
00792                 LastProgressUpdate = CharsRead;
00793             }
00794         }
00795     }
00796 
00797     return FALSE;
00798 }
00799 
00800 
00801 /********************************************************************************************
00802 
00803 >   void AI5EPSFilter::DecodeAI5GradFill(const DocCoord& StartPoint, 
00804                                      double Angle, 
00805                                      double Length, 
00806                                      const String_64& FillName)
00807 
00808     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00809     Created:    12/08/94
00810     Inputs:     StartPoint - the start of the grad fill arrow.
00811                 Angle      - the angle of the grad fill arrow.
00812                 Length     - the length of the grad fill arrow.
00813                 FillName   - the gradient fill to use (i.e. what colours and type)
00814     Purpose:    Given the AI5 format infor on a grad fill, convert it into a Camelot
00815                 grad fill, and set it as the current attribute.
00816     SeeAlso:    AI5EPSFilter::ProcessFilterComment
00817 
00818 ********************************************************************************************/
00819 
00820 void AI5EPSFilter::DecodeAI5GradFill(const DocCoord& StartPoint, 
00821                                      double Angle, 
00822                                      double Length, 
00823                                      const String_64& FillName)
00824 {
00825     if ( !mpGradientProc ) 
00826         return;
00827     // First find this named gradient fill
00828     AI5Gradient* pGradient = mpGradientProc->FindGradient( FillName );
00829 
00830     // Did we find it?
00831     ENSURE(pGradient != NULL, "Could not find named grad fill in AI5 file!");
00832     if (pGradient == NULL)
00833         // No - oh dear just pretend we didn't notice and use current fill instead
00834         return;
00835 
00836     // Convert the length into millipoints.
00837     Length *= 1000;
00838 
00839     // Ok - got the named fill; first convert the angle+length into an end-point.
00840     DocCoord EndPoint;
00841     double Radians = (((double) Angle) / 180.0) * PI;
00842     
00843     EndPoint.x = StartPoint.x + (MILLIPOINT) (Length * cos(Radians));
00844     EndPoint.y = StartPoint.y + (MILLIPOINT) (Length * sin(Radians));
00845 
00846     // We appear to have all the info we need - set the gradient fill.
00847     if (pGradient->IsRadial)
00848     {
00849         if ( pGradient->mpHighlight )   // we have a highlight so make it a conical fill
00850         {
00851             SetConicalFill( pGradient->StartColour, pGradient->EndColour,
00852                         StartPoint, EndPoint);
00853         }
00854         SetRadialFill(pGradient->StartColour, pGradient->EndColour,
00855                       StartPoint, EndPoint);
00856     }
00857     else
00858     {
00859         SetLinearFill(pGradient->StartColour, pGradient->EndColour,
00860                       StartPoint, EndPoint);
00861     }
00862 
00864     // if we have only a gradient fill use that instead
00865     //  first get the attribute we just set...
00867 
00868     // Find out which fill attribute to change
00869     AttributeEntry* const pEntry = FillAttr.pAttr ? &FillAttr : &CurrentAttrs[ATTR_FILLGEOMETRY];
00870 
00871     // We've got an attribute - change it.
00872     GradFillAttribute* pAttr = static_cast<GradFillAttribute*>( pEntry->pAttr );
00873 
00874     // (ChrisG 3/4/2001) Added support for importing profiles. 
00875     //
00876     //  If this has a colour ramp, then add it in. If it doesn't, but it has a profile, then
00877     //  set that up instead.
00878     if ( pGradient->mpCurrentRamp &&
00879          pGradient->mpCurrentRamp->GetCount ())
00880     {
00881         pAttr->SetColourRamp( pGradient->mpCurrentRamp );
00882 
00883         // Clean up any old profiling information, so that we make sure that this fill isn't 
00884         //  profiled, as profiling doesn't work with multi-stage fills.
00885         CProfileBiasGain profile;
00886         pAttr->SetProfile (profile);
00887     }
00888     else if (pGradient->midPoint != 0)
00889     {
00890         // Convert profile from the 0 to 100 range into the -1 to +1 range, then set it.
00891         CProfileBiasGain profile = pAttr->GetProfile ();
00892         profile.SetBias (1 - ((double) pGradient->midPoint/50));
00893         pAttr->SetProfile (profile);
00894     }
00895 }
00896 
00897 /********************************************************************************************
00898 
00899 >   BOOL AI5EPSFilter::DecodeLayer ( void )
00900 
00901     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00902     Created:    16/4/00
00903     Inputs:     -  
00904     Returns:    TRUE    - The command was processed.
00905                 FALSE   - It wasn't used by this filter.
00906     Purpose:    Inserts a layer into the tree.
00907 
00908 ********************************************************************************************/
00909 
00910 BOOL AI5EPSFilter::DecodeLayer ( void )
00911 {
00912     // If there's still an active layer, the LB token has been missed out, so throw an EPS
00913     // error message.
00914     if ( mpLayerProc != NULL )
00915     {
00916         return FALSE;
00917     }
00918 
00919     // Create the new layer processor.
00920     mpLayerProc = new AILayerProcessor;
00921 
00922     ERROR2IF( mpLayerProc == NULL, FALSE, "Insufficient memory to create layer processor.");
00923 
00924     // Insert the layer into the tree.
00925     return mpLayerProc->DecodeAI5Lb ( *this );
00926 }
00927 
00928 /********************************************************************************************
00929 
00930 >   BOOL AI5EPSFilter::ProcessFilterComment()
00931 
00932     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00933     Created:    08/04/94
00934     Returns:    TRUE if the comment was processed, 
00935                 FALSE if not used by this filter..
00936     Purpose:    Decodes the EPS comments that specify Illustrator 5 grad fills.
00937 
00938 ********************************************************************************************/
00939 
00940 BOOL AI5EPSFilter::ProcessFilterComment()
00941 {
00942     BOOL ok = TRUE;
00943 
00944     if (camStrncmp(TokenBuf, _T("%AI5_BeginGradient"), 18) == 0)
00945     {
00946         ENSURE(!mbReadingGradFill, "Already reading a grad fill!");
00947 
00948         if ( !mpGradientProc )
00949         {
00950             mpGradientProc = new AIGradientProcessor;
00951             if ( !mpGradientProc )
00952                 ok = FALSE;
00953         }
00954 
00955         if (ok)
00956             ok = mpGradientProc->BeginGradient();
00957 
00958         if (ok)
00959             mbReadingGradFill = TRUE;
00960 
00961         // (this is a (close) copy of the loop in the main importing section).
00962         //  we need to do this because the definition is in the setup header
00963         //  which doesn't pass tokens back
00964         do
00965         {
00966             GetToken();
00967         }
00968         while (mbReadingGradFill && HandleToken() && (!EPSFile->eof()));
00969     
00970         // Put the token back onto the input stream to allow the caller to use it.
00971         EPSFile->UngetToken();
00972     }
00973     else if (camStrncmp(TokenBuf, _T("%AI5_EndGradient"), 16) == 0)
00974     {
00975         ENSURE(mbReadingGradFill, "Not reading a grad fill!");
00976 
00977         if ( mpGradientProc )
00978             ok = mpGradientProc->EndGradient( *this );
00979 
00980         if (ok)
00981             mbReadingGradFill = FALSE;
00982 
00983         return ok;
00984     }
00985     else if (camStrncmp(TokenBuf, _T("%AI5_BeginRaster"), 16) == 0)
00986     {
00987         ENSURE(!mbReadingBitmap, "Already reading a bitmap!");
00988 
00989         if ( !mpBitmapProc )
00990         {
00991             mpBitmapProc = new AIBitmapProcessor;
00992             if ( !mpBitmapProc )
00993                 ok = FALSE;
00994         }
00995 
00996         if ( mpBitmapProc )
00997         {
00998             ok = mpBitmapProc->BeginRaster();
00999         }
01000 
01001         if (ok)
01002         {
01003             // Found the start of a bitmap definition
01004             mbReadingBitmap = TRUE;
01005         }
01006 
01007         // All done - don't pass this on to document components.
01008         return ok;
01009     }
01010     else if (camStrncmp(TokenBuf, _T("%AI5_EndRaster"), 14) == 0)
01011     {
01012         ENSURE(mbReadingBitmap, "Not reading a bitmap!");
01013 
01015         // add bitmap to tentative bitmap list, giving an index number
01017 
01018         if ( mpBitmapProc )
01019         {
01020             ok = mpBitmapProc->EndRaster();
01021         }
01022 
01023         mbReadingBitmap = FALSE;
01024 
01025         return ok;
01026     }
01027     else if (camStrncmp(TokenBuf, _T("%AI8_BeginMesh"), 14) == 0)
01028     {
01030         // completely ignore the mesh definition 'cos it isn't in the current documentation
01032 
01033         do
01034         {
01035             GetToken();
01036         }
01037         while ((camStrncmp(TokenBuf, _T("%AI8_EndMesh"), 12) != 0) && (!EPSFile->eof()));
01038 
01039         return TRUE;
01040     }
01041     else if ( camStrncmp ( TokenBuf, _T ( "%AI3_BeginPattern" ), 17 ) == 0 )
01042     {
01043 /*      // Get the fillname - we need this to get the rest of the fill details.
01044         String_64 PatternName;
01045 
01046         GetLineToken ();
01047 
01048         Stack.Discard ( 4 );
01049 
01050         if ( !Stack.Pop ( &PatternName ) || !Stack.Discard () )
01051             return FALSE;
01052 */
01053         return TRUE;
01054     }
01055     else if ( camStrncmp ( TokenBuf, _T( "%AI3_EndPattern" ), 15 ) == 0 )
01056     {
01057         // NOP for now.
01058 //      INT32 NOP = 0;
01059         return TRUE;
01060     }
01061     else if ( camStrncmp ( TokenBuf, _T ( "%AI6_BeginPatternLayer" ), 22 ) == 0 )
01062     {
01063         // NOP for now.
01064 //      INT32 NOP = 0;
01065         return TRUE;
01066     }
01067     else if (camStrncmp(TokenBuf, _T("%AI6_EndPatternLayer"), 20) == 0)
01068     {
01069         // NOP for now.
01070 //      INT32 NOP = 0;
01071         return TRUE;
01072     }
01073 
01074     // Otherwise, we don't want this comment
01075     return FALSE;
01076 }
01077 
01078 /********************************************************************************************
01079 
01080 >   TCHAR *AI5EPSFilter::GetEPSCommand(EPSCommand Cmd)
01081 
01082     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01083     Created:    28/02/94
01084     Inputs:     Cmd - the EPS token, e.g. EPSC_aoa
01085     Returns:    Pointer to the string representation of the token, e.g. "aoa"
01086     Purpose:    Given an EPS token, return the string representation of it; mainly for
01087                 debugging purposes.
01088 
01089 ********************************************************************************************/
01090 
01091 TCHAR *AI5EPSFilter::GetEPSCommand(EPSCommand Cmd)
01092 {
01093     INT32 i = 0;
01094     while (AI5Commands[i].Cmd != EPSC_Invalid)
01095     {
01096         if (AI5Commands[i].Cmd == Cmd)
01097             return AI5Commands[i].CmdStr;
01098 
01099         // Try next command
01100         i++;
01101     }
01102 
01103     // Couldn't find it - default to base class method
01104     return AIEPSFilter::GetEPSCommand(Cmd);
01105 }
01106 
01107 /********************************************************************************************
01108 
01109 >   BOOL AI5EPSFilter::CreateLayer ( String_256 &LayerName,
01110                                      BOOL       IsLocked,
01111                                      BOOL       IsPrintable,
01112                                      BOOL       IsVisible )
01113 
01114     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01115     Created:    17/4/00
01116     Inputs:     LayerName   - The name of the new layer.
01117                 IsLocked    - Is the layer locked?
01118                 IsPrintable - Is the layer printable?
01119                 IsVisible   - Is the layer visible?
01120     Returns:    TRUE        - Success.
01121                 FALSE       - Failure - the layer wasn't created.
01122     Purpose:    Creates a new layer using the AddLayer () method in the EPSFilter class.
01123                 The returned pointer is then used so that I can set the layer property flags
01124                 individually.
01125     SeeAlso:    EPSFilter::AddLayer ()
01126 
01127 ********************************************************************************************/
01128 
01129 BOOL AI5EPSFilter::CreateLayer ( String_256 &LayerName,
01130                                  BOOL       IsLocked,
01131                                  BOOL       IsPrintable,
01132                                  BOOL       IsVisible )
01133 {
01134     // Create the new layer.
01135     Layer   *pLayer = AddLayer ( LayerName, FALSE );
01136 
01137     // Check that things worked.
01138     if ( pLayer != NULL )
01139     {
01140         // It went OK - set the flags.
01141         pLayer->SetLocked       ( IsLocked );
01142         pLayer->SetPrintable    ( IsPrintable );
01143         pLayer->SetVisible      ( IsVisible );
01144 
01145         // Success!
01146         return TRUE;
01147     }
01148     else
01149     {
01150         // A problem occurred.
01151         return FALSE;
01152     }
01153 }

Generated on Sat Nov 10 03:44:07 2007 for Camelot by  doxygen 1.4.4