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