00001 // $Id: ai_epsrr.cpp 1336 2006-06-17 16:18:41Z alex $ 00002 // Implementation of Adobe Illustrator EPS filter. 00003 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00004 ================================XARAHEADERSTART=========================== 00005 00006 Xara LX, a vector drawing and manipulation program. 00007 Copyright (C) 1993-2006 Xara Group Ltd. 00008 Copyright on certain contributions may be held in joint with their 00009 respective authors. See AUTHORS file for details. 00010 00011 LICENSE TO USE AND MODIFY SOFTWARE 00012 ---------------------------------- 00013 00014 This file is part of Xara LX. 00015 00016 Xara LX is free software; you can redistribute it and/or modify it 00017 under the terms of the GNU General Public License version 2 as published 00018 by the Free Software Foundation. 00019 00020 Xara LX and its component source files are distributed in the hope 00021 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00022 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00023 See the GNU General Public License for more details. 00024 00025 You should have received a copy of the GNU General Public License along 00026 with Xara LX (see the file GPL in the root directory of the 00027 distribution); if not, write to the Free Software Foundation, Inc., 51 00028 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00029 00030 00031 ADDITIONAL RIGHTS 00032 ----------------- 00033 00034 Conditional upon your continuing compliance with the GNU General Public 00035 License described above, Xara Group Ltd grants to you certain additional 00036 rights. 00037 00038 The additional rights are to use, modify, and distribute the software 00039 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00040 library and any other such library that any version of Xara LX relased 00041 by Xara Group Ltd requires in order to compile and execute, including 00042 the static linking of that library to XaraLX. In the case of the 00043 "CDraw" library, you may satisfy obligation under the GNU General Public 00044 License to provide source code by providing a binary copy of the library 00045 concerned and a copy of the license accompanying it. 00046 00047 Nothing in this section restricts any of the rights you have under 00048 the GNU General Public License. 00049 00050 00051 SCOPE OF LICENSE 00052 ---------------- 00053 00054 This license applies to this program (XaraLX) and its constituent source 00055 files only, and does not necessarily apply to other Xara products which may 00056 in part share the same code base, and are subject to their own licensing 00057 terms. 00058 00059 This license does not apply to files in the wxXtra directory, which 00060 are built into a separate library, and are subject to the wxWindows 00061 license contained within that directory in the file "WXXTRA-LICENSE". 00062 00063 This license does not apply to the binary libraries (if any) within 00064 the "libs" directory, which are subject to a separate license contained 00065 within that directory in the file "LIBS-LICENSE". 00066 00067 00068 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00069 ---------------------------------------------- 00070 00071 Subject to the terms of the GNU Public License (see above), you are 00072 free to do whatever you like with your modifications. However, you may 00073 (at your option) wish contribute them to Xara's source tree. You can 00074 find details of how to do this at: 00075 http://www.xaraxtreme.org/developers/ 00076 00077 Prior to contributing your modifications, you will need to complete our 00078 contributor agreement. This can be found at: 00079 http://www.xaraxtreme.org/developers/contribute/ 00080 00081 Please note that Xara will not accept modifications which modify any of 00082 the text between the start and end of this header (marked 00083 XARAHEADERSTART and XARAHEADEREND). 00084 00085 00086 MARKS 00087 ----- 00088 00089 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00090 designs are registered or unregistered trademarks, design-marks, and/or 00091 service marks of Xara Group Ltd. All rights in these marks are reserved. 00092 00093 00094 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00095 http://www.xara.com/ 00096 00097 =================================XARAHEADEREND============================ 00098 */ 00099 00100 #include "camtypes.h" 00101 00102 #include "ai_epsrr.h" 00103 00104 #include <stdio.h> 00105 #include <math.h> 00106 00107 #include "vectrndr.h" 00108 #include "ccdc.h" 00109 //#include "colmodel.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 #include "opbevel.h" 00112 #include "swfexpdc.h" 00113 #include "swfrndr.h" 00114 #include "slicehelper.h" 00115 #include "fillramp.h" 00116 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00117 #include "nodebmp.h" 00118 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00119 //#include "range.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00120 //#include "rendsel.h" 00121 //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00122 #include "fontman.h" // for FontManager - for writing font changes to overflow text 00123 #include "colplate.h" // for ColourPlate - in overflow text functions 00124 #include "colourix.h" // for Indexed Colour - for writing colour changes to overflow 00125 #include "nodebev.h" 00126 #include "layer.h" 00127 #include "clipattr.h" 00128 00129 CC_IMPLEMENT_DYNAMIC(AIEPSRenderRegion, EPSRenderRegion) 00130 00131 /******************************************************************************************** 00132 00133 > AIEPSRenderRegion::AIEPSRenderRegion ( DocRect ClipRect, 00134 Matrix ConvertMatrix, 00135 FIXED16 ViewScale ) 00136 00137 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00138 Created: 29/3/00 00139 Purpose: Create and initialise a render region for exporting AI EPS. Sets up the 00140 string to put in the %%Creator comment. 00141 SeeAlso: EPSRenderRegion::EPSRenderRegion () 00142 00143 ********************************************************************************************/ 00144 00145 AIEPSRenderRegion::AIEPSRenderRegion ( DocRect ClipRect, 00146 Matrix ConvertMatrix, 00147 FIXED16 ViewScale ) 00148 : EPSRenderRegion ( ClipRect, ConvertMatrix, ViewScale ) 00149 { 00150 // Set up member variables. 00151 m_a = 1; 00152 m_b = 0; 00153 m_c = 0; 00154 m_d = 1; 00155 m_T = DocCoord ( 0, 0 ); 00156 m_ActiveLayer = FALSE; 00157 m_LayerColour = 0; 00158 00159 m_fpOverflowText = NULL; 00160 00161 m_bInTextGap = FALSE; 00162 m_bTextAsShapes = FALSE; 00163 00164 m_pLinearGradList = NULL; 00165 m_pRadialGradList = NULL; 00166 00167 // Initialise the creator string to show that it's an AI file. 00168 CreatorString = _T("Adobe Illustrator(TM) 7.0 by Xara."); 00169 } 00170 00171 /******************************************************************************************** 00172 00173 > AIEPSRenderRegion::~AIEPSRenderRegion 00174 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00175 Created: 30/3/2001 00176 Purpose: Destructor for an AI render region. All this really does is dispose of the 00177 gradient fill cache (if there is one) 00178 SeeAlso: EPSRenderRegion::EPSRenderRegion () 00179 00180 ********************************************************************************************/ 00181 AIEPSRenderRegion::~AIEPSRenderRegion () 00182 { 00183 ClearGradientCache (); 00184 } 00185 00186 /******************************************************************************************** 00187 00188 > BOOL AIEPSRenderRegion::ExportBitmap ( NodeBitmap *pNodeBMP ) 00189 00190 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00191 Created: 31/3/00 00192 Inputs: pNodeBMP - A pointer to the NodeBitmap being exported. 00193 Returns: TRUE - If successful. 00194 FALSE - If an error is encountered. 00195 Purpose: Kicks off the NodeBitmap export process.. 00196 SeeAlso: NodeBitmap::ExportRender () 00197 00198 ********************************************************************************************/ 00199 00200 BOOL AIEPSRenderRegion::ExportBitmap ( NodeBitmap *pNodeBMP ) 00201 { 00202 // Set up the local variables. 00203 KernelBitmap *pBitmap = pNodeBMP->GetBitmap (); 00204 00205 // Set up the bitmap's transformation matrix. 00206 LoadBitmapMatrix ( pNodeBMP ); 00207 00208 // Write out the bitmap record. 00209 WriteBitmapRecord ( pBitmap->GetActualBitmap () ); 00210 00211 return TRUE; 00212 } 00213 00214 /******************************************************************************************** 00215 00216 > BOOL AIEPSRenderRegion::ExportBevel ( NodeBevel *pBevel ) 00217 00218 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00219 Created: 6/4/00 00220 Inputs: pBevel - A pointer to a bevel node. 00221 Returns: TRUE - Success. 00222 FALSE - An error occured. 00223 Purpose: Renders a bevel into a DIB, and exports this as a bitmap to the AI file. 00224 SeeAlso: NodeBevel::ExportRender 00225 00226 ********************************************************************************************/ 00227 00228 BOOL AIEPSRenderRegion::ExportBevel ( NodeBevel *pBevel ) 00229 { 00230 // Set up the local variables. 00231 KernelDC *pDC = static_cast<KernelDC *> ( CCDC::ConvertFromNativeDC(RenderDC) ); 00232 RangeControl ControlFlags ( TRUE, TRUE ); 00233 Range ToRender ( pBevel, pBevel, ControlFlags ); 00234 KernelBitmap *pBitmap = NULL; 00235 Path *pSourcePath = &( pBevel->InkPath ); 00236 DocRect Bounds = pBevel->GetBoundingRect (); 00237 DocCoord Position ( Bounds.lo.x, Bounds.hi.y ); 00238 double Width = static_cast<double> ( Bounds.Width () ); 00239 double Height = static_cast<double> ( Bounds.Height () ); 00240 00241 // Create and render the bitmap. 00242 pBitmap = pBevel->CreateBitmapCopy(-1.0,FALSE); 00243 00244 if(!pBitmap) 00245 return FALSE; 00246 00247 // Get the width and height of the bitmap. 00248 double BMPWidth = static_cast<double> ( pBitmap->GetWidth () ); 00249 double BMPHeight = static_cast<double> ( pBitmap->GetHeight () ); 00250 00251 // Write the path. (ChrisG 16/01/01) If we have one. 00252 if (pSourcePath->GetNumCoords () != 0) 00253 { 00254 WriteMask ( pSourcePath, TRUE ); 00255 } 00256 00257 // Set up the bitmap translation matrix. 00258 LoadTranslationMatrix ( Position ); 00259 00260 // Scale width and height to be valid value for AI co-ordinates. 00261 Width /= 1000; 00262 Height /= 1000; 00263 00264 // And calcuate the scale values for placing the bitmap. 00265 m_a = Width / BMPWidth; 00266 m_d = Height / BMPHeight; 00267 00268 // Write the bitmap record. 00269 WriteBitmapRecord ( pBitmap->ActualBitmap ); 00270 00271 // Write the end of mask operator. (ChrisG 16/01/01) If we've written a mask. 00272 if (pSourcePath->GetNumCoords () != 0) 00273 { 00274 pDC->OutputToken ( _T("Q") ); 00275 pDC->OutputNewLine (); 00276 } 00277 00278 if(pBitmap) 00279 { 00280 pBitmap->DestroyGreyscaleVersion(); 00281 delete pBitmap; 00282 } 00283 00284 // Success! 00285 return TRUE; 00286 } 00287 00288 /******************************************************************************************** 00289 00290 > BOOL AIEPSRenderRegion::ExportShadow ( OILBitmap *pBitmap, 00291 UINT32 Darkness, 00292 DocRect &Bounds ) 00293 00294 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00295 Created: 11/4/00 00296 Inputs: pShadow - A pointer to a shadow node. 00297 Returns: TRUE - Success. 00298 FALSE - An error occured. 00299 Purpose: Renders a shadow into a DIB, and exports this as a bitmap to the AI file. 00300 SeeAlso: NodeBevel::ExportRender 00301 00302 ********************************************************************************************/ 00303 00304 BOOL AIEPSRenderRegion::ExportShadow ( OILBitmap *pBitmap, 00305 UINT32 Darkness, 00306 DocRect &Bounds ) 00307 { 00308 // Set up the local variables. 00309 // KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00310 DocCoord Position ( Bounds.lo.x, Bounds.hi.y ); 00311 double Width = static_cast<double> ( Bounds.Width () ) / 1000; 00312 double Height = static_cast<double> ( Bounds.Height () ) / 1000; 00313 double BMPWidth = static_cast<double> ( pBitmap->GetWidth () ); 00314 double BMPHeight = static_cast<double> ( pBitmap->GetHeight () ); 00315 DocColour ShadowColour = *( static_cast<FillGeometryAttribute*> 00316 ( GetCurrentAttribute ( ATTR_FILLGEOMETRY ) ) 00317 ->GetStartColour () ); 00318 DocColour BlendedShadow = AlphaBlend ( ShadowColour, mBackgroundColour, Darkness ); 00319 00320 // And use the shadow colour to build a contone bitmap palette. 00321 pBitmap->BuildContonePalette ( BlendedShadow, mBackgroundColour, EFFECT_RGB, 00322 RenderView ); 00323 00324 // Set up the bitmap translation matrix. 00325 LoadTranslationMatrix ( Position ); 00326 00327 // And calcuate the scale values for placing the bitmap. 00328 m_a = Width / BMPWidth; 00329 m_d = Height / BMPHeight; 00330 00331 // Write out the bitmap header. 00332 WriteBitmapHeader ( (INT32)BMPWidth, (INT32)BMPHeight ); 00333 00334 // Export the bitmap. 00335 WriteContoneBody ( pBitmap ); 00336 00337 // Finish off the bitmap record. 00338 WriteBitmapTail (); 00339 00340 return TRUE; 00341 } 00342 00343 /******************************************************************************************** 00344 00345 > BOOL AIEPSRenderRegion::ExportLayer ( Layer *pLayer ) 00346 00347 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00348 Created: 11/4/00 00349 Inputs: pLayer - A pointer to a layer object. 00350 Returns: TRUE - Success. 00351 FALSE - An error occured. 00352 Purpose: If there is an existing layer, it writes the end of layer tags, before 00353 creating a new layer record. 00354 SeeAlso: AIEPSRenderRegion::EndLayer () 00355 00356 ********************************************************************************************/ 00357 00358 BOOL AIEPSRenderRegion::ExportLayer ( Layer *pLayer ) 00359 { 00360 // Tidy up the existing layer, if it exists. 00361 EndLayer (); 00362 00363 // And write out the next layer. 00364 return StartLayer ( static_cast<Layer*> ( pLayer->FindNext 00365 ( CC_RUNTIME_CLASS ( Layer ) ) ) ); 00366 } 00367 00368 /******************************************************************************************** 00369 00370 > BOOL AIEPSRenderRegion::StartLayer ( Layer *pLayer ) 00371 00372 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00373 Created: 11/4/00 00374 Inputs: pLayer - A pointer to a layer object. 00375 Returns: TRUE - Success. 00376 FALSE - An error occured. 00377 Purpose: Writes a layer record to the file. 00378 SeeAlso: AIEPSRenderRegion::EndLayer () 00379 00380 ********************************************************************************************/ 00381 00382 BOOL AIEPSRenderRegion::StartLayer ( Layer *pLayer ) 00383 { 00384 // Catch null pointers to layers. 00385 if ( pLayer != NULL ) 00386 { 00387 KernelDC *pDC = static_cast<KernelDC *> ( CCDC::ConvertFromNativeDC(RenderDC) ); 00388 TCHAR LayerName [258]; 00389 00390 // Set up the layer's name. 00391 camSprintf ( LayerName, _T("(%s)"), ( TCHAR* ) pLayer->GetLayerID () ); 00392 00393 // Start a layer definition. 00394 pDC->OutputToken ( _T("%AI5_BeginLayer") ); 00395 pDC->OutputNewLine (); 00396 00397 // Set the layer's properties. 00398 pDC->OutputValue ( ( UINT32 ) pLayer->IsVisible () ); // Is the layer visible? 00399 pDC->OutputValue ( ( UINT32 ) 1 ); // Is the layer previewed? 00400 pDC->OutputValue ( ( UINT32 ) !pLayer->IsLocked () ); // Is the layer enabled? 00401 pDC->OutputValue ( ( UINT32 ) pLayer->IsPrintable () );//Is the layer printable? 00402 pDC->OutputValue ( ( UINT32 ) 0 ); // Is the layer dimmed? 00403 pDC->OutputValue ( ( UINT32 ) 0 ); // No multilayer masks. 00404 00405 // The ID colour. 00406 pDC->OutputValue ( ( UINT32 ) m_LayerColour % 27 ); // Set the layer's ID colour. 00407 m_LayerColour ++; // Increment colour ID. 00408 00409 // Colour values - I don't know what they're used for. 00410 pDC->OutputValue ( ( UINT32 ) 0 ); // Red intensity. 00411 pDC->OutputValue ( ( UINT32 ) 0 ); // Blue intensity. 00412 pDC->OutputValue ( ( UINT32 ) 0 ); // Green intensity. 00413 00414 // Write out the Lb tag. 00415 pDC->OutputToken ( _T("Lb") ); 00416 pDC->OutputNewLine (); 00417 00418 // Set the layer's name. 00419 pDC->OutputToken ( LayerName ); 00420 pDC->OutputToken ( _T("Ln") ); 00421 pDC->OutputNewLine (); 00422 00423 // Tell Camelot that there is an active layer. 00424 m_ActiveLayer = TRUE; 00425 } 00426 00427 // Success! 00428 return TRUE; 00429 } 00430 00431 /******************************************************************************************** 00432 00433 > void AIEPSRenderRegion::RenderChar (WCHAR ch, Matrix * pMatrix) 00434 00435 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00436 Created: 1/11/00 00437 Purpose: Overrides the default behaviour for rendering a single character. Used to 00438 store additional information on text blocks needed for AI text. i.e. the 00439 overflow text block ((xxxxxxxxx) TX) which occurs after the unjustified 00440 ((x) Tx\n (x) Tx\n) block. Both of these are needed for correct Illustrator 00441 export of text. 00442 SeeAlso: EPSRenderRegion::RenderChar 00443 00444 ********************************************************************************************/ 00445 00446 BOOL AIEPSRenderRegion::RenderChar(WCHAR ch, Matrix* pMatrix) 00447 { 00448 TCHAR buf[20]; 00449 BOOL result = FALSE; // assume failure if nothing given. 00450 00451 if (m_bTextAsShapes) 00452 { 00453 result = RenderCharAsShape (ch, pMatrix); 00454 } 00455 else 00456 { 00457 // Output matrix (a b c d e f Tm\n) - a,b,c and d are in the range 1.0 to -1.0 00458 // Only do this for text on paths 00459 if (ExportingOnPath ()) 00460 { 00461 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00462 00463 pDC->OutputMatrix(pMatrix); 00464 pDC->OutputToken(_T("Tm")); 00465 pDC->OutputNewLine(); 00466 } 00467 00468 // call the base class first, so that the attributes are exported BEFORE the character 00469 result = EPSRenderRegion::RenderChar (ch, pMatrix);; 00470 00471 // store any extra information, closing an attribute gap if one is open. 00472 if (ExportingOnPath ()) 00473 { 00474 OverflowTextFinishGap (); 00475 camSprintf (buf,_T("%c"),ch); 00476 OverflowTextWrite (buf); 00477 } 00478 } 00479 // Call the base class' function to do the standard export. 00480 return result; 00481 } 00482 00483 00484 /******************************************************************************************** 00485 00486 > void AIEPSRenderRegion::RenderCharAsShape (WCHAR ch, Matrix * pMatrix) 00487 00488 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 00489 Created: 1/11/00 00490 Purpose: Allows text to be drawn as shapes, not characters, so that AI can cope 00491 with gradient filled text. 00492 SeeAlso: AIEPSRenderRegion::RenderChar, EPSRenderRegion::RenderChar 00493 00494 ********************************************************************************************/ 00495 00496 BOOL AIEPSRenderRegion::RenderCharAsShape (WCHAR ch, Matrix* pMatrix) 00497 { 00498 BOOL result = FALSE; 00499 00500 // create the char's path 00501 Path* pCharPath=CreateCharPath(ch,pMatrix); 00502 00503 // if the path got created correctly, then we done good... 00504 if (pCharPath!=NULL) 00505 { 00506 // if at least one point, draw path using current attibutes in render region 00507 if (pCharPath->GetNumCoords()!=0) 00508 DrawPath(pCharPath); 00509 00510 // clean up 00511 delete pCharPath; 00512 00513 result = TRUE; 00514 } 00515 00516 return result; 00517 } 00518 00519 /******************************************************************************************** 00520 00521 > void AIEPSRenderRegion::Initialise() 00522 00523 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00524 Created: 29/3/00 00525 Purpose: Sets up render region - it outputs the AIEPS file header comments, and 00526 intialises the rendering attributes. 00527 SeeAlso: EPSRenderRegion::Initialise, EPSRenderRegion::InitAttributes 00528 00529 ********************************************************************************************/ 00530 00531 void AIEPSRenderRegion::Initialise() 00532 { 00533 // Set up member variables. 00534 m_a = 1; 00535 m_b = 0; 00536 m_c = 0; 00537 m_d = 1; 00538 m_T = DocCoord ( 0, 0 ); 00539 m_ActiveLayer = FALSE; 00540 m_LayerColour = 0; 00541 00542 ClearGradientCache (); 00543 00544 // Call the EPSRenderRegion method to re-enter the export loop. 00545 EPSRenderRegion::InitAttributes (); 00546 } 00547 00548 /******************************************************************************************** 00549 00550 > BOOL AIEPSRenderRegion::WriteEPSVersion ( void ) 00551 00552 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00553 Created: 28/3/000 00554 Inputs: pDC - The device context to output to. 00555 Returns: TRUE if ok; 00556 FALSE if error (e.g. file/disk error or printer driver error) 00557 Purpose: Writes the relevant EPS version declaration. 00558 SeeAlso: EPSRenderRegion::WriteEPSVersion 00559 00560 ********************************************************************************************/ 00561 00562 BOOL AIEPSRenderRegion::WriteEPSVersion ( void ) 00563 { 00564 // Cast the pointer to an appropriate DC. 00565 KernelDC *pDC = static_cast<KernelDC *> ( CCDC::ConvertFromNativeDC(RenderDC) ); 00566 00567 // Output the special AIEPS header start token. 00568 pDC->OutputToken ( _T("%!PS-Adobe-3.0") ); 00569 pDC->OutputNewLine (); 00570 00571 return TRUE; 00572 } 00573 00574 /******************************************************************************************** 00575 00576 > BOOL AIEPSRenderRegion::WriteEPSProcessColours ( void ) 00577 00578 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00579 Created: 28/3/000 00580 Inputs: pDC - The device context to output to. 00581 Returns: TRUE if ok; 00582 FALSE if error (e.g. file/disk error or printer driver error) 00583 Purpose: Writes the colour type used to disk. 00584 SeeAlso: EPSRenderRegion::WriteEPSProcessColours 00585 00586 ********************************************************************************************/ 00587 00588 BOOL AIEPSRenderRegion::WriteEPSProcessColours ( void ) 00589 { 00590 // Cast a pointer to the appropriate DC. 00591 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00592 00593 // Output the process colours 00594 pDC->OutputToken ( _T("%%DocumentProcessColors: Cyan Magenta Yellow Black") ); 00595 pDC->OutputNewLine (); 00596 00597 return TRUE; 00598 } 00599 00600 /******************************************************************************************** 00601 00602 > BOOL AIEPSRenderRegion::WriteEPSResources ( EPSFilter *pFilter, 00603 Document *pDocument ) 00604 00605 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00606 Created: 28/3/00 00607 Inputs: pDC - The device context to output to. 00608 Returns: TRUE if ok; 00609 FALSE if error (e.g. file/disk error or printer driver error) 00610 Purpose: This function writes out the resource inclusion string required for the AI 00611 file. 00612 SeeAlso: EPSRenderRegion::WriteSetup 00613 00614 ********************************************************************************************/ 00615 00616 BOOL AIEPSRenderRegion::WriteEPSResources ( EPSFilter *pFilter, 00617 Document *pDocument ) 00618 { 00619 // Cast a pointer to the appropriate DC. 00620 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 00621 00622 // Call the export method in the document. 00623 pDocument->WriteEPSResources ( pFilter ); 00624 00625 // Add a few things necessary for the AI file format. 00626 pDC->OutputToken ( _T("%AI3_ColorUsage: Color") ); 00627 pDC->OutputNewLine (); 00628 pDC->OutputToken ( _T("%AI5_FileFormat 2.0") ); 00629 pDC->OutputNewLine (); 00630 00631 // All done. 00632 return TRUE; 00633 } 00634 00635 /******************************************************************************************** 00636 00637 > BOOL AIEPSRenderRegion::WriteEPSProlog ( EPSFilter *pFilter, 00638 Document *pDocument ) 00639 00640 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00641 Created: 28/3/00 00642 Inputs: pDC - The device context to output to. 00643 Returns: TRUE if ok; 00644 FALSE if error (e.g. file/disk error or printer driver error) 00645 Purpose: This method writes out the initialisation code for the included resources. 00646 SeeAlso: EPSRenderRegion::WriteSetup 00647 00648 ********************************************************************************************/ 00649 00650 BOOL AIEPSRenderRegion::WriteEPSProlog ( EPSFilter *pFilter, 00651 Document *pDocument ) 00652 { 00653 // Call the export method in the document. 00654 pDocument->WriteEPSProlog ( pFilter ); 00655 00656 // All done. 00657 return TRUE; 00658 } 00659 00660 /******************************************************************************************** 00661 00662 > virtual BOOL AIEPSRenderRegion::WriteGradientFills ( Document *pDocument ) 00663 00664 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00665 Created: 1/3/00 00666 Inputs: pDocument - The document to be written. 00667 Outputs: - 00668 Returns: TRUE if successful. 00669 FALSE if error (e.g. file/disk error) 00670 Purpose: Parses through the tree, identifies any gradient fills, and writes them to 00671 the export DC's file. 00672 00673 ********************************************************************************************/ 00674 00675 BOOL AIEPSRenderRegion::WriteGradientFills ( Document *pDocument ) 00676 { 00677 // Get the spread from the document. 00678 Spread *pSpread = pDocument->FindFirstSpread (); 00679 00680 // Build the gradient cache up from all the fills under the spread, after cleaning any 00681 // junk out of it (there shouldn't be any there, but that ain't the point) 00682 ClearGradientCache (); 00683 BuildGradientCache (pSpread); 00684 00685 // Write out the number of fills and their definition. 00686 WriteGradientCount (); 00687 WriteGradientDefinitions (); 00688 00689 // The fill has been successfully saved, so return TRUE. 00690 return TRUE; 00691 } 00692 00693 /******************************************************************************************** 00694 00695 > BOOL AIEPSRenderRegion::WriteLinearFill ( FillGeometryAttribute *pFill, INT32 id ) 00696 00697 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00698 Created: 1/3/00 00699 Inputs: pFill - A pointer to the fill attribute record. 00700 id - the id number for the fill 00701 Returns: TRUE - If successful. 00702 FALSE - The was an error (e.g. file/disk error). 00703 Purpose: Writes a linear fill to the disk file. 00704 00705 ********************************************************************************************/ 00706 00707 BOOL AIEPSRenderRegion::WriteLinearFill ( FillGeometryAttribute * pFill, EFFECTTYPE effect, INT32 id ) 00708 { 00709 // Extract the fill attribute - this is necessary for processing the fill type. 00710 KernelDC *pDC = static_cast<KernelDC *> ( CCDC::ConvertFromNativeDC(RenderDC) ); 00711 INT32 Colours = 2; 00712 TCHAR GradientName [32]; 00713 DocColour StartColour = *( pFill->GetStartColour () ); 00714 DocColour EndColour; 00715 ColourRamp *pRamp = pFill->GetColourRamp (); 00716 00717 // The fill is, or can be approximated by, a linear fill. 00718 camSprintf ( GradientName, _T("(%s %d)"), LinearGradient, id ); 00719 00720 // (ChrisG 16/01/01) Four colour fill MUST come first, as it's derived from Three 00721 // colour fill, and returns valid for IsThreeColFill(). 00722 if ( pFill->IsAFourColFill () ) 00723 { 00724 // I'm going to use a version of the below here, but for now I'll just 00725 // set up the end colour as the most distant end colour. 00726 EndColour = *( pFill->GetEndColour3 () ); 00727 } 00728 else if ( pFill->IsAThreeColFill () ) 00729 { 00730 // AI doesn't support three colour fills, so I'm going to fake it. This 00731 // code merges the two end colours to approximate the fill with a two 00732 // colour linear fill. 00733 EndColour.Mix ( pFill->GetEndColour (), pFill->GetEndColour2(), 00734 0.5f, NULL, FALSE, NULL ); 00735 } 00736 else 00737 { 00738 // Set up the end colour value appropriately. 00739 EndColour = *( pFill->GetEndColour () ); 00740 } 00741 00742 // Count the number of colours. 00743 if ( pRamp != NULL ) 00744 { 00745 UINT32 First = 0; 00746 UINT32 Last = 0; 00747 00748 // Extract the indices from the colour ramp. 00749 pRamp->GetIndexRange ( &First, &Last ); 00750 00751 // And add their difference to the colour count. Note, you need to add one 00752 // to the result so that you don't register having no colours. There really 00753 // should be a count number of elements method in the ramp code, though. 00754 Colours += 1 + Last - First; 00755 } 00756 00757 // (ChrisG 15/01/01) If this is a four colour fill, since we will be adding a mid-colour 00758 // below, then we need to include it in the definition 00759 if (pFill->IsAFourColFill ()) 00760 { 00761 Colours ++; 00762 } 00763 00764 // (ChrisG 4/4/2001) Add in the extra colours given from the HSV fill effect emulation 00765 if (effect == EFFECT_HSV_SHORT || effect == EFFECT_HSV_LONG) 00766 { 00767 Colours += (Colours - 1) * NumFillEmulationSteps; 00768 } 00769 00770 // Write the gradient's header. 00771 pDC->OutputToken ( _T("%AI5_BeginGradient:") ); 00772 pDC->OutputToken ( GradientName ); 00773 pDC->OutputNewLine (); 00774 00775 // Then the type definition. 00776 pDC->OutputToken ( GradientName ); 00777 pDC->OutputValue ( static_cast<INT32> ( LinearFill ) ); 00778 pDC->OutputValue ( static_cast<INT32> ( Colours ) ); 00779 pDC->OutputToken ( _T("Bd") ); 00780 pDC->OutputNewLine (); 00781 pDC->OutputToken ( _T("[") ); 00782 pDC->OutputNewLine (); 00783 00784 // (ChrisG 3/4/2001) Get bias and convert to 0-100 range (from -1 to +1) 00785 // This will be used later on to offset the positions 00786 CProfileBiasGain profile = pFill->GetProfile (); 00787 INT32 bias = (INT32) ((1 - (double) profile.GetBias ()) * 50); 00788 00789 // Write out the last colour. 00790 WriteGradientEntry ( &EndColour, 100, 50 ); 00791 00792 // set up the last colour and position (for the fill effect emulation. 00793 DocColour * pLastColour = &EndColour; 00794 INT32 lastPos = 100; 00795 00796 // Mid colour for four colour fills - this needs to be stored longer so that it can be 00797 // re-used in the case of HSV fill effects. 00798 DocColour MidColour; 00799 00800 // If the fill is a four colour fill, add a mid-colour that's a blend of the 00801 // second and third colours. 00802 if ( pFill->IsAFourColFill () ) 00803 { 00804 00805 MidColour.Mix ( pFill->GetEndColour (), pFill->GetEndColour2 (), 00806 0.5f, NULL, FALSE, NULL ); 00807 00808 // Write out the extra fill steps, if there are any. 00809 if (effect != EFFECT_RGB) 00810 { 00811 WriteFillEffectSteps (pLastColour, lastPos, &MidColour, 50, bias, effect); 00812 pLastColour = &MidColour; 00813 } 00814 00815 // And set the value. 00816 WriteGradientEntry ( &MidColour, 50, bias); 00817 } 00818 00819 // Otherwise, process the colour ramp. 00820 else if ( pRamp != NULL ) 00821 { 00822 ColRampItem *pItem = pRamp->GetLastCol (); 00823 00824 // Write in the ramp's colour values. 00825 while ( pItem != NULL ) 00826 { 00827 // Get the position of the colour in the fill. 00828 INT32 Ratio = static_cast <INT32> ( 100 * pItem->GetPosition () ); 00829 DocColour *pCol = pItem->GetColourAddr (); 00830 00831 // Write out the extra fill steps, if there are any. 00832 if (effect != EFFECT_RGB) 00833 { 00834 WriteFillEffectSteps (pLastColour, lastPos, pCol, Ratio, bias, effect); 00835 pLastColour = pCol; 00836 lastPos = Ratio; 00837 } 00838 00839 // And set the value. 00840 WriteGradientEntry ( pCol, Ratio, 50 ); 00841 00842 // Increment the pointer onto the next item. 00843 pItem = pRamp->GetPrevCol ( pItem ); 00844 } 00845 } 00846 00847 // Write out the extra fill steps, if there are any. 00848 if (effect != EFFECT_RGB) 00849 { 00850 WriteFillEffectSteps (pLastColour, lastPos, &StartColour, 0, bias, effect); 00851 } 00852 00853 // Write out the start colour. 00854 WriteGradientEntry ( &StartColour, 0, bias ); 00855 00856 // Write out the end of gradient tokens. 00857 pDC->OutputToken ( _T("BD") ); 00858 pDC->OutputNewLine (); 00859 pDC->OutputToken ( _T("%AI5_EndGradient") ); 00860 pDC->OutputNewLine (); 00861 00862 // It worked! 00863 return TRUE; 00864 } 00865 00866 00867 /******************************************************************************************** 00868 00869 > BOOL AIEPSRenderRegion::WriteRadialFill ( AttrFillGeometry *pFill, INT32 id ) 00870 00871 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00872 Created: 1/3/00 00873 Inputs: pFill - A pointer to the fill attribute record. 00874 id - The fill's id number 00875 Returns: TRUE - If successful. 00876 FALSE - The was an error (e.g. file/disk error). 00877 Purpose: Writes a Radial fill to the disk file. 00878 00879 ********************************************************************************************/ 00880 BOOL AIEPSRenderRegion::WriteRadialFill (FillGeometryAttribute * pFill, EFFECTTYPE effect, INT32 id) 00881 { 00882 // Extract the fill attribute - this is necessary for processing the fill type. 00883 KernelDC *pDC = static_cast<KernelDC *> ( CCDC::ConvertFromNativeDC(RenderDC) ); 00884 INT32 Colours = 2; 00885 TCHAR GradientName [32]; 00886 DocColour StartColour = *( pFill->GetStartColour () ); 00887 DocColour EndColour = *( pFill->GetEndColour () ); 00888 ColourRamp *pRamp = pFill->GetColourRamp (); 00889 00890 // The fill is, or can be approximated by, a Radial fill. 00891 camSprintf ( GradientName, _T("(%s %d)"), RadialGradient, id ); 00892 00893 // Count the number of colours. 00894 if ( pRamp != NULL ) 00895 { 00896 UINT32 First = 0; 00897 UINT32 Last = 0; 00898 00899 // Extract the indices from the colour ramp. 00900 pRamp->GetIndexRange ( &First, &Last ); 00901 00902 // And add their difference to the colour count. Note, you need to add one 00903 // to the result so that you don't register having no colours. There really 00904 // should be a count number of elements method in the ramp code, though. 00905 Colours += 1 + Last - First; 00906 00907 if (effect != EFFECT_RGB) 00908 { 00909 // Add in the extra steps for the fill effect (Five extra steps between each 00910 // pair of colours). 00911 Colours += (Colours - 1) * NumFillEmulationSteps; 00912 } 00913 } 00914 00915 // Write the gradient's header. 00916 pDC->OutputToken ( _T("%AI5_BeginGradient:") ); 00917 pDC->OutputToken ( GradientName ); 00918 pDC->OutputNewLine (); 00919 00920 // Then the type definition. 00921 pDC->OutputToken ( GradientName ); 00922 pDC->OutputValue ( static_cast<INT32> ( RadialFill ) ); 00923 pDC->OutputValue ( static_cast<INT32> ( Colours ) ); 00924 pDC->OutputToken ( _T("Bd") ); 00925 pDC->OutputNewLine (); 00926 pDC->OutputToken ( _T("[") ); 00927 pDC->OutputNewLine (); 00928 00929 // (ChrisG 3/4/2001) Get bias and convert to 0-100 range (from -1 to +1) 00930 CProfileBiasGain profile = pFill->GetProfile (); 00931 INT32 bias = (INT32) ((1 - (double) profile.GetBias ()) * 50); 00932 00933 // Write out the start colour. 00934 WriteGradientEntry ( &StartColour, 0, bias ); 00935 00936 DocColour * pLastCol = &StartColour; 00937 INT32 lastPos = 0; 00938 00939 // Process the colour ramp. 00940 if ( pRamp != NULL ) 00941 { 00942 ColRampItem *pItem = pRamp->GetFirstCol (); 00943 00944 // Write in the ramp's colour values. 00945 while ( pItem != NULL ) 00946 { 00947 // Get the position of the colour in the fill. 00948 INT32 Ratio = static_cast <INT32> ( 100 * pItem->GetPosition () ); 00949 DocColour *pCol = pItem->GetColourAddr (); 00950 00951 // Write out the intermediate fill steps (if there are any). 00952 if (effect != EFFECT_RGB) 00953 { 00954 WriteFillEffectSteps (pLastCol, lastPos, pCol, Ratio, bias, effect); 00955 pLastCol = pCol; 00956 lastPos = Ratio; 00957 } 00958 00959 // And set the value. 00960 WriteGradientEntry ( pCol, Ratio, 50 ); 00961 00962 // Increment the pointer onto the next item. 00963 pItem = pRamp->GetNextCol ( pItem ); 00964 } 00965 } 00966 00967 // Write out the intermediate fill steps (if there are any). 00968 if (effect != EFFECT_RGB) 00969 { 00970 WriteFillEffectSteps (pLastCol, lastPos, &EndColour, 100, bias, effect); 00971 } 00972 00973 // Write out the last colour. 00974 WriteGradientEntry ( &EndColour, 100, 50 ); 00975 00976 // Write out the end of gradient tokens. 00977 pDC->OutputToken ( _T("BD") ); 00978 pDC->OutputNewLine (); 00979 pDC->OutputToken ( _T("%AI5_EndGradient") ); 00980 pDC->OutputNewLine (); 00981 00982 // It worked! 00983 return TRUE; 00984 } 00985 00986 /******************************************************************************************** 00987 00988 > virtual BOOL AIEPSRenderRegion::WriteGradientEntry ( DocColour *pColour, 00989 INT32 Position, 00990 INT32 Midpoint ) 00991 00992 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00993 Created: 24/3/00 00994 Inputs: pColour - A pointer to a Camelot colour. 00995 Position - The position of the colour within the fill. 00996 Midpoint - The midpoint of the fill. 00997 Returns: TRUE if successful. 00998 FALSE if error (e.g. file/disk error) 00999 Purpose: Writes a line into the definition of a gradient fill. 01000 01001 ********************************************************************************************/ 01002 BOOL AIEPSRenderRegion::WriteGradientEntry ( DocColour *pColour, 01003 INT32 Position, 01004 INT32 Midpoint ) 01005 { 01006 INT32 red; // 01007 INT32 green; // RGB colour values 01008 INT32 blue; // 01009 PColourCMYK CMYKColour; // The colour to be stored. 01010 01011 KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); 01012 TCHAR Line [80]; // Contains the string to be stored. 01013 01014 // (ChrisG 3/4/2001) 01015 if (Midpoint < 13) 01016 Midpoint = 13; 01017 else if (Midpoint > 87) 01018 Midpoint = 87; 01019 01020 pColour->GetCMYKValue ( &CMYKColour ); // Extract the CMYK value. 01021 01022 if (pColour->GetColourModel () == COLOURMODEL_RGBT || 01023 pColour->GetColourModel () == COLOURMODEL_HSVT) 01024 { 01025 // Use RGB syntax. 01026 pColour->GetRGBValue ( &red, &green, &blue ); 01027 01028 camSprintf ( Line, _T("2 %d %d%%_Bs"), Midpoint, Position ); 01029 pDC->OutputColour ( &CMYKColour ); 01030 pDC->OutputColourValue ( red ); 01031 pDC->OutputColourValue ( green ); 01032 pDC->OutputColourValue ( blue ); 01033 pDC->OutputToken ( Line ); 01034 pDC->OutputNewLine (); 01035 } 01036 else 01037 { 01038 01039 // It is necessary to build the output line like this, so that there isn't a space 01040 // between the position of the colour, and the %_Bs operator. 01041 camSprintf ( Line, _T("1 %d %d%%_Bs"), Midpoint, Position ); // Build the output string. 01042 01043 pDC->OutputColour ( &CMYKColour ); // Write the colour to the file. 01044 pDC->OutputToken ( Line ); // Write the output string out. 01045 pDC->OutputNewLine (); // And write a new-line tag. 01046 } 01047 01048 return TRUE; // All done successfully. 01049 } 01050 01051 /******************************************************************************************** 01052 01053 > virtual BOOL AIEPSRenderRegion::WriteFillEffectSteps ( DocColour * pColour1, 01054 INT32 pos1, 01055 DocColour * pColour2, 01056 INT32 pos2, 01057 INT32 bias, 01058 EFFECTTYPE effect) 01059 01060 Author: Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com> 01061 Created: 4/4/2001 01062 Inputs: pColour1 - The colour to start from. 01063 pos1 - The position of the start colour within the fill (0-100%). 01064 pColour2 - The colour to end at. 01065 pos2 - The position of the end colour within the entire fill (0-100%) 01066 bias - The fill's bias part of any profile (0-100%). 01067 effect - The type of fill effect (EFFECT_HSV_SHORT or EFFECT_HSV_LONG) 01068 Returns: TRUE if successful. 01069 FALSE if error (e.g. file/disk error) 01070 Purpose: Writes the additional entries required for a special fill effect (rainbow or 01071 alt-rainbow) to the gradient definition, as a series of steps. 01072 See Also: AIEPSRenderRegion::WriteGradientEntry 01073 AIEPSRenderRegion::WriteLinearFill 01074 AIEPSRenderRegion::WriteRadialFill 01075 01076 ********************************************************************************************/ 01077 BOOL AIEPSRenderRegion::WriteFillEffectSteps ( DocColour *pColour1, 01078 INT32 pos1, 01079 DocColour *pColour2, 01080 INT32 pos2, 01081 INT32 bias, 01082 EFFECTTYPE effect) 01083 { 01084 ERROR3IF (effect == EFFECT_RGB, "AIEPSRenderRegion::WriteFillEffectSteps, an attempt was made to write HSV fill effect steps on an RGB fade fill"); 01085 01086 // RGB fades are the 'standard' fill, so we don't want to do any special processing on them 01087 if (effect != EFFECT_RGB) 01088 { 01089 // Start and end colour values 01090 INT32 h1 = 0; 01091 INT32 h2 = 0; 01092 INT32 s1 = 0; 01093 INT32 s2 = 0; 01094 INT32 v1 = 0; 01095 INT32 v2 = 0; 01096 01097 // intermediate colour values / increments 01098 DocColour midColour; 01099 double hAdd = 0; 01100 double sAdd = 0; 01101 double vAdd = 0; 01102 double posAdd = 0; 01103 01104 // First get the start and end colour components 01105 pColour1->GetHSVValue (&h1, &s1, &v1); 01106 pColour2->GetHSVValue (&h2, &s2, &v2); 01107 01108 // Calculate the increments 01109 // 01110 // NOTE: if the hue changes by more than 180 deg. in a short HSV (rainbow) fill 01111 // (or not more than 180 deg. in a long HSV (alt-rainbow) fill), then the direction 01112 // must be reversed. This is done by changing the hue increment value. 01113 hAdd = h2-h1; 01114 if (effect == EFFECT_HSV_SHORT) 01115 { 01116 if (hAdd > 180) 01117 hAdd -= 360; 01118 else if (hAdd < -180) 01119 hAdd += 360; 01120 } 01121 else 01122 { 01123 if ((hAdd > 0) && (hAdd <= 180)) 01124 hAdd -= 360; 01125 else if ((hAdd <= 0) && (hAdd >= -180)) 01126 hAdd += 360; 01127 } 01128 hAdd = hAdd / (NumFillEmulationSteps + 1); 01129 sAdd = (s2-s1) / (NumFillEmulationSteps + 1); 01130 vAdd = (v2-v1) / (NumFillEmulationSteps + 1); 01131 posAdd = ((double) pos2-pos1) / (NumFillEmulationSteps + 1); 01132 01133 // Cycle through the stops calcuating each stop's colour and position, before 01134 // writing them out. 01135 for (INT32 i=1; i<NumFillEmulationSteps + 1; i++) 01136 { 01137 // increment each colour value and the position 01138 h2 = (INT32)(h1 + (i * hAdd)); 01139 s2 = (INT32)(s1 + (i * sAdd)); 01140 v2 = (INT32)(v1 + (i * vAdd)); 01141 pos2 = (INT32)(pos1 + (i * posAdd)); 01142 01143 // wrap the hue around if it's gone past 360 deg or 0 deg. 01144 if (h2>=360) 01145 h2 -= 360; 01146 else if (h2<0) 01147 h2 += 360; 01148 01149 // create the colour and export. 01150 midColour.SetHSVValue (h2, s2, v2); 01151 WriteGradientEntry (&midColour, pos2, 50); 01152 } 01153 } // End of is fill effect not an RGB fade. 01154 01155 return TRUE; 01156 } 01157 01158 /******************************************************************************************** 01159 01160 > virtual BOOL AIEPSRenderRegion::WriteDocumentSetup ( Document *pDocument, 01161 EPSFilter *pFilter ) 01162 01163 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 01164 Created: 24/3/00 01165 Inputs: pDocument - The document being outputted. 01166 pFilter - A pointer to the export filter. 01167 Outputs: - 01168 Returns: TRUE if successful. 01169 FALSE if error (e.g. file/disk error) 01170 Purpose: Browse through the tree, and if a text story is found invoke the document 01171 setup function. By only exporting the font setup when necessary, the file 01172 size produced is smaller (which makes it easier for me to interpret :) ), 01173 and it should hopefully make the filter run a bit faster too. 01174 01175 ********************************************************************************************/ 01176 01177 BOOL AIEPSRenderRegion::WriteDocumentSetup ( Document *pDocument, 01178 EPSFilter *pFilter ) 01179 { 01180 // Get the spread from the document. 01181 Spread *pSpread = pDocument->FindFirstSpread (); 01182 Node *pTextStory = NULL; 01183 01184 // Try to find a single instance of the TextStory node. 01185 pTextStory = SliceHelper::FindNextOfClass ( pSpread, pSpread, 01186 CC_RUNTIME_CLASS ( TextStory ) ); 01187 01188 // If something was found... 01189 if ( pTextStory != NULL ) 01190 { 01191 // ... write out the font set-up. 01192 pDocument->WriteEPSSetup ( pFilter ); 01193 } 01194 else 01195 { 01196 // Otherwise just get the relevant bits. 01197 pDocument->AIExportExtras ( pFilter->GetExportDC () ); 01198 } 01199 01200 // It worked! 01201 return TRUE; 01202 } 01203 01204 /******************************************************************************************** 01205 01206 > BOOL AIEPSRenderRegion::EndLayer () 01207 01208 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 01209 Created: 11/4/00 01210 Inputs: - 01211 Returns: TRUE - Success. 01212 FALSE - An error occured. 01213 Purpose: If there is an existing layer, it writes the end of layer tags, before 01214 creating a new layer record. 01215 SeeAlso: AIEPSRenderRegion::ExportLayer () 01216 01217 ********************************************************************************************/ 01218 01219 BOOL AIEPSRenderRegion::EndLayer () 01220 { 01221 // Only act if there's an active layer. 01222 if ( m_ActiveLayer ) 01223 { 01224 // Cast the RenderDC pointer into a useful form. 01225 KernelDC *pDC = static_cast<KernelDC *> ( CCDC::ConvertFromNativeDC(RenderDC) ); 01226 01227 // Write out the end of layer tag. 01228 pDC->OutputToken ( _T("LB") ); 01229 pDC->OutputNewLine