// $Id: nativeps.cpp 1668 2006-08-04 11:45:17Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // The Native file format for Camelot first version. /* */ #include "camtypes.h" //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nativeps.h" //#include "filtrres.h" //#include "rik.h" //#include "tim.h" //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "cversion.h" #include "progress.h" //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "bmpcomp.h" //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "opgrad.h" #include "nodetext.h" //#include "nev.h" #include "zstream.h" // zipping stream class #include #include "fontman.h" #include "expbmp.h" //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "colormgr.h" // for ColourManager (see NativeRenderRegion::OutputGradFillColours) // An implement to match the Declare in the .h file. CC_IMPLEMENT_DYNAMIC(CamelotNativeEPSFilter, CamelotEPSFilter); #if !defined(EXCLUDE_FROM_RALPH) CC_IMPLEMENT_DYNAMIC(NativeRenderRegion, CamelotEPSRenderRegion); #endif // This will get Camelot to display the filename and linenumber of any memory allocations // that are not released at program exit #define new CAM_DEBUG_NEW typedef enum { TRANSPFILL_NONE, TRANSPFILL_FLAT, TRANSPFILL_LINEAR, TRANSPFILL_CIRCULAR, TRANSPFILL_ELLIPTICAL, TRANSPFILL_CONICAL, TRANSPFILL_TEXTURE, TRANSPFILL_FRACTAL, TRANSPFILL_NEWLINEAR, TRANSPFILL_NEWTEXTURE, TRANSPFILL_NEWFRACTAL } TranspFillGeometryType; // This is the array of Camelot EPS command/keyword names. CommandMap CamelotNativeEPSFilter::NativeCommands[] = { // Bitmap Pool Tokens { EPSC_cbmp, _T("cbmp") }, // Sentinel { EPSC_Invalid, _T("Invalid") } }; // The native file version numbers and some comments about what they can cope with typedef enum { // First version number // Created: 29/5/95 // Copes with: // - File compression // Does not cope with: FIRSTVERSION = 100 } NativeFileVersion; // Define what the current read and write versions are const NativeFileVersion ReadNativeVersion100 = FIRSTVERSION; const NativeFileVersion WriteNativeVersion100 = FIRSTVERSION; const double ReadNativeVersion = (ReadNativeVersion100/100); const double WriteNativeVersion = (WriteNativeVersion100/100); /******************************************************************************************** Preference: CompressNative Section: Filters Range: 0 to 1 Purpose: Flag for whether we compress the native files saved from Xara Studio. True means do compress the files. SeeAlso: - ********************************************************************************************/ BOOL CamelotNativeEPSFilter::CompressNative = TRUE; /******************************************************************************************** > CamelotNativeEPSFilter::CamelotNativeEPSFilter() Author: Rik_Heywood (Xara Group Ltd) Created: 15/12/94 Purpose: Constructor for the Native save/load filter. ********************************************************************************************/ CamelotNativeEPSFilter::CamelotNativeEPSFilter() { // Set up filter descriptions. FilterNameID = _R(IDS_NATIVE_EPS_FILTERNAME); FilterInfoID = _R(IDS_NATIVE_EPS_FILTERINFO); ImportMsgID = _R(IDS_IMPORTMSG_NATIVE_EPS); ExportMsgID = _R(IDS_EXPORTMSG_NATIVE_EPS); FilterID = FILTERID_NATIVE_EPS; #ifndef STANDALONE Flags.CanImport = TRUE; //WEBSTER-Martin-27/01/97 #ifdef WEBSTER Flags.CanExport = FALSE; #else Flags.CanExport = FALSE; #endif //WEBSTER #else Flags.CanImport = TRUE; Flags.CanExport = FALSE; #endif // We don't want to re-position Camelot files because they should be ok and // Charles gets upset if his drawings move. AdjustOrigin = FALSE; // Prepare the bitmap pool data IsSavingBitmapPool = FALSE; BitmapCount = 0; BitmapPoolRefs = NULL; PendingBitmapNum = 0; // A flag to store the Value of the ImportWithLayers flag in OldImportWithLayers = TRUE; OldOpenWithLayers = TRUE; // Items to handle the file compression CompressionType = 0; // type of compression in use (0 at present) CompressionOn = FALSE; // on/off flag FileVersionNumber = 0.0; BuildVersionNumber = 0.0; } /******************************************************************************************** > CamelotNativeEPSFilter::~CamelotNativeEPSFilter() Author: Rik_Heywood (Xara Group Ltd) Created: 20/1/95 Purpose: Tidies up when the filter is destroyed. Mostly takes care of the bitmap pool references that may have been built during the import. ********************************************************************************************/ CamelotNativeEPSFilter::~CamelotNativeEPSFilter() { // Get rid of the bitmap references if we have any if (BitmapPoolRefs != NULL) delete [] BitmapPoolRefs; } /******************************************************************************************** > BOOL CamelotNativeEPSFilter::Init() Author: Rik_Heywood (Xara Group Ltd) Created: 15/12/94 Returns: TRUE if it worked, FALSE if it failed Purpose: Initalises the Filter ready for use. Will fail if it can not get enough memory to work with. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::Init() { // Get the OILFilter object pOILFilter = new NativeEPSOILFilter(this); if (pOILFilter == NULL) return FALSE; // Load the description strings FilterName.Load(FilterNameID); FilterInfo.Load(FilterInfoID); // Preference to turn native file compression on or off if (Camelot.DeclareSection(_T("Filters"), 10)) { Camelot.DeclarePref( NULL, _T("CompressNative"), &CompressNative, 0, 1 ); } // All ok return TRUE; } /******************************************************************************************** > static BOOL CamelotNativeEPSFilter::SetNativeCompression(BOOL NewState) Author: Neville_Humphrys (Xara Group Ltd) Created: 27/5/95 Inputs: New state for native file compression, TRUE if want on, FALSE if want off. Returns: The old state of the compression. Purpose: Set the prefernece as to whether we are to compress the native files or not. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::SetNativeCompression(BOOL NewState) { // BOOL OldState = CompressNative; CompressNative = NewState; return CompressNative; } /******************************************************************************************** > static BOOL CamelotNativeEPSFilter::GetNativeCompression(BOOL NewState) Author: Neville_Humphrys (Xara Group Ltd) Created: 27/5/95 Inputs: New state for native file compression, TRUE if want on, FALSE if want off. Returns: The old state of the compression. Purpose: Set the prefernece as to whether we are to compress the native files or not. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::GetNativeCompression() { return CompressNative; } /******************************************************************************************** > virtual BOOL CamelotNativeEPSFilter::SetFileCompressionState(BOOL NewState) Author: Neville_Humphrys (Xara Group Ltd) Created: 19/5/95 Inputs: New state for file compression, TRUE if want on, FALSE if want off. Returns: True if succesful or False if not. Purpose: Set a new file compression status into action. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::SetFileCompressionState(BOOL NewState) { TRACEUSER( "Neville", _T("CamelotNativeEPSFilter::SetFileCompressionState new state= %d\n"),NewState); CompressionOn = NewState; return TRUE; } /******************************************************************************************** > virtual BOOL CamelotNativeEPSFilter::GetFileCompressionState() Author: Neville_Humphrys (Xara Group Ltd) Created: 19/5/95 Returns: The current state of the file compression. Purpose: Get the current file compression state. True if compressing. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::GetFileCompressionState() { return CompressionOn; } /******************************************************************************************** > virtual void CamelotNativeEPSFilter::LookUpToken() Author: Rik_Heywood (Xara Group Ltd) Created: 6/1/95 Purpose: Look up one of the tokens used by the Camelot Native EPS file format. ********************************************************************************************/ void CamelotNativeEPSFilter::LookUpToken() { // Not interested in comments if (Token == EPSC_Comment) return; // Check to see if it is a keyword - cycle through the array of keyword names and // compare against our token (could use a hash table?) INT32 i = 0; while (NativeCommands[i].Cmd != EPSC_Invalid) { if (camStrcmp(TokenBuf, NativeCommands[i].CmdStr) == 0) { // Found the token - set the token variable and return success Token = NativeCommands[i].Cmd; return; } // Try next command i++; } // Did not find this token - pass on to base class. CamelotEPSFilter::LookUpToken(); } /******************************************************************************************** > virtual BOOL CamelotNativeEPSFilter::ProcessToken() Author: Rik_Heywood (Xara Group Ltd) Created: 6/1/95 Returns: TRUE if it was able to process the token, FALSE if not. Purpose: Deals with the current token. This function deals with tokens that are specific to the Camelot Native EPS format, or different from Camelot EPS. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::ProcessToken() { ArrowRec Arrow; double ArrowWidth; double ArrowHeight; INT32 ArrowID; DashRec Dash; INT32 DashID; DashPatternAttribute* pDash; // Decode the command, and execute it... switch (Token) { // Bitmap Pool Token case EPSC_cbmp: { INT32 PoolType; // Find out what type of bitmap pool thing this is (currently 0 is only valid option) if ((!Stack.Pop(&PoolType)) || (PoolType!=0)) goto EPSError; // get the bitmap number if (!Stack.Pop(&PendingBitmapNum)) goto EPSError; // Next thing will be a pool item TRACEUSER( "Rik", _T("Got a Bitmap pool item....\n")); m_PendingBitmap = PENDING_BITMAP_POOLITEM; break; } // Stroke transparency case EPSC_cst: INT32 TranspType, Transp; // Get transparency type... if (!Stack.Pop(&TranspType)) goto EPSError; // Get line transparency value if (!Stack.Pop(&Transp)) goto EPSError; TRACEUSER( "Will", _T("Importing Line transp, Val=%d, Type=%d\n"),Transp, TranspType); if (!SetLineTransp((UINT32)TranspType, (UINT32)Transp)) goto NoMemory; break; // Start Arrow head case EPSC_csah: if (!Stack.Pop(&ArrowHeight)) goto EPSError; if (!Stack.Pop(&ArrowWidth)) goto EPSError; if (!Stack.Pop(&ArrowID)) goto EPSError; TRACEUSER( "Will", _T("Importing StartArrow, ID=%d\n"),ArrowID); if (!Arrow.CreateStockArrow((StockArrow)ArrowID)) goto NoMemory; Arrow.SetArrowSize(FIXED16(ArrowWidth), FIXED16(ArrowHeight)); if (!SetStartArrow(Arrow)) goto NoMemory; break; // End Arrow head case EPSC_ceah: if (!Stack.Pop(&ArrowHeight)) goto EPSError; if (!Stack.Pop(&ArrowWidth)) goto EPSError; if (!Stack.Pop(&ArrowID)) goto EPSError; TRACEUSER( "Will", _T("Importing EndArrow, ID=%d\n"),ArrowID); if (!Arrow.CreateStockArrow((StockArrow)ArrowID)) goto NoMemory; Arrow.SetArrowSize(FIXED16(ArrowWidth), FIXED16(ArrowHeight)); if (!SetEndArrow(Arrow)) goto NoMemory; break; // Dash Patterns case EPSC_cdp: if (!Stack.Pop(&DashID)) goto EPSError; TRACEUSER( "Will", _T("Importing Dash Pattern, ID=%d\n"),DashID); pDash = new DashPatternAttribute; if (pDash == NULL) goto NoMemory; if (!pDash->SetStockDashPattern((StockDash)DashID)) goto NoMemory; Dash = pDash->DashPattern; delete pDash; if (!SetDashPattern(Dash)) goto NoMemory; break; // Transparency fills. case EPSC_cxt: { DocCoord StartPoint, EndPoint, EndPoint2; INT32 StartTransp, EndTransp, TranspType; INT32 FillType; INT32 Tileable; // Used for fractal fills INT32 Seed; double Graininess, Gravity, Squash; UINT32 DPI; // Get fill type if (!Stack.Pop(&FillType)) goto EPSError; TRACEUSER( "Will", _T("Importing Transp Fill, Type=%d\n"),FillType); // Read in transparency type and levels... if (FillType != TRANSPFILL_NONE) { // Get transparency type... if (!Stack.Pop(&TranspType)) goto EPSError; if ((FillType != TRANSPFILL_TEXTURE) && (FillType != TRANSPFILL_FRACTAL)) { // Get second transparency level if there is one. switch (FillType) { case TRANSPFILL_LINEAR: case TRANSPFILL_ELLIPTICAL: case TRANSPFILL_CIRCULAR: case TRANSPFILL_CONICAL: case TRANSPFILL_NEWLINEAR: case TRANSPFILL_NEWTEXTURE: case TRANSPFILL_NEWFRACTAL: if (!Stack.Pop(&EndTransp)) goto EPSError; break; default: // This is a valid situation - no second transparency level. break; } // Get first transparency level if (!Stack.Pop(&StartTransp)) goto EPSError; } } if (FillType == TRANSPFILL_FRACTAL || FillType == TRANSPFILL_NEWFRACTAL) { // If it's a fractal fill type, discard the 'sub-type' parameter (should // always be zero or one currently!) INT32 SubType; if (!Stack.Pop(&SubType)) goto EPSError; // Default to no tiling Tileable = FALSE; // Work out the sub-type, either it has no tileable flag, or it does, // or it's a type that is not supported. if (SubType != 0) { if (SubType == 1) { // Get the tileable flag if (!Stack.Pop(&Tileable)) goto EPSError; } else { ERROR2RAW("Bad fractal fill sub-type"); goto EPSError; } } // Now get the fractal parameters: if (!Stack.Pop(&DPI) || !Stack.Pop(&Squash) || !Stack.Pop(&Gravity) || !Stack.Pop(&Graininess) || !Stack.Pop(&Seed)) { // Error in fractal parameteres goto EPSError; } } // For elliptical & texture/fractal fills, get the second end-point of the fill if ((FillType == TRANSPFILL_ELLIPTICAL) || (FillType == TRANSPFILL_TEXTURE) || (FillType == TRANSPFILL_FRACTAL) || (FillType == TRANSPFILL_NEWTEXTURE) || (FillType == TRANSPFILL_NEWFRACTAL) || (FillType == TRANSPFILL_NEWLINEAR)) { if (!Stack.PopCoordPair(&EndPoint2)) goto EPSError; } // Get start and end positions for variable transparency fills if ((FillType == TRANSPFILL_ELLIPTICAL) || (FillType == TRANSPFILL_CIRCULAR) || (FillType == TRANSPFILL_LINEAR) || (FillType == TRANSPFILL_CONICAL) || (FillType == TRANSPFILL_TEXTURE) || (FillType == TRANSPFILL_FRACTAL) || (FillType == TRANSPFILL_NEWLINEAR) || (FillType == TRANSPFILL_NEWFRACTAL) || (FillType == TRANSPFILL_NEWTEXTURE)) { if (!Stack.PopCoordPair(&EndPoint) || !Stack.PopCoordPair(&StartPoint)) goto EPSError; } switch (FillType) { // Decode Camelot EPS transparency fill codes case TRANSPFILL_NONE: if (!SetNoTranspFill()) goto NoMemory; break; case TRANSPFILL_FLAT: if (!SetFlatTranspFill(TranspType, StartTransp)) goto NoMemory; break; case TRANSPFILL_LINEAR: if (!SetLinearTranspFill(TranspType, StartTransp, EndTransp, StartPoint, EndPoint)) goto NoMemory; break; case TRANSPFILL_NEWLINEAR: if (!SetLinearTranspFill(TranspType, StartTransp, EndTransp, StartPoint, EndPoint, &EndPoint2)) goto NoMemory; break; case TRANSPFILL_ELLIPTICAL: if (!SetRadialTranspFill(TranspType, StartTransp, EndTransp, StartPoint, EndPoint, EndPoint2)) goto NoMemory; break; case TRANSPFILL_CIRCULAR: if (!SetRadialTranspFill(TranspType, StartTransp, EndTransp, StartPoint, EndPoint)) goto NoMemory; break; case TRANSPFILL_CONICAL: if (!SetConicalTranspFill(TranspType, StartTransp, EndTransp, StartPoint, EndPoint)) goto NoMemory; break; case TRANSPFILL_TEXTURE: m_PendingBitmap = PENDING_BITMAP_TRANSPFILL; BitmapAttrs.Coords[0] = StartPoint; BitmapAttrs.Coords[1] = EndPoint; BitmapAttrs.Coords[2] = EndPoint2; BitmapAttrs.TranspType = TranspType; BitmapAttrs.Transp = 0; BitmapAttrs.EndTransp = 255; break; case TRANSPFILL_NEWTEXTURE: m_PendingBitmap = PENDING_BITMAP_TRANSPFILL; BitmapAttrs.Coords[0] = StartPoint; BitmapAttrs.Coords[1] = EndPoint; BitmapAttrs.Coords[2] = EndPoint2; BitmapAttrs.TranspType = TranspType; BitmapAttrs.Transp = StartTransp; BitmapAttrs.EndTransp = EndTransp; break; case TRANSPFILL_FRACTAL: if (!SetFractalTranspFill(TranspType, StartPoint, EndPoint, EndPoint2, Seed, Graininess, Gravity, Squash, DPI, Tileable)) goto NoMemory; break; case TRANSPFILL_NEWFRACTAL: if (!SetFractalTranspFill(TranspType, StartPoint, EndPoint, EndPoint2, Seed, Graininess, Gravity, Squash, DPI, Tileable, StartTransp, EndTransp)) goto NoMemory; break; default: ENSURE(FALSE, "Unknown fill type found!"); break; // Don't know this fill type } break; } case EPSC_cxmt: { INT32 MappingType; INT32 Repeat; // Get fill mapping type (should always be 0) if (!Stack.Pop(&MappingType)) goto EPSError; if (MappingType != 0) { ERROR2RAW("Bad mapping type in EPS"); goto EPSError; } // Get proper fill mapping type (should be 1, 2 or 3) if (!Stack.Pop(&Repeat)) goto EPSError; if ((Repeat < 1) || (Repeat > 3)) { ERROR2RAW("Bad mapping type in EPS"); goto EPSError; } // Call base class to use it if (Token == EPSC_cxm) { if (!SetLinearFillMapping(Repeat)) goto NoMemory; } else { if (!SetLinearTranspFillMapping(Repeat)) goto NoMemory; } break; } case EPSC_ctf: { // ctf String_64 FName; if (!Stack.Pop(&FName)) goto EPSError; FName.SwapChar('-',' '); if ((FONTMANAGER->CacheNamedFont(&FName, EPSFilter::ClassOfFont) == ILLEGALFHANDLE)) goto EPSError; if (!SetTextTypeFace(&FName, EPSFilter::ClassOfFont)) goto EPSError; // Reset the font class to true type. EPSFilter::ClassOfFont = FC_TRUETYPE; break; } case EPSC_ctb: { // <0|1> ctb INT32 Bold; if (!Stack.Pop(&Bold)) goto EPSError; BOOL Boldon = (Bold==1); // Build any style definitions we need if (FontFlags.Bold) { if (!SetTextBoldFont(Boldon)) goto EPSError; } else { if (!SetTextBold(Boldon)) goto EPSError; } // Turn it off again FontFlags.Bold = FALSE; break; } case EPSC_cti: { // <0|1> cti INT32 Italic; if (!Stack.Pop(&Italic)) goto EPSError; BOOL ItalicOn = (Italic==1); // Build any style definitions we need if (FontFlags.Italic) { if (!SetTextItalicFont(ItalicOn)) goto EPSError; } else { if (!SetTextItalic(ItalicOn)) goto EPSError; } FontFlags.Italic = FALSE; break; } case EPSC_cts: { // cts INT32 rise,ptsize; if (!Stack.Pop(&ptsize)) goto EPSError; if (!Stack.Pop(&rise)) goto EPSError; if (!SetTextScript(rise,ptsize)) goto EPSError; break; } case EPSC_ctp: { // ctp INT32 ptsize; if (!Stack.Pop(&ptsize)) goto EPSError; if (!SetTextSize(ptsize)) goto EPSError; break; } case EPSC_ctls: { INT32 type; if (!Stack.Pop(&type)) goto EPSError; switch (type) { case 0: { MILLIPOINT linespace; if (!Stack.Pop(&linespace)) goto EPSError; if (!SetTextLineSpacing(1,0,linespace,0)) goto EPSError; break; } case 1: { double proportional; if (!Stack.Pop(&proportional)) goto EPSError; if (!SetTextLineSpacing(2,0,0,proportional)) goto EPSError; break; } } break; } default: // Token not understood - pass on to base class return CamelotEPSFilter::ProcessToken(); } // All seemed to work OK return TRUE; // Error handlers EPSError: HandleEPSError(); return FALSE; NoMemory: HandleNoMemory(); return FALSE; } /******************************************************************************************** > INT32 CamelotNativeEPSFilter::EPSHeaderIsOk(ADDR pFileHeader, UINT32 HeaderSize) Author: Rik_Heywood (Xara Group Ltd) Created: 16/12/94 Returns: 0 - 10. 0 means not interested in this file, 10 means I know all about this file. Purpose: Checks to see if the EPS comment headers specify that this is an Camelot Native file, as required. ********************************************************************************************/ INT32 CamelotNativeEPSFilter::EPSHeaderIsOk(ADDR pFileHeader, UINT32 HeaderSize) { // This function is NOT unicode // Check the first line in EPS file if (strncmp((char *) pFileHeader, "%!PS-Adobe-2.0 EPSF-1.2", 23) != 0) { // Incorrect version of EPS header line - we don't want this return 0; } // !PS-Adobe line is ok - check creator line... std::istringstream HeaderFile((char *) pFileHeader, ios_base::in /* HeaderSize*/); char Buffer[200]; UINT32 Lines = 0; while ((Lines < 20) && !HeaderFile.eof()) { HeaderFile.getline(Buffer, 200); Lines++; // if the file is native camelot, return indicating strong 'interest'! if (strncmp(Buffer, "%%Creator: Xara Studio (Native)", 31) == 0) return 10; // If we find the compression token then stop the search as we don't want to start // looking in the compressed data! if (strncmp(Buffer, "%%Compression:", 14)==0) break; } // Didn't find a suitable Creator line. Since this is not really an eps filter it // will claim to know nothing about it. Camelot EPS will have a go at this file // but we can not really try. return 0; } /******************************************************************************************** > BOOL CamelotNativeEPSFilter::PrepareToImport() Author: Rik_Heywood (Xara Group Ltd) Created: 16/12/94 Returns: TRUE if filter initialised ok; FALSE if not. Purpose: See base class. Errors: See base class. SeeAlso: EPSFilter::PrepareToImport; ********************************************************************************************/ BOOL CamelotNativeEPSFilter::PrepareToImport() { // Note the old state so we can put it back at the end OldImportWithLayers = Filter::ImportWithLayers; OldOpenWithLayers = Filter::OpenWithLayers; // Neville 7/8/97 - Layers are bad in Webster as they conflict with frames #ifndef WEBSTER // We always wanted to import with layers in the native filter // Nowadays, its a bit more complicated // If we are during template loading then always load the layers if (TheDocument->IsTemplateLoading()) { ImportWithLayers = TRUE; OpenWithLayers = TRUE; } else { // Otherwise if we are in:- // - a framed document then remove all layers from importing // - a layered document then import with layers if (TheDocument->IsImporting()) { ERROR2IF(ImportInfo.pSpread == NULL,FALSE,"CamelotNativeEPSFilter::PrepareToImport No spread"); Layer * pFrame = ImportInfo.pSpread->FindFirstFrameLayer(); if (pFrame == NULL) ImportWithLayers = TRUE; // Layered = allow layers else ImportWithLayers = FALSE; // Framed = disallow layers } else ImportWithLayers = TRUE; OpenWithLayers = TRUE; // Always open with layers } #else // If we are during template loading then always load the layers if (TheDocument->IsTemplateLoading()) { ImportWithLayers = TRUE; OpenWithLayers = TRUE; } else // Otherwise remove all layers from importing { ImportWithLayers = FALSE; OpenWithLayers = FALSE; } #endif // WEBSTER */ // reset version numbers so files without this info have numbers 0.0 FileVersionNumber = 0.0; BuildVersionNumber = 0.0; // Initialise base class first. if (!CamelotEPSFilter::PrepareToImport()) return FALSE; // set min line width to zero and store old value OldMinLineWidth = MinLineWidth; MinLineWidth = 0; return TRUE; } /******************************************************************************************** > virtual void CamelotNativeEPSFilter::CleanUpAfterImport(BOOL Successful) Author: Rik_Heywood (Xara Group Ltd) Created: 20/1/95 Inputs: Successful - TRUE if the import went OK, FALSE if it failed Purpose: Happens at the end of the import to allow the filters to clean up after themselves ********************************************************************************************/ void CamelotNativeEPSFilter::CleanUpAfterImport(BOOL Successful) { // Call the base class CamelotEPSFilter::CleanUpAfterImport(Successful); // restore the old min line width MinLineWidth = OldMinLineWidth; // Get rid of the bitmap references if we have any // This will cause all bitmaps that were loaded, but are not used to be thrown away if (BitmapPoolRefs != NULL) delete [] BitmapPoolRefs; // Ready for the next one BitmapPoolRefs = NULL; // Put the Import with layers flag back as it was ImportWithLayers = OldImportWithLayers; OpenWithLayers = OldOpenWithLayers; // Flag this as an old format document if (TheDocument && Successful) { // But only flag it if we are opening the document rather than importing into an exisiting one if (!TheDocument->IsImporting()) TheDocument->SetLoadedAsVersion1File(TRUE); } } /******************************************************************************************** > virtual void CamelotNativeEPSFilter::BitmapPoolAttach(KernelBitmap* pBitmap) Author: Rik_Heywood (Xara Group Ltd) Created: 20/1/95 Inputs: pBitmap - The bitmap to attach Purpose: Makes a reference to the bitmap so that it can be used throughout the eps file with repeating the data. ********************************************************************************************/ void CamelotNativeEPSFilter::BitmapPoolAttach(KernelBitmap* pBitmap) { // Make sure we have some refs and its in range if ((BitmapPoolRefs!=NULL) && (PendingBitmapNum < BitmapCount)) { // yep, so attach the bitmap to the reference BitmapPoolRefs[PendingBitmapNum].Attach(pBitmap, GetDocument()); if (BitmapPoolRefs[PendingBitmapNum].GetBitmap() != pBitmap) { // It didn't use the bitmap we gave it, so we can delete it delete pBitmap; } } } /******************************************************************************************** > virtual BOOL CamelotNativeEPSFilter::ReadBitmap() Author: Rik_Heywood (Xara Group Ltd) Created: 20/1/95 Returns: TRUE if it worked, FALSE if it found an error Purpose: Reads in a bitmap. If it is a Type 0 bitmap (ie one with all its data) it will ask the base class to import it. If it is a Type 1 bitmap it will look up the reference in the bitmap pool and use that. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::ReadBitmap() { TRACEUSER( "Rik", _T("ReadBitmap...\n")); // Find out what kind of bitmap it is - always type 0 or 1 at present. INT32 BitmapType; if (!Stack.Pop(&BitmapType)) { // Error - not enough operands HandleEPSError(); return FALSE; } // if it is the old type 0 bitmap get the base class to do all the work if (BitmapType == 0) { // Need to push the type back on the stack again ready for the base class to read it TRACEUSER( "Rik", _T("Bitmap with data (in the pool I hope)\n")); Stack.Push(BitmapType); return CamelotEPSFilter::ReadBitmap(); } // OK, see if we have a type we do not know about if (BitmapType != 1) { // Error - Bad Type HandleEPSError(); return FALSE; } // Right, we have a type 1 bitmap.... INT32 BitmapIndex = 0; // Read in info on the bitmap (ie, which bitmap from the pool do we want) ... if ((!Stack.Pop(&BitmapIndex)) /*|| (BitmapIndex >= BitmapCount)*/) { // Error - not enough operands HandleEPSError(); return FALSE; } // ... and make sure that is in the range of bitmaps we have. // If the Index is out of range then use the Last one rather than just erroring. if (BitmapIndex >= BitmapCount) BitmapIndex = (BitmapCount-1); TRACEUSER( "Rik", _T("Bitmap reference found - refers to bitmap %d\n"), BitmapIndex); // Want to find bitmap 'BitmapIndex' and set pBitmap to point at it pBitmap = BitmapPoolRefs[BitmapIndex].GetBitmap(); return TRUE; } /******************************************************************************************** > virtual INT32 CamelotNativeEPSFilter::ImportBinary(ADDR pData, INT32 Length) Author: Rik_Heywood (Xara Group Ltd) Created: 19/12/94 Inputs: Length - the number of bytes to read, in terms of binary data imported, as opposed to how many bytes the file format takes to represent this binary data. Outputs: pData - the buffer to put the data into. Returns: TRUE if it imported the specified number of bytes correctly; FALSE if not. Purpose: Reads the binary data out of the file and puts it into the buffer supplied. It also makes checks to see if the appropriate chars are found surounding the Binary stream. Errors: File input errors; EOF SeeAlso: Filter::ImportBinary ********************************************************************************************/ INT32 CamelotNativeEPSFilter::ImportBinary(ADDR pData, INT32 Length) { // read chars until we get a > INT32 CountDown = 50; TCHAR Ch; do { // Read a TCHAR if (EPSFile->read(&Ch, 1).fail()) { HandleEPSError(); return FALSE; } // Count it CountDown--; } while ((CountDown>0) && (Ch!='>')); // See if we found it if (CountDown==0) { HandleEPSError(); return FALSE; } // Read binary section if (EPSFile->read(pData, Length).fail()) { HandleEPSError(); return FALSE; } // Read TCHAR and check that it is a < if (EPSFile->read(&Ch, 1).fail()) { HandleEPSError(); return FALSE; } if (Ch!='<') { HandleEPSError(); return FALSE; } // Find out how much of the file we have read INT32 CharsRead = EPSFile->GetCharsRead(); if (CharsRead > (LastProgressUpdate + 2048)) { if (!ContinueSlowJob(CharsRead)) { // Abort operation - make sure nodes are deleted and not added to the tree. ERROR(_R(IDT_IMPORT_USERABORT), FALSE); } else { LastProgressUpdate = CharsRead; } } // Re-sync the tokeniser EPSFile->GetLine(); EPSFile->GetCh(); // Must have worked return TRUE; } /******************************************************************************************** > virtual BOOL CamelotNativeEPSFilter::ProcessFilterComment() Author: Rik_Heywood (Xara Group Ltd) Created: 23/12/94 Returns: TRUE if it finds something it likes, FALSE if not Purpose: This deals with the page info held in comments in the EPS stream ********************************************************************************************/ BOOL CamelotNativeEPSFilter::ProcessFilterComment() { // read the build version number of the app which saved this file if (camStrncmp(TokenBuf, _T("%%Creator: Xara Studio (Native)"), 31) == 0) { return TRUE; } // Go and have a look at the token buffer and see if it is our special // file version comment. If so, then extract the version number from it. if (camStrncmp(TokenBuf, _T("%%File version:"), 15)==0) { TCHAR* pVersion = &(((TCHAR*)TokenBuf)[15]); double Version=0.0; camSscanf(pVersion, _T("%lf"), &Version); TRACEUSER( "Neville", _T("Native file version = %f\n"), Version); FileVersionNumber = Version; // Must stop later file versions loading back into this version. if (Version > ReadNativeVersion) { InformWarning(_R(IDW_FILEISWRONGVERSION)); // flag the error state EPSFlags.EPSErrorEncountered = TRUE; // set the user has cancelled the error message so that this one is not reported Error::SetError(_R(IDN_USER_CANCELLED), 0); // We recokonised the token but it is invalid return TRUE; } } // Go and have a look at the token buffer and see if it is our special // compression comment if (camStrncmp(TokenBuf, _T("%%Compression:"), 14)==0) { //#ifdef STANDALONE // // First release of the file viewer will not have the native file compression // // loading code in. Therefore, we must abort if the compression tokens are // // encountered. // //if (FileVersionNumber < 0.500) // InformWarning(_R(IDW_FILEISCOMPRESSED)); // // flag the error state // EPSFlags.EPSErrorEncountered = TRUE; // // set the user has cancelled the error message so that this one is not reported // Error::SetError(_R(IDN_USER_CANCELLED), 0); // // // We recokonised the token but it is invalid // return TRUE; //#endif TCHAR* pType = &(((TCHAR*)TokenBuf)[14]); camSscanf(pType, _T("%d"), &CompressionType); TRACEUSER( "Neville", _T("CamelotNativeEPSFilter::ProcessFilterComment compression type %d\n"), CompressionType); // We have found our compression token so turn compression on BOOL ok = EPSFile->SetCompression(TRUE); if (!ok) { // We had a problem starting up the decompressor // flag the error state EPSFlags.EPSErrorEncountered = TRUE; // set up a useful error message, this one seems to say that we ran out of memory // and this is the most likely reason why Error::SetError(_R(IDT_EPS_NOMEMORY), 0); // We recokonised the token but it is invalid return TRUE; } return TRUE; } if (camStrncmp(TokenBuf, _T("%%Compression info:"), 19)==0) { TCHAR* pVersion = &(((TCHAR*)TokenBuf)[19]); double CompVersion=0.0; camSscanf(pVersion, _T("%lf"), &CompVersion); TRACEUSER( "Neville", _T("Compression version = %f\n"), CompVersion); double StreamVersion = GZipFile::GetStreamVersionNo(); // If the version stored in the file is later than the one in the stream class // then we cannot cope with this data, so error. if (CompVersion > StreamVersion) { InformWarning(_R(IDW_FILEISCOMPRESSED)); // flag the error state EPSFlags.EPSErrorEncountered = TRUE; // set the user has cancelled the error message so that this one is not reported Error::SetError(_R(IDN_USER_CANCELLED), 0); // We recokonised the token but it is invalid return TRUE; } return TRUE; } if (camStrncmp(TokenBuf, _T("%%EndCompression:"), 17)==0) { // We have found our compression token so turn compression on BOOL ok = EPSFile->SetCompression(FALSE); if (!ok) { // We had a problem stoping up the decompressor // flag the error state EPSFlags.EPSErrorEncountered = TRUE; // We will assume that an error has been set up. At present, the only one // most likely is a CRC error. // We recokonised the token but it is invalid return TRUE; } return TRUE; } if (camStrncmp(TokenBuf, _T("%%EndCompressionInfo:"), 21)==0) { return TRUE; } // Go and have a look at the token buffer and see if it looks like bitmap count if (camStrncmp(TokenBuf, _T("%%BitmapPoolCount"), 17)==0) { TCHAR* pCount = &(((TCHAR*)TokenBuf)[17]); camSscanf(pCount, _T("%d"), &BitmapCount); TRACEUSER( "Rik", _T("%d\n"), BitmapCount); // There are no bitmaps in this file if (BitmapCount==0) return TRUE; // Make sure that we have not already found one of these if (BitmapPoolRefs!=NULL) ERROR3("Bitmap Pool already in use!"); // Allocate a few references to bitmaps BitmapPoolRefs = new KernelBitmapRef[BitmapCount]; return TRUE; } // Check for any text comments if (camStrncmp(TokenBuf, _T("%%XSScript"), 10)==0) { TextComment[0]=2; return TRUE; } return FALSE; } /******************************************************************************************** > virtual EPSExportDC* CamelotNativeEPSFilter::CreateExportDC() Author: Rik_Heywood (Xara Group Ltd) Created: 19/12/94 Returns: Pointer to a new ExportDC. Purpose: Creates a new export DC (NativeExportDC) ready to export the Native file to. ********************************************************************************************/ EPSExportDC* CamelotNativeEPSFilter::CreateExportDC() { #if !defined(EXCLUDE_FROM_RALPH) return new NativeExportDC(this); #else return NULL; #endif } /******************************************************************************************** > virtual BOOL CamelotNativeEPSFilter::GetExportOptions( ) Author: Neville_Humphrys (Xara Group Ltd) HUmphrys Created: 22/12/95 Inputs: - Returns: TRUE if OK, FALSE if user pressed Cancel. Purpose: Allows the user to be prompted to get information for export. This overriden version returns True so that nothing happens. Scope: Protected. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::GetExportOptions( ) { // Overide the CamelotEPS form so that we do nothing again i.e. just return TRUE return TRUE; } /******************************************************************************************** > BOOL CamelotNativeEPSFilter::PrepareToExport(CCLexFile* pFile, Spread* pSpread) Author: Rik_Heywood (Xara Group Ltd) Created: 15/12/94 Inputs: pFile - the path name pSpread - The spread to save Returns: TRUE if it worked, FALSE if it failed Purpose: Gets things ready for the export. Creates the render region to do all the exporting with. ********************************************************************************************/ BOOL CamelotNativeEPSFilter::PrepareToExport(CCLexFile* pFile, Spread* pSpread) { #if !defined(EXCLUDE_FROM_RALPH) // Use base class to do most of it if (!CamelotEPSFilter::PrepareToExport(pFile, pSpread)) return FALSE; // Try and create a render region if we are really a // Native filter and not something derived from it if (IS_A(this, CamelotNativeEPSFilter)) { // Don't care about clip regions when exporting - create a null region. DocRect NullClipRect; NullClipRect.MakeEmpty(); // Don't use rendering matrix when exporting EPS as it uses fractional coordinates. Matrix Identity; // Don't use view scale; set to 1 FIXED16 Scale(1); // Create the render region ExportRegion = new NativeRenderRegion(NullClipRect, Identity, Scale); if (ExportRegion == NULL) return FALSE; // use the first docview DocView * pDocView = TheDocument->GetFirstDocView(); // fallback - help no docviews if ((!pDocView) || (!pDocView->IsKindOf(CC_RUNTIME_CLASS(DocView)))) pDocView = DocView::GetSelected(); // help! use selected docview // Attach to the right device. ExportRegion->AttachDevice(pDocView, ExportDCPtr->GetDC(), pSpread); } #endif // Thats it return TRUE; } /******************************************************************************************** > BOOL CamelotNativeEPSFilter::ExportBitmap(KernelBitmap& TheBitmap) Author: Rik_Heywood (Xara Group Ltd) Created: 20/1/95 Inputs: TheBitmap - the bitmap to export Returns: TRUE if the bitmap was exported ok (or if it wasn't exported because the file format does not support it; FALSE if an error occured. Purpose: Export a bitmap to a Camelot EPS file. This does one of 2 things. If we are in the middle of exporting the bitmap pool it will save out all the bitmap data, just as CamelotEPS does. If we are not in the bitmap pool it will simply save out a reference to the bitmap in the pool Errors: Usual disk/file errors. SeeAlso: Filter::ExportBitmap ********************************************************************************************/ BOOL CamelotNativeEPSFilter::ExportBitmap(KernelBitmap& TheBitmap) { #if !defined(EXCLUDE_FROM_RALPH) // If this is the bitmap pool, then save out some data if (IsSavingBitmapPool) { TRACEUSER( "Rik", _T("In the bitmap pool, so saving out real data\n")); return CamelotEPSFilter::ExportBitmap(TheBitmap); } // If we get here then we must be saving out a reference to a bitmap saved earlier in the pool TRACEUSER( "Rik", _T("Trying to save a reference to a bitmap\n")); // Try and find the bitmap in the bitmap pool // Get the document that we are saving Document* pDoc = GetDocument(); if (pDoc==NULL) return FALSE; // Find the doccomponent with the list of bitmaps in it DocComponent* DocBitmapList = pDoc->GetDocComponent(CC_RUNTIME_CLASS(BitmapListComponent)); if (DocBitmapList==NULL) return FALSE; ExportedBitmaps* pBitmapExportPool = ((BitmapListComponent*)DocBitmapList)->GetBitmapExportPool(); ERROR3IF(pBitmapExportPool == NULL, "No BitmapExportPool in CamelotNativeEPSFilter::ExportBitmap"); if (pBitmapExportPool==NULL) return FALSE; INT32 BitmapPoolNum = -1; // Get ready to look for our bitmap class ExportBitmap* pExportBitmap = pBitmapExportPool->GetBitmap(&TheBitmap); // The 'class' statement is because this filter has a function called 'ExportBitmap' ERROR3IF(pExportBitmap == NULL, "Couldn't find the bitmap in the pool in CamelotNativeEPSFilter::ExportBitmap"); if (pExportBitmap) { BitmapPoolNum = pExportBitmap->RecordNumber; } // Did we find it if (BitmapPoolNum >= 0) { // Export the number of the bitmap ExportDCPtr->OutputValue((UINT32) BitmapPoolNum); // Bitmap type is always 1 to represent a reference (0 is an actual bitmap) ExportDCPtr->OutputToken(_T("1")); // Write out the bitmap start token ExportDCPtr->OutputToken(_T("csbm")); ExportDCPtr->OutputNewLine(); // Write out the bitmap end token ExportDCPtr->OutputToken(_T("cebm")); ExportDCPtr->OutputNewLine(); // All ok return TRUE; } #endif // Did not find the bitmap return FALSE; } /******************************************************************************************** > BitmapFilterSupport CamelotNativeEPSFilter::GetBitmapSupportLevel() Author: Tim_Browse (Xara Group Ltd) Created: 30/01/95 Returns: IndirectedBitmapSupport - This filter supports bitmap indirection; i.e. a bitmap pool of some type is saved and then this can be referenced in the file. Purpose: Determine how well this filter supports bitmaps when exporting. ********************************************************************************************/ BitmapFilterSupport CamelotNativeEPSFilter::GetBitmapSupportLevel() { return IndirectedBitmapSupport; } /******************************************************************************************** > double CamelotNativeEPSFilter::SmartGetBuildNumber() Author: Ed_Cornes (Xara Group Ltd) Created: 17/10/95 Returns: Build version number Purpose: Determines a monotomic build version number based on BuildVersionNumber which unfortunately jumps to v1.00/a/b/c/d but these are mapped back to real build numbers. v1.00/a/b/c/d all have BuildVersionNumbers of 1.00 and are all descended from an isolated liniage based on 0.586 so all map to this number Note: Only guaranteed for build versions greater than 0.586! ********************************************************************************************/ double CamelotNativeEPSFilter::SmartGetBuildNumber() { double BuildNumber = GetBuildNumber(); if (BuildNumber==1.00) BuildNumber = 0.586; return BuildNumber; } #if !defined(EXCLUDE_FROM_RALPH) ///////////////////////////////////////////////////////////////////////////////////////////// // NativeRenderRegion /******************************************************************************************** > NativeRenderRegion::NativeRenderRegion(DocRect ClipRect, Matrix ConvertMatrix, FIXED16 ViewScale) Author: Rik_Heywood (Xara Group Ltd) Created: 15/12/94 Inputs: ClipRect - The rectangle to use as the clip rect for the rendering ConvertMatrix - the rendering matrix ViewScale - the scale to render at Purpose: Constructor for the Native Save/Load filter render region. ********************************************************************************************/ NativeRenderRegion::NativeRenderRegion(DocRect ClipRect, Matrix ConvertMatrix, FIXED16 ViewScale) : CamelotEPSRenderRegion(ClipRect, ConvertMatrix, ViewScale) { CreatorString = _T("Xara Studio (Native) ") CAMELOT_VERSION_STRING; // Flag that we have not started up the compressor ok by default. CompressionInitedOk = FALSE; } /******************************************************************************************** > virtual void NativeRenderRegion::ConditionalSuicide ( void ) Author: Graeme_Sutherland (Xara Group Ltd) Created: 24/2/00 Inputs: - Returns: - Purpose: Causes the object to commit suicide. This is to get around using a few if IS_A calls elsewhere in Camelot. ********************************************************************************************/ void NativeRenderRegion::ConditionalSuicide ( void ) { // Delete the object. delete this; } /******************************************************************************************** > virtual void NativeRenderRegion::GetRenderRegionCaps(RRCaps* pCaps) Author: Tim_Browse (Xara Group Ltd) Created: 10/4/95 Outputs: pCaps - The details about what types of thing this render region can render Purpose: This function allows render regions to admit to what they can and can not render. This allows other areas of the program to come in and help render regions out in some situations, if they are unable to render everything. eg. an OSRenderRegion can not render transparancy. ********************************************************************************************/ void NativeRenderRegion::GetRenderRegionCaps(RRCaps* pCaps) { // We can do everything mate cos we're fabby. pCaps->CanDoAll(); } /******************************************************************************************** > BOOL NativeRenderRegion::WriteProlog(KernelDC *pDC) Author: Tim_Browse (Xara Group Ltd) Created: 24/04/95 Inputs: pDC - the device context to output to. Outputs: - Returns: TRUE if ok; FALSE if error (e.g. file/disk error or printer driver error) Purpose: Over-ride the routines defined by CamelotEPSRenderRegion - we don't need any PostScript prolog in ART files. SeeAlso: EPSRenderRegion::WriteSetup ********************************************************************************************/ BOOL NativeRenderRegion::WriteProlog(KernelDC *pDC) { // No PostScript procedure defns here... return TRUE; } /******************************************************************************************** > BOOL NativeRenderRegion::WriteSetup(KernelDC *pDC) Author: Tim_Browse (Xara Group Ltd) Created: 24/04/95 Inputs: pDC - the device context to output to. Outputs: - Returns: TRUE if ok; FALSE if error (e.g. file/disk error or printer driver error) Purpose: Over-ride the routines defined by CamelotEPSRenderRegion - we don't need any PostScript setup in ART files. SeeAlso: NativeRenderRegion::WriteSetup ********************************************************************************************/ BOOL NativeRenderRegion::WriteSetup(KernelDC *pDC) { // No PostScript setup code here... return TRUE; } /******************************************************************************************** > void NativeRenderRegion::GetValidPathAttributes() Author: Tim_Browse (Xara Group Ltd) Created: 5/5/95 Purpose: See CamelotEPSRenderRegion::GetValidPathAttributes. This version checks and handles special native features. SeeAlso: EPSRenderRegion::GetValidPathAttributes ********************************************************************************************/ void NativeRenderRegion::GetValidPathAttributes() { KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); // Find out what this render region can do. RRCaps Caps; GetRenderRegionCaps(&Caps); if (SetLastOutputAttribute(ATTR_STARTARROW)) { // Start arrow head StartArrowAttribute *pArrow = (StartArrowAttribute *) CurrentAttrs[ATTR_STARTARROW].pAttr; TRACEUSER( "Will", _T("Outputing Start Arrow, ID=%d\n"),pArrow->StartArrow.GetArrowID()); if (pArrow->StartArrow.GetArrowID() >= 0) { pDC->OutputValue((INT32)pArrow->StartArrow.GetArrowID()); pDC->OutputReal((pArrow->StartArrow.GetArrowWidth()).MakeDouble()); pDC->OutputReal((pArrow->StartArrow.GetArrowHeight()).MakeDouble()); pDC->OutputToken(_T("csah")); pDC->OutputNewLine(); } } if (SetLastOutputAttribute(ATTR_ENDARROW)) { // End arrow head EndArrowAttribute *pArrow = (EndArrowAttribute *) CurrentAttrs[ATTR_ENDARROW].pAttr; TRACEUSER( "Will", _T("Outputing End Arrow, ID=%d\n"),pArrow->EndArrow.GetArrowID()); if (pArrow->EndArrow.GetArrowID() >= 0) { pDC->OutputValue((INT32)pArrow->EndArrow.GetArrowID()); pDC->OutputReal((pArrow->EndArrow.GetArrowWidth()).MakeDouble()); pDC->OutputReal((pArrow->EndArrow.GetArrowHeight()).MakeDouble()); pDC->OutputToken(_T("ceah")); pDC->OutputNewLine(); } } if (SetLastOutputAttribute(ATTR_DASHPATTERN)) { // Get dash pattern DashPatternAttribute *pDash = (DashPatternAttribute *) CurrentAttrs[ATTR_DASHPATTERN].pAttr; TRACEUSER( "Will", _T("Outputing Dash Pattern, ID=%d\n"),pDash->DashPattern.GetDashID()); pDC->OutputValue((INT32)pDash->DashPattern.GetDashID()); pDC->OutputToken(_T("cdp")); pDC->OutputNewLine(); } // Now do transparency fills GetValidTransparencyAttributes(); // Handle usual pens/brushes CamelotEPSRenderRegion::GetValidPathAttributes(); } void NativeRenderRegion::GetValidTransparencyAttributes() { // Find out what this render region can do. RRCaps Caps; GetRenderRegionCaps(&Caps); // Can we do transparency? if (!Caps.Transparency) // No - so don't do anything return; KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); if (SetLastOutputAttribute(ATTR_STROKETRANSP)) { // Now do the line transparency StrokeTranspAttribute *pAttr = (StrokeTranspAttribute *) CurrentAttrs[ATTR_STROKETRANSP].pAttr; UINT32 Transp = *pAttr->GetStartTransp(); UINT32 TranspType = pAttr->GetTranspType(); TRACEUSER( "Will", _T("Outputing Line transp, Val=%d, Type=%d\n"),Transp, TranspType); // Output transparency level pDC->OutputValue((UINT32) Transp); // Output transparency type... pDC->OutputValue((UINT32) TranspType); pDC->OutputToken(_T("cst")); pDC->OutputNewLine(); } if (SetLastOutputAttribute(ATTR_TRANSPFILLGEOMETRY)) { // Now do the transparent fill geometry TranspFillAttribute *pFillAttr = (TranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr; // Get the transparency information UINT32 *StartTransp, *EndTransp, TranspType, FillType = TRANSPFILL_NONE; TranspType = pFillAttr->GetTranspType(); //pPaintMode->m_PaintingMode; ENSURE((TranspType >= 1) && (TranspType <= 3), "Bad transparency type!"); // Deliberately restrictive? StartTransp = pFillAttr->GetStartTransp(); ENSURE((StartTransp == NULL) || ((*StartTransp >= 0) && (*StartTransp <= 255)), "Bad start transparency level!"); // Get the correct brush - may be a grad fill. if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(FlatTranspFillAttribute))) { // Check special case for 'no transparency' (0% transparent and type 1) if (((*StartTransp) != 0) || (TranspType != TT_Mix)) FillType = TRANSPFILL_FLAT; } else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(GradTranspFillAttribute)) && !pFillAttr->IsKindOf(CC_RUNTIME_CLASS(BitmapTranspFillAttribute)) ) { // Output the start and end points of the grad fill DocCoord *Point; Point = pFillAttr->GetStartPoint(); pDC->OutputCoord(*Point); Point = pFillAttr->GetEndPoint(); pDC->OutputCoord(*Point); // Output the fill type if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(LinearTranspFillAttribute))) { DocCoord* Start = pFillAttr->GetStartPoint(); DocCoord* End = pFillAttr->GetEndPoint(); DocCoord* End2 = pFillAttr->GetEndPoint2(); if (AreLinesPerpendicular(Start, End, End2)) { TRACEUSER( "Will", _T("Exporting Simple Transp Linear Fill\n")); FillType = TRANSPFILL_LINEAR; } else { TRACEUSER( "Will", _T("Exporting New Style Transp Linear Fill\n")); pDC->OutputCoord(*pFillAttr->GetEndPoint2()); FillType = TRANSPFILL_NEWLINEAR; } } else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(RadialTranspFillAttribute))) { // Is it circular or elliptical? RadialTranspFillAttribute *pRadialFillAttr = (RadialTranspFillAttribute *) pFillAttr; if (pRadialFillAttr->IsElliptical()) { // Elliptical fill - output the second end point. Point = pRadialFillAttr->GetEndPoint2(); pDC->OutputCoord(*Point); FillType = TRANSPFILL_ELLIPTICAL; } else { // Circular fill FillType = TRANSPFILL_CIRCULAR; } } else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(ConicalTranspFillAttribute))) { FillType = TRANSPFILL_CONICAL; } else { // Unknown fill type - fall back to basic attributes. ERROR3("Unsupported grad fill encountered while exporting"); EPSRenderRegion::GetValidPathAttributes(); return; } } else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(FractalTranspFillAttribute)) && Caps.BitmapFills) { // Fractal fill - output fractal fill command... FractalTranspFillAttribute *pFractalFill = (FractalTranspFillAttribute *) pFillAttr; // Save the coords of the fill mesh pDC->OutputCoord(pFractalFill->StartPoint); pDC->OutputCoord(pFractalFill->EndPoint); pDC->OutputCoord(pFractalFill->EndPoint2); // Save the fractal parameters out. pDC->OutputValue(pFractalFill->Seed); pDC->OutputReal(pFractalFill->Graininess.MakeDouble()); pDC->OutputReal(pFractalFill->Gravity.MakeDouble()); pDC->OutputReal(pFractalFill->Squash.MakeDouble()); // And now the DPI of the fractal bitmap UINT32 DPI = pFractalFill->GetFractalDPI(); pDC->OutputValue(DPI); // And now the 'tileable' flag pDC->OutputValue((INT32) (pFractalFill->GetTileable())); // Always Fractal type 1 at present pDC->OutputToken(_T("1")); TRACEUSER( "Will", _T("Exporting new fractal transp\n")); // This is a fractal fill FillType = TRANSPFILL_NEWFRACTAL; } else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(NoiseTranspFillAttribute))) { FillType = TRANSPFILL_NONE; } else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(BitmapTranspFillAttribute)) && Caps.BitmapFills) { // Texture fill - output texture fill command: // BitmapFillAttribute *pBitmapFill = (BitmapFillAttribute *) pFillAttr; // Output the 3 fill points... DocCoord *Point; Point = pFillAttr->GetStartPoint(); pDC->OutputCoord(*Point); Point = pFillAttr->GetEndPoint(); pDC->OutputCoord(*Point); Point = pFillAttr->GetEndPoint2(); pDC->OutputCoord(*Point); TRACEUSER( "Will", _T("Exporting new bitmap transp\n")); // This is a texture fill FillType = TRANSPFILL_NEWTEXTURE; } else { ERROR3("Illegal transparency fill type!"); } // Output transparency levels... if (FillType != TRANSPFILL_NONE) { if ((FillType != TRANSPFILL_TEXTURE) && (FillType != TRANSPFILL_FRACTAL)) { // Output first transparency level pDC->OutputValue((UINT32) (*StartTransp)); // Output second transparency level if there is one. switch (FillType) { case TRANSPFILL_LINEAR: case TRANSPFILL_ELLIPTICAL: case TRANSPFILL_CIRCULAR: case TRANSPFILL_CONICAL: case TRANSPFILL_NEWLINEAR: case TRANSPFILL_NEWTEXTURE: case TRANSPFILL_NEWFRACTAL: EndTransp = pFillAttr->GetEndTransp(); ENSURE((*EndTransp >= 0) && (*EndTransp <= 255), "Bad end transparency level!"); pDC->OutputValue((UINT32) (*EndTransp)); break; default: // This is a valid situation - no second transparency level. break; } } // Output transparency type... pDC->OutputValue((UINT32) TranspType); } // Output transparency fill type pDC->OutputValue((UINT32) FillType); // Output the transparent fill token pDC->OutputToken(_T("cxt")); pDC->OutputNewLine(); // If this is a bitmap-based transprency fill, output the bitmap if ((FillType == TRANSPFILL_TEXTURE || FillType == TRANSPFILL_NEWTEXTURE) && Caps.BitmapFills) { BitmapTranspFillAttribute *pBitmapFill = (BitmapTranspFillAttribute *) pFillAttr; ExportDC *pExportDC = (ExportDC *) pDC; if (pBitmapFill->GetBitmap()) pExportDC->GetParentFilter()->ExportBitmap(*pBitmapFill->GetBitmap()); } } if (SetLastOutputAttribute(ATTR_TRANSPFILLMAPPING)) { // Now do the chromatic fill mapping TranspFillMappingAttribute *pFillAttr = (TranspFillMappingAttribute *) CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr; // Get the correct mapping INT32 MappingType = pFillAttr->Repeat; ERROR3IF((MappingType < 1) || (MappingType > 3), "Illegal fill mapping value!"); // Output fill mapping pDC->OutputValue((UINT32) MappingType); // Allow for future extension of fill mappings. pDC->OutputToken(_T("0")); // Output the fill mapping token pDC->OutputToken(_T("cxmt")); pDC->OutputNewLine(); } } /******************************************************************************************** > void NativeRenderRegion::GetValidTextAttributes() Author: Mike_Kenny (Xara Group Ltd) Created: 18/05/95 Purpose: Output Native file compatible text attribute tokens. ********************************************************************************************/ void NativeRenderRegion::GetValidTextAttributes() { KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); /* In native format documents we output fontname = ctf fontsize = ctp bold = <0|1> ctb italic = <0|1> cti sub/superscript = cts linespacing = <0> ctls <1> ctls all other styles are output by the baseclass */ if (SetLastOutputAttribute(ATTR_TXTFONTTYPEFACE)) { TxtFontTypefaceAttribute* pFontAttr = (TxtFontTypefaceAttribute*)CurrentAttrs[ATTR_TXTFONTTYPEFACE].pAttr; if (pFontAttr) { String_64 OutputFont; FontClass Class; CachedFontItem* pItem = FONTMANAGER->GetCachedFont(pFontAttr->HTypeface); ERROR3IF(pItem==NULL,"Cannot find the cached font in GetValidTextAttributes"); OutputFont = *(pItem->GetFontName()); Class = pItem->GetFontClass(); // If we are not outputting true type fonts we need to output an // extension token to say, the next ctf on the input stream should be // treated as a FontClass type of font. This allows us to load back // ATM fonts which have the same name as true type fonts. if (Class!=FC_TRUETYPE) { pDC->OutputValue((INT32)EOTAG_FONTTYPE); pDC->OutputToken(_T("cso")); pDC->OutputValue((INT32)Class); pDC->OutputToken(_T("cftf")); pDC->OutputToken(_T("ceo")); pDC->OutputNewLine(); } /*BOOL ok =*/ FONTMANAGER->GetFontName(pFontAttr->HTypeface, OutputFont); OutputFont.SwapChar(' ','-'); pDC->OutputToken((TCHAR *)OutputFont); pDC->OutputToken(_T("ctf")); pDC->OutputNewLine(); if ((pFontAttr->IsBold) || (pFontAttr->IsItalic)) { // font flags a bold or italic substyle. pDC->OutputValue((INT32)EOTAG_FONTFLAGS); pDC->OutputToken(_T("cso")); pDC->OutputNewLine(); pDC->OutputToken(_T("cfft")); pDC->OutputNewLine(); pDC->OutputToken(_T("ceo")); pDC->OutputNewLine(); pDC->OutputValue((INT32) pFontAttr->IsBold); pDC->OutputToken(_T("ctb")); pDC->OutputNewLine(); pDC->OutputValue((INT32) pFontAttr->IsItalic); pDC->OutputToken(_T("cti")); pDC->OutputNewLine(); } } } if (SetLastOutputAttribute(ATTR_TXTFONTSIZE)) { // Output the fontsize next pDC->OutputValue(RR_TXTFONTSIZE()); pDC->OutputToken(_T("ctp")); pDC->OutputNewLine(); } if (SetLastOutputAttribute(ATTR_TXTBOLD)) { // read the bold attribute value explicitly (dont use RR_TXTBOLD) BOOL Bold = ( (TxtBoldAttribute*)(CurrentAttrs[ATTR_TXTBOLD].pAttr) )->BoldOn; pDC->OutputValue((INT32)Bold); pDC->OutputToken(_T("ctb")); pDC->OutputNewLine(); } if (SetLastOutputAttribute(ATTR_TXTITALIC)) { // read the italic attribute value explicitly (dont use RR_TXTITALIC) BOOL Italic = ( (TxtItalicAttribute*)(CurrentAttrs[ATTR_TXTITALIC].pAttr) )->ItalicOn; pDC->OutputValue((INT32)Italic); pDC->OutputToken(_T("cti")); pDC->OutputNewLine(); } if (SetLastOutputAttribute(ATTR_TXTSCRIPT)) { TxtScriptAttribute* pScript = RR_TXTSCRIPT(); double FontSize = (double)RR_TXTFONTSIZE(); // in millipoints double offset = (pScript->Offset).MakeDouble(); double size = (pScript->Size).MakeDouble(); MILLIPOINT rise = (MILLIPOINT)(FontSize*offset); // rise in millipoints MILLIPOINT ptsize = (MILLIPOINT)(FontSize*size); // pointsize in millipoints pDC->OutputValue(rise); pDC->OutputValue(ptsize); pDC->OutputToken(_T("cts")); pDC->OutputNewLine(); } // output proportional or none proportional line spacing if (SetLastOutputAttribute(ATTR_TXTLINESPACE)) { TxtLineSpaceAttribute* pLineSpace = (TxtLineSpaceAttribute*)(CurrentAttrs[ATTR_TXTLINESPACE].pAttr); // There are some rules for reading the linespacing value which I shall divulge // If IsARatio is true then use the proportinal linespacing value. // else use the absolute linespacing // However if the absolute linespacing is zero, then we MUST use the proportional // linespacing. Eeek! // ie it is an error if (absolute==0 && !IsARatio()) which we will check for here if (!pLineSpace->IsARatio()) { INT32 LineSpace = pLineSpace->Value; ERROR3IF(LineSpace==0, "Absolute line spacing is zero yet IsARatio() is FALSE, in GetValidTextAttributes()"); pDC->OutputValue(LineSpace); pDC->OutputValue((INT32)0); } else { double Ratio = (pLineSpace->Ratio).MakeDouble(); pDC->OutputFloat(Ratio,4); pDC->OutputValue((INT32)1); } pDC->OutputToken(_T("ctls")); pDC->OutputNewLine(); } // Handle all other types EPSRenderRegion::GetValidTextAttributes(); } /******************************************************************************************** > BOOL NativeRenderRegion::RenderChar(WCHAR ch, Matrix* pMatrix) Author: Mike_Kenny (Xara Group Ltd) Created: 25/05/95 Inputs: ch - unicode value of TCHAR pMatrix - matrix specifying transforms to place TCHAR correctly in document Returns: FALSE if fails Purpose: ********************************************************************************************/ BOOL NativeRenderRegion::RenderChar(WCHAR ch, Matrix* pMatrix) { // If we are not drawing complex shapes and this shape is, then return if ((!RenderComplexShapes) && (TestForComplexShape(&Caps))) return TRUE; ERROR2IF( this==NULL,FALSE,"RenderRegion::RenderChar() - this==NULL"); ERROR2IF(pMatrix==NULL,FALSE,"RenderRegion::RenderChar() - pMatrix==NULL"); #if EXPORT_TEXT // Check for changed attributes GetValidPathAttributes(); GetValidTextAttributes(); KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); INT32 CharOut = (INT32)ch; INT32 NumCodes = 1; pDC->OutputValue(CharOut); pDC->OutputValue(NumCodes); pDC->OutputToken(_T("ctx")); pDC->OutputNewLine(); #else // just do what RenderRegion::RenderChar() would do! // create the TCHAR's path Path* pCharPath=CreateCharPath(ch,pMatrix); if (pCharPath==NULL) return FALSE; // draw path using current attibutes in render region if (pCharPath->GetNumCoords()!=0) DrawPath(pCharPath); // clean up delete pCharPath; #endif return TRUE; } /******************************************************************************************** > virtual BOOL NativeRenderRegion::WriteFileVersion(KernelDC *pDC) Author: Neville_Humphrys (Xara Group Ltd) Created: 29/05/95 Inputs: pDC - the device context to output to. Outputs: - Returns: TRUE if ok; FALSE if error (e.g. file/disk error) Purpose: This allows the filter to save out a comment line giving file version information. In this Native format version we actually write out the current file version information. SeeAlso: EPSRenderRegion::WriteSetup ********************************************************************************************/ BOOL NativeRenderRegion::WriteFileVersion(KernelDC *pDC) { // Buffer used to build up the file version comment. TCHAR buf[50]; // Output the current file version in the format 1.00 for NativeFileVersion 100 camSprintf(buf, _T("%%%%File version: %.2f"), WriteNativeVersion); pDC->OutputToken(buf); pDC->OutputNewLine(); return TRUE; } /******************************************************************************************** > BOOL NativeRenderRegion::WriteCompressionState(KernelDC *pDC) Author: Neville_Humphrys (Xara Group Ltd) Created: 19/05/95 Inputs: pDC - the device context to output to. Outputs: - Returns: TRUE if ok; FALSE if error (e.g. file/disk error or printer driver error) Purpose: In this native file saving class version we save out the compression status of this file with other useful compression type information. We also start compressing the data from this point onwards. SeeAlso: EPSRenderRegion::WriteSetup ********************************************************************************************/ BOOL NativeRenderRegion::WriteCompressionState(KernelDC *pDC) { TRACEUSER( "Neville", _T("WriteCompressionState\n")); // If the preference is set then compress the file, otherwise do nothing if (CamelotNativeEPSFilter::GetNativeCompression()) { // Get a pointer to the CCDiskFile object EPSExportDC *pEPSDC = (EPSExportDC *) pDC; if (pEPSDC == NULL || ExportFile == NULL) return FALSE; // First, see if we have enough memory to start up the compression system BOOL Ok = pEPSDC->ExportFile->InitCompression(); // If this fails then don't try anything if (!Ok) { // Flag that we have not started up the compressor ok. // Do not try and save out the end compression tokens. CompressionInitedOk = FALSE; return FALSE; } // Flag that we have started up the compressor ok. // We can write out the end compression bits CompressionInitedOk = TRUE; // Could require some compression here... pDC->OutputToken(_T("%%Compression: ")); // The compression type that we are using. pDC->OutputToken(_T("0 ")); pDC->OutputNewLine(); // Output an extra line to sync to pDC->OutputToken(_T("%%Compression info:")); // Write a very simple .gz header: // Just output the two magic numbers plus a status word plus a flags word // We must output text rather than numbers and must never output LF or CR in the // middle as this will screw the lexer double StreamVersion = GZipFile::GetStreamVersionNo(); TCHAR buf[300]; camSprintf(buf, _T(" %.2fD"), StreamVersion); // version in form 0.92 followed by D for deflated pDC->OutputToken(buf); TRACEUSER( "Neville", _T("WriteCompressionState wrote version %.2f\n"),StreamVersion); pDC->OutputNewLine(); // Now that we have written out compression token to say that this is a compressed file, // start up the file compression. // This will write out some useful data such as compressed file version pEPSDC->ExportFile->SetCompression(TRUE); } return TRUE; } /******************************************************************************************** > virtual BOOL NativeRenderRegion::WriteEndCompressionState(KernelDC *pDC) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/05/95 Inputs: pDC - the device context to output to. Outputs: - Returns: TRUE if ok; FALSE if error (e.g. file/disk error or printer driver error) Purpose: This is called once everything has been output and before we fix the EPS header. In this baseclass version we do nothing as compression would be a very bad thing. SeeAlso: EPSRenderRegion::WriteSetup ********************************************************************************************/ BOOL NativeRenderRegion::WriteEndCompressionState(KernelDC* pDC) { TRACEUSER( "Neville", _T("WriteEndCompressionState\n")); // If the preference is set then compress the file, otherwise do nothing // Check though that the compressor started up ok. if (CamelotNativeEPSFilter::GetNativeCompression() && CompressionInitedOk) { // Could require some compression ending here... pDC->OutputToken(_T("%%EndCompression: ")); pDC->OutputNewLine(); // Output an extra line to sync to pDC->OutputToken(_T("%%EndCompressionInfo: ")); pDC->OutputNewLine(); // Now that we have written out compression token to say that this is a compressed file, // start up the file compression. // This will output some useful data such as a crc check and amoutn written // Get a pointer to the CCDiskFile object EPSExportDC *pEPSDC = (EPSExportDC *) pDC; if (pEPSDC && ExportFile) pEPSDC->ExportFile->SetCompression(FALSE); } return TRUE; } /******************************************************************************************** > virtual BOOL NativeRenderRegion::WantsGrids() Author: Rik_Heywood (Xara Group Ltd) Created: 12/12/95 Returns: TRUE Purpose: This function is designed to help with the rendering of grids, as they are not always wanted (eg xara eps). If your class of render region does not want grids to appear, then overide this function and get it to return FALSE. The default behaviour is to return TRUE, which will allow grids to render if they want to. ********************************************************************************************/ BOOL NativeRenderRegion::WantsGrids() { return TRUE; } /******************************************************************************************** > virtual void NativeRenderRegion::OutputFillColour() Author: Chris_Gallimore (Xara Group Ltd) Created: 30/01/01 Purpose: Used to output fill colours (in any colour model). Since the CorelXara pre-1.5 format can only cope with CMYK colours (not RGB ones), we export the colour as CMYK, regardless of the colour model used. ********************************************************************************************/ void NativeRenderRegion::OutputFillColour () { OutputFillCMYKColour (); } /******************************************************************************************** > virtual void NativeRenderRegion::OutputStrokeColour() Author: Chris_Gallimore (Xara Group Ltd) Created: 30/01/01 Purpose: Used to output stroke colours (in any colour model). Since the CorelXara pre-1.5 format can only cope with CMYK colours (not RGB ones), we export the colour in CMYK format, regardless of the colour model used.. ********************************************************************************************/ void NativeRenderRegion::OutputStrokeColour () { OutputStrokeCMYKColour (); } /******************************************************************************************** > virtual BOOL NativeRenderRegion::OutputGradFillColours (DocColour* StartCol, DocColour* EndCol, ColourContext* pContext) Author: Chris_Gallimore (Xara Group Ltd) Created: 30/01/01 Inputs: See CamelotEPSRenderRegion (they're identical) Purpose: Used to output gradient fill colours, using the CMYK clour model. This is necessary, as the standard EPS export uses RGB colours for gradient fills, which pre-1.5 CorelXara doesn't understand. ********************************************************************************************/ BOOL NativeRenderRegion::OutputGradFillColours(DocColour* StartCol, DocColour* EndCol, ColourContext* pContext) { KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC); bool outputNames = FALSE; if ((StartCol->FindParentIndexedColour() == NULL) && (EndCol->FindParentIndexedColour() == NULL)) { // Neither colour is named...use unnamed colour syntax. outputNames = FALSE; } else { // One or two of the colours are named, so use the named colour syntax. outputNames = TRUE; } // Start writing stuff to the EPS file. PColourCMYK CMYK; // Write out the start colour StartCol->GetCMYKValue (pContext, &CMYK); pDC->OutputColour (&CMYK); if (outputNames) { // Write out the name pDC->OutputColourName (StartCol); // Write out the tint value. This isn't actually used at the moment, but is left // for possible future expansion pDC->OutputValue ((INT32)0); } // And the End colour. EndCol->GetCMYKValue (pContext, &CMYK); pDC->OutputColour (&CMYK); if (outputNames) { // Write out the name pDC->OutputColourName (EndCol); // Write out the tint value. This isn't actually used at the moment, but is left // for possible future expansion pDC->OutputValue ((INT32)0); } // Return TRUE for no names used, FALSE for names used. return (!outputNames); } /******************************************************************************************** > NativeExportDC::NativeExportDC(Filter* pFilter) Author: Rik_Heywood (Xara Group Ltd) Created: 19/12/94 Inputs: pFilter Purpose: Constructor for the NativeExportDC. This does nothing, except call the base class constructor. ********************************************************************************************/ NativeExportDC::NativeExportDC(Filter* pFilter) : EPSExportDC(pFilter) { } /******************************************************************************************** > virtual INT32 NativeExportDC::OutputRawBinary(BYTE* Data, UINT32 Length, UINT32 Alignment=1) Author: Rik_Heywood (Xara Group Ltd) Created: 19/12/94 Inputs: Data - pointer to the data to output. Length - the number of bytes to output. Alignment - the byte alignment to use - it will pad the end of the data with 0 bytes if Length is not divisible by this parameter. Hence use 1 for no padding. Returns: The number of bytes output to the file, in terms of the source data, not in terms of the number of ASCII characters used to represent them. -1 => error occured while writing => ERROR1 Purpose: Outputs a sequence of bytes as raw data Errors: Disk/file error => ERROR1 ********************************************************************************************/ INT32 NativeExportDC::OutputRawBinary(BYTE* Data, UINT32 Length, UINT32 Alignment) { // Param to note how many bytes we are writing out to the file INT32 nBytes = 0; // Start off with a blank line if (!OutputNewLine()) // Error encountered return -1; // Set the mode to binary //ExportFile.setMode(filebuf::binary); // Output a character to mark the begining of the binary section static TCHAR Begin = _T('>'); if (!OutputTCHARAsChar(&Begin, 1)) // Error return -1; // Output the line of binary data if (!OutputDirect(Data, Length)) { // Error return -1; } // We saved out 'Length' bytes there nBytes += Length; // Work out the padding needed ENSURE(Alignment != 0, "Bad alignment in OutputRawBinary!"); UINT32 Padding = Alignment - (Length % Alignment); if (Padding == Alignment) Padding = 0; if (Padding > 0) { // Put the string into a Buffer TCHAR Buffer[2]; Buffer[0] = 0; Buffer[1] = 0; // Output it however many times we need to while (Padding > 0) { if (OutputTCHARAsChar(Buffer, 1)) // Error return -1; nBytes++; Padding--; } } //output an end marker static TCHAR End = _T('<'); if (!OutputTCHARAsChar(&End, 1)) // Error return -1; // Set the mode to binary //ExportFile.setMode(filebuf::text); // All done return nBytes; } #endif // EXCLUDE_FROM_RALPH