saveeps.cpp

Go to the documentation of this file.
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 

Generated on Sat Nov 10 03:46:47 2007 for Camelot by  doxygen 1.4.4