epsstack.cpp

Go to the documentation of this file.
00001 // $Id: epsstack.cpp 1660 2006-08-03 17:28:20Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // Implementation of a PostScript style stack for the EPS reader
00100 
00101 
00102 #include "camtypes.h"
00103 //#include "list.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "listitem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "basestr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "tim.h"
00109 //#include "epsfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "epsstack.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "epssitem.h"
00112 
00113 /********************************************************************************************
00114 
00115 >   void FIXEDPOINT::FromAscii(const TCHAR *FltPtString)
00116 
00117     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00118     Created:    28/02/94
00119     Inputs:     FltPtString - string form of required number.
00120     Returns:    TRUE if ok, FALSE if not (e.g. syntax error in string)
00121     Purpose:    Decodes the ASCII string containing a floating point number and stores it
00122                 as fixed point in this object.
00123     SeeAlso:    FIXEDPOINT
00124 
00125 ********************************************************************************************/
00126 
00127 void FIXEDPOINT::FromAscii(const TCHAR *Str)
00128 {
00129     // Initialise data member.
00130     Long = 0;
00131 
00132     // keep a check on the sign
00133     BOOL neg = (Str[0] == '-');
00134 
00135     // Look for the decimal place
00136     INT32 i = 0;
00137     while ((Str[i] != 0) && (Str[i] != '.'))
00138         i++;
00139 
00140     if (Str[i] == '.')
00141     {
00142         // Found a decimal point - extract the integer and fractional parts and use them
00143         // to construct the fixed point number.
00144         TCHAR Tmp[20];
00145         camStrcpy(Tmp, Str);
00146         Tmp[i] = 0;
00147         Long = 0;
00148         camSscanf(Tmp, _T("%d"), &Long);
00149         Long *= 1000;
00150 
00151         // Force fraction to be 3 digits at the most (as we only store with 3 digits accuracy)
00152         Tmp[i + 4] = 0;
00153 
00154         // Convert fraction to integer
00155         INT32 Frac = 0;
00156         camSscanf(&(Tmp[i+1]), _T("%d"), &Frac);
00157 
00158         // The fraction can be of the form .1, .10, or .100 - we must scale it correctly.
00159         INT32 FracLen = camStrlen(Tmp + i + 1);
00160 
00161         if (FracLen == 1)
00162             Frac *= 100;
00163         else if (FracLen == 2)
00164             Frac *= 10;
00165 
00166         // Fraction is now scaled correctly - add to integer part.
00167         if (neg)
00168             // Negative number, so subtract the fractional part
00169             Long -= Frac;
00170         else
00171             // Positive number, so add the fractional part
00172             Long += Frac;
00173     }
00174     else
00175     {
00176         // No decimal point found - just scale the integer part.
00177         Long = 0;
00178         camSscanf(Str, _T("%d"), &Long);
00179         Long *= 1000;
00180     }
00181 }
00182 
00183 CC_IMPLEMENT_MEMDUMP(EPSStack, CC_CLASS_MEMDUMP)
00184 
00185 /********************************************************************************************
00186 
00187 >   EPSStack::EPSStack(UINT32 StackLimit = 50)
00188 
00189     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00190     Created:    13/10/93
00191     Purpose:    Constructor.  Initialises scaling factor to be 1.
00192 
00193 ********************************************************************************************/
00194 
00195 EPSStack::EPSStack() : List ()
00196 {
00197     // Set scaling to unity.
00198     ScaleFactor = 1;
00199 
00200     // Set origin to default
00201     Origin.x = 0;
00202     Origin.y = 0;
00203 
00204     // By default, no additional transformation matrix is used. 
00205     UseXformMatrix = FALSE;
00206 }
00207 
00208 /********************************************************************************************
00209 
00210 >   EPSStack::~EPSStack()
00211 
00212     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00213     Created:    13/10/93
00214     Purpose:    Destructor - deallocates all storage associated with the stack.
00215 
00216 ********************************************************************************************/
00217 
00218 EPSStack::~EPSStack()
00219 {
00220     // Delete the contents of the list.
00221     DeleteAll ();
00222 }
00223 
00224 /********************************************************************************************
00225 
00226 >   BOOL EPSStack::Push(const INT32 Long)
00227 
00228     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00229     Created:    13/10/93
00230     Inputs:     Long - the data to push onto the stack.
00231     Returns:    TRUE if successful, FALSE if out of stack space.
00232     Purpose:    Push a INT32 value onto the stack.
00233 
00234 ********************************************************************************************/
00235 
00236 BOOL EPSStack::Push ( const INT32 Long )
00237 {
00238     EPSStackItem *pItem = new EPSStackItem;
00239 
00240     // Ensure that the item has been created.
00241     if ( pItem == NULL)
00242     {
00243         // Clear the stack as the caller will now abort.
00244         DeleteAll ();
00245             
00246         // Tell caller about the error
00247         ERROR ( _R(IDT_EPS_STACKLIMIT), FALSE );
00248     }
00249     
00250     // Initialise stack item.
00251     pItem->Init ( Long );
00252 
00253     // Add it to the list.
00254     AddHead ( pItem );
00255 
00256     return TRUE;
00257 }
00258 
00259 /********************************************************************************************
00260 
00261 >   BOOL EPSStack::Push(const FIXEDPOINT FixedPoint)
00262 
00263     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00264     Created:    13/10/93
00265     Inputs:     FixedPoint - the data to push onto the stack.
00266     Outputs:    -
00267     Returns:    TRUE if successful, FALSE if out of stack space.
00268     Purpose:    Push a fixed point value onto the stack.
00269 
00270 ********************************************************************************************/
00271 
00272 BOOL EPSStack::Push ( const FIXEDPOINT FixedPoint )
00273 {
00274     EPSStackItem *pItem = new EPSStackItem;
00275 
00276     // Ensure that the item has been created.
00277     if ( pItem == NULL)
00278     {
00279         // Clear the stack as the caller will now abort.
00280         DeleteAll ();
00281             
00282         // Tell caller about the error
00283         ERROR ( _R(IDT_EPS_STACKLIMIT), FALSE );
00284     }
00285     
00286     // Initialise stack item.
00287     pItem->Init ( FixedPoint );
00288 
00289     // Add it to the list.
00290     AddHead ( pItem );
00291 
00292     return TRUE;
00293 }
00294 
00295 /********************************************************************************************
00296 
00297 >   BOOL EPSStack::Push(const double Double)
00298 
00299     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00300     Created:    13/10/93
00301     Inputs:     Double - the data to push onto the stack.
00302     Outputs:    -
00303     Returns:    TRUE if successful, FALSE if out of stack space.
00304     Purpose:    Push a double value onto the stack.
00305 
00306 ********************************************************************************************/
00307 
00308 BOOL EPSStack::Push ( const double Double )
00309 {
00310     EPSStackItem *pItem = new EPSStackItem;
00311 
00312     // Ensure that the item has been created.
00313     if ( pItem == NULL)
00314     {
00315         // Clear the stack as the caller will now abort.
00316         DeleteAll ();
00317             
00318         // Tell caller about the error
00319         ERROR ( _R(IDT_EPS_STACKLIMIT), FALSE );
00320     }
00321     
00322     // Initialise stack item.
00323     pItem->Init ( Double );
00324 
00325     // Add it to the list.
00326     AddHead ( pItem );
00327 
00328     return TRUE;
00329 }
00330 
00331 /********************************************************************************************
00332 
00333 >   BOOL EPSStack::Push ( const TCHAR *pString,
00334                           BOOL IsName = FALSE )
00335 
00336     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00337     Created:    13/10/93
00338     Inputs:     pString - pointer to the string data to push onto the stack.
00339     Returns:    TRUE if successful, FALSE if out of memory or stack space.
00340     Purpose:    Push a TCHAR* string item onto the stack.
00341 
00342 ********************************************************************************************/
00343 
00344 BOOL EPSStack::Push ( const TCHAR *pString,
00345                       BOOL IsName )
00346 {
00347     EPSStackItem *pItem = new EPSStackItem;
00348 
00349     // Ensure that the item has been created.
00350     if ( pItem == NULL)
00351     {
00352         // Clear the stack as the caller will now abort.
00353         DeleteAll ();
00354             
00355         // Tell caller about the error
00356         ERROR ( _R(IDT_EPS_STACKLIMIT), FALSE );
00357     }
00358     
00359     // Try to copy string
00360     TCHAR *NewStr = new TCHAR[camStrlen(pString) + 1];
00361     ERRORIF(NewStr == NULL,  _R(IDT_EPS_NOMEMORY), FALSE);
00362     camStrcpy(NewStr, pString);
00363 
00364     // Initialise stack item.
00365     pItem->Init ( NewStr );
00366 
00367     // Add it to the list.
00368     AddHead ( pItem );
00369 
00370     return TRUE;
00371 }
00372     
00373 /********************************************************************************************
00374 
00375 >   BOOL EPSStack::Push ( const EPSCommand Cmd )
00376 
00377     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00378     Created:    13/10/93
00379     Inputs:     Cmd - the EPS command to push onto the stack.
00380     Returns:    TRUE if successful, FALSE if out of stack space.
00381     Purpose:    Push an EPS command onto the stack.
00382 
00383 ********************************************************************************************/
00384 
00385 BOOL EPSStack::Push ( const EPSCommand Cmd )
00386 {
00387     EPSStackItem *pItem = new EPSStackItem;
00388 
00389     // Ensure that the item has been created.
00390     if ( pItem == NULL)
00391     {
00392         // Clear the stack as the caller will now abort.
00393         DeleteAll ();
00394             
00395         // Tell caller about the error
00396         ERROR ( _R(IDT_EPS_STACKLIMIT), FALSE );
00397     }
00398     
00399     // Initialise stack item.
00400     pItem->Init ( Cmd );
00401 
00402     // Add it to the list.
00403     AddHead ( pItem );
00404 
00405     return TRUE;
00406 }
00407 
00408     
00409 /********************************************************************************************
00410 
00411 >   BOOL EPSStack::Pop(INT32 *pLong)
00412 
00413     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00414     Created:    13/10/93
00415     Outputs:    pLong - the value popped from the stack.
00416     Returns:    TRUE if there is a numeric value on the top of the stack; FALSE if not.
00417     Purpose:    Pop a INT32 value from the top of the stack.  If there is a floating point
00418                 value on the stack, it is converted before being returned to the caller.
00419 
00420 ********************************************************************************************/
00421 
00422 BOOL EPSStack::Pop( INT32 *pLong )
00423 {
00424     // Get pointer to the stack item.
00425     EPSStackItem *pItem = static_cast<EPSStackItem*> ( RemoveHead () );
00426 
00427     // Return error if no items on stack.
00428     if ( pItem == NULL )
00429         return FALSE;
00430 
00431     // Check that the item is of the correct type
00432     switch ( pItem->Type )
00433     {
00434         case EPSTYPE_INT32:
00435             // Correct type - remove item from stack and return to caller.
00436             *pLong = static_cast<INT32> ( pItem->Data.Long );
00437             break;
00438 
00439         case EPSTYPE_FIXEDPOINT:
00440             // Perform implicit type conversion a la PostScript
00441             *pLong = static_cast<INT32> ( pItem->Data.FixedPoint.Long / FixedPointScale );
00442             break;
00443 
00444         case EPSTYPE_DOUBLE:
00445             // Perform implicit type conversion a la PostScript
00446             *pLong = static_cast<INT32> ( pItem->Data.Double );
00447             break;
00448 
00449         default:
00450             // Type mismatch - return error condition
00451             return FALSE;
00452     }
00453 
00454     // Delete item fron stack and return
00455     delete pItem;
00456 
00457     return TRUE;
00458 }
00459 
00460 /********************************************************************************************
00461 
00462 >   BOOL EPSStack::Pop(UINT32 *pUint)
00463 
00464     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00465     Created:    13/10/93
00466     Outputs:    pUint - the value popped from the stack.
00467     Returns:    TRUE if there is a numeric value on the top of the stack; FALSE if not.
00468     Purpose:    Pop a UINT32 value from the top of the stack.  If there is a floating point
00469                 value on the stack, it is converted before being returned to the caller.
00470 
00471 ********************************************************************************************/
00472 
00473 BOOL EPSStack::Pop ( UINT32 *pUint )
00474 {
00475     // Get pointer to the stack item.
00476     EPSStackItem *pItem = static_cast<EPSStackItem*> ( RemoveHead () );
00477 
00478     // Return error if no items on stack.
00479     if ( pItem == NULL )
00480         return FALSE;
00481 
00482     // Check that the item is of the correct type
00483     switch ( pItem->Type )
00484     {
00485         case EPSTYPE_INT32:
00486             // Correct type - remove item from stack and return to caller.
00487             *pUint = static_cast<UINT32> ( pItem->Data.Long );
00488             break;
00489 
00490         case EPSTYPE_FIXEDPOINT:
00491             // Perform implicit type conversion a la PostScript
00492             *pUint = static_cast<UINT32> ( pItem->Data.FixedPoint.Long / FixedPointScale );
00493             break;
00494 
00495         case EPSTYPE_DOUBLE:
00496             // Perform implicit type conversion a la PostScript
00497             *pUint = static_cast<UINT32> ( pItem->Data.Double );
00498             break;
00499 
00500         default:
00501             // Type mismatch - return error condition
00502             return FALSE;
00503     }
00504 
00505     // Delete item fron stack and return
00506     delete pItem;
00507 
00508     return TRUE;
00509 }
00510 
00511 /********************************************************************************************
00512 
00513 >   BOOL EPSStack::Pop(FIXEDPOINT *pFixedPoint)
00514 
00515     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00516     Created:    13/10/93
00517     Outputs:    pFixedPoint - the value popped from the stack.
00518     Returns:    TRUE if there is a numeric value on the top of the stack; FALSE if not.
00519     Purpose:    Pop a double value from the top of the stack.  If there is an integer value
00520                 on top of the stack, it is converted to a floating point value before being
00521                 returned to the caller.
00522 
00523 ********************************************************************************************/
00524 
00525 BOOL EPSStack::Pop ( FIXEDPOINT *pFixedPoint )
00526 {
00527     // Get pointer to the stack item.
00528     EPSStackItem *pItem = static_cast<EPSStackItem*> ( RemoveHead () );
00529 
00530     // Return error if no items on stack.
00531     if ( pItem == NULL )
00532         return FALSE;
00533     
00534     // Check that the item is of the correct type
00535     switch (pItem->Type)
00536     {
00537         case EPSTYPE_INT32:
00538             // Correct type - remove item from stack and return to caller.
00539             pFixedPoint->Long = ( pItem->Data.Long * FixedPointScale );
00540             break;
00541 
00542         case EPSTYPE_FIXEDPOINT:
00543             // Perform implicit type conversion a la PostScript
00544             *pFixedPoint = pItem->Data.FixedPoint;
00545             break;
00546 
00547         case EPSTYPE_DOUBLE:
00548             // Perform implicit type conversion a la PostScript
00549             pFixedPoint->Long = static_cast <INT32> ( pItem->Data.Double );
00550             break;
00551 
00552         default:
00553             // Type mismatch - return error condition
00554             return FALSE;
00555     }
00556         
00557     // Delete item fron stack and return
00558     delete pItem;
00559 
00560     return TRUE;
00561 }
00562 
00563 /********************************************************************************************
00564 
00565 >   BOOL EPSStack::Pop(double *pDouble)
00566 
00567     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00568     Created:    13/10/93
00569     Outputs:    pDouble - the value popped from the stack.
00570     Returns:    TRUE if there is a numeric value on the top of the stack; FALSE if not.
00571     Purpose:    Pop a double value from the top of the stack.  If there is an integer value
00572                 on top of the stack, it is converted to a floating point value before being
00573                 returned to the caller.
00574 
00575 ********************************************************************************************/
00576 
00577 BOOL EPSStack::Pop ( double *pDouble )
00578 {
00579     // Get pointer to the stack item.
00580     EPSStackItem *pItem = static_cast<EPSStackItem*> ( RemoveHead () );
00581 
00582     // Return error if no items on stack.
00583     if ( pItem == NULL )
00584         return FALSE;
00585     
00586     // Check that the item is of the correct type
00587     switch ( pItem->Type )
00588     {
00589         case EPSTYPE_INT32:
00590             // Correct type - remove item from stack and return to caller.
00591             *pDouble = static_cast<double> ( pItem->Data.Long );
00592             break;
00593 
00594         case EPSTYPE_FIXEDPOINT:
00595             // Perform implicit type conversion a la PostScript
00596             *pDouble = static_cast<double> ( pItem->Data.FixedPoint.Long ) / FixedPointScale;
00597             break;
00598 
00599         case EPSTYPE_DOUBLE:
00600             // Perform implicit type conversion a la PostScript
00601             *pDouble = pItem->Data.Double;
00602             break;
00603 
00604         default:
00605             // Type mismatch - return error condition
00606             return FALSE;
00607     }
00608                 
00609     // Delete item fron stack and return    
00610     delete pItem;
00611 
00612     return TRUE;
00613 }
00614 
00615 /********************************************************************************************
00616 
00617 >   BOOL EPSStack::Pop(TCHAR* pString)
00618 
00619     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00620     Created:    13/10/93
00621     Outputs:    pString - the buffer to put the string value into.
00622     Returns:    TRUE if there is a string value on the top of the stack; FALSE if not.
00623     Purpose:    Pop a TCHAR* string value from the top of the stack.
00624 
00625 ********************************************************************************************/
00626 
00627 BOOL EPSStack::Pop ( TCHAR* pString )
00628 {
00629     // Get pointer to the stack item.
00630     EPSStackItem *pItem = static_cast<EPSStackItem*> ( RemoveHead () );
00631 
00632     // Return error if no items on stack.
00633     if ( pItem == NULL )
00634         return FALSE;
00635     
00636     // Check that the item is of the correct type
00637     if ( pItem->Type == EPSTYPE_STRING )
00638     {
00639         // Correct type - remove item from stack and return to caller.
00640         camStrcpy ( pString, pItem->Data.pString );
00641         delete pItem;
00642         return TRUE;
00643     }
00644     else
00645     {
00646         // Tidy up the memory.
00647         delete pItem;
00648 
00649         // Type mismatch - return error condition
00650         return FALSE;
00651     }
00652 }
00653 
00654 /********************************************************************************************
00655 
00656 >   BOOL EPSStack::Pop(StringBase* pString)
00657 
00658     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00659     Created:    13/10/93
00660     Outputs:    pString - the String object to put the string value into.
00661     Returns:    TRUE if there is a string value on the top of the stack; FALSE if not.
00662     Purpose:    Pop a string value from the top of the stack.
00663 
00664 ********************************************************************************************/
00665 
00666 BOOL EPSStack::Pop(StringBase* pString)
00667 {
00668     // Get pointer to the stack item.
00669     EPSStackItem *pItem = static_cast<EPSStackItem*> ( RemoveHead () );
00670 
00671     // Return error if no items on stack.
00672     if ( pItem == NULL )
00673         return FALSE;
00674     
00675     // Check that the item is of the correct type
00676     if ( pItem->Type == EPSTYPE_STRING )
00677     {
00678         // Correct type - remove item from stack and return to caller.
00679         *pString = String_256(pItem->Data.pString);
00680         delete pItem;
00681         return TRUE;
00682     }
00683     else
00684     {
00685         // Tidy up the memory.
00686         delete pItem;
00687 
00688         // Type mismatch - return error condition
00689         return FALSE;
00690     }
00691 }
00692 
00693 
00694 /********************************************************************************************
00695 
00696 >   BOOL EPSStack::PopCmd(EPSCommand *pCmd)
00697 
00698     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00699     Created:    13/10/93
00700     Outputs:    pCmd - the command on top of the stack.
00701     Returns:    TRUE if there is an EPS command on the top of the stack; FALSE if not.
00702     Purpose:    Pop an EPS command from the top of the stack.
00703 
00704 ********************************************************************************************/
00705 
00706 BOOL EPSStack::PopCmd(EPSCommand *pCmd)
00707 {
00708     // Get pointer to the stack item.
00709     EPSStackItem *pItem = static_cast<EPSStackItem*> ( RemoveHead () );
00710 
00711     // Return error if no items on stack.
00712     if ( pItem == NULL )
00713         return FALSE;
00714     
00715     // Check that the item is of the correct type
00716     if (pItem->Type == EPSTYPE_COMMAND)
00717     {
00718         // Correct type - remove item from stack and return to caller.
00719         *pCmd = pItem->Data.Cmd;
00720         delete pItem;
00721         return TRUE;
00722     }
00723     else
00724     {
00725         // Type mismatch - return error condition
00726         delete pItem;
00727         return FALSE;
00728     }
00729 }
00730 
00731 /********************************************************************************************
00732 
00733 >   BOOL EPSStack::PopCoord(INT32 *pLong)
00734 
00735     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00736     Created:    13/10/93
00737     Outputs:    pLong - the (scaled) value popped from the stack.
00738     Returns:    TRUE if there is a numeric value on the top of the stack; FALSE if not.
00739     Purpose:    Pop a INT32 value from the top of the stack.  If there is a fixed point
00740                 value on the stack, it is converted before being returned to the caller.
00741                 The value is scaled before being returned, so that it is easy to cope with
00742                 EPS files that use brainless coordinate schemes (i.e. all of them).
00743                 Scaling factor is initially 1, but can be changed via SetCoordScaleFactor().
00744     SeeAlso:    EPSStack::SetCoordScaleFactor
00745 
00746 ********************************************************************************************/
00747 
00748 BOOL EPSStack::PopCoord ( INT32 *pLong )
00749 {
00750     // Get pointer to the stack item.
00751     EPSStackItem *pItem = static_cast<EPSStackItem*> ( RemoveHead () );
00752 
00753     // Return error if no items on stack.
00754     if ( pItem == NULL )
00755         return FALSE;
00756     
00757     // Check that the item is of the correct type
00758     switch ( pItem->Type )
00759     {
00760         case EPSTYPE_INT32:
00761             // Correct type - remove item from stack and return to caller.
00762             *pLong = ScaleFactor * (pItem->Data.Long);
00763             break;
00764 
00765         case EPSTYPE_FIXEDPOINT:
00766             // Perform implicit type conversion a la PostScript
00767 
00768             // Fixed point values are stored as value * 1000, so if the ScaleFactor is
00769             // actually 1000, don't bother to scale - just return the value.
00770             if (ScaleFactor == FixedPointScale)
00771                 *pLong = static_cast<INT32> ( pItem->Data.FixedPoint.Long );
00772             else
00773             {
00774                 // Perform the necessary scaling
00775                 *pLong = static_cast<INT32> ( pItem->Data.FixedPoint.Long * 
00776                          ( static_cast<double> ( ScaleFactor ) ) );
00777                 *pLong /= FixedPointScale;
00778             }
00779             break;
00780 
00781         case EPSTYPE_DOUBLE:
00782             // Perform implicit type conversion a la PostScript
00783             *pLong = static_cast<INT32> ( static_cast<double> ( ScaleFactor ) *
00784                      pItem->Data.Double );
00785             break;
00786 
00787         default:
00788             // Type mismatch - return error condition
00789             return FALSE;
00790     }
00791     
00792     // Delete item fron stack and return    
00793     delete pItem;
00794     return TRUE;
00795 }
00796 
00797 /********************************************************************************************
00798 
00799 >   BOOL EPSStack::PopCoordPair(DocCoord *pCoord)
00800 
00801     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00802     Created:    13/10/93
00803     Outputs:    pCoord - the (scaled and translated) coordinate pair popped from the stack.
00804     Returns:    TRUE if there is a coord pair on the top of the stack; FALSE if not.
00805     Purpose:    Pop two INT32 values from the top of the stack.
00806                 If they are in floating point format, they are converted before being
00807                 returned to the caller.
00808                 The coords are scaled and translated before being returned, so that it is 
00809                 easy to cope with EPS files that use brainless coordinate schemes (ArtWorks 
00810                 EPS are you listening?).
00811                 Scaling factor is initially 1, but can be changed via SetCoordScaleFactor().
00812                 Origin is initially (0,0), but can be changed via SetCoordOrigin().
00813     SeeAlso:    EPSStack::SetCoordScaleFactor; EPSStack::SetCoordOrigin
00814 
00815 ********************************************************************************************/
00816 
00817 BOOL EPSStack::PopCoordPair(DocCoord *pCoord)
00818 {
00819     if (PopCoord(&(pCoord->y)) && PopCoord(&(pCoord->x)))
00820     {
00821         // Use the transform matrix if necessary.
00822         if (UseXformMatrix)
00823             XformMatrix.transform((Coord *) pCoord, 1);
00824 
00825         // Translate coord using given origin and return success.
00826         pCoord->x += Origin.x;
00827         pCoord->y += Origin.y;
00828 
00829         return TRUE;
00830     }
00831     else
00832         return FALSE;
00833 }
00834 
00835 /********************************************************************************************
00836 
00837 >   BOOL EPSStack::PopColour(PColourCMYK *Col, TintType Tint = TINT_NONE,
00838                              FIXEDPOINT *pTintVal = NULL,
00839                              String_64 *pName = NULL)
00840 
00841     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00842     Created:    18/10/93
00843     Outputs:    Col - the CMYK values popped from the stack and converted to 0-255 range.
00844 
00845                 TintType - indicates what kind of tint is on the stack:
00846                     TINT_NONE        - no tint is on the stack
00847                     TINT_ILLUSTRATOR - An Illustrator type tint is on the stack, i.e. a value
00848                                        between 0 and 1, with 0 being 100% and 1 being 0%.
00849                     TINT_COREL       - An Corel Draw type tint is on the stack, i.e. a value
00850                                        between 0 and 1, with 1 being 100% and 0 being 0%.
00851 
00852                 TintVal - the value of the tint operand.
00853                 pName - the textual name of this colour.
00854 
00855                 If there is a tint, then the CMYK values are followed by a colour name and a
00856                 tint value (0.0 to 1.0).  The colour name is discarded, and the colour
00857                 is adjusted according to the tint value found.
00858     Returns:    TRUE if valid colour parameters were found on the stack; FALSE if not enough
00859                 parameters, or if there are not enough, or if they are outside the 0-1 range.
00860     Purpose:    Extract CYMK values from an ArtWorks EPS format and convert to Camelot range.
00861                 AWEPS colour values are in the range 0 to 1; this function converts them
00862                 to the 0 to 255 range.
00863     See Also:   EPSStack::PopColourRGB
00864 
00865 ********************************************************************************************/
00866 
00867 BOOL EPSStack::PopColour(PColourCMYK *Col, TintType Tint, 
00868                          FIXEDPOINT *pTintVal, String_64 *pName)
00869 {
00870     double Cyan, Magenta, Yellow, Key;
00871     FIXEDPOINT TintValue;
00872     TintValue=0; // Warning suppression
00873 
00874     if (Tint != TINT_NONE)
00875     {
00876         // Get the tint.
00877         if (!Pop(&TintValue))
00878             return FALSE;
00879 
00880         // Does the caller want the name of the colour?
00881         if (pName == NULL)
00882         {
00883             // Name is not wanted - discard it
00884             if (!Discard())
00885                 return FALSE;
00886         }
00887         else
00888         {
00889             // Name is wanted - get it from the stack
00890             if (!Pop(pName))
00891                 return FALSE;
00892         }
00893 
00894         ENSURE((TintValue >= 0) && (TintValue <= 1000), "Bad tint");
00895 
00896         // Convert Tint to sensible value, if required
00897         if (Tint == TINT_ILLUSTRATOR)
00898             TintValue = (1 * FixedPointScale) - (INT32) TintValue;
00899 
00900         if (pTintVal != NULL)
00901             *pTintVal = TintValue;
00902     }
00903                 
00904     if (Pop(&Key) && Pop(&Yellow) && Pop(&Magenta) && Pop(&Cyan))
00905     {
00906         if ((Cyan < 0.0) || (Cyan > 1.0) || (Magenta < 0.0) || (Magenta > 1.0) || 
00907             (Yellow < 0.0) || (Yellow > 1.0) || (Key < 0.0) || (Key > 1.0))
00908             // Invalid colour value
00909             return FALSE;
00910             
00911         // Got the values ok - translate from 0->1 range to sensible range.
00912         // NB. Important that we round up here, because otherwise 8 bit values will
00913         //     sometimes fail to match on boundary conditions.
00914         Col->Cyan    = (INT32) ((Cyan   * 255.0) + 0.5);
00915         Col->Magenta = (INT32) ((Magenta * 255.0) + 0.5);
00916         Col->Yellow  = (INT32) ((Yellow     * 255.0) + 0.5);
00917         Col->Key     = (INT32) ((Key    * 255.0) + 0.5);
00918 
00919         if (Tint != TINT_NONE)
00920         {
00921             // Tint the colour
00922             Col->Cyan    = (Col->Cyan    * TintValue) / FixedPointScale;
00923             Col->Magenta = (Col->Magenta * TintValue) / FixedPointScale;
00924             Col->Yellow  = (Col->Yellow  * TintValue) / FixedPointScale;
00925             Col->Key     = (Col->Key     * TintValue) / FixedPointScale;
00926         }
00927                 
00928         return TRUE;
00929     }
00930     else
00931         return FALSE;
00932 }
00933 
00934 /********************************************************************************************
00935 
00936 >   BOOL EPSStack::PopColourRGB (INT32 * red, INT32 * green, INT32 * blue, 
00937                                 TintType Tint = TINT_NONE,
00938                                 FIXEDPOINT *pTintVal = NULL,
00939                                 String_64 *pName = NULL)
00940 
00941     Author:     Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com>
00942     Created:    12/12/00
00943     Outputs:    red, green, blue - the RGB values popped from the stack and converted to 
00944                 0-255 range.
00945 
00946                 TintType - indicates what kind of tint is on the stack:
00947                     TINT_NONE        - no tint is on the stack
00948                     TINT_ILLUSTRATOR - An Illustrator type tint is on the stack, i.e. a value
00949                                        between 0 and 1, with 0 being 100% and 1 being 0%.
00950                     TINT_COREL       - An Corel Draw type tint is on the stack, i.e. a value
00951                                        between 0 and 1, with 1 being 100% and 0 being 0%.
00952 
00953                 TintVal - the value of the tint operand.
00954                 pName - the textual name of this colour.
00955 
00956                 NOTE: The tint is currently not supported for RGB colours, although the 
00957                 syntax has been kept to keep it consistent with the CMYK/Greyscale versions, 
00958                 as well to enable expansion of this function.
00959 
00960     Returns:    TRUE if valid colour parameters were found on the stack; FALSE if not enough
00961                 parameters, or if there are not enough, or if they are outside the 0-1 range.
00962     Purpose:    Extract RGB values from a generic EPS format and convert to Camelot range. 
00963                 EPS colour values are in the range 0 to 1; this function converts them
00964                 to the 0 to 255 range.
00965     See Also:   EPSStack::PopColour
00966 
00967 ********************************************************************************************/
00968 
00969 BOOL EPSStack::PopColourRGB (INT32 * red, INT32 * green, INT32 * blue, TintType Tint, 
00970                             FIXEDPOINT *pTintVal, String_64 *pName)
00971 {
00972     double tempRed, tempGreen, tempBlue;
00973     FIXEDPOINT TintValue;
00974 
00975     if (Tint != TINT_NONE)
00976     {
00977         // Get the tint.
00978         if (!Pop(&TintValue))
00979             return FALSE;
00980 
00981         // Does the caller want the name of the colour?
00982         if (pName == NULL)
00983         {
00984             // Name is not wanted - discard it
00985             if (!Discard())
00986                 return FALSE;
00987         }
00988         else
00989         {
00990             // Name is wanted - get it from the stack
00991             if (!Pop(pName))
00992                 return FALSE;
00993         }
00994 
00995         ENSURE((TintValue >= 0) && (TintValue <= 1000), "Bad tint");
00996 
00997         // Convert Tint to sensible value, if required
00998         if (Tint == TINT_ILLUSTRATOR)
00999             TintValue = (1 * FixedPointScale) - (INT32) TintValue;
01000 
01001         if (pTintVal != NULL)
01002             *pTintVal = TintValue;
01003     }
01004                 
01005     if (Pop(&tempBlue) && Pop(&tempGreen) && Pop(&tempRed))
01006     {
01007         if ((tempRed < 0.0) || (tempRed > 1.0) || 
01008             (tempBlue < 0.0) || (tempBlue > 1.0) || 
01009             (tempGreen < 0.0) || (tempGreen > 1.0))
01010             // Invalid colour value
01011             return FALSE;
01012             
01013         // Got the values ok - translate from 0->1 range to sensible range.
01014         // NB. Important that we round up here, because otherwise 8 bit values will
01015         //     sometimes fail to match on boundary conditions.
01016         *red    = (INT32) ((tempRed  * 255.0) + 0.5);
01017         *green  = (INT32) ((tempGreen * 255.0) + 0.5);
01018         *blue   = (INT32) ((tempBlue     * 255.0) + 0.5);
01019 
01020         if (Tint != TINT_NONE)
01021         {
01022             // Tint the colour - Not currently done for RGB colours
01023         }
01024                 
01025         return TRUE;
01026     }
01027     else
01028         return FALSE;
01029 }
01030 
01031 /********************************************************************************************
01032 
01033 >   BOOL EPSStack::PopGrayScale(PColourCMYK *Col)
01034 
01035     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01036     Created:    28/02/94
01037     Outputs:    Col - the CMYK version of the grayscale popped from the stack and converted 
01038                       to 0-255 range.
01039     Returns:    TRUE if a valid grayscale parameter was found on the stack; FALSE if not.
01040     Purpose:    Extract grayscale value from an EPS format file and convert to Camelot range.
01041     SeeAlso:    PopColour
01042 
01043 ********************************************************************************************/
01044 
01045 BOOL EPSStack::PopGrayScale(PColourCMYK *Col)
01046 {
01047     double Gray=0.0;
01048 
01049     if (Pop(&Gray))
01050     {
01051         if ((Gray < 0.0) || (Gray > 1.0))
01052             // invalid gray scale value
01053             return FALSE;
01054 
01055         // Got the grayscale ok - translate from 0->1 range to sensible range.
01056         PColourValue GrayVal = 255 - (static_cast<INT32> (Gray * 255));
01057 
01058         Col->Cyan    = 0;
01059         Col->Magenta = 0;
01060         Col->Yellow  = 0;
01061         Col->Key     = static_cast<BYTE> ( GrayVal );
01062 
01063         return TRUE;
01064     }
01065     else
01066         return FALSE;
01067 }
01068 
01069 
01070 
01071 /********************************************************************************************
01072 
01073 >   BOOL EPSStack::Pop(Matrix *pMatrix, BOOL UseBrackets)
01074 
01075     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01076     Created:    2/2/95
01077     Inputs:     pMatrix - the matrix to hold the popped values.
01078                 UseBrackets - TRUE if the matrix is bracketed by [];
01079                              FALSE if just the numbers are in the file.
01080     Returns:    TRUE if the matrix was decode ok;
01081                 FALSE otherwise
01082     Purpose:    Pop a matrix object from the EPS stack.
01083     Errors:     Not enough parameters/incorrect parameters.
01084 
01085 ********************************************************************************************/
01086 
01087 BOOL EPSStack::Pop(Matrix *pMatrix, BOOL UseBrackets)
01088 {
01089     if (UseBrackets)
01090     {
01091         EPSCommand Cmd=EPSC_Invalid;
01092         PopCmd(&Cmd);
01093         if (Cmd != EPSC_ArrayEnd)
01094             return FALSE;
01095     }
01096 
01097     // Extract the six array values from the stack.
01098     double M[6];
01099     INT32 i = 5;
01100     for (i = 5; i >= 0; i--)
01101     {
01102         if (!Pop(&M[i]))
01103             return FALSE;
01104     }
01105 
01106     if (UseBrackets)
01107     {
01108         EPSCommand Cmd=EPSC_Invalid;
01109         PopCmd(&Cmd);
01110         if (Cmd != EPSC_ArrayStart)
01111             return FALSE;
01112     }
01113 
01114     // Convert the abcd values into FIXED16s, cos that's what we use.
01115     FIXED16 F16[4];
01116     for (i = 0; i < 4; i++)
01117     {
01118         F16[i] = FIXED16(M[i]);
01119     }
01120 
01121     // Convert the Tx and Ty to MILLIPOINTS, cos that's what we use.
01122     INT32 L1 = (INT32) (M[4] * 1000.0);
01123     INT32 L2 = (INT32) (M[5] * 1000.0);
01124 
01125     // Construct the matrix in the variable supplied by the caller.
01126     *pMatrix = Matrix(F16[0], F16[1], F16[2], F16[3], L1, L2);
01127 
01128     // Success
01129     return TRUE;
01130 }
01131 
01132 /********************************************************************************************
01133 
01134 >   void EPSStack::SetCoordScaleFactor(INT32 NewScaleFactor)
01135 
01136     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01137     Created:    15/10/93
01138     Inputs:     NewScaleFactor - the new factor to use when scaling coordinates.
01139     Purpose:    Set the scale factor used by PopCoord().  Scaling factor is initially 1.
01140     SeeAlso:    EPSStack::PopCoord()
01141 
01142 ********************************************************************************************/
01143 
01144 void EPSStack::SetCoordScaleFactor(INT32 NewScaleFactor)
01145 {
01146     ScaleFactor = NewScaleFactor;
01147 }
01148     
01149 /********************************************************************************************
01150 
01151 >   void EPSStack::SetCoordOrigin(DocCoord NewOrigin)
01152 
01153     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01154     Created:    15/10/93
01155     Inputs:     NewOrigin - the new origin to use when translating coordinates.
01156     Purpose:    Set the translation values used by PopCoord().  Initially (0,0).
01157     SeeAlso:    EPSStack::PopCoord()
01158 
01159 ********************************************************************************************/
01160 
01161 void EPSStack::SetCoordOrigin(DocCoord NewOrigin)
01162 {
01163     Origin = NewOrigin;
01164 }
01165 
01166 /********************************************************************************************
01167 
01168 >   void EPSStack::TranslateCoordOrigin(MILLIPOINT dx, MILLIPOINT dy)
01169 
01170     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01171     Created:    08/04/94
01172     Inputs:     dx, dy - the translation values.
01173     Purpose:    Translate the current origin for the EPS file by the given amounts.
01174                 This is used when the %%BoundingBox comment is encountered, so that the
01175                 image appears in a sensible place.
01176     SeeAlso:    EPSStack::SetCoordOrigin
01177 
01178 ********************************************************************************************/
01179 
01180 void EPSStack::TranslateCoordOrigin(MILLIPOINT dx, MILLIPOINT dy)
01181 {
01182     Origin.x += dx;
01183     Origin.y += dy;
01184 }
01185 
01186 /********************************************************************************************
01187 
01188 >   void EPSStack::SetXformMatrix(Matrix& NewMatrix)
01189 
01190     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01191     Created:    10/08/94
01192     Inputs:     NewMatrix - the matrix to use from now on.
01193     Purpose:    Sets up an additional transformation matrix to be used when decoding
01194                 document coordinates (via EPSStack::PopCoordPair).
01195                 When a transform matrix is active, all coords returned from PopCoordPair
01196                 will have been transformed by the matrix after first having had the usual
01197                 origin translation performed.
01198                 The transformation matrix can be disabled by called SetNoXFormMatrix().
01199     Errors:     -
01200     SeeAlso:    EPSStack::PopCoordPair; EPSStack::SetNoXFormMatrix
01201 
01202 ********************************************************************************************/
01203 
01204 void EPSStack::SetXformMatrix(Matrix& NewMatrix)
01205 {
01206     // Install the new matrix
01207     XformMatrix = NewMatrix;
01208     UseXformMatrix = TRUE;
01209 }
01210 
01211 /********************************************************************************************
01212 
01213 >   void EPSStack::SetNoXFormMatrix()
01214 
01215     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01216     Created:    10/08/94
01217     Purpose:    Disable the transformation matrix used by EPSStack::PopCoordPair().
01218                 See SetXFormMatrix() for details.
01219     SeeAlso:    EPSStack::PopCoordPair; EPSStack::SetXFormMatrix
01220 
01221 ********************************************************************************************/
01222 
01223 void EPSStack::SetNoXformMatrix()
01224 {
01225     UseXformMatrix = FALSE;
01226 }
01227 
01228 /********************************************************************************************
01229 
01230 >   BOOL EPSStack::Discard(UINT32 NumToDiscard = 1, BOOL EvenCommands = FALSE)
01231 
01232     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01233     Created:    14/10/93
01234     Inputs:     NumToDiscard - the number of items to remove from the top of the stack.
01235     Returns:    TRUE if there were sufficient items on the stack to satisfy request, FALSE
01236                 if not.
01237     Purpose:    Discard a number of items from the stack, irrespective of their type.
01238                 NB. The exception is that you cannot discard a command, only operands (e.g.
01239                 strings, numbers or names) unless EvenCommands == TRUE.
01240     SeeAlso:    EPSStack::Pop
01241 
01242 ********************************************************************************************/
01243 
01244 BOOL EPSStack::Discard(UINT32 NumToDiscard, BOOL EvenCommands)
01245 {
01246     // Check we can discard this many items
01247     if ( GetCount () < NumToDiscard )
01248         return FALSE;
01249         
01250     while (NumToDiscard > 0)
01251     {
01252         EPSStackItem *pItem = static_cast<EPSStackItem*> ( GetHead () );
01253 
01254         // Catch NULL pointers.
01255         if ( pItem == NULL )
01256         {
01257             // Cannot discard any more list items.
01258             break;
01259         }
01260 
01261         if((pItem->Type == EPSTYPE_COMMAND) && (EvenCommands == FALSE))
01262         {   // Cannot discard a command
01263             return FALSE;
01264         }
01265 
01266         // Clean up any storage for this item
01267         RemoveHead ();
01268         delete pItem;
01269         
01270         // Move to next item
01271         NumToDiscard--;
01272     }
01273 
01274     return TRUE;
01275 }
01276 
01277 /********************************************************************************************
01278 
01279 >   BOOL EPSStack::PopArray(INT32 *Array, INT32* Elements)
01280 
01281     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01282     Created:    15/4/95
01283     Returns:    TRUE if the array was popped ok, FALSE if an error occured.
01284     Purpose:    Pop a PostScript array object from the stack.
01285     Errors:     No syntactically correct array on the stack.
01286     SeeAlso:    EPSStack::Discard
01287 
01288 ********************************************************************************************/
01289 
01290 BOOL EPSStack::PopArray(INT32 *Array, INT32* Elements)
01291 {
01292     if (Array == NULL || Elements == NULL)
01293         return FALSE;
01294 
01295     if (GetType() != EPSTYPE_COMMAND)
01296     {
01297         TRACEUSER( "Will", _T("EPSStack::PopArray: Expected ArrayEnd\n"));
01298         return FALSE;
01299     }
01300     
01301     // First this we find should be the 'Array End' command (']')
01302     EPSCommand Cmd=EPSC_Invalid;
01303     PopCmd(&Cmd);
01304     if (Cmd != EPSC_ArrayEnd)
01305     {
01306         TRACEUSER( "Will", _T("EPSStack::PopArray: Expected ArrayEnd\n"));
01307         return FALSE;
01308     }
01309 
01310     INT32 NumElements = 0;  
01311 
01312     // The array element will be popped off the stack backwards,
01313     // so we need to make a tempory array, so we can swap them,
01314     // around at the end.
01315     INT32* TempArray = new INT32[*Elements];
01316     if (TempArray == NULL)
01317         return FALSE;
01318 
01319     // Read the rest of the array
01320     for(;;)
01321     {
01322         if (IsEmpty())
01323         {
01324             // Run out of operands!
01325             TRACEUSER( "Will", _T("EPSStack::PopArray: Run out of operands\n"));
01326             delete TempArray;
01327             return FALSE;
01328         }
01329             
01330         if (GetType() != EPSTYPE_COMMAND)
01331         {
01332             // Pop the array member
01333             double Double=0.0;
01334             if (!Pop(&Double))
01335             {
01336                 delete TempArray;
01337                 return FALSE;
01338             }
01339 
01340             if (NumElements < *Elements)
01341             {
01342                 TempArray[NumElements] = (INT32) (Double * EPSScaleFactor);
01343                 NumElements++;
01344             }
01345         }
01346         else
01347         {
01348             EPSCommand Cmd = ReadCmd();
01349             if (!PopCmd(&Cmd) || Cmd != EPSC_ArrayStart)
01350             {
01351                 TRACEUSER( "Will", _T("EPSStack::PopArray: Expected ArrayStart\n"));
01352                 delete TempArray;
01353                 return FALSE;
01354             }
01355             else
01356                 break; // exit loop - end of array found
01357         }
01358     }
01359 
01360     *Elements = NumElements;    // Actual number of elements read
01361 
01362     // Now swap the elements so they are the correct way around.
01363     if (NumElements > 0)
01364     {
01365         INT32 LastEl = NumElements - 1;
01366 
01367         for (INT32 el = 0; el < NumElements; el++)
01368         {
01369             Array[el] = TempArray[LastEl - el];
01370         }
01371     }
01372 
01373     delete TempArray;
01374 
01375     // Array popped ok
01376     return TRUE;
01377 }
01378 
01379 /********************************************************************************************
01380 
01381 >   BOOL EPSStack::DiscardArray()
01382 
01383     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01384     Created:    07/03/94
01385     Returns:    TRUE if the array was discarded ok, FALSE if an error occured.
01386     Purpose:    Discard a PostScript array object from the stack.  This is normally used
01387                 when an EPS filter is not complete, but the file is still parsed correctly
01388                 by discarding information that is npt yet needed/processed.
01389     Errors:     No syntactically correct array on the stack.
01390     SeeAlso:    EPSStack::Discard
01391 
01392 ********************************************************************************************/
01393 
01394 BOOL EPSStack::DiscardArray()
01395 {
01396     if (GetType() != EPSTYPE_COMMAND)
01397     {
01398         TRACEUSER( "Tim", _T("EPSStack::DiscardArray: Expected ArrayEnd\n"));
01399         return FALSE;
01400     }
01401     
01402     EPSCommand Cmd=EPSC_Invalid;
01403     PopCmd(&Cmd);
01404     if (Cmd != EPSC_ArrayEnd)
01405     {
01406         TRACEUSER( "Tim", _T("EPSStack::DiscardArray: Expected ArrayEnd\n"));
01407         return FALSE;
01408     }
01409     
01410     // Discard the rest of the array
01411     for(;;)
01412     {
01413         if (IsEmpty())
01414         {
01415             // Run out of operands!
01416             TRACEUSER( "Tim", _T("EPSStack::DiscardArray: Run out of operands\n"));
01417             return FALSE;
01418         }
01419             
01420         if (GetType() != EPSTYPE_COMMAND)
01421             // Discard array member
01422             Discard();
01423         else
01424         {
01425             EPSCommand Cmd = ReadCmd();
01426             if (!PopCmd(&Cmd) || Cmd != EPSC_ArrayStart)
01427             {
01428                 TRACEUSER( "Tim", _T("EPSStack::DiscardArray: Expected ArrayStart\n"));
01429                 return FALSE;
01430             }
01431             else
01432                 break; // exit loop - end of array found
01433         }
01434     }
01435 
01436     // Array discarded ok
01437     return TRUE;
01438 }
01439 
01440 /********************************************************************************************
01441 
01442 >   EPSType EPSStack::GetType()
01443 
01444     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01445     Created:    14/10/93
01446     Returns:    The type of the object on the top of the stack (if the stack is empty, 
01447                 the value EPSTYPE_NONE is returned).
01448     Purpose:    Find out what type of object is on the top of the stack.
01449                 The item is not removed from the stack by this operation.
01450 
01451 ********************************************************************************************/
01452 
01453 EPSType EPSStack::GetType()
01454 {
01455     EPSStackItem *pItem = static_cast<EPSStackItem*> ( GetHead () );
01456 
01457     if ( pItem == NULL )
01458         return EPSTYPE_NONE;
01459     else
01460         return pItem->Type;
01461 }
01462     
01463 /********************************************************************************************
01464 
01465 >   EPSCommand EPSStack::ReadCmd()
01466 
01467     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01468     Created:    14/10/93
01469     Returns:    The EPS command on the top of the stack, or EPSC_Invalid if there is no 
01470                 EPS command at the top of the stack.
01471     Purpose:    Find out what command is on top of the stack.  The command is not removed
01472                 from the stack.  Numbers, strings, names, etc. do not count as being
01473                 commands.
01474     SeeAlso:    EPSStack::GetType
01475 
01476 ********************************************************************************************/
01477 
01478 EPSCommand EPSStack::ReadCmd()
01479 {
01480     EPSStackItem *pItem = static_cast<EPSStackItem*> ( GetHead () );
01481 
01482     if ( ( pItem == NULL ) || ( pItem->Type != EPSTYPE_COMMAND ) )
01483         return EPSC_Invalid;
01484     else
01485         return pItem->Data.Cmd;
01486 }
01487     
01488 /********************************************************************************************
01489 
01490 >   BOOL EPSStack::IsEmpty()
01491 
01492     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01493     Created:    13/10/93
01494     Returns:    Returns TRUE if the stack is empty, FALSE if it is not.
01495     Purpose:    Test to see if the stack is empty.
01496     SeeAlso:    EPSStack::GetCount();
01497 
01498 ********************************************************************************************/
01499 
01500 BOOL EPSStack::IsEmpty()
01501 {
01502     return ( GetCount () == 0 );
01503 }
01504 
01505 /********************************************************************************************
01506 
01507 >   void EPSStack::Dump(EPSFilter *pFilter)
01508 
01509     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01510     Created:    15/10/93
01511     Inputs:     Pointer to the filter that this stack is owned by.
01512     Purpose:    Dump out the contents of the stack to the debug window.
01513                 The stack is unchanged.
01514 
01515 ********************************************************************************************/
01516 
01517 void EPSStack::Dump(EPSFilter *pFilter)
01518 {
01519 #if defined(_DEBUG)
01520     if (!Error::IsUserName("Tim") && !Error::IsUserName("Ben"))
01521         return;
01522 
01523     TRACE( _T("EPS STACK DUMP START\n\n")); 
01524     
01525     for ( DWORD i = 0; i < GetCount (); i++ )
01526     {
01527         EPSStackItem *pItem = static_cast<EPSStackItem*> ( FindItem ( i ) );
01528 
01529         switch (pItem->Type)
01530         {
01531             case EPSTYPE_COMMAND:
01532                 TRACE( _T("Command: %s\n"), pFilter->GetEPSCommand(pItem->Data.Cmd));
01533                 break;
01534                 
01535             case EPSTYPE_FIXEDPOINT:
01536                 TRACE( _T("Fixed point: %f\n"), ((double) pItem->Data.FixedPoint.Long) / FixedPointScale);
01537                 break;
01538                 
01539             case EPSTYPE_INT32:
01540                 TRACE( _T("Long: %ld\n"), pItem->Data.Long);
01541                 break;
01542                 
01543             case EPSTYPE_STRING:
01544                 TRACE( _T("String: '%s'\n"), pItem->Data.pString);
01545                 break;
01546                 
01547             case EPSTYPE_NAME:
01548                 TRACE( _T("Name: '%s'\n"), pItem->Data.pString);
01549                 break;
01550 
01551             case EPSTYPE_DOUBLE:
01552                 TRACE( _T("Double: %f\n"), pItem->Data.Double);
01553                 break;
01554                 
01555             case EPSTYPE_EMPTY:
01556             case EPSTYPE_NONE:
01557                 TRACE( _T("Empty/None\n"));
01558                 break;
01559 
01560             default:
01561                 TRACE( _T("Unknown type\n"));
01562                 break;
01563         }
01564 
01565     }
01566     
01567     TRACE( _T("\nEPS STACK DUMP END\n"));   
01568 #endif
01569 }
01570 

Generated on Sat Nov 10 03:45:06 2007 for Camelot by  doxygen 1.4.4