#include <ai_eps.h>
Inheritance diagram for AIEPSFilter:
Public Member Functions | |
AIEPSFilter () | |
Constructor for an AIEPSFilter object. The object should be initialised before use. | |
virtual BOOL | Init () |
Initialise an AIEPSFilter object. | |
BOOL | PrepareToExport (CCLexFile *, Spread *pSpread) |
Prepare to import EPS data using this filter. This sets up the filter to a sensible state for reading. | |
TCHAR * | GetEPSCommand (EPSCommand Cmd) |
Given an EPS token, return the string representation of it; mainly for debugging purposes. | |
virtual BOOL | NeedsPrintComponents (void) |
Informs the print components code that no data should be written. | |
Protected Member Functions | |
virtual BOOL | WriteNodes (RenderRegion *pRegion, ExportDC *pDC, BOOL VisibleLayersOnly, BOOL CheckSelected, BOOL ShowProgress) |
Exports the nodes from the tree. Unlike the standard export, the layer is dispatched first, followed by its children in their usual order. | |
virtual void | LookUpToken () |
Compare the current token against the AI keywords to see if it is one of them. | |
virtual BOOL | ProcessToken () |
Processes EPS tokens that are not part of the standard Illustrator set, or which need to be handled differently to the standard Illustrator meanings. i.e. this is the function that handles all the AI EPS operators. | |
INT32 | EPSHeaderIsOk (ADDR pFileHeader, UINT32 HeaderSize) |
Checks to see if the EPS comment headers specify that this is an AI generated EPS file, as required. | |
virtual void | ProcessTextMatrix (Matrix *pMatrix) |
Having read a text object position matrix from the file, we may (dependent on the filter type), need to process it in some way, ie add in the spread origin. | |
virtual BOOL | SetTextLineSpacing (INT32 Type, INT32 EMLSpace, MILLIPOINT MLSpace, double DLSpace) |
This is simply here to allow Illustrator import to catch attempts to set the line spacing to zero. | |
Protected Attributes | |
BOOL | bDoClip |
Static Protected Attributes | |
static CommandMap | AICommands [] |
Private Member Functions | |
CC_DECLARE_DYNAMIC (AIEPSFilter) |
Definition at line 130 of file ai_eps.h.
|
Constructor for an AIEPSFilter object. The object should be initialised before use.
Definition at line 161 of file ai_eps.cpp. 00162 { 00163 // Set up filter descriptions. 00164 FilterNameID = _R(IDT_AIEPS_FILTERNAME); 00165 FilterInfoID = _R(IDT_AIEPS_FILTERINFO); 00166 ImportMsgID = _R(IDT_IMPORTMSG_AI); 00167 00168 FilterID = FILTERID_AIEPS; 00169 00170 #ifndef STANDALONE 00171 Flags.CanImport = TRUE; 00172 //WEBSTER-Martin-27/01/97 00173 #ifdef WEBSTER 00174 Flags.CanExport = FALSE; 00175 #else 00176 Flags.CanExport = TRUE; 00177 #endif //WEBSTER 00178 #else 00179 Flags.CanImport = TRUE; 00180 Flags.CanExport = FALSE; 00181 #endif 00182 00183 AdjustOrigin = FALSE; // Illustrator gets it right... 00184 00185 bDoClip = FALSE; 00186 }
|
|
|
|
Checks to see if the EPS comment headers specify that this is an AI generated EPS file, as required.
Reimplemented from EPSFilter. Reimplemented in AI5EPSFilter, and AI8EPSFilter. Definition at line 230 of file ai_eps.cpp. 00231 { 00232 UINT32 Lines = 0; 00233 TCHAR *Buffer = NULL; 00234 00235 // !PS-Adobe line is ok - check creator line... 00236 CCMemTextFile HeaderFile ( reinterpret_cast<char *> ( pFileHeader ), HeaderSize ); 00237 00238 if( HeaderFile.IsMemFileInited () == FALSE || HeaderFile.InitLexer () == FALSE ) 00239 { 00240 HeaderFile.close(); 00241 return 0; 00242 } 00243 00244 // Graeme (28/6/00) - Adobe have changed their file format, and so the first line can 00245 // now be a %PDF directive. Therefore look for this directive in the first twenty 00246 // lines. 00247 while ( ( Lines < 100 ) && !HeaderFile.eof () ) 00248 { 00249 // Get the current line from the file. 00250 HeaderFile.GetLineToken(); 00251 Buffer = const_cast<TCHAR *> ( HeaderFile.GetTokenBuf () ); 00252 00253 // Ensure that it's OK. 00254 ERROR2IF(Buffer == 0, 0, "Returned buffer from lex file == 0"); 00255 00256 // Increment the line counter. 00257 Lines++; 00258 00259 if (camStrncmp(Buffer, _T("%!PS-Adobe"), 10) == 0) 00260 { 00261 // Now find the %%Creator string. 00262 while ((Lines < 100) && !HeaderFile.eof()) 00263 { 00264 HeaderFile.GetLineToken(); 00265 Buffer = const_cast<TCHAR *> ( HeaderFile.GetTokenBuf() ); 00266 ERROR2IF(Buffer == 0, 0, "Returned buffer from lex file == 0"); 00267 Lines++; 00268 00269 // Return TRUE if this file was created by Illustrator, or has been exported 00270 // in Illustrator format. 00271 if (camStrncmp(Buffer, _T("%%Creator: Adobe Illustrator"), 28) == 0) 00272 { 00273 // We definitely want this. 00274 HeaderFile.close(); 00275 return 9; 00276 } 00277 00278 // Another variation on the Illustrator theme 00279 if (camStrncmp(Buffer, _T("%%Creator: AI"), 13) == 0) 00280 { 00281 // We definitely want this. 00282 HeaderFile.close(); 00283 return 9; 00284 } 00285 00286 // yet another variation (see cru_logo.eps for this one) 00287 if (camStrncmp(Buffer, _T("%%Creator: ps2ai.ps"), 19) == 0) 00288 { 00289 HeaderFile.close (); 00290 return 9; 00291 } 00292 00293 // If there is a creator field, see if it mentions Illustrator 00294 // NOTE: this test must be the last one of the "Creator:" tests. 00295 if (camStrncmp(Buffer, _T("%%Creator:"), 10) == 0) 00296 { 00297 // Found the creator line - does it contain the word Illustrator? 00298 if (camStrstr( (const TCHAR*)Buffer, _T("Illustrator")) != NULL) 00299 { 00300 HeaderFile.close(); 00301 return 9; 00302 } 00303 else 00304 break; 00305 } 00306 00307 // If we find the compression token then stop the search as we don't want to 00308 // start looking in the compressed data! 00309 if (camStrncmp(Buffer, _T("%%Compression:"), 14)==0) 00310 break; 00311 } 00312 00313 // Remember to close the file before returning. 00314 HeaderFile.close(); 00315 00316 // Didn't find a suitable Creator line, but the EPS line was ok, so return 00317 // that we're interested, but not sure. 00318 return 5; 00319 } 00320 00321 // If we find the compression token then stop the search as we don't want to start 00322 // looking in the compressed data! 00323 if (camStrncmp(Buffer, _T("%%Compression:"), 14)==0) 00324 break; 00325 } 00326 00327 // Remember to close the file before returning. 00328 HeaderFile.close(); 00329 00330 // This file type isn't suitable. 00331 return 0; 00332 }
|
|
Given an EPS token, return the string representation of it; mainly for debugging purposes.
Reimplemented from EPSFilter. Reimplemented in AI5EPSFilter. Definition at line 735 of file ai_eps.cpp. 00736 { 00737 INT32 i = 0; 00738 while (AICommands[i].Cmd != EPSC_Invalid) 00739 { 00740 if (AICommands[i].Cmd == Cmd) 00741 return AICommands[i].CmdStr; 00742 00743 // Try next command 00744 i++; 00745 } 00746 00747 // Couldn't find it - default to base class method 00748 return EPSFilter::GetEPSCommand(Cmd); 00749 }
|
|
Initialise an AIEPSFilter object.
Reimplemented from EPSFilter. Reimplemented in AI5EPSFilter, and AI8EPSFilter. Definition at line 201 of file ai_eps.cpp. 00202 { 00203 // Get the OILFilter object 00204 pOILFilter = new AIEPSOILFilter(this); 00205 if (pOILFilter == NULL) 00206 return FALSE; 00207 00208 // Load the description strings 00209 FilterName.Load(FilterNameID); 00210 FilterInfo.Load(FilterInfoID); 00211 00212 bDoClip = FALSE; 00213 00214 // All ok 00215 return TRUE; 00216 }
|
|
Compare the current token against the AI keywords to see if it is one of them.
Reimplemented from EPSFilter. Reimplemented in AI5EPSFilter, and AI8EPSFilter. Definition at line 394 of file ai_eps.cpp. 00395 { 00396 // Not interested in comments 00397 if (Token == EPSC_Comment) 00398 return; 00399 00400 // Check to see if it is a keyword - cycle through the array of keyword names and 00401 // compare against our token (could use a hash table?) 00402 INT32 i = 0; 00403 while (AICommands[i].Cmd != EPSC_Invalid) 00404 { 00405 if (camStrcmp(TokenBuf, AICommands[i].CmdStr) == 0) 00406 { 00407 // Found the token - set the token variable and return success 00408 Token = AICommands[i].Cmd; 00409 return; 00410 } 00411 // Try next command 00412 i++; 00413 } 00414 00415 // Did not find this token - pass on to base class. 00416 EPSFilter::LookUpToken(); 00417 }
|
|
Informs the print components code that no data should be written.
Reimplemented from EPSFilter. Definition at line 762 of file ai_eps.cpp. 00763 { 00764 // We don't want print components! 00765 return FALSE; 00766 }
|
|
Prepare to import EPS data using this filter. This sets up the filter to a sensible state for reading.
Reimplemented from EPSFilter. Definition at line 351 of file ai_eps.cpp. 00352 { 00353 // Use base class to do most of it 00354 if (!EPSFilter::PrepareToExport(pFile, pSpread)) 00355 return FALSE; 00356 00357 // Create a new render region to export to: 00358 00359 // Don't care about clip regions when exporting - create a null region. 00360 DocRect NullClipRect; 00361 NullClipRect.MakeEmpty(); 00362 00363 // Don't use rendering matrix when exporting EPS as it uses fractional coordinates. 00364 Matrix Identity; 00365 00366 // Don't use view scale; set to 1 00367 FIXED16 Scale(1); 00368 00369 // Create the region specific to our filter. 00370 ExportRegion = new AIEPSRenderRegion(NullClipRect, Identity, Scale); 00371 if (ExportRegion == NULL) 00372 return FALSE; 00373 00374 // Attach to the right device. 00375 ExportRegion->AttachDevice(DocView::GetSelected(), ExportDCPtr->GetDC(), pSpread); 00376 00377 // All ok 00378 return TRUE; 00379 };
|
|
Having read a text object position matrix from the file, we may (dependent on the filter type), need to process it in some way, ie add in the spread origin.
Reimplemented from EPSFilter. Definition at line 861 of file ai_eps.cpp. 00862 { 00863 // We need to find the current import spread 00864 // and add in the spread origin to this matrix. 00865 DocCoord pos,result; 00866 pMatrix->GetTranslation(pos); 00867 if (ImportInfo.pSpread->PagesCoordToSpreadCoord(&result,pos)) 00868 pMatrix->SetTranslation(result); 00869 }
|
|
Processes EPS tokens that are not part of the standard Illustrator set, or which need to be handled differently to the standard Illustrator meanings. i.e. this is the function that handles all the AI EPS operators.
Reimplemented from EPSFilter. Reimplemented in AI5EPSFilter, and AI8EPSFilter. Definition at line 434 of file ai_eps.cpp. 00435 { 00436 // Decode the command, and execute it... 00437 switch (Token) 00438 { 00439 // 00440 // Various random text stuff - ignore it for now. 00441 // 00442 00443 case EPSC_z: 00444 if (!Stack.Discard(5)) 00445 goto EPSError; 00446 break; 00447 00448 case EPSC_e: 00449 if (!Stack.DiscardArray()) 00450 goto EPSError; 00451 break; 00452 00453 case EPSC_t: 00454 if (!Stack.Discard()) 00455 goto EPSError; 00456 break; 00457 00458 case EPSC_T: 00459 break; 00460 00461 // These are the new implementations of the appropriate illustrator tokens. 00462 // In order to work properly and handle complex paths properly, the 00463 // stroking and filling commands have to do something different if they're 00464 // in the middle of some kind of complex path or other 00465 00466 /* 00467 /N % - N - 00468 { 00469 _pola 0 eq 00470 { 00471 _doClip 1 eq {clip /_doClip 0 ddef} if 00472 newpath 00473 } 00474 { 00475 /CRender {N} ddef 00476 }ifelse 00477 } def 00478 00479 */ 00480 case EPSC_N: 00481 case EPSC_n: 00482 if (EPSFlags.ComplexPath == 0) 00483 { 00484 if (bDoClip) 00485 { 00486 // cannot continue as there's no path 00487 if (pInkPath == NULL) 00488 goto EPSError; 00489 00490 if (!ClipRegion.AddNewClippingPath(pInkPath)) 00491 // Error! 00492 return FALSE; 00493 00494 bDoClip = FALSE; 00495 pInkPath->ClearPath(); 00496 delete pPath; 00497 pPath = NULL; 00498 pInkPath = NULL; 00499 } 00500 else 00501 { 00502 // Graeme (14/4/00) - Catch NULL pointers. 00503 if ( pInkPath != NULL ) 00504 { 00505 // Deleting pInkPath throws access violations, which basically break 00506 // the import proceedure. Do not add a delete pInkPath line here! 00507 pInkPath->ClearPath (); 00508 pInkPath = NULL; 00509 } 00510 00511 // Delete isn't worried about NULL pointers. 00512 delete pPath; 00513 pPath = NULL; 00514 } 00515 } 00516 else 00517 { 00518 // We have a deferred render situation. Simply remember the token 00519 DeferredToken = Token; 00520 } 00521 break; 00522 00523 /* 00524 /W % - W - 00525 { 00526 /_doClip 1 ddef 00527 } def 00528 */ 00529 00530 case EPSC_W: 00531 bDoClip = TRUE; 00532 break; 00533 00534 /*u % - *u - 00535 { 00536 _pola 1 add /_pola exch ddef 00537 } def 00538 */ 00539 case EPSC__u: 00540 EPSFlags.ComplexPath++; 00541 break; 00542 00543 /*U % - *U - 00544 { 00545 _pola 1 sub /_pola exch ddef 00546 _pola 0 eq {CRender} if 00547 } def 00548 */ 00549 case EPSC__U: 00550 EPSFlags.ComplexPath--; 00551 if (EPSFlags.ComplexPath <0) 00552 return FALSE; 00553 if (EPSFlags.ComplexPath == 0) 00554 { 00555 EPSCommand oldToken = Token; 00556 Token = DeferredToken; 00557 if (!ProcessToken()) 00558 return FALSE; 00559 Token = oldToken; 00560 } 00561 break; 00562 00563 00564 // Now come the actualy path rendering primitives 00565 // These basically amount to either stroking or 00566 // filling the path, or both. However, if the 00567 // ComplexPath flag is not zero, they will do nothing 00568 // and merely record their token as the deferred token 00569 // Allowing the *U operator to render them at the end 00570 // of the complex group. 00571 // Clipping is equally complicated - if bDoClip is set 00572 // when ComplexPath is zero, it adds the current path 00573 // to the clipping region (i.e. clips to the clipping 00574 // region). 00575 // if bDoClip is zero (FALSE) then it goes ahead and 00576 // renders the path as it normally would 00577 /* 00578 /N % - N - 00579 { 00580 _pola 0 eq 00581 { 00582 _doClip 1 eq {clip /_doClip 0 ddef} if 00583 newpath 00584 } 00585 { 00586 /CRender {N} ddef 00587 }ifelse 00588 } def 00589 /n % - n - 00590 {N} def 00591 /F % - F - 00592 { 00593 _pola 0 eq 00594 { 00595 _doClip 1 eq 00596 { 00597 gsave _pf grestore clip newpath /_lp /none ddef _fc 00598 /_doClip 0 ddef 00599 } 00600 { 00601 _pf 00602 }ifelse 00603 } 00604 { 00605 /CRender {F} ddef 00606 }ifelse 00607 } def 00608 /f % - f - 00609 { 00610 closepath 00611 F 00612 } def 00613 /S % - S - 00614 { 00615 _pola 0 eq 00616 { 00617 _doClip 1 eq 00618 { 00619 gsave _ps grestore clip newpath /_lp /none ddef _sc 00620 /_doClip 0 ddef 00621 } 00622 { 00623 _ps 00624 }ifelse 00625 } 00626 { 00627 /CRender {S} ddef 00628 }ifelse 00629 } def 00630 /s % - s - 00631 { 00632 closepath 00633 S 00634 } def 00635 /B % - B - 00636 { 00637 _pola 0 eq 00638 { 00639 _doClip 1 eq % F clears _doClip 00640 gsave F grestore 00641 { 00642 gsave S grestore clip newpath /_lp /none ddef _sc 00643 /_doClip 0 ddef 00644 } 00645 { 00646 S 00647 }ifelse 00648 } 00649 { 00650 /CRender {B} ddef 00651 }ifelse 00652 } def 00653 /b % - b - 00654 { 00655 closepath 00656 B 00657 } def 00658 */ 00659 case EPSC_S: 00660 case EPSC_b: 00661 case EPSC_B: 00662 case EPSC_f: 00663 case EPSC_F: 00664 case EPSC_s: 00665 if (EPSFlags.ComplexPath > 0) 00666 { 00667 DeferredToken = Token; 00668 break; 00669 } 00670 00671 if (bDoClip) 00672 { 00673 // cannot continue as there's no path 00674 if (pInkPath == NULL) 00675 goto EPSError; 00676 00677 if (!ClipRegion.AddNewClippingPath(pInkPath)) 00678 // Error! 00679 return FALSE; 00680 00681 bDoClip = FALSE; 00682 pInkPath->ClearPath(); 00683 delete pPath; 00684 pPath = NULL; 00685 pInkPath = NULL; 00686 break; 00687 } 00688 // Since now all we want is for it to do what the default 00689 // filter will do, pass it on. 00690 return EPSFilter::ProcessToken(); 00691 break; 00692 00693 case EPSC_H: 00694 case EPSC_h: 00695 // This operator does nothing in Illustrator. Let's follow suit: 00696 break; 00697 00698 00699 default: 00700 // Token not understood - pass on to base class 00701 return EPSFilter::ProcessToken(); 00702 } 00703 00704 00705 // No errors encountered while parsing this token and its operands. 00706 return TRUE; 00707 00708 00709 // Error handlers: 00710 EPSError: 00711 HandleEPSError(); 00712 return FALSE; 00713 00714 #if 0 00715 NoMemory: 00716 HandleNoMemory(); 00717 return FALSE; 00718 #endif 00719 }
|
|
This is simply here to allow Illustrator import to catch attempts to set the line spacing to zero.
Reimplemented from Filter. Definition at line 883 of file ai_eps.cpp. 00884 { 00885 BOOL isZero = FALSE; 00886 BOOL success = FALSE; 00887 00888 // is the line spacing going to be set to zero 00889 switch (Type) 00890 { 00891 case 0: // Em based 00892 if (EMLSpace) 00893 isZero = FALSE; 00894 else 00895 isZero = TRUE; 00896 break; 00897 00898 case 1: // Millipoint based 00899 if (MLSpace) 00900 isZero = FALSE; 00901 else 00902 isZero = TRUE; 00903 break; 00904 00905 case 2: // Proportional 00906 if (DLSpace) 00907 isZero = FALSE; 00908 else 00909 isZero = TRUE; 00910 } 00911 00912 // for some reason, Illustrator assumes that a line spacing of 0 actually 00913 // means 100% and confuses more capable apps by overriding this with 00914 // final-form (i.e. printing only) attributes. 00915 if (isZero) 00916 { 00917 success = EPSFilter::SetTextLineSpacing(2,0,0,1.0); 00918 } 00919 else 00920 { 00921 success = EPSFilter::SetTextLineSpacing(Type, EMLSpace, MLSpace, DLSpace); 00922 } 00923 00924 return success; 00925 }
|
|
Exports the nodes from the tree. Unlike the standard export, the layer is dispatched first, followed by its children in their usual order.
Reimplemented from Filter. Definition at line 790 of file ai_eps.cpp. 00795 { 00796 BOOL success = FALSE; 00797 00798 #ifdef DO_EXPORT 00799 00800 // Find the first node that we should export from this spread 00801 AIEPSRenderRegion *pAIEPSRR = static_cast<AIEPSRenderRegion*> ( pRegion ); 00802 Spread *pSpread = pRegion->GetRenderSpread (); 00803 Layer *pLayer = static_cast<Layer*> ( pSpread->FindFirstChild 00804 ( CC_RUNTIME_CLASS ( Layer ) ) ); 00805 Node *pBGNode = NULL; 00806 00807 // Set the background colour. 00808 DocColour bg(FlashFilter::GetPageColour ( pSpread, &pBGNode ) ); 00809 pRegion->SetBackgroundColour ( bg ); 00810 00811 // Export the file, but catch any file errors. 00812 try 00813 { 00814 // (ChrisG 5/4/2001) Find the first non-guide layer. 00815 while (pLayer && pLayer->IsGuide ()) 00816 { 00817 pLayer = pLayer->FindNextLayer (); 00818 } 00819 00820 // Export the layer and all the nodes if one is found. 00821 if (pLayer) 00822 { 00823 // Export the layer. 00824 pAIEPSRR->StartLayer ( pLayer ); 00825 00826 // Invoke the base class WriteNodes function. 00827 success = Filter::WriteNodes ( pRegion, pDC, VisibleLayersOnly, CheckSelected, 00828 ShowProgress ); 00829 } 00830 } // TRY 00831 00832 catch ( CFileException) 00833 { 00834 // Didn't work - report failure to caller. 00835 if ( pDC ) 00836 pDC->ExportFile->SetThrowExceptions ( FALSE ); 00837 pRegion->StopRender (); 00838 if ( ShowProgress ) 00839 EndSlowJob (); 00840 success = FALSE; 00841 } 00842 00843 #endif 00844 00845 return success; 00846 }
|
|
Initial value: { { EPSC_z, _T("z")}, { EPSC_e, _T("e")}, { EPSC_T, _T("T")}, { EPSC_t, _T("t")}, { EPSC_Invalid, _T("Invalid") } } |
|
|