00001 // $Id: saveeps.cpp 1433 2006-07-11 15:47:28Z 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 // RenderRegion derived classes to export Camelot documents in EPS format. 00100 00101 /* 00102 */ 00103 00104 #include "camtypes.h" 00105 #include "saveeps.h" 00106 00107 //#include <afxdlgs.h> 00108 #include <ctype.h> 00109 #include <time.h> 00110 00111 //#include "pathname.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00113 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 #include "paper.h" 00116 #include "nodepath.h" 00117 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00118 #include "lineattr.h" 00119 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00120 //#include "tim.h" 00121 #include "kerneldc.h" 00122 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00123 //#include "userenv.h" 00124 //#include "doccomp.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00125 #include "colourix.h" 00126 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00127 #include "cameleps.h" 00128 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00129 //#include "txtattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00130 #include "nodetext.h" 00131 #include "psrndrgn.h" 00132 #include "psdc.h" 00133 #include "nativeps.h" // The old style EPS native filter, used in v1.1 00134 //#include "fixmem.h" // for CCFree() - in camtypes.h [AUTOMATICALLY REMOVED] 00135 //#include "release.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00136 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00137 #include "fontman.h" 00138 #include "colplate.h" 00139 #include "clipattr.h" // for ClipRegionAttribute. 00140 00141 CC_IMPLEMENT_DYNAMIC(EPSRenderRegion, VectorFileRenderRegion) 00142 00143 /******************************************************************************************** 00144 00145 > EPSRenderRegion::EPSRenderRegion(DocRect ClipRect, Matrix ConvertMatrix, 00146 FIXED16 ViewScale) : 00147 RenderRegion(ClipRect, ConvertMatrix, ViewScale) 00148 00149 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00150 Created: 28/10/93 00151 Purpose: Constructor for an EPSOutputFilter object. The object should be initialised 00152 before use. 00153 SeeAlso: EPSOutputFilter::Init 00154 00155 ********************************************************************************************/ 00156 00157 EPSRenderRegion::EPSRenderRegion(DocRect ClipRect, Matrix ConvertMatrix, FIXED16 ViewScale) : 00158 VectorFileRenderRegion(ClipRect, ConvertMatrix, ViewScale) 00159 { 00160 ValidPen = FALSE; 00161 CreatorString = _T("Adobe Illustrator 3.0 (exported by Camelot)"); 00162 00163 ExportFile = NULL; 00164 m_bValidPathAttrs = TRUE; 00165 m_bValidTextAttrs = TRUE; 00166 } 00167 00168 00169 /******************************************************************************************** 00170 00171 > BOOL EPSRenderRegion::Init() 00172 00173 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00174 Created: 28/10/93 00175 Returns: TRUE if the filter was initialised ok, FALSE otherwise. 00176 Purpose: Initialise an EPSOutputFilter object. 00177 Errors: Will fail if not enough memory to initialise the EPS stack. 00178 SeeAlso: EPSStack 00179 00180 ********************************************************************************************/ 00181 00182 BOOL EPSRenderRegion::Init() 00183 { 00184 // Initialise all member variables. 00185 ValidPen = FALSE; 00186 LastOutputAttrs = NULL; 00187 ExportFile = NULL; 00188 CreatorString = NULL; 00189 00190 m_bValidPathAttrs = TRUE; 00191 m_bValidTextAttrs = TRUE; 00192 00193 // All ok 00194 return TRUE; 00195 } 00196 00197 00198 /******************************************************************************************** 00199 00200 > BOOL EPSRenderRegion::AttachDevice(View* pView, CDC* pDC, Spread* pSpread) 00201 00202 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00203 Created: 30/03/94 00204 Inputs: pView - the view to attach this region to - ignored (must be NULL). 00205 pDC - the device context to attach the render region to. 00206 pSpread - the spread to attach the render region to. 00207 Purpose: Attach the EPS render region to a device context and a spread to export. 00208 SeeAlso: RenderRegion::AttachDevice; EPSExportDC 00209 00210 ********************************************************************************************/ 00211 00212 BOOL EPSRenderRegion::AttachDevice(View* pView, CNativeDC* pDC, Spread* pSpread, bool /*fOwned = false*/) 00213 { 00214 // Sanity checks 00215 // ENSURE(pView == NULL, "Bad window pointer in EPSRenderRegion::AttachDevice"); 00216 00217 // Call the base class first 00218 if (!RenderRegion::AttachDevice(pView, pDC, pSpread)) 00219 return FALSE; 00220 00221 // Save the first node we need to export. 00222 // CurrentRenderState = pSpread->FindFirstForExport(this, FALSE); 00223 00224 // Get a pointer to the CCDiskFile object 00225 EPSExportDC* pEPSDC = (EPSExportDC*) CCDC::ConvertFromNativeDC(pDC); 00226 ExportFile = pEPSDC->ExportFile; 00227 00228 // All okey dokey 00229 return TRUE; 00230 } 00231 00232 00233 /******************************************************************************************** 00234 00235 > BOOL EPSRenderRegion::InitDevice () 00236 00237 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00238 Created: 09/05/95 00239 Returns: TRUE if the device context is initialised ok; 00240 FALSE if not. 00241 Purpose: Initialise the device specific mechanisms for this render region. 00242 Errors: Same as base class. 00243 SeeAlso: RenderRegion::InitDevice 00244 00245 ********************************************************************************************/ 00246 00247 BOOL EPSRenderRegion::InitDevice () 00248 { 00249 // Call base class 00250 if (!RenderRegion::InitDevice()) 00251 return FALSE; 00252 00253 // Set the render caps up 00254 GetRenderRegionCaps(&Caps); 00255 00256 // Buffer used to build up the %%For and %%CreationDate comments. 00257 TCHAR buf[300]; 00258 00259 // Find out which document we're using 00260 ENSURE(RenderView->GetDoc() != NULL, "View's document is NULL!"); 00261 Document *TheDocument = RenderView->GetDoc(); 00262 00263 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00264 00265 // Output the standard EPS header affair... 00266 WriteEPSVersion (); 00267 00268 // Name of program that created this file. 00269 pDC->OutputToken ( _T("%%Creator:") ); 00270 pDC->OutputToken ( CreatorString ); 00271 pDC->OutputNewLine (); 00272 00273 // File version saving. In anything but Native format does nothing 00274 WriteFileVersion ( pDC ); 00275 00276 // Output the %%For comment 00277 camSprintf(buf, _T("%%%%For: (%s) (%s)"), ReleaseInfo::GetLicensee(), ReleaseInfo::GetCompany()); 00278 pDC->OutputToken(buf); 00279 pDC->OutputNewLine(); 00280 00281 // The title of the picture 00282 String_256 DocumentTitle = TheDocument->GetTitle(); 00283 camSprintf(buf, _T("%%%%Title: (%s)"), (TCHAR *) DocumentTitle); 00284 pDC->OutputToken(buf); 00285 pDC->OutputNewLine(); 00286 00287 // Date this file was created. 00288 time_t Now; 00289 time(&Now); 00290 struct tm *pNow = localtime(&Now); 00291 #if 1 00292 char buf2[100]; 00293 strftime(buf2, 100, "%%%%CreationDate: (%d/%m/%y) (%I:%M %p)", pNow); 00294 INT32 i=0; 00295 char c; 00296 do 00297 { 00298 c=buf2[i]; 00299 buf[i]=c; // 1:1 char/TCHAR conversion 00300 i++; 00301 } while (c); 00302 00303 #else 00304 _tcsftime(buf, 100, "%%%%CreationDate: (%d/%m/%y) (%I:%M %p)", pNow); 00305 #endif 00306 pDC->OutputToken(buf); 00307 pDC->OutputNewLine(); 00308 00309 // Bounding box. 00310 WriteEPSBoundingBox (); 00311 00312 // Get a handle to our filter 00313 EPSExportDC *pExportDC = (EPSExportDC *) pDC; 00314 EPSFilter *pFilter = (EPSFilter *) pExportDC->GetParentFilter(); 00315 00316 // Write out the document's process colours. (Only for AIEPS.) 00317 WriteEPSProcessColours (); 00318 00319 // Write out the Documents fonts 00320 TheDocument->WriteEPSFonts ( pFilter ); 00321 00322 // Write out the Documents resources 00323 WriteEPSResources ( pFilter, TheDocument ); 00324 00325 // Write out the Documents comments 00326 TheDocument->WriteEPSComments ( pFilter ); 00327 00328 // We can say compress this file if native. 00329 // We will leave the document comments in so that things like the clipart gallery 00330 // can still easily access this useful information. 00331 // 00332 // Compressed saving. In anything but Native format does nothing 00333 WriteCompressionState ( pDC ); 00334 00335 // Get all the document components to output their header comments (if any) 00336 DocComponent *pComponent = TheDocument->EnumerateDocComponents ( NULL ); 00337 00338 while (pComponent != NULL) 00339 { 00340 // Inform this document component that we are about to start an EPS export. 00341 pComponent->WriteEPSComments(pFilter); 00342 00343 // Look for next doc component 00344 pComponent = TheDocument->EnumerateDocComponents(pComponent); 00345 } 00346 00347 // No more comments 00348 pDC->OutputToken ( _T("%%EndComments") ); 00349 pDC->OutputNewLine (); 00350 00351 // Do the prolog... 00352 pDC->OutputToken ( _T("%%BeginProlog") ); 00353 pDC->OutputNewLine (); 00354 00355 // Do the render region specific prolog. 00356 WriteProlog ( pDC ); 00357 00358 // Write out the document,s Prolog script. 00359 WriteEPSProlog ( pFilter, TheDocument ); 00360 00361 // and the doc components prolog 00362 pComponent = TheDocument->EnumerateDocComponents(NULL); 00363 while (pComponent != NULL) 00364 { 00365 // Get this document component to write its EPS prolog out to the file. 00366 pComponent->WriteEPSProlog(pFilter); 00367 00368 // Look for next doc component 00369 pComponent = TheDocument->EnumerateDocComponents(pComponent); 00370 } 00371 00372 pDC->OutputToken(_T("%%EndProlog")); 00373 pDC->OutputNewLine(); 00374 00375 // Do the setup... 00376 pDC->OutputToken(_T("%%BeginSetup")); 00377 pDC->OutputNewLine(); 00378 00379 // Do the render region specific setup. 00380 WriteSetup ( pDC ); 00381 00382 // Write out the font definition. 00383 WriteDocumentSetup ( TheDocument, pFilter ); 00384 00385 // and the components setup 00386 pComponent = TheDocument->EnumerateDocComponents(NULL); 00387 while (pComponent != NULL) 00388 { 00389 // Get this document component to write its EPS setup out to the file. 00390 pComponent->WriteEPSSetup(pFilter); 00391 00392 // Look for next doc component 00393 pComponent = TheDocument->EnumerateDocComponents(pComponent); 00394 } 00395 00396 // Parse through the tree, locate the gradient fills, and write them out 00397 // to the file. 00398 WriteGradientFills ( TheDocument ); 00399 00400 // Wrap up the header section 00401 pDC->OutputToken(_T("%%EndSetup")); 00402 pDC->OutputNewLine(); 00403 00404 // We are into the main script of the EPS file here, so give the 00405 // doc components one last chance to write something out 00406 pComponent = TheDocument->EnumerateDocComponents(NULL); 00407 00408 while (pComponent != NULL) 00409 { 00410 // Get this document component to write its EPS Script data to the file 00411 pComponent->WriteScript(pFilter); 00412 00413 // Look for next doc component 00414 pComponent = TheDocument->EnumerateDocComponents(pComponent); 00415 } 00416 00417 // Set up render region 00418 InitClipping (); 00419 00420 // All ok 00421 return TRUE; 00422 } 00423 00424 /******************************************************************************************** 00425 00426 > BOOL EPSRenderRegion::CloseDown() 00427 00428 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00429 Created: 05/09/95 00430 Returns: TRUE if region was shut down ok; 00431 FALSE if not. 00432 Purpose: Tells the EPS render region that all rendering is finished and the region 00433 is about to be shut down, so it should output any trailer etc that is 00434 required. 00435 00436 ********************************************************************************************/ 00437 00438 BOOL EPSRenderRegion::CloseDown() 00439 { 00440 // Close down any active layers. 00441 EndLayer (); 00442 00443 // Write out the trailer. 00444 WriteEPSTrailerComments (); 00445 00446 return TRUE; 00447 } 00448 00449 /******************************************************************************************** 00450 00451 > BOOL EPSRenderRegion::SaveAttribute(UINT32 Index, AttributeValue *pAttr, BOOL Temp) 00452 00453 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00454 Created: 20/04/95 00455 Inputs: Index - Unique attribute ID (See AttributeManager::RegisterDefaultAttribute). 00456 pAttr - the new attribute to use as the current one. 00457 Temp - TRUE if pAttr points to a temporary object, FALSE if not. 00458 Returns: TRUE if the operation completed successfully, FALSE if not. 00459 Purpose: Saves the current attribute on the attribute context stack, and installs 00460 the given attribute as the new attribute. 00461 If the attribute object is temporary, then it is deleted when the attribute 00462 is popped off the stack. See RenderRegion::RestoreAttribute 00463 00464 Errors: Out of memory. 00465 SeeAlso: AttributeManager::RegisterDefaultAttribute 00466 00467 ********************************************************************************************/ 00468 00469 BOOL EPSRenderRegion::SaveAttribute(UINT32 Index, AttributeValue *pAttr, BOOL Temp) 00470 { 00471 // Push the current attribute onto the stack, and install the new attribute as 00472 // the 'current' one. 00473 if (TheStack.Push(CurrentAttrs[Index].pAttr, CurrentAttrs[Index].Temp)) 00474 { 00475 CurrentAttrs[Index].pAttr = pAttr; 00476 CurrentAttrs[Index].Temp = Temp; 00477 00478 // Everything worked ok. 00479 return TRUE; 00480 } 00481 00482 // Failed 00483 return FALSE; 00484 } 00485 00486 /******************************************************************************************** 00487 > BOOL EPSRenderRegion::RenderChar(WCHAR ch, Matrix* pMatrix) 00488 00489 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 00490 Created: 19/3/95 00491 Inputs: ch - unicode value of TCHAR 00492 pMatrix - matrix specifying transforms to place TCHAR correctly in document 00493 Returns: FALSE if fails 00494 Purpose: 00495 ********************************************************************************************/ 00496 00497 BOOL EPSRenderRegion::RenderChar(WCHAR ch, Matrix* pMatrix) 00498 { 00499 // If we are not drawing complex shapes and this shape is, then return 00500 if ((!RenderComplexShapes) && (TestForComplexShape(&Caps))) 00501 return TRUE; 00502 00503 ERROR2IF( this==NULL,FALSE,"RenderRegion::RenderChar() - this==NULL"); 00504 ERROR2IF(pMatrix==NULL,FALSE,"RenderRegion::RenderChar() - pMatrix==NULL"); 00505 00506 00507 #if EXPORT_TEXT 00508 // Check for changed attributes 00509 GetValidPathAttributes(); 00510 GetValidTextAttributes(); 00511 00512 // BODGE TEXT - need to account for unicode! 00513 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00514 00515 TCHAR Buf[64]; 00516 00517 camSprintf(Buf,_T("%c"),ch); 00518 00519 pDC->OutputString(Buf); 00520 pDC->OutputToken(_T("Tx")); 00521 pDC->OutputNewLine(); 00522 00523 #else 00524 // just do what RenderRegion::RenderChar() would do! 00525 00526 // create the TCHAR's path 00527 Path* pCharPath=CreateCharPath(ch,pMatrix); 00528 if (pCharPath==NULL) 00529 return FALSE; 00530 00531 // draw path using current attibutes in render region 00532 if (pCharPath->GetNumCoords()!=0) 00533 DrawPath(pCharPath); 00534 00535 // clean up 00536 delete pCharPath; 00537 #endif 00538 00539 return TRUE; 00540 } 00541 00542 /******************************************************************************************** 00543 00544 > BOOL EPSRenderRegion::WriteNewLine ( void ) 00545 00546 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00547 Created: 27/4/00 00548 Inputs: - 00549 Returns: TRUE - Success. 00550 FALSE - Failure. 00551 Purpose: Outputs a new line tag to the file. 00552 00553 ********************************************************************************************/ 00554 00555 BOOL EPSRenderRegion::WriteNewLine ( void ) 00556 { 00557 EPSExportDC *pDC = static_cast<EPSExportDC*> ( CCDC::ConvertFromNativeDC(RenderDC) ); 00558 00559 // Check for changed attributes. 00560 GetValidPathAttributes (); 00561 GetValidTextAttributes (); 00562 00563 // Output the tokens 00564 pDC->OutputToken ( _T("(\\r)") ); 00565 pDC->OutputToken ( _T("TX") ); 00566 pDC->OutputNewLine (); 00567 00568 return TRUE; 00569 } 00570 00571 /******************************************************************************************** 00572 00573 > void EPSRenderRegion::OutputFontName() 00574 00575 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00576 Created: 18/4/95 00577 Purpose: Output an Illustrator format fontname and pointsize token. The format is 00578 /_fontname[-Bold|-Italic|-BoldItalic] pointsize Tf. 00579 EncodeFontName will generate this format from an internal fontname. 00580 DocodeFontName will return an internal format fontname and flags where nec. 00581 00582 ********************************************************************************************/ 00583 00584 void EPSRenderRegion::OutputFontName() 00585 { 00586 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00587 00588 String_64 FontName; 00589 String_64 EncodedFontName; 00590 String_64 Append(_T("/_")); 00591 00592 // get information about the current font 00593 FONTMANAGER->GetFontName(RR_TXTFONTTYPEFACE(), FontName); 00594 00595 // Graeme (31-3-00) - I've lifted this piece of code from the CamelotEPSRenderRegion. It 00596 // appears to map an existing, encoded font name onto its Postscript counterpart. 00597 FONTMANAGER->EncodeAndMapFontName(FontName, EncodedFontName, GetFontStyle()); 00598 00599 EncodedFontName.Insert(Append,0); 00600 pDC->OutputToken((TCHAR *)EncodedFontName); 00601 00602 // Output the fontsize next 00603 double PointSize = ((double)RR_TXTFONTSIZE())/1000; 00604 pDC->OutputFloat(PointSize,3); 00605 00606 // finally do output the font token 00607 pDC->OutputToken(_T("Tf")); 00608 pDC->OutputNewLine(); 00609 } 00610 00611 00612 /******************************************************************************************** 00613 00614 > INT32 EPSRenderRegion::GetFontStyle() 00615 00616 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00617 Created: 18/4/95 00618 Purpose: Compile the current style attributes. 00619 00620 ********************************************************************************************/ 00621 00622 INT32 EPSRenderRegion::GetFontStyle() 00623 { 00624 INT32 Style = 0; 00625 if (RR_TXTBOLD()) Style+=1; 00626 if (RR_TXTITALIC()) Style+=2; 00627 return Style; 00628 } 00629 00630 00631 // 00632 // These are the functions that actually do the exporting... 00633 /******************************************************************************************** 00634 00635 > void EPSRenderRegion::GetValidTextAttributes() 00636 00637 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 00638 Created: 30/03/94 00639 Purpose: Text equivalent of GetValidPathAttributes(). 00640 00641 ********************************************************************************************/ 00642 00643 void EPSRenderRegion::GetValidTextAttributes() 00644 { 00645 // Illustrator does not specify a token for changing 00646 // -fontsize 00647 // -bold 00648 // -italic 00649 // We need to use the standard Tf token. (see OutputFontName) 00650 00651 BOOL FontOut = FALSE; 00652 if (SetLastOutputAttribute(ATTR_TXTFONTTYPEFACE)) 00653 { 00654 FontOut=TRUE; 00655 } 00656 00657 if (SetLastOutputAttribute(ATTR_TXTFONTSIZE)) 00658 { 00659 FontOut=TRUE; 00660 } 00661 00662 if (SetLastOutputAttribute(ATTR_TXTBOLD)) 00663 { 00664 FontOut=TRUE; 00665 } 00666 00667 if (SetLastOutputAttribute(ATTR_TXTITALIC)) 00668 { 00669 FontOut=TRUE; 00670 } 00671 00672 if (!m_bValidTextAttrs) 00673 { 00674 FontOut = TRUE; 00675 } 00676 00677 // ok check whether a font change needs generating 00678 if (FontOut) 00679 OutputFontName(); 00680 00681 00682 BOOL FillNLine = FALSE; 00683 if (SetLastOutputAttribute(ATTR_STROKECOLOUR)) 00684 { 00685 FillNLine = TRUE; 00686 } 00687 00688 if (SetLastOutputAttribute(ATTR_FILLGEOMETRY)) 00689 { 00690 FillNLine = TRUE; 00691 } 00692 00693 if (!m_bValidTextAttrs) 00694 { 00695 FillNLine = TRUE; 00696 } 00697 00698 // Text Render mode needs changing as Text has gained or lost fill and/or 00699 // line colours 00700 if (FillNLine) 00701 { 00702 OutputTextRenderMode (); 00703 } 00704 00705 if (SetLastOutputAttribute(ATTR_TXTASPECTRATIO) || !m_bValidTextAttrs) 00706 { 00707 OutputTextAspectRatio (); 00708 } 00709 00710 if (SetLastOutputAttribute(ATTR_TXTTRACKING) || !m_bValidTextAttrs) 00711 { 00712 OutputTextTracking (); 00713 } 00714 00715 if (SetLastOutputAttribute(ATTR_TXTJUSTIFICATION) || !m_bValidTextAttrs) 00716 { 00717 OutputTextJustification (); 00718 } 00719 00720 // BODGE TEXT - should this be output before any lines rather than on a line 00721 // by line basis? 00722 if (SetLastOutputAttribute(ATTR_TXTLINESPACE) || !m_bValidTextAttrs) 00723 { 00724 OutputTextLineSpacing (); 00725 } 00726 00727 if (SetLastOutputAttribute(ATTR_TXTBASELINE) || !m_bValidTextAttrs) 00728 { 00729 OutputTextBaselineShift (); 00730 } 00731 00732 if (SetLastOutputAttribute(ATTR_TXTSCRIPT) || !m_bValidTextAttrs) 00733 { 00734 OutputTextSubSuperScript (); 00735 } 00736 00737 // The text attributes are now Definitely valid (as we've just written all of them) 00738 m_bValidTextAttrs = TRUE; 00739 } 00740 00741 00742 00743 /******************************************************************************************** 00744 00745 > void EPSRenderRegion::OutputTextRenderMode() 00746 00747 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00748 Created: 1/11/00 00749 Purpose: Output the change in the text's Render Mode (Tr) - this happens when the 00750 text's fill or line colour changes to or from blank, see-through colour 00751 00752 ********************************************************************************************/ 00753 00754 void EPSRenderRegion::OutputTextRenderMode () 00755 { 00756 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00757 00758 INT32 Style=0; 00759 00760 // Is there a currently active fill colour? 00761 if (! (RR_FILLCOLOUR().IsTransparent()) ) 00762 Style+=1; 00763 00764 // Is there a currently active line colour? 00765 if (! (RR_STROKECOLOUR().IsTransparent()) ) 00766 Style+=2; 00767 00768 switch (Style) 00769 { 00770 case 0: pDC->OutputToken(_T("3 Tr")); // Invisible 00771 pDC->OutputNewLine(); 00772 break; 00773 case 1: pDC->OutputToken(_T("0 Tr")); // filled only 00774 pDC->OutputNewLine(); 00775 break; 00776 case 2: pDC->OutputToken(_T("1 Tr")); // stroked only 00777 pDC->OutputNewLine(); 00778 break; 00779 case 3: pDC->OutputToken(_T("2 Tr")); // filled and stroked 00780 pDC->OutputNewLine(); 00781 break; 00782 } 00783 } 00784 00785 00786 00787 /******************************************************************************************** 00788 00789 > void EPSRenderRegion::OutputTextAspectRatio() 00790 00791 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00792 Created: 1/11/00 00793 Purpose: Output the change in the text's aspect ratio (Tx) 00794 00795 ********************************************************************************************/ 00796 00797 void EPSRenderRegion::OutputTextAspectRatio () 00798 { 00799 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00800 00801 pDC->OutputReal(RR_TXTASPECTRATIO().MakeDouble()*100.0); // convert from ratio to % 00802 pDC->OutputToken(_T("Tz")); 00803 pDC->OutputNewLine(); 00804 } 00805 00806 00807 00808 /******************************************************************************************** 00809 00810 > void EPSRenderRegion::OutputTextTracking() 00811 00812 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00813 Created: 1/11/00 00814 Purpose: Output the change in the tracking (Tt) 00815 00816 ********************************************************************************************/ 00817 00818 void EPSRenderRegion::OutputTextTracking () 00819 { 00820 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00821 00822 // Must be output in 1/1000 of an em. 00823 // 1 em = point size of font. 00824 // Tracking internally =millipoints. 00825 pDC->OutputValue(RR_TXTTRACKING()); 00826 pDC->OutputToken(_T("Tt")); 00827 pDC->OutputNewLine(); 00828 } 00829 00830 00831 00832 /******************************************************************************************** 00833 00834 > void EPSRenderRegion::OutputTextJustification() 00835 00836 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00837 Created: 1/11/00 00838 Purpose: Output the change in the text justification (Ta) 00839 00840 ********************************************************************************************/ 00841 00842 void EPSRenderRegion::OutputTextJustification () 00843 { 00844 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00845 00846 // Output aspect ratio in %, 100 is default 00847 switch (RR_TXTJUSTIFICATION()) 00848 { 00849 case JLEFT: 00850 pDC->OutputValue((INT32)0); 00851 break; 00852 case JRIGHT: 00853 pDC->OutputValue((INT32)2); 00854 break; 00855 case JCENTRE: 00856 pDC->OutputValue((INT32)1); 00857 break; 00858 case JFULL: 00859 pDC->OutputValue((INT32)3); 00860 break; 00861 } 00862 pDC->OutputToken(_T("Ta")); 00863 pDC->OutputNewLine(); 00864 } 00865 00866 /******************************************************************************************** 00867 00868 > void EPSRenderRegion::OutputTextLineSpacing() 00869 00870 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00871 Created: 1/11/00 00872 Purpose: Output the change in the line spacing (Tl) 00873 00874 ********************************************************************************************/ 00875 00876 void EPSRenderRegion::OutputTextLineSpacing () 00877 { 00878 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00879 00880 // Output line spacing in points. 00881 // format - paraspace linespace Tl 00882 double ptLineSpace; 00883 double ptParaSpace=0; 00884 00885 TxtLineSpaceAttribute* pLineSpace = (TxtLineSpaceAttribute*)(CurrentAttrs[ATTR_TXTLINESPACE].pAttr); 00886 00887 // There are some rules for reading the linespacing value which I shall divulge 00888 // If IsARation is true then use the proportinal linespacing value. 00889 // else use the absolute linespacing 00890 // However if the absolute linespacing is zero, then we MUST use the proportional 00891 // linespacing. Eeek! 00892 // ie it is an error if (absolute==0 && !IsARatio()) which we will check for here 00893 00894 double FontSize = (double)RR_TXTFONTSIZE(); // in millipoints 12pt = 12000 mp 00895 double absLineSpace = (double)pLineSpace->Value; 00896 double proLineSpace = (pLineSpace->Ratio).MakeDouble(); 00897 00898 BOOL Proportional = pLineSpace->IsARatio(); 00899 00900 if (!Proportional && absLineSpace==0) 00901 { 00902 ERROR3("Absolute line spacing is zero yet IsARatio() is FALSE, in GetValidTextAttributes()"); 00903 // Make sure we use the proportional value no matter what. 00904 Proportional=TRUE; 00905 } 00906 00907 if (Proportional) 00908 ptLineSpace = FontSize*proLineSpace/1000; 00909 else 00910 ptLineSpace = absLineSpace/1000; 00911 00912 pDC->OutputReal(ptLineSpace); 00913 pDC->OutputReal(ptParaSpace); 00914 pDC->OutputToken(_T("Tl")); 00915 pDC->OutputNewLine(); 00916 } 00917 00918 00919 /******************************************************************************************** 00920 00921 > void EPSRenderRegion::OutputTextBaselineShift() 00922 00923 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00924 Created: 1/11/00 00925 Purpose: Output the change in Baseline shift (Ts) 00926 00927 ********************************************************************************************/ 00928 00929 void EPSRenderRegion::OutputTextBaselineShift () 00930 { 00931 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00932 00933 // Output baseline shift in points 00934 // format = rise Ts 00935 double BaseLine = ((double)RR_TXTBASELINE())/1000; 00936 pDC->OutputFloat(BaseLine,3); 00937 pDC->OutputToken(_T("Ts")); 00938 pDC->OutputNewLine(); 00939 } 00940 00941 00942 /******************************************************************************************** 00943 00944 > void EPSRenderRegion::OutputTextSubSuperScript() 00945 00946 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00947 Created: 1/11/00 00948 Purpose: Output the change in the Sub/Super script attribute (Ts) 00949 00950 ********************************************************************************************/ 00951 00952 void EPSRenderRegion::OutputTextSubSuperScript () 00953 { 00954 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00955 00956 // Output sub/superscript 00957 double FontSize = ((double)RR_TXTFONTSIZE())/1000; // in millipoints 12pt = 12000 mp 00958 00959 TxtScriptAttribute* pScript = RR_TXTSCRIPT(); 00960 double offset = (pScript->Offset).MakeDouble(); 00961 double size = (pScript->Size).MakeDouble(); 00962 00963 pDC->OutputToken(_T("%%XSScript")); 00964 pDC->OutputNewLine(); 00965 00966 double rise = FontSize*offset; 00967 00968 pDC->OutputFloat(rise,3); 00969 pDC->OutputToken(_T("Ts")); 00970 pDC->OutputNewLine(); 00971 00972 double ptsize = FontSize*size; 00973 00974 String_64 MappedFont; 00975 String_64 Append(_T("/_")); 00976 00977 String_64 FontName; 00978 FONTMANAGER->GetFontName(RR_TXTFONTTYPEFACE(), FontName); 00979 00980 // Graeme (31-3-00) - Map the encoded name onto the PS font name. 00981 FONTMANAGER->EncodeAndMapFontName(FontName,MappedFont,GetFontStyle()); 00982 00983 // Graeme (14-6-00) - I should add ascent and descent values, but Camelot doesn't 00984 // seem to store them anywhere. 00985 MappedFont.Insert(Append,0); 00986 pDC->OutputToken((TCHAR *)MappedFont); 00987 pDC->OutputFloat(ptsize,3); 00988 // Output the ascent. 00989 // Output the descent. 00990 pDC->OutputToken(_T("Tf")); 00991 pDC->OutputNewLine(); 00992 } 00993 00994 /******************************************************************************************** 00995 00996 > void EPSRenderRegion::GetValidPathAttributes() 00997 00998 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> (Will) 00999 Created: 30/03/94 01000 Purpose: Ensure the EPS context has the correct attributes for drawing paths. 01001 This required because when the path attributes change, we don't output 01002 the EPS commands to reflect this straight away - we set a flag to indicate 01003 that the attributes have changed, and then when this function is called, 01004 it notices that the attributes have changed, and outputs the EPS commands 01005 to select these attributes. This avoids redundant and copious attribute 01006 code in our EPS files. 01007 (The flags used are ValidPen and FillFlags.ValidGeometry). 01008 01009 ********************************************************************************************/ 01010 01011 void EPSRenderRegion::GetValidPathAttributes() 01012 { 01013 // Path stroking. Do nothing if the stroke is transparent. 01014 // Note, if this changes you MUST investigate and change GetValidTextAttributes 01015 // cause this needs to output transparent stroke colours. 01016 if (SetLastOutputAttribute(ATTR_WINDINGRULE) || !m_bValidPathAttrs) 01017 { 01018 OutputWindingRule (); 01019 } 01020 01021 if (!RR_STROKECOLOUR().IsTransparent()) 01022 { 01023 if (SetLastOutputAttribute(ATTR_STROKECOLOUR) || !m_bValidPathAttrs) 01024 OutputStrokeColour(); 01025 } 01026 01027 if (SetLastOutputAttribute(ATTR_LINEWIDTH) || !m_bValidPathAttrs) 01028 OutputLineWidth(); 01029 01030 if (SetLastOutputAttribute(ATTR_JOINTYPE) || !m_bValidPathAttrs) 01031 OutputJoinType(); 01032 01033 // Set up the dash pattern first. 01034 OutputDashPatternInit(); 01035 if (SetLastOutputAttribute(ATTR_DASHPATTERN) || !m_bValidPathAttrs) 01036 OutputDashPattern(); 01037 01038 if (SetLastOutputAttribute(ATTR_STARTCAP) || !m_bValidPathAttrs) 01039 OutputStartCap(); 01040 01041 if (SetLastOutputAttribute(ATTR_MITRELIMIT) || !m_bValidPathAttrs) 01042 OutputMitreLimit(); 01043 01044 // Path filling 01045 01046 if (!RR_FILLCOLOUR().IsTransparent()) 01047 { 01048 if (SetLastOutputAttribute(ATTR_FILLGEOMETRY) || !m_bValidPathAttrs) 01049 OutputFillColour(); 01050 } 01051 01052 // The path attributes must be valid (as we've just written them). 01053 m_bValidPathAttrs = TRUE; 01054 01055 } 01056 01057 01058 01059 /******************************************************************************************** 01060 01061 > void EPSRenderRegion::OutputWindingRule() 01062 01063 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 01064 Created: 19/12/00 01065 Purpose: Output winding rule token to the EPS file 01066 01067 This doesn't actually do anything, it's just here so that derived classes can 01068 override it. 01069 01070 ********************************************************************************************/ 01071 01072 void EPSRenderRegion::OutputWindingRule () 01073 { 01074 01075 } 01076 01077 01078 01079 01080 /******************************************************************************************** 01081 01082 > void EPSRenderRegion::OutputLineWidth() 01083 01084 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01085 Created: 3/7/96 01086 Purpose: Output the standard line width token and measure for EPS 01087 01088 ********************************************************************************************/ 01089 01090 void EPSRenderRegion::OutputLineWidth() 01091 { 01092 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01093 01094 // Set line width 01095 pDC->OutputUserSpaceValue(RR_LINEWIDTH()); 01096 pDC->OutputToken(_T("w")); 01097 pDC->OutputNewLine(); 01098 } 01099 01100 01101 /******************************************************************************************** 01102 01103 > void EPSRenderRegion::OutputJoinType() 01104 01105 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01106 Created: 3/7/96 01107 Purpose: Output the standard EPS join type 01108 01109 ********************************************************************************************/ 01110 01111 void EPSRenderRegion::OutputJoinType() 01112 { 01113 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01114 01115 // Set line Join Type 01116 pDC->OutputValue((UINT32)RR_JOINTYPE()); 01117 pDC->OutputToken(_T("j")); 01118 pDC->OutputNewLine(); 01119 } 01120 01121 01122 /******************************************************************************************** 01123 01124 > void EPSRenderRegion::OutputDashPatternInit() 01125 01126 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01127 Created: 3/7/96 01128 Purpose: Sets up the next dash pattern for output. 01129 SeeAlso: OutputDashPattern() 01130 01131 Notes: Special code for dash patterns, as they are affected by another 01132 attribute, which is line width, so we need to watch out for this by 01133 checking the base class 'StrokeFlags' variable (a change of line 01134 width automatically causes the dash pattern flag to be invalidated). 01135 01136 ********************************************************************************************/ 01137 01138 void EPSRenderRegion::OutputDashPatternInit() 01139 { 01140 if (!StrokeFlags.ValidDashPattern && (RR_DASHPATTERN().Elements > 0)) 01141 { 01142 // Delete the attribute if necessary 01143 if (LastOutputAttrs[ATTR_DASHPATTERN].Temp) 01144 delete LastOutputAttrs[ATTR_DASHPATTERN].pAttr; 01145 01146 // Set to NULL to force it to be output by SetLastOutputAttribute() 01147 LastOutputAttrs[ATTR_DASHPATTERN].pAttr = NULL; 01148 } 01149 01150 // Don't do this again until we need to. 01151 StrokeFlags.ValidDashPattern = TRUE; 01152 } 01153 01154 01155 /******************************************************************************************** 01156 01157 > void EPSRenderRegion::OutputDashPattern() 01158 01159 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01160 Created: 3/7/96 01161 Purpose: Output the current dash pattern settings. Watch for interaction with line 01162 widths, a change of line width causes the dash pattern to become invalid. 01163 To output a dash pattern correctly, use the following code 01164 01165 OutputDashPatternInit(); 01166 if (SetLastOutputAttribute(ATTR_DASHPATTERN)) 01167 OutputDashPattern(); 01168 01169 SeeAlso: OutputDashPatternInit(); 01170 01171 ********************************************************************************************/ 01172 01173 void EPSRenderRegion::OutputDashPattern() 01174 { 01175 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01176 01177 // Set dash pattern 01178 INT32 NumEls = RR_DASHPATTERN().Elements; 01179 INT32* TempArray = NULL; 01180 01181 // If the dash patterns need scaling, then we need to scale them 01182 // here, as Illustrator format uses absolute sizes for the dash 01183 // patterns, rather than the 'relative to line width' that we use 01184 // INT32 DashLineWidth = RR_DASHPATTERN().LineWidth; 01185 INT32 LineWidth = RR_LINEWIDTH(); 01186 01187 BOOL DoScale = RR_DASHPATTERN().ScaleWithLineWidth; 01188 FIXED16 Scale = DoScale ? (double(LineWidth) / double(RR_DASHPATTERN().LineWidth)) : 1; 01189 01190 // Don't bother with zero width lines 01191 if (LineWidth == 0) 01192 NumEls = 0; 01193 01194 // But we needn't bother if there are no elements 01195 if (NumEls > 0) 01196 { 01197 INT32* DashArray = RR_DASHPATTERN().ElementData; 01198 TempArray = new INT32[NumEls]; 01199 01200 if (TempArray) 01201 { 01202 for (INT32 el=0; el<NumEls; el++) 01203 { 01204 TempArray[el] = LongMulFixed16(DashArray[el], Scale); 01205 01206 if (TempArray[el] == 0) 01207 { 01208 // Found a zero dash element - this line is obviously too small 01209 // to bother with dash patterns. 01210 NumEls = 0; 01211 break; 01212 } 01213 } 01214 } 01215 } 01216 01217 // Output the (possibly scaled) array of On-Off distances 01218 pDC->OutputArray(TempArray, NumEls); 01219 01220 // Delete the temp buffer if necessary 01221 delete TempArray; 01222 01223 // Also scale the Dash Start Offset if need be 01224 INT32 Offset = LongMulFixed16(RR_DASHPATTERN().DashStart, Scale); 01225 pDC->OutputUserSpaceValue(Offset); 01226 01227 pDC->OutputToken(_T("d")); 01228 pDC->OutputNewLine(); 01229 } 01230 01231 01232 /******************************************************************************************** 01233 01234 > void EPSRenderRegion::OutputStartCap() 01235 01236 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01237 Created: 3/7/96 01238 Purpose: Output the start cap setting using the usual 'J' EPS token 01239 01240 ********************************************************************************************/ 01241 01242 void EPSRenderRegion::OutputStartCap() 01243 { 01244 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01245 01246 // Set line cap style 01247 pDC->OutputValue((UINT32)RR_STARTCAP()); 01248 pDC->OutputToken(_T("J")); 01249 pDC->OutputNewLine(); 01250 } 01251 01252 01253 /******************************************************************************************** 01254 01255 > void EPSRenderRegion::OutputMitreLimit() 01256 01257 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01258 Created: 3/7/96 01259 Purpose: Output the current mitre limit value using the usual 'M' EPS token 01260 01261 ********************************************************************************************/ 01262 01263 void EPSRenderRegion::OutputMitreLimit() 01264 { 01265 // KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01266 01267 // Set mitre limit 01268 01269 // We have no way of altering Mitre Limits, so there's not 01270 // much point in saving them. 01271 01272 // pDC->OutputUserSpaceValue(RR_MITRELIMIT()); 01273 // pDC->OutputToken("M"); 01274 // pDC->OutputNewLine(); 01275 } 01276 01277 01278 01279 01280 /******************************************************************************************** 01281 01282 > void EPSRenderRegion::OutputStrokeColour() 01283 01284 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01285 Created: 3/7/96 01286 Purpose: Output a stroke colour. This calls either OutputStrokeRGBcolour or 01287 OutputStrokeCMYKColour depending on the colour model. 01288 01289 ********************************************************************************************/ 01290 01291 void EPSRenderRegion::OutputStrokeColour() 01292 { 01293 if (RR_STROKECOLOUR().GetColourModel() == COLOURMODEL_RGBT || 01294 RR_STROKECOLOUR().GetColourModel() == COLOURMODEL_HSVT) 01295 { 01296 // Use new RGB fill colours if we're using an RGB colour model 01297 OutputStrokeRGBColour (); 01298 } 01299 else 01300 { 01301 // Use old CMYK version if we're not. 01302 OutputStrokeCMYKColour (); 01303 } 01304 } 01305 01306 01307 /******************************************************************************************** 01308 01309 > void EPSRenderRegion::OutputStrokeCMYKColour() 01310 01311 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 01312 Created: 7/12/00 01313 Purpose: Output the current stroke colour. This function will use one of the 01314 following EPS tokens 01315 K - if not separating and colour is unnamed 01316 X - if not separating and colour is named 01317 G - if separating 01318 01319 ********************************************************************************************/ 01320 01321 void EPSRenderRegion::OutputStrokeCMYKColour() 01322 { 01323 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01324 01325 PColourCMYK CMYK; 01326 01327 // Assume no local context at present 01328 ColourContext* pContext; 01329 ColourPlate* pSeparation; 01330 GetOutputColourPlate(COLOURMODEL_CMYK, &pContext, &pSeparation); 01331 01332 if (pSeparation==NULL) 01333 { 01334 // Get the current line colour in CMYK values, unless it's transparent 01335 // Print out colour component values 01336 RR_STROKECOLOUR().GetCMYKValue(pContext, &CMYK); 01337 pDC->OutputColour(&CMYK); 01338 01339 if (RR_STROKECOLOUR().FindParentIndexedColour() == NULL) 01340 { 01341 // Unnamed colour - just add 'K' token 01342 pDC->OutputToken(_T("K")); 01343 } 01344 else 01345 { 01346 // Named colour - add Name, tint value, and 'X' token 01347 pDC->OutputColourName(&(RR_STROKECOLOUR())); 01348 pDC->OutputValue((INT32)0); 01349 pDC->OutputToken(_T("X")); 01350 } 01351 } 01352 else 01353 { 01354 // Assume unnamed colour as 'g' grey fill operator does 01355 // not allow for custom greys. 01356 if (pSeparation->IsMonochrome()) 01357 { 01358 RR_STROKECOLOUR().GetCMYKValue(pContext, &CMYK); 01359 BYTE c = 0xFF - CMYK.Key; 01360 pDC->OutputColourValue(c); 01361 pDC->OutputToken(_T("G")); 01362 } 01363 else 01364 { 01365 RR_STROKECOLOUR().GetCMYKValue(pContext, &CMYK); 01366 pDC->OutputColour(&CMYK); 01367 pDC->OutputToken(_T("X")); 01368 } 01369 } 01370 01371 pDC->OutputNewLine(); 01372 } 01373 01374 01375 01376 /******************************************************************************************** 01377 01378 > void EPSRenderRegion::OutputStrokeRGBColour() 01379 01380 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 01381 Created: 29/11/00 01382 Purpose: Output the current stroke colour as RGB. This function will use one of the 01383 following EPS tokens 01384 XA - if not separating and colour is unnamed 01385 XX - if not separating and colour is named 01386 G - if separating 01387 01388 ********************************************************************************************/ 01389 01390 void EPSRenderRegion::OutputStrokeRGBColour() 01391 { 01392 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01393 01394 // Colour values. 01395 INT32 red; 01396 INT32 green; 01397 INT32 blue; 01398 PColourCMYK CMYK; 01399 01400 // Assume no local context at present - used as a check to make sure that we 01401 // aren't exporting as seperations. 01402 ColourContext* pContext; 01403 ColourPlate* pSeparation; 01404 GetOutputColourPlate (COLOURMODEL_CMYK, &pContext, &pSeparation); 01405 01406 if (pSeparation==NULL) 01407 { 01408 // As expected, we ain't using seperations, so we can output as RGB. 01409 01410 // Get the current line colour in RGB values and print them out. 01411 RR_STROKECOLOUR().GetRGBValue (&red, &green, &blue); 01412 pDC->OutputColourValue (red); 01413 pDC->OutputColourValue (green); 01414 pDC->OutputColourValue (blue); 01415 01416 if (RR_STROKECOLOUR().FindParentIndexedColour() == NULL) 01417 { 01418 // Unnamed colour - just add 'XA' token 01419 pDC->OutputToken (_T("XA")); 01420 } 01421 else 01422 { 01423 // Named colour - add Name, tint value, RGB flag and 'XX' token 01424 pDC->OutputColourName (&(RR_STROKECOLOUR())); 01425 pDC->OutputValue((INT32)0); 01426 pDC->OutputValue((INT32)1); 01427 pDC->OutputToken(_T("XX")); 01428 } 01429 } 01430 else 01431 { 01432 // Since we are seperating the colours, then use CMYK mode. 01433 01434 // Assume unnamed colour as 'g' grey fill operator does 01435 // not allow for custom greys. 01436 if (pSeparation->IsMonochrome()) 01437 { 01438 RR_STROKECOLOUR().GetCMYKValue(pContext, &CMYK); 01439 BYTE c = 0xFF - CMYK.Key; 01440 pDC->OutputColourValue(c); 01441 pDC->OutputToken(_T("G")); 01442 } 01443 else 01444 { 01445 RR_STROKECOLOUR().GetCMYKValue(pContext, &CMYK); 01446 pDC->OutputColour(&CMYK); 01447 pDC->OutputToken(_T("X")); 01448 } 01449 } 01450 01451 pDC->OutputNewLine(); 01452 } 01453 01454 /******************************************************************************************** 01455 01456 > void EPSRenderRegion::OutputFillColour() 01457 01458 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01459 Created: 3/7/96 01460 Purpose: This now delegates the output to either OutputFillRGBColour or 01461 OutputFillCMYKColour, depending on the colour model used. 01462 01463 ********************************************************************************************/ 01464 01465 void EPSRenderRegion::OutputFillColour() 01466 { 01467 if (RR_FILLCOLOUR().GetColourModel() == COLOURMODEL_RGBT || 01468 RR_FILLCOLOUR().GetColourModel() == COLOURMODEL_HSVT) 01469 { 01470 // Use new RGB fill colours if we're using an RGB colour model 01471 OutputFillRGBColour (); 01472 } 01473 else 01474 { 01475 // Use old CMYK version if we're not. 01476 OutputFillCMYKColour (); 01477 } 01478 } 01479 01480 /******************************************************************************************** 01481 01482 > void EPSRenderRegion::OutputFillCMYKColour() 01483 01484 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 01485 Created: 7/12/00 01486 Purpose: Output the current fill colour in CMYK mode. This function will use one of 01487 the following EPS tokens 01488 k - if not separating and colour is unnamed 01489 x - if not separating and colour is named 01490 g - if separating 01491 01492 ********************************************************************************************/ 01493 01494 void EPSRenderRegion::OutputFillCMYKColour() 01495 { 01496 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01497 01498 PColourCMYK CMYK; 01499 01500 // retrieve the output plate if there is one 01501 ColourContext* pContext; 01502 ColourPlate* pSeparation; 01503 GetOutputColourPlate(COLOURMODEL_CMYK, &pContext, &pSeparation); 01504 01505 // It seems that in composite mode we always output c,m,y,k colour 01506 // and don't have a monochromatic composite mode. So we don't need 01507 // to check this. 01508 if (pSeparation==NULL) 01509 { 01510 // We're in colour output mode, so output the colour values. 01511 RR_FILLCOLOUR().GetCMYKValue(pContext, &CMYK); 01512 pDC->OutputColour(&CMYK); 01513 01514 if (RR_FILLCOLOUR().FindParentIndexedColour() == NULL) 01515 { 01516 // Unnamed colour - add 'k' token 01517 pDC->OutputToken(_T("k")); 01518 } 01519 else 01520 { 01521 // Named colour - add Name, tint and 'x' token 01522 pDC->OutputColourName(&(RR_FILLCOLOUR())); 01523 pDC->OutputValue((INT32)0); 01524 pDC->OutputToken(_T("x")); 01525 } 01526 } 01527 else 01528 { 01529 // Assume unnamed colour as 'g' grey fill operator does 01530 // not allow for custom greys. 01531 if (pSeparation->IsMonochrome()) 01532 { 01533 RR_FILLCOLOUR().GetCMYKValue(pContext, &CMYK); 01534 BYTE c = 0xFF - CMYK.Key; 01535 pDC->OutputColourValue(c); 01536 pDC->OutputToken(_T("g")); 01537 } 01538 else 01539 { 01540 RR_FILLCOLOUR().GetCMYKValue(pContext, &CMYK); 01541 pDC->OutputColour(&CMYK); 01542 pDC->OutputToken(_T("k")); 01543 } 01544 } 01545 01546 pDC->OutputNewLine(); 01547 } 01548 01549 01550 /******************************************************************************************** 01551 01552 > void EPSRenderRegion::OutputFillRGBColour() 01553 01554 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 01555 Created: 29/11/00 01556 Purpose: Output the current fill colour as RGB. This function will use one of the 01557 following EPS tokens 01558 Xa - if not separating and colour is unnamed 01559 Xx - if not separating and colour is named 01560 g - if separating 01561 01562 ********************************************************************************************/ 01563 01564 void EPSRenderRegion::OutputFillRGBColour() 01565 { 01566 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01567 01568 INT32 red; 01569 INT32 green; 01570 INT32 blue;; 01571 PColourCMYK CMYK; 01572 01573 // retrieve the output plate if there is one 01574 ColourContext* pContext; 01575 ColourPlate* pSeparation; 01576 GetOutputColourPlate(COLOURMODEL_CMYK, &pContext, &pSeparation); 01577 01578 if (pSeparation==NULL) 01579 { 01580 // We're in colour output mode, so output the colour values (as RGB). 01581 RR_FILLCOLOUR().GetRGBValue (&red, &green, &blue); 01582 pDC->OutputColourValue (red); 01583 pDC->OutputColourValue (green); 01584 pDC->OutputColourValue (blue); 01585 01586 if (RR_FILLCOLOUR().FindParentIndexedColour() == NULL) 01587 { 01588 // Unnamed colour - add 'Xa' token 01589 pDC->OutputToken(_T("Xa")); 01590 } 01591 else 01592 { 01593 // Named colour - add Name, tint, RGB flag and 'Xx' token 01594 pDC->OutputColourName(&(RR_FILLCOLOUR())); 01595 pDC->OutputValue((INT32)0); 01596 pDC->OutputValue((INT32)1); 01597 pDC->OutputToken(_T("Xx")); 01598 } 01599 } 01600 else 01601 { 01602 // Assume unnamed colour as 'g' grey fill operator does 01603 // not allow for custom greys. 01604 if (pSeparation->IsMonochrome()) 01605 { 01606 RR_FILLCOLOUR().GetCMYKValue(pContext, &CMYK); 01607 BYTE c = 0xFF - CMYK.Key; 01608 pDC->OutputColourValue(c); 01609 pDC->OutputToken(_T("g")); 01610 } 01611 else 01612 { 01613 RR_FILLCOLOUR().GetCMYKValue(pContext, &CMYK); 01614 pDC->OutputColour(&CMYK); 01615 pDC->OutputToken(_T("k")); 01616 } 01617 } 01618 01619 pDC->OutputNewLine(); 01620 } 01621 01622 01623 /******************************************************************************************** 01624 01625 > void EPSRenderRegion::GetOutputColourPlate(ColourModel ColModel, ColourContext** pContext, ColourPlate** pPlate) 01626 01627 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01628 Created: 17/06/96 01629 Inputs: The colour model of the active output context to use. 01630 A pointer to a pointer to a colour context (can be NULL) 01631 A pointer to a pointer to a colour plate (again can be NULL) 01632 Outputs: pContext points to the current context in the view attached to this render region 01633 pPlate points to the plate whose model was required. 01634 Returns: - 01635 Purpose: This render region is associated with a document view. This function 01636 retrieves the colour context from this view and returns it along with 01637 a plate (if available). ColourModel is used to determin which plate to 01638 return from the context. 01639 If there is no view pContext and pPlate will be NULL. 01640 If there is no context in the view both return values will be NULL 01641 If there is a context but no plate attached to it, one can assume the 01642 current render action is not separated. 01643 01644 ********************************************************************************************/ 01645 01646 void EPSRenderRegion::GetOutputColourPlate(ColourModel ColModel, ColourContext** pContext, ColourPlate** pPlate) 01647 { 01648 ColourContext *pCurContext=NULL; 01649 ColourPlate *pCurPlate=NULL; 01650 01651 // Get the render region view and find its local CMYK colour context 01652 View* pCurrView = GetRenderView(); 01653 if (pCurrView!=NULL) 01654 pCurContext = pCurrView->GetColourContext(ColModel, TRUE); 01655 01656 // If we have a context, check for mono output. 01657 if (pCurContext!=NULL) 01658 pCurPlate = pCurContext->GetColourPlate(); 01659 01660 // Set return vars 01661 if (pContext!=NULL) 01662 (*pContext) = pCurContext; 01663 if (pPlate!=NULL) 01664 (*pPlate) = pCurPlate; 01665 } 01666 01667 01668 /******************************************************************************************** 01669 01670 > void EPSRenderRegion::DrawPathToOutputDevice(Path *DrawPath, BOOL DataOnly) 01671 01672 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01673 Created: 30/03/94 01674 Inputs: DrawPath - the path to render. 01675 Purpose: Output all the commands required to render this path to the EPS file. 01676 SeeAlso: RenderRegion::DrawPath; EPSRenderRegion::GetValidPathAttributes 01677 EPSRenderRegion::ExportPath 01678 01679 ********************************************************************************************/ 01680 01681 void EPSRenderRegion::DrawPathToOutputDevice(Path *DrawPath, PathShape) 01682 { 01683 // ChrisG - 26/10/00 Only export paths if they have any co-ordinates - Exporting 01684 // paths with no co-ords causes no end of hassle in the ExportPath function below, 01685 // where they are used as controls for while loops, positions in arrays (but with 01686 // one subtracted), etc... 01687 if (DrawPath->GetNumCoords ()) 01688 { 01689 // If we are not drawing complex shapes and this shape is, then return 01690 if ((!RenderComplexShapes) && (TestForComplexShape(&Caps))) 01691 return; 01692 01693 ExportPath(DrawPath, FALSE); 01694 01695 // Now do the arrow heads if the render region can't do them directly 01696 // -- But only draw arrow heads if the path is "stroked" 01697 if (DrawPath->IsStroked && !Caps.ArrowHeads) 01698 { 01699 // Doesn't support arrow heads directly so we render them as paths. 01700 DrawPathArrowHeads(DrawPath->GetCoordArray(), 01701 DrawPath->GetVerbArray(), 01702 DrawPath->GetNumCoords()); 01703 } 01704 } 01705 } 01706 01707 /******************************************************************************************** 01708 01709 > void EPSRenderRegion::ExportPath(Path *DrawPath, BOOL DataOnly, BOOL PureDataOnly = FALSE) 01710 01711 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01712 Created: 30/03/94 01713 Inputs: DrawPath - the path to render. 01714 DataOnly - if TRUE, only output the line/curve/moveto data, and not the stroke 01715 or fill operators. 01716 if FALSE, just output path normally. NB. see Purpose 01717 PureDataOnly if TRUE, will do what the DataOnly flag does, but will really 01718 do it, instead of bottling out on compound paths! 01719 01720 Purpose: Output all the commands required to render this path to the EPS file. 01721 If this is a compound path, the stroke/fill operators will always be output, 01722 regardless of the value of the DataOnly parameter. 01723 01724 Hello, Karim here. The above is is *no longer the case* if the PureDataOnly 01725 flag is set. I *don't want any* stroke or fill operators on compound clipping 01726 paths, thankyou very much! 01727 01728 SeeAlso: RenderRegion::DrawPath; EPSRenderRegion::GetValidPathAttributes 01729 01730 ********************************************************************************************/ 01731 01732 void EPSRenderRegion::ExportPath(Path *DrawPath, BOOL DataOnly, BOOL PureDataOnly) 01733 { 01734 // Only change data if we have actually have data to change 01735 if (!PureDataOnly) 01736 { 01737 // Make sure we draw in the right colours 01738 GetValidPathAttributes(); 01739 } 01740 01741 // Get the device context for our export file. 01742 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01743 01744 DocCoord* Coords = DrawPath->GetCoordArray(); 01745 PathVerb* Verbs = DrawPath->GetVerbArray(); 01746 INT32 NumCoords = DrawPath->GetNumCoords(); 01747 01748 // Position we are reading points from 01749 INT32 ReadPos = 1; 01750 01751 // Check to see if this is a compound path. If it is, there will be more than one 01752 // moveto command. 01753 BOOL CompoundPath = FALSE; 01754 01755 while (ReadPos < NumCoords) 01756 { 01757 // Find out the type of element that we are over (after the close flag has been removed) 01758 if (((Verbs[ReadPos]) & (~PT_CLOSEFIGURE) ) == PT_MOVETO) 01759 { 01760 // This is a compound path - stop searching for moveto's. 01761 CompoundPath = TRUE; 01762 break; 01763 } 01764 // Try next point 01765 ReadPos++; 01766 } 01767 01768 // Karim 24/05/2000 - don't want this bracket data if the PureDataOnly flag is set. 01769 if (CompoundPath && !PureDataOnly) 01770 { 01771 // Bracket compound paths./ 01772 pDC->OutputToken(_T("*u")); 01773 pDC->OutputNewLine(); 01774 } 01775 01776 // Work out how to render the path (stroke, fill, both, none, etc.) 01777 TCHAR PathTypeOpen[2] = _T("N"); 01778 TCHAR PathTypeClosed[2]; 01779 01780 // Work out if the path is filled. 01781 BOOL IsFilled = TRUE; 01782 01783 ColourFillAttribute *pFillAttr = 01784 (ColourFillAttribute *) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr; 01785 01786 if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(FlatFillAttribute)) && 01787 pFillAttr->Colour.IsTransparent()) 01788 { 01789 // Flat fill with transparent colour => no fill 01790 IsFilled = FALSE; 01791 } 01792 01793 if (!DrawPath->IsFilled) 01794 IsFilled = FALSE; 01795 01796 // Work out what should be done to the path 01797 if (RR_STROKECOLOUR().IsTransparent() || !DrawPath->IsStroked) 01798 { 01799 if (IsFilled) 01800 // Fill path 01801 PathTypeOpen[0] = 'F'; 01802 } 01803 else 01804 { 01805 if (IsFilled) 01806 // Stroke and fill path 01807 PathTypeOpen[0] = 'B'; 01808 else 01809 // Stroke path, leaving it unfilled 01810 PathTypeOpen[0] = 'S'; 01811 } 01812 01813 // make closed varity of PathType 01814 PathTypeClosed[0] = camTolower(PathTypeOpen[0]); 01815 PathTypeClosed[1] = '\0'; 01816 01817 // Reset to start of path 01818 ReadPos = 0; 01819 01820 // loop through the whole path 01821 while(ReadPos < NumCoords) 01822 { 01823 // Find out the type of element that we are over (after the close flag has been removed) 01824 // Coord P[4]; 01825 switch ( (Verbs[ReadPos]) & (~PT_CLOSEFIGURE) ) 01826 { 01827 case PT_MOVETO: 01828 // If this is in the middle of the path, specify how this sub-path 01829 // should be rendered - this is needed so that we re-import all the flags 01830 // correctly on complex paths (e.g. PT_CLOSEFIGURE) 01831 // Karim 25/05/2000 - changed so we don't output this stroking token if PureDataOnly. 01832 if (ReadPos > 0 && !PureDataOnly) 01833 { 01834 pDC->OutputToken(((Verbs[ReadPos - 1] & PT_CLOSEFIGURE) != 0)?PathTypeClosed:PathTypeOpen); 01835 pDC->OutputNewLine(); 01836 } 01837 01838 // Output the moveto command 01839 pDC->OutputCoord(Coords[ReadPos]); 01840 pDC->OutputToken(TEXT("m")); 01841 pDC->OutputNewLine(); 01842 ReadPos++; 01843 break; 01844 01845 01846 case PT_LINETO: 01847 // Output the lineto command 01848 pDC->OutputCoord(Coords[ReadPos]); 01849 pDC->OutputToken(TEXT("l")); 01850 pDC->OutputNewLine(); 01851 ReadPos++; 01852 break; 01853 01854 01855 case PT_BEZIERTO: 01856 // If this point is a bezier, then the next 2 points should be beziers to 01857 ENSURE((Verbs[ReadPos+1]) & (~PT_CLOSEFIGURE), "Bezier found with 1 point"); 01858 ENSURE((Verbs[ReadPos+2]) & (~PT_CLOSEFIGURE), "Bezier found with 2 points"); 01859 01860 // Make sure that this is not at the start of the path 01861 ENSURE(ReadPos > 0, "Broken path found while exporting EPS" ); 01862 01863 // Output the moveto command 01864 pDC->OutputCoord(Coords[ReadPos]); 01865 pDC->OutputCoord(Coords[ReadPos+1]); 01866 pDC->OutputCoord(Coords[ReadPos+2]); 01867 pDC->OutputToken(TEXT("c")); 01868 pDC->OutputNewLine(); 01869 ReadPos += 3; 01870 break; 01871 01872 default: 01873 ENSURE( FALSE, "We found a Path Element that does not exist!" ); 01874 break; 01875 } 01876 } 01877 01878 // Karim 24/05/2000 - if PureDataOnly is specified, then we *really* don't want to render here! 01879 if (!PureDataOnly && (!DataOnly || CompoundPath)) 01880 { 01881 // Write out any additional info it's a gradient fill. 01882 if (pFillAttr->IsAGradFill ()) 01883 { 01884 WriteGradientFillInstance (); 01885 } 01886 01887 // Do the final (or possibly only) render command 01888 pDC->OutputToken(((Verbs[NumCoords - 1] & PT_CLOSEFIGURE) != 0)?PathTypeClosed:PathTypeOpen); 01889 pDC->OutputNewLine(); 01890 } 01891 01892 // Karim 24/05/2000 - don't want this bracket data if the PureDataOnly flag is set. 01893 if (CompoundPath && !PureDataOnly) 01894 { 01895 // End compound path 01896 pDC->OutputToken(_T("*U")); 01897 pDC->OutputNewLine(); 01898 } 01899 } 01900 01901 /******************************************************************************************** 01902 01903 > BOOL EPSRenderRegion::SetLastOutputAttribute(INT32 AttrID) 01904 01905 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01906 Created: 1/5/95 01907 Inputs: AttrID, is the AttrIndex (see kernel\attrmgr.h) of the attribute to set 01908 Returns: TRUE, if the attribute is different, and SHOULD be output 01909 FALSE, if the attribute is the same as the last one output 01910 Purpose: Check to see if the current attribute is the same as the last one that 01911 was output in EPS. 01912 01913 ********************************************************************************************/ 01914 01915 BOOL EPSRenderRegion::SetLastOutputAttribute(INT32 AttrID) 01916 { 01917 ERROR2IF(LastOutputAttrs == NULL, FALSE, "No 'LastOutputAttrs' array in EPSRenderRegion::SetLastOutputAttribute"); 01918 ERROR2IF(CurrentAttrs == NULL, FALSE, "No 'CurrentAttrs' array in EPSRenderRegion::SetLastOutputAttribute"); 01919 ERROR2IF(AttrID > NumCurrentAttrs, FALSE, "Bad AttrID passed to EPSRenderRegion::SetLastOutputAttribute"); 01920 01921 // Find the Current Attr of the same Type 01922 AttributeValue* pAttr = CurrentAttrs[AttrID].pAttr; 01923 01924 // Removed by Will. Bitmap output now sets these to NULL, so force certain attributes 01925 // to be output again. 01926 //ERROR2IF(pAttr == NULL, FALSE, "Couldn't find Current Attr in EPSRenderRegion::SetLastOutputAttribute"); 01927 01928 // If no attribute of this type has been output yet, 01929 // or the current attribute is different to the last 01930 // attribute we output, then set the Last Output 01931 // attribute to the current one 01932 01933 if (LastOutputAttrs[AttrID].pAttr == NULL || 01934 LastOutputAttrs[AttrID].pAttr->IsDifferent(pAttr)) 01935 { 01936 if (LastOutputAttrs[AttrID].Temp && 01937 LastOutputAttrs[AttrID].pAttr != NULL) 01938 { 01939 // Get rid of this copy, as we are about to over write it 01940 delete LastOutputAttrs[AttrID].pAttr; 01941 } 01942 01943 // We always take a copy because blends create attributes that are temporary 01944 // but are not marked as such (for complex reasons). 01945 if (TRUE) // (CurrentAttrs[AttrID].Temp) 01946 { 01947 // If the current attribute is a temporary attribute, 01948 // then we need to make a copy of it, otherwise it may 01949 // have been deleted when we try and look at it later on 01950 CCRuntimeClass* ObjectType = pAttr->GetRuntimeClass(); 01951 AttributeValue* AttrClone = (AttributeValue*)ObjectType->CreateObject(); 01952 AttrClone->SimpleCopy(pAttr); 01953 01954 LastOutputAttrs[AttrID].pAttr = AttrClone; 01955 LastOutputAttrs[AttrID].Temp = TRUE; 01956 } 01957 else 01958 { 01959 // This must be an attribute in the tree, so we know 01960 // it won't get deleted 01961 LastOutputAttrs[AttrID].pAttr = pAttr; 01962 LastOutputAttrs[AttrID].Temp = FALSE; 01963 } 01964 01965 return TRUE; 01966 } 01967 else 01968 { 01969 // The current attribute is the same as the last one 01970 // that was output 01971 return FALSE; 01972 } 01973 } 01974 01975 /******************************************************************************************** 01976 01977 > void EPSRenderRegion::ResetOutputAttributes() 01978 01979 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01980 Created: 20/06/95 01981 Purpose: Resets the attribute array so that all attributes are considered to 01982 be invalidated - i.e. the next time an attribute is needed, it will 01983 always be output, regardless of whether the last attribute output 01984 was the same as it. 01985 This is mainly used for PostScript printing when we use the OS to do 01986 text, because we cannot be sure of how the OS will leave the graphics 01987 state after doing text output, so we assume nothing, and reset all 01988 required attributes after doing text output via the OS. 01989 01990 ********************************************************************************************/ 01991 01992 void EPSRenderRegion::ResetOutputAttributes() 01993 { 01994 // Delete any temp attributes and mark all attrs as NULL. 01995 if (LastOutputAttrs != NULL) 01996 { 01997 for (INT32 i = 0; i < NumCurrentAttrs; i++) 01998 { 01999 if (LastOutputAttrs[i].Temp) 02000 delete LastOutputAttrs[i].pAttr; 02001 02002 LastOutputAttrs[i].pAttr = NULL; 02003 LastOutputAttrs[i].Temp = FALSE; 02004 } 02005 } 02006 } 02007 02008 /******************************************************************************************** 02009 02010 > virtual BOOL EPSRenderRegion::WriteFileVersion(KernelDC *pDC) 02011 02012 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 02013 Created: 29/05/95 02014 Inputs: pDC - the device context to output to. 02015 Outputs: - 02016 Returns: TRUE if ok; 02017 FALSE if error (e.g. file/disk error) 02018 Purpose: This allows the filter to save out a comment line giving file version 02019 information. At present, in anything but Native format, it does nothing. 02020 SeeAlso: EPSRenderRegion::WriteSetup 02021 02022 ********************************************************************************************/ 02023 02024 BOOL EPSRenderRegion::WriteFileVersion(KernelDC *pDC) 02025 { 02026 // No file version required here... 02027 return TRUE; 02028 } 02029 02030 /******************************************************************************************** 02031 02032 > virtual BOOL EPSRenderRegion::WriteCompressionState(KernelDC *pDC) 02033 02034 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 02035 Created: 19/05/95 02036 Inputs: pDC - the device context to output to. 02037 Outputs: - 02038 Returns: TRUE if ok; 02039 FALSE if error (e.g. file/disk error) 02040 Purpose: This starts the compression process. Called just after we output the document 02041 information so that this is not compressed and the galleries can access it 02042 easily. 02043 In this baseclass version we do nothing as compression would be a very bad 02044 thing. 02045 SeeAlso: EPSRenderRegion::WriteSetup 02046 02047 ********************************************************************************************/ 02048 02049 BOOL EPSRenderRegion::WriteCompressionState(KernelDC *pDC) 02050 { 02051 // No compression required here... 02052 return TRUE; 02053 } 02054 02055 /******************************************************************************************** 02056 02057 > virtual BOOL EPSRenderRegion::WriteEndCompressionState(KernelDC *pDC) 02058 02059 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 02060 Created: 22/05/95 02061 Inputs: pDC - the device context to output to. 02062 Outputs: - 02063 Returns: TRUE if ok; 02064 FALSE if error (e.g. file/disk error) 02065 Purpose: This is called once almost everything has been output, just before we output 02066 the EOF and we fix the EPS header. 02067 In this baseclass version we do nothing as compression would be a very bad 02068 thing. 02069 SeeAlso: EPSRenderRegion::WriteSetup 02070 02071 ********************************************************************************************/ 02072 02073 BOOL EPSRenderRegion::WriteEndCompressionState(KernelDC*) 02074 { 02075 // No compression required here... 02076 return TRUE; 02077 } 02078 02079 /******************************************************************************************** 02080 02081 > virtual BOOL EPSRenderRegion::WriteGradientFills ( Document *pDocument ) 02082 02083 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02084 Created: 1/3/00 02085 Inputs: Document - The document being outputted. 02086 Outputs: - 02087 Returns: TRUE if successful. 02088 FALSE if error (e.g. file/disk error) 02089 Purpose: This function is a stub function, which is overwritten in the AI render 02090 region. 02091 02092 ********************************************************************************************/ 02093 02094 BOOL EPSRenderRegion::WriteGradientFills ( Document *pDocument ) 02095 { 02096 // We don't do anything, so just return TRUE. 02097 return TRUE; 02098 } 02099 02100 /******************************************************************************************** 02101 02102 > virtual BOOL EPSRenderRegion::WriteDocumentSetup ( Document *pDocument, 02103 EPSFilter *pFilter ) 02104 02105 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02106 Created: 24/3/00 02107 Inputs: pDocument - The document being outputted. 02108 pFilter - A pointer to the export filter. 02109 Outputs: - 02110 Returns: TRUE if successful. 02111 FALSE if error (e.g. file/disk error) 02112 Purpose: Browse through the tree, and if a text story is found invoke the document 02113 setup function. By only exporting the font setup when necessary, the file 02114 size produced is smaller (which makes it easier for me to interpret :) ), 02115 and it should hopefully make the filter run a bit faster too. 02116 02117 ********************************************************************************************/ 02118 02119 BOOL EPSRenderRegion::WriteDocumentSetup ( Document *pDocument, 02120 EPSFilter *pFilter ) 02121 { 02122 // Do nothing for normal EPS, only AIEPS files. 02123 return TRUE; 02124 } 02125 02126 /******************************************************************************************** 02127 02128 > BOOL EPSRenderRegion::EndLayer () 02129 02130 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02131 Created: 11/4/00 02132 Inputs: - 02133 Returns: TRUE - Success. 02134 FALSE - An error occured. 02135 Purpose: If there is an existing layer, it writes the end of layer tags, before 02136 creating a new layer record. 02137 SeeAlso: AIEPSRenderRegion::EndLayer () 02138 02139 ********************************************************************************************/ 02140 02141 BOOL EPSRenderRegion::EndLayer () 02142 { 02143 // Don't do anything. 02144 return TRUE; 02145 } 02146 02147 /******************************************************************************************** 02148 02149 > BOOL EPSRenderRegion::WriteEPSVersion ( void ) 02150 02151 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02152 Created: 30/3/000 02153 Inputs: - 02154 Returns: TRUE if ok; 02155 FALSE if error (e.g. file/disk error or printer driver error) 02156 Purpose: Writes the EPS version used by this particular file type. 02157 SeeAlso: EPSRenderRegion::InitDevice 02158 02159 ********************************************************************************************/ 02160 02161 BOOL EPSRenderRegion::WriteEPSVersion ( void ) 02162 { 02163 // Cast a pointer to the appropriate DC. 02164 KernelDC *pDC = static_cast<KernelDC*> ( CCDC::ConvertFromNativeDC(RenderDC) ); 02165 02166 // Output the standard EPS header start token. 02167 pDC->OutputToken ( _T("%!PS-Adobe-2.0 EPSF-1.2") ); 02168 pDC->OutputNewLine (); 02169 02170 // Success. 02171 return TRUE; 02172 } 02173 02174 /******************************************************************************************** 02175 02176 > BOOL EPSRenderRegion::WriteEPSBoundingBox ( void ) 02177 02178 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02179 Created: 19/5/000 02180 Inputs: - 02181 Returns: TRUE if ok; 02182 FALSE if error (e.g. file/disk error or printer driver error) 02183 Purpose: Writes an EPS bounding box. 02184 SeeAlso: EPSRenderRegion::InitDevice 02185 02186 ********************************************************************************************/ 02187 02188 BOOL EPSRenderRegion::WriteEPSBoundingBox ( void ) 02189 { 02190 // Cast a pointer to the appropriate DC. 02191 KernelDC *pDC = static_cast<KernelDC*> ( CCDC::ConvertFromNativeDC(RenderDC) ); 02192 DocRect BBox = RenderSpread->GetBoundingRect (); 02193 02194 // Bounding box type stuff - get the spread's bounding box and convert from DocCoords 02195 // to spread coords. 02196 RenderSpread->DocCoordToSpreadCoord(&BBox); 02197 02198 // Write the bounding box to the file. 02199 pDC->OutputToken ( _T("%%BoundingBox:") ); 02200 pDC->OutputCoord ( BBox.lo, ACCURACY_ROUNDDOWN ); 02201 pDC->OutputCoord ( BBox.hi, ACCURACY_ROUNDUP ); 02202 pDC->OutputNewLine (); 02203 02204 // Write a hires bounding box to the file. 02205 pDC->OutputToken ( _T("%%HiResBoundingBox:") ); 02206 pDC->OutputCoord ( BBox.lo, ACCURACY_NORMAL ); 02207 pDC->OutputCoord ( BBox.hi, ACCURACY_NORMAL ); 02208 pDC->OutputNewLine (); 02209 02210 // Success. 02211 return TRUE; 02212 } 02213 02214 /******************************************************************************************** 02215 02216 > BOOL EPSRenderRegion::WriteEPSProcessColours ( void ) 02217 02218 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02219 Created: 28/3/000 02220 Inputs: pDC - The device context to output to. 02221 Returns: TRUE if ok; 02222 FALSE if error (e.g. file/disk error or printer driver error) 02223 Purpose: Does nothing - process colours are only relevant in AI files. 02224 SeeAlso: EPSRenderRegion::InitDevice 02225 02226 ********************************************************************************************/ 02227 02228 BOOL EPSRenderRegion::WriteEPSProcessColours ( void ) 02229 { 02230 // It always works! :) 02231 return TRUE; 02232 } 02233 02234 /******************************************************************************************** 02235 02236 > BOOL EPSRenderRegion::WriteEPSResources ( EPSFilter *pFilter, 02237 Document *pDocument ) 02238 02239 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02240 Created: 28/3/000 02241 Inputs: pDC - The device context to output to. 02242 Returns: TRUE if ok; 02243 FALSE if error (e.g. file/disk error or printer driver error) 02244 Purpose: This is a stub function, that's over-loaded in the AIEPS render region. It's 02245 used to write out the necessary resources for an AI file. 02246 SeeAlso: EPSRenderRegion::WriteSetup 02247 02248 ********************************************************************************************/ 02249 02250 BOOL EPSRenderRegion::WriteEPSResources ( EPSFilter *pFilter, 02251 Document *pDocument ) 02252 { 02253 // We don't need to do anything yet. 02254 return TRUE; 02255 } 02256 02257 /******************************************************************************************** 02258 02259 > BOOL EPSRenderRegion::WriteEPSProlog ( EPSFilter *pFilter, 02260 Document *pDocument ) 02261 02262 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02263 Created: 28/3/000 02264 Inputs: pFilter - The output filter being used. 02265 pDocument - The document being exported. 02266 Returns: TRUE if ok; 02267 FALSE if error (e.g. file/disk error or printer driver error) 02268 Purpose: This is a stub function, that's over-loaded in the AIEPS render region. It's 02269 used to write out the necessary Prolog script for an AI file. 02270 SeeAlso: EPSRenderRegion::WriteSetup 02271 02272 ********************************************************************************************/ 02273 02274 BOOL EPSRenderRegion::WriteEPSProlog ( EPSFilter *pFilter, 02275 Document *pDocument ) 02276 { 02277 // We don't need to do anything yet. 02278 return TRUE; 02279 } 02280 02281 /******************************************************************************************** 02282 02283 > BOOL EPSRenderRegion::WriteEPSTrailerComments ( void ) 02284 02285 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 02286 Created: 22/5/000 02287 Inputs: - 02288 Returns: TRUE if ok; 02289 FALSE if error (e.g. file/disk error or printer driver error) 02290 Purpose: Writes the comments out at the end of an EPS file. 02291 SeeAlso: EPSRenderRegion::CloseDown 02292 02293 ********************************************************************************************/ 02294 02295 BOOL EPSRenderRegion::WriteEPSTrailerComments ( void ) 02296 { 02297 // Get a pointer to the kernel DC. 02298 KernelDC *pDC = static_cast<KernelDC*> ( CCDC::ConvertFromNativeDC(RenderDC) ); 02299 EPSExportDC *pExportDC = static_cast<EPSExportDC*> ( pDC ); 02300 EPSFilter *pFilter = static_cast<EPSFilter *> ( pExportDC->GetParentFilter () ); 02301 Document *pDocument = RenderView->GetDoc (); 02302 // Find out which document we're using. 02303 ENSURE ( pDocument != NULL, "View's document is NULL!" ); 02304 02305 // Write out the page trailer. 02306 pDC->OutputToken ( _T("%%PageTrailer") ); 02307 pDC->OutputNewLine (); 02308 pDC->OutputToken ( _T("showpage") ); 02309 pDC->OutputNewLine (); 02310 pDC->OutputToken ( _T("%%Trailer") ); 02311 pDC->OutputNewLine (); 02312 02313 // Write out the Documents trailer comments 02314 pDocument->WriteEPSTrailer ( pFilter ); 02315 02316 // Close down the compression system before we write out the fixed form of the header. 02317 WriteEndCompressionState ( pDC ); 02318 02319 // End of file token. 02320 pDC->OutputToken ( _T("%%EOF") ); 02321 pDC->OutputNewLine (); 02322 02323 // Success! 02324 return TRUE; 02325 } 02326 02327 /******************************************************************************************** 02328 02329 > BOOL EPSRenderRegion::WriteProlog(KernelDC *pDC) 02330 02331 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02332 Created: 24/04/95 02333 Inputs: pDC - the device context to output to. 02334 Outputs: - 02335 Returns: TRUE if ok; 02336 FALSE if error (e.g. file/disk error or printer driver error) 02337 Purpose: Output any PostScript prolog for this render region. For EPS and printing, 02338 this means output of our PostScript rendering procedures; for Native 02339 files we do nothing. 02340 SeeAlso: EPSRenderRegion::WriteSetup 02341 02342 ********************************************************************************************/ 02343 02344 BOOL EPSRenderRegion::WriteProlog(KernelDC *pDC) 02345 { 02346 // No PostScript procedure defns here... 02347 return TRUE; 02348 } 02349 02350 /******************************************************************************************** 02351 02352 > BOOL EPSRenderRegion::WriteSetup(KernelDC *pDC) 02353 02354 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02355 Created: 24/04/95 02356 Inputs: pDC - the device context to output to. 02357 Outputs: - 02358 Returns: TRUE if ok; 02359 FALSE if error (e.g. file/disk error or printer driver error) 02360 Purpose: Output any PostScript setup for this render region. For EPS and printing, 02361 this means output of our PostScript code to initialise the context for 02362 rendering; for Native files we do nothing. 02363 SeeAlso: PrintPSRenderRegion::WriteSetup 02364 02365 ********************************************************************************************/ 02366 02367 BOOL EPSRenderRegion::WriteSetup(KernelDC *pDC) 02368 { 02369 // No PostScript setup code here... 02370 return TRUE; 02371 } 02372 02373 /******************************************************************************************** 02374 02375 > virtual BOOL EPSRenderRegion::WriteSepTables(KernelDC *pDC) 02376 02377 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 02378 Created: 19/06/96 02379 Inputs: pDC - the device context to output to. 02380 Outputs: - 02381 Returns: TRUE if ok; 02382 FALSE if error (e.g. file/disk error or printer driver error) 02383 Purpose: Output the current set of device printer profiles as Postscript data 02384 arrays. Our Postscript prolog functions will use these arrays when 02385 creating separations. (if we are not separating, we do nothing) 02386 SeeAlso: 02387 02388 ********************************************************************************************/ 02389 02390 BOOL EPSRenderRegion::WriteSepTables(KernelDC *pDC) 02391 { 02392 // No Postscript separation tables here 02393 return TRUE; 02394 } 02395 02396 02397 /******************************************************************************************** 02398 02399 > virtual BOOL EPSRenderRegion::WriteSepTables(KernelDC *pDC) 02400 02401 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 02402 Created: 27/06/96 02403 Inputs: pDC - the device context to output to. 02404 Outputs: - 02405 Returns: TRUE if ok; 02406 FALSE if error (e.g. file/disk error or printer driver error) 02407 Purpose: Output the current set of separation functions for this EPS file if 02408 any. These will usually be present in printable postscript versions of 02409 EPS render regions. 02410 SeeAlso: WriteProlog 02411 02412 ********************************************************************************************/ 02413 02414 BOOL EPSRenderRegion::WriteSepFunctions(KernelDC *pDC) 02415 { 02416 // No Postscript separation functions here 02417 return TRUE; 02418 } 02419 02420 02421 /******************************************************************************************** 02422 02423 > virtual void EPSRenderRegion::GetRenderRegionCaps(RRCaps* pCaps) 02424 02425 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02426 Created: 10/4/95 02427 Outputs: pCaps - The details about what types of thing this render region can render 02428 Purpose: This function allows render regions to admit to what they can and can not 02429 render. This allows other areas of the program to come in and help render 02430 regions out in some situations, if they are unable to render everything. 02431 eg. an OSRenderRegion can not render transparancy. 02432 02433 ********************************************************************************************/ 02434 02435 void EPSRenderRegion::GetRenderRegionCaps(RRCaps* pCaps) 02436 { 02437 // This forces line attributes - dash patterns and arrow heads to be output 02438 // properly for EPS, rather than using Camelot 'shorthand' tokens. 02439 pCaps->CanDoNothing(); 02440 pCaps->ClippedOutput = TRUE; 02441 } 02442 02443 /******************************************************************************************** 02444 02445 > virtual BOOL EPSRenderRegion::WantsGrids() 02446 02447 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 02448 Created: 12/12/95 02449 Returns: FALSE 02450 Purpose: This function is designed to help with the rendering of grids, as they are 02451 not always wanted (eg xara eps). EPS classes generally do not want to render 02452 grids. The ones that do (NativeEPS) should replace this with a version that 02453 returns TRUE. 02454 02455 ********************************************************************************************/ 02456 02457 BOOL EPSRenderRegion::WantsGrids() 02458 { 02459 return FALSE; 02460 } 02461 02462 02463 02464 /******************************************************************************************** 02465 02466 > virtual void EPSRenderRegion::SetClipRegion(ClipRegionAttribute* pClipAttr, BOOL Temp) 02467 02468 Author: Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com> 02469 Created: 23 May 2000 02470 Inputs: pClipAttr ptr to the new ClipRegionAttribute to set as current in our RR. 02471 Temp whether the attr is temporary or not. 02472 02473 Outputs: Postscript's context is saved and the commands are output to intersect its 02474 current clipping path with that defined by the ClipAttr. 02475 Also, the RR's current attr context is updated to use this new ClipAttr. 02476 02477 Purpose: Shrink the RR's clipping region to the region defined by pClipAttr. 02478 We do this by: 02479 1. Recording a save-state command. 02480 2. Exporting a description of the clipping path in pClipAttr. 02481 3. Recording a 'clip-to-last-path' command. 02482 4. Recording a 'start-new-path' command, as we don't want our clip-path 02483 to get stroked or rendered in any way. 02484 02485 Notes: We mustn't record clipping commands when rendering the default attribute. 02486 Therefore this method does *nothing whatsoever* unless pClipAttr's ptr to 02487 its clipping-path is non-NULL. This ptr is NULL in the default attr. 02488 02489 See also: RenderRegion::SetClipRegion() 02490 02491 ********************************************************************************************/ 02492 void EPSRenderRegion::SetClipRegion(ClipRegionAttribute* pClipAttr, BOOL Temp) 02493 { 02494 if (pClipAttr->GetClipPath() != NULL) 02495 { 02496 // Update the RR's table of current attributes. 02497 RenderRegion::SetClipRegion(pClipAttr, Temp); 02498 02499 // Get the device context for our export file. 02500 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 02501 02502 // export a 'gsave' command. 02503 pDC->OutputToken(TEXT("gsave")); 02504 pDC->OutputNewLine(); 02505 02506 // export a description of the clipping path - data only, please. 02507 ExportPath(pClipAttr->GetClipPath(), TRUE, TRUE); 02508 02509 // export a 'clip' command. note that if our current winding rule is for even-odd 02510 // winding, we must export an 'eoclip' command instead. 02511 if (RR_WINDINGRULE() == EvenOddWinding) 02512 pDC->OutputToken(TEXT("eoclip")); 02513 else 02514 pDC->OutputToken(TEXT("clip")); 02515 pDC->OutputNewLine(); 02516 02517 // export a 'newpath' command. 02518 pDC->OutputToken(TEXT("newpath")); 02519 pDC->OutputNewLine(); 02520 } 02521 } 02522 02523 02524 02525 /******************************************************************************************** 02526 02527 > virtual void EPSRenderRegion::RestoreClipRegion(ClipRegionAttribute* pClipAttr, BOOL Temp) 02528 02529 Author: Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com> 02530 Created: 23 May 2000 02531 Inputs: pClipAttr ptr to the ClipRegionAttribute to restore over the current one. 02532 Temp whether the attr is temporary or not. 02533 02534 Outputs: Postscript is told to restore its last saved context. 02535 02536 Purpose: Restore the RR's clipping region. 02537 We do this by recording a restore-state command. 02538 02539 Errors: ERROR3 if the current ClipRegionAttribute holds a NULL clip-path ptr. 02540 This state of affairs should not happen. You can't set a ClipRegionAttribute 02541 with a NULL clip-path ptr, so the only such attr is the default one, and you 02542 should never be restoring over _that_. 02543 02544 See also: RenderRegion::RestoreClipRegion() 02545 02546 ********************************************************************************************/ 02547 02548 void EPSRenderRegion::RestoreClipRegion(ClipRegionAttribute* pClipAttr, BOOL Temp) 02549 { 02550 // we should never be entered when the current clipattr has a NULL path, as what this 02551 // means is that either somebody somehow did a SetClipRegion() with such an attr, or 02552 // somebody is trying to Restore() over the default ClipRegionAttribute (which holds a 02553 // NULL path ptr). Neither of these actions should occur. 02554 02555 if (RR_CLIPREGION()->GetClipPath() == NULL) 02556 { 02557 ERROR3("EPSRenderRegion::RestoreClipRegion; Current ClipRegionAttribute has a NULL path"); 02558 } 02559 else 02560 { 02561 // Update the RR's table of current attributes. 02562 RenderRegion::RestoreClipRegion(pClipAttr, Temp); 02563 02564 // Get the device context for our export file. 02565 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 02566 02567 // export a 'grestore' command. 02568 pDC->OutputToken(TEXT("grestore")); 02569 pDC->OutputNewLine(); 02570 } 02571 } 02572 02573 /******************************************************************************************** 02574 02575 > void EPSRenderRegion::WriteGradientFillInstance() 02576 02577 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 02578 Created: 18/12/00 02579 Purpose: This function allows extra work to be done on gradient fills, when the fill 02580 and/or stroke operators are written. i.e. at the last possible moment before 02581 rendering. 02582 02583 It is currently only used by the AI export, as this requires gradient fills 02584 to be written at this position, and re-written for each new object. 02585 02586 SeeAlso: AIEPSRenderRegion::WriteGradientFillUsage 02587 02588 ********************************************************************************************/ 02589 02590 void EPSRenderRegion::WriteGradientFillInstance () 02591 { 02592 // do absolutely nothing, unless it's AI (which should be picked up in AIEPSRenderRegion) 02593 } 02594 02595 // 02596 // EPSExportDC class 02597 // 02598 02599 02600 /******************************************************************************************** 02601 02602 > EPSExportDC::EPSExportDC(Filter *Parent) 02603 02604 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02605 Created: 28/03/94 02606 Inputs: The filter object associated with this export DC. 02607 Purpose: Initialise a DC for exporting EPS. 02608 02609 ********************************************************************************************/ 02610 02611 EPSExportDC::EPSExportDC(Filter *Parent) : ExportDC(Parent) 02612 { 02613 } 02614 02615 02616 02617 /******************************************************************************************** 02618 02619 > BOOL EPSExport::Init(CCLexFile* pFile) 02620 02621 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 02622 Created: 2/2/95 02623 Inputs: pFile - The file to attach to the DC 02624 Returns: TRUE if all went well, FALSE if not 02625 Purpose: Calls the base class Init function and then sets up the DC to throw exceptions 02626 when it gets errors as that is how the EPS stuff expects errors to be reported. 02627 SeeAlso: ExportDC::Init 02628 02629 ********************************************************************************************/ 02630 02631 BOOL EPSExportDC::Init(CCLexFile* pFile) 02632 { 02633 // First get the base class to do its thing 02634 if (!ExportDC::Init(pFile)) return FALSE; 02635 02636 // now do what I want done. 02637 // We want export files to throw exceptions, and not report errors. 02638 ExportFile->SetThrowExceptions(TRUE); 02639 ExportFile->SetReportErrors(FALSE); 02640 return TRUE; 02641 } 02642 02643 02644 02645 /******************************************************************************************** 02646 02647 > BOOL EPSExportDC::OutputNewLine() 02648 02649 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02650 Created: 28/03/94 02651 Returns: TRUE if the data was written ok; 02652 FALSE if not => ERROR1 02653 Purpose: Causes a new line to be started in the EPS output file. This is used 02654 to give a pleasant appearance to the EPS file - most EPS commands (as 02655 opposed to operands) are followed by a new line. 02656 SeeAlso: EPSExportDC; EPSExportDC::OutputToken 02657 Errors: Disk/file error => ERROR1 02658 02659 ********************************************************************************************/ 02660 02661 BOOL EPSExportDC::OutputNewLine() 02662 { 02663 // Graeme (22-2-00) - Windows uses \r\n as the newline code in its files. 02664 static TCHAR NewLine[] = _T("\r\n"); 02665 if (!OutputTCHARAsChar(NewLine, 2)) 02666 // Error occured 02667 return FALSE; 02668 02669 LineWidth = 0; 02670 02671 // Success 02672 return TRUE; 02673 } 02674 02675 /******************************************************************************************** 02676 02677 > BOOL EPSExportDC::OutputToken(TCHAR *Str) 02678 02679 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02680 Created: 28/03/94 02681 Inputs: Str - the character string to write to the file. 02682 Returns: TRUE if the data was written ok; 02683 FALSE if not => ERROR1 02684 Purpose: Outputs a string token to the EPS file. 02685 This is the central routine through which the other high-level routines 02686 eventually come. The other routines convert their output to a string, 02687 which theythen pass on to this routine. 02688 A record is kept of the current line width - if it is over 70 characters 02689 wide before the token is output, then a new line is output to keep 02690 the lines in the EPS file reasonably short. 02691 For this reason, it is important not to output strings that contain 02692 newline characters, because this routine will not notice, and hence 02693 the LineWidth count will be wrong. 02694 This routine also ensures that tokens are separated by either a space 02695 or a newline, so it is not necessary to output spaces directly to keep the 02696 tokens separate - it happens automatically. 02697 SeeAlso: EPSExportDC 02698 Errors: Disk/file error => ERROR1 02699 02700 ********************************************************************************************/ 02701 02702 BOOL EPSExportDC::OutputToken(TCHAR *Str) 02703 { 02704 // Special tokens 02705 static TCHAR Space = _T(' '); 02706 02707 if (LineWidth > 100) 02708 { 02709 // (ChrisG 8/12/00) We now have only one way of writing a newline out. The old method 02710 // used "/n/r" to write a newline, which doesn't work, while OutputNewLine used "/r/n", 02711 // which does, Also the max line width has been expanded to 100 characters. 02712 if (OutputNewLine () == FALSE) 02713 // Error 02714 return FALSE; 02715 } 02716 02717 // Pad with a space (unless at the beginning of the line) 02718 if (LineWidth > 0) 02719 { 02720 if (!OutputTCHARAsChar(&Space, 1)) 02721 // Error 02722 return FALSE; 02723 LineWidth++; 02724 } 02725 02726 // Write the token out to the file 02727 INT32 Len = camStrlen(Str); 02728 if (!OutputTCHARAsChar(Str, Len)) 02729 // Error 02730 return FALSE; 02731 02732 LineWidth += Len; 02733 02734 // Success 02735 return TRUE; 02736 } 02737 02738 02739 /******************************************************************************************** 02740 02741 > BOOL EPSExportDC::OutputDirect(BYTE *Buf, INT32 nBytes) 02742 02743 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02744 Created: 04/23/95 02745 Inputs: Buf - the bytes to send to the stream. 02746 nBytes - the number of bytes to send to the stream. 02747 Returns: TRUE if all the bytes were sent ok; 02748 FALSE if not. 02749 Purpose: Send bytes directly to the PostScript stream with no alteration or padding. 02750 Used for sending binary/hex data to stream. 02751 SeeAlso: KernelDC::OutputNewLine; KernelDC::OutputToken 02752 02753 ********************************************************************************************/ 02754 02755 BOOL EPSExportDC::OutputDirect(BYTE *Buf, INT32 nBytes) 02756 { 02757 if (ExportFile->write(Buf, nBytes).fail()) 02758 { 02759 // Error 02760 return FALSE; 02761 } 02762 02763 // All ok 02764 return TRUE; 02765 } 02766 02767 02768 02769