CamelotEPSRenderRegion Class Reference

A render region for exporting files in the native EPS format. More...

#include <cameleps.h>

Inheritance diagram for CamelotEPSRenderRegion:

ArtWorksEPSRenderRegion EPSRenderRegion VectorFileRenderRegion RenderRegion ListItem CCObject SimpleCCObject NativeRenderRegion PrintPSRenderRegion List of all members.

Public Member Functions

 CamelotEPSRenderRegion (DocRect ClipRect, Matrix ConvertMatrix, FIXED16 ViewScale)
 Initialise a render region for exporting Camelot EPS. Sets up the string to put in the %Creator comment.
virtual ~CamelotEPSRenderRegion ()
 destructor
void GetValidPathAttributes ()
 See EPSRenderRegion::GetValidPathAttributes. This version checks and handles grad fill colours before calling the base class version.
void GetRenderRegionCaps (RRCaps *pCaps)
 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.
BOOL StartRender ()
 Prepare the render region for rendering (exporting).
BOOL StopRender ()
 Deinitialise the render region after rendering (exporting).
void DrawPathToOutputDevice (Path *DrawPath, PathShape shapePath=PATHSHAPE_PATH)
 Output all the commands required to render this path to the EPS file.
BOOL DrawTransformedBitmap (NodeBitmap *pNodeBitmap)
 Plot an arbitrarily transformed bitmap using a matrix and an offset. The bitmap is assumed to occupy a rectangle at the origin, which has pixels 1 point across, and the matrix supplied transforms this area to the correct place. The Point parameter supplies an optional offset which can be applied after the transform. If the offset is 0,0, this means there is no offset (surprise, surprise!).
virtual SlowJobResult DrawMaskedBitmap (const DocRect &Rect, KernelBitmap *pBitmap, MaskedRenderRegion *pMask, ProgressDisplay *Progress)
 Plots the bitmap using the mask supplied.
virtual BOOL RenderChar (WCHAR ch, Matrix *pMatrix)
 Render a character, using the specified transform and current attributes in the render region.
virtual BOOL NeedsPrintComponents (void)
 Lets the print component class know that they are needed in this format's export.
virtual void ConditionalSuicide (void)
 Doesn't delete the object when invoked. This is to get around using a few if IS_A calls elsewhere in Camelot.
virtual BOOL WriteNewLine (void)
 Outputs a new line tag to the file.
virtual void OutputStrokeColour ()
 This simply calls EPSRenderRegion::OutputStrokeColour, as otherwise the ArtWorks version is used (which can't cope with the RGB colour tokens).
virtual void OutputFillColour ()
 This simply calls EPSRenderRegion::OutputFillColour, otherwise this render region uses the overridden version found in ArtWorksEPSRenderRegion.
virtual BOOL DrawParallelogramBitmap (DocCoord *Coords, OILBitmap *pBitmap, EFFECTTYPE Effect=EFFECT_RGB, DocColour *StartCol=NULL, DocColour *EndCol=NULL)
 Plot an arbitrarily transformed bitmap in the position specified.

Protected Member Functions

virtual BOOL WriteEPSBoundingBox (void)
 Calls the base EPS bounding box function.
virtual BOOL WriteProlog (KernelDC *)
 Output any PostScript prolog for this render region. For EPS and printing, this means output of our PostScript rendering procedures; for Native files we do nothing.
virtual BOOL WriteSetup (KernelDC *)
 Output any PostScript setup for this render region. For EPS and printing, this means output of our PostScript code to initialise the context for rendering; for Native files we do nothing.
virtual BOOL WriteEPSTrailerComments (void)
 Writes out an EPS trailer by calling the base class function.
BOOL DrawClippedBitmap (Path *DrawPath)
 Render a clipped bitmap using the given path. This is because we can do clipped bitmap rendering in PostScript, and it is much cheaper to do it via PostScript instead of via the 'transparency' mask (via GDraw).
BOOL SelectNewFont (WORD Typeface, BOOL Bold, BOOL Italic, MILLIPOINT Size)
 Get the font name being used by the Camelot EPS exporter.
BOOL SelectNewFont (WORD Typeface, BOOL Bold, BOOL Italic, FIXED16 *abcd)
virtual BOOL OutputGradFillColours (DocColour *StartCol, DocColour *EndCol, ColourContext *pContext=NULL)
BOOL GetCurrFillEffect (UINT32 &EffectType)
 Return the state of the current fill effect in the EPS attributes stack.
void ColourSeparateScanline24 (BYTE *DestBuffer, BYTE *SrcBuffer, INT32 PixelWidth)
 Copies the scanline of 24bpp RGB values from SrcBuffer to DestBuffer, running the pixels through colour separation tables en route.

Protected Attributes

EPSFontCache FontInfo
BYTE * SepTables

Detailed Description

A render region for exporting files in the native EPS format.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/03/94
See also:
EPSRenderRegion; ArtWorksEPSRenderRegion

Definition at line 375 of file cameleps.h.


Constructor & Destructor Documentation

CamelotEPSRenderRegion::CamelotEPSRenderRegion DocRect  ClipRect,
Matrix  ConvertMatrix,
FIXED16  ViewScale
 

Initialise a render region for exporting Camelot EPS. Sets up the string to put in the %Creator comment.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/04/94
See also:
EPSRenderRegion::EPSRenderRegion

Definition at line 3194 of file cameleps.cpp.

03197     : ArtWorksEPSRenderRegion(ClipRect, ConvertMatrix, ViewScale)
03198 {
03199     CreatorString = _T("Xara X");
03200 
03201     SepTables = NULL;
03202 }

CamelotEPSRenderRegion::~CamelotEPSRenderRegion  )  [virtual]
 

destructor

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/6/96

Definition at line 3216 of file cameleps.cpp.

03217 {
03218     if (SepTables != NULL)
03219     {
03220         CCFree(SepTables);
03221         SepTables = NULL;
03222     }
03223 }


Member Function Documentation

void CamelotEPSRenderRegion::ColourSeparateScanline24 BYTE *  DestBuffer,
BYTE *  SrcBuffer,
INT32  PixelWidth
[protected]
 

Copies the scanline of 24bpp RGB values from SrcBuffer to DestBuffer, running the pixels through colour separation tables en route.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/6/96
Parameters:
DestBuffer - points to a destination 24bpp RGB scanline buffer [INPUTS] SrcBuffer - points to a source 24bpp RGB scanline buffer PixelWidth - The number of pixels to copy from Src to Dest
If you're not colour-separating, then you should replace this function call with a simple memcpy.

Notes: ONLY handles 24bpp RGB scanlines, and expects that SepTables points at the separation tables. The pixel bytes must be in the order R,G,B.

NOTE that it handles data in RGB (postscript) format, rather than the normal Bitmap BGR format!

All deep bitmap data separates to white on spot plates.

The CMYK separation plates could have been written generically, but I have separated out the cases in order to squeeze a bit of speed out of the inner pixel conversion loop. The conversion algorithm is basically like this, only optimised to move as much work out of the loop as possible:

MonoOn Cyan = SepTables + 0 // Find the look up tables Magenta = SepTables + 256 Yellow = SepTables + 512 UCR = SepTables + 768 BGT = SepTables + 1024

c = 255-r; m = 255-g; y = 255-b;

k = min(c, m, y);

kr = UCR[k]; ok = BGT[k];

c -= kr; m -= kr; y -= kr;

if (c<0) c=0; if (m<0) m=0; if (y<0) y=0;

oc = Cyan[c]; om = Magenta[m]; oy = Yellow[y]; MonoOff

Definition at line 4100 of file cameleps.cpp.

04102 {
04103     ERROR3IF(DestBuffer == NULL || SrcBuffer == NULL || PixelWidth < 1, _T("Illegal params"));
04104     ERROR3IF(SepTables == NULL, _T("No separation tables!?"));
04105     ERROR3IF(CurrentColContext->GetColourPlate() == NULL,
04106                 _T("The separation ColourPlate has gone missing!"));
04107 
04108     // --- A wee macro to find the Maximum of R,G,B, and place it into a variable called 
04109     // Temp, which we define right now in function scope so it's always available
04110     BYTE Temp;
04111     #define TEMPMAX(R,G,B)                  \
04112     {                                       \
04113         Temp = ((R) > (G))  ? (R) : (G);    \
04114         Temp = (Temp > (B)) ? Temp : (B);   \
04115     }
04116 
04117 
04118     // --- OK, let'ts get busy
04119     INT32 i;                                // Loop i
04120     BYTE Ink;                               // Temporary variable for storing the ink value in
04121 
04122     BYTE *UCR = SepTables + 768 + 255;      // UCR is the 4th table, but this points at the
04123                                             // END of the table for optimisation - precalcs (255 - Temp)
04124 
04125 
04126 PORTNOTE("cms", "Disabled colour separations");
04127 #ifndef EXCLUDE_FROM_XARALX
04128     BOOL PrintRGBBlackAsKey=XaraCMS::PrintRGBBlackAsKey;
04129 #else
04130     BOOL PrintRGBBlackAsKey=TRUE;
04131 #endif
04132 
04133     // I've unrolled the shared code for each plate in order to optimise the inner loop
04134     switch (CurrentColContext->GetColourPlate()->GetType())
04135     {
04136         case COLOURPLATE_CYAN:
04137             {
04138                 BYTE *LUT = SepTables + 0;                  // Cyan table is the 1st table
04139 
04140                 for (i = 0; i < PixelWidth * 3; i += 3)
04141                 {
04142                     TEMPMAX(SrcBuffer[i], SrcBuffer[i+1], SrcBuffer[i+2]);
04143 
04144                     if (!PrintRGBBlackAsKey || Temp > 0)
04145                     {
04146                         Ink = 255 - SrcBuffer[i];           // Cyan ink is (255 - Red)
04147 
04148                         // Look up UCR(Key), which is UCR(255 - Temp), but the 255 is precalculated
04149                         // into the base address above, so we i with (-Temp)!
04150                         // Make Ink the ink value for the given plate. Crop at 0
04151                         if ((UINT32)Ink>(UINT32)UCR[-Temp])
04152                             Ink -= UCR[-Temp];
04153                         else
04154                             Ink = 0;
04155 
04156                         Ink = LUT[Ink];
04157 
04158                         DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 255 - Ink;
04159                     }
04160                     else
04161                     {
04162                         DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 255;
04163                     }
04164                 }
04165             }
04166             break;
04167 
04168 
04169         case COLOURPLATE_MAGENTA:
04170             {
04171                 BYTE *LUT = SepTables + 256;                // Magenta table is the 2nd table
04172 
04173                 for (i = 0; i < PixelWidth * 3; i += 3)
04174                 {
04175                     TEMPMAX(SrcBuffer[i], SrcBuffer[i+1], SrcBuffer[i+2]);
04176 
04177                     if (!PrintRGBBlackAsKey || Temp > 0)
04178                     {
04179                         Ink = 255 - SrcBuffer[i+1];         // Magenta ink is (255 - Green)
04180 
04181                         // Look up UCR(Key), which is UCR(255 - Temp), but the 255 is precalculated
04182                         // into the base address above, so we i with (-Temp)!
04183                         // Make Ink the ink value for the given plate. Crop at 0
04184                         if ((UINT32)Ink>(UINT32)UCR[-Temp])
04185                             Ink -= UCR[-Temp];
04186                         else
04187                             Ink = 0;
04188 
04189                         Ink = LUT[Ink];
04190 
04191                         DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 255 - Ink;
04192                     }
04193                     else
04194                     {
04195                         DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 255;
04196                     }
04197                 }
04198             }
04199             break;
04200 
04201 
04202         case COLOURPLATE_YELLOW:
04203             {
04204                 BYTE *LUT = SepTables + 512;                // Yellow table is the 3rd table
04205 
04206                 for (i = 0; i < PixelWidth * 3; i += 3)
04207                 {
04208                     TEMPMAX(SrcBuffer[i], SrcBuffer[i+1], SrcBuffer[i+2]);
04209 
04210                     if (!PrintRGBBlackAsKey || Temp > 0)
04211                     {
04212                         Ink = 255 - SrcBuffer[i+2];         // Yellow ink is (255 - Blue)
04213 
04214                         // Look up UCR(Key), which is UCR(255 - Temp), but the 255 is precalculated
04215                         // into the base address above, so we i with (-Temp)!
04216                         // Make Ink the ink value for the given plate. Crop at 0
04217                         if ((UINT32)Ink>(UINT32)UCR[-Temp])
04218                             Ink -= UCR[-Temp];
04219                         else
04220                             Ink = 0;
04221 
04222                         Ink = LUT[Ink];
04223 
04224                         DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 255 - Ink;
04225                     }
04226                     else
04227                     {
04228                         DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 255;
04229                     }
04230                 }
04231             }
04232             break;
04233 
04234 
04235         case COLOURPLATE_KEY:
04236             {
04237                 BYTE *BGT = SepTables + 1024;           // Black generation is the 5th table
04238 
04239                 for (i = 0; i < PixelWidth * 3; i += 3)
04240                 {
04241                     // Get the maximum of R,G,B into Temp
04242                     TEMPMAX(SrcBuffer[i], SrcBuffer[i+1], SrcBuffer[i+2]);
04243 
04244                     if (!PrintRGBBlackAsKey || Temp > 0)
04245                     {
04246                         // Key = 255 - Temp. Look up Key in the Black Generation table
04247                         Ink = BGT[255 - Temp];
04248 
04249                         DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 255 - Ink;
04250                     }
04251                     else
04252                     {
04253                         DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 0;
04254                     }
04255                 }
04256             }
04257             break;
04258 
04259 
04260         case COLOURPLATE_SPOT:
04261             // Deep colour bitmaps cannot include spot colours, so they always separate out
04262             // to white...
04263             for (i = 0; i < PixelWidth * 3; i += 3)
04264                 DestBuffer[i] = DestBuffer[i+1] = DestBuffer[i+2] = 255;
04265             break;
04266 
04267 
04268         default:
04269             ERROR3(_T("Unsupported separation plate!"));
04270             break;
04271     }
04272 
04273     // And finally, vape our helper macro
04274     #undef TEMPMAX
04275 }

void CamelotEPSRenderRegion::ConditionalSuicide void   )  [virtual]
 

Doesn't delete the object when invoked. This is to get around using a few if IS_A calls elsewhere in Camelot.

Author:
Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/2/00
Parameters:
- [INPUTS]
Returns:
-

Reimplemented from RenderRegion.

Reimplemented in NativeRenderRegion, and PrintPSRenderRegion.

Definition at line 4846 of file cameleps.cpp.

04847 {
04848     // Don't delete this!
04849 }

BOOL CamelotEPSRenderRegion::DrawClippedBitmap Path DrawPath  )  [protected]
 

Render a clipped bitmap using the given path. This is because we can do clipped bitmap rendering in PostScript, and it is much cheaper to do it via PostScript instead of via the 'transparency' mask (via GDraw).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/7/95
Parameters:
DrawPath - the path to use to clip the bitmap fill. [INPUTS]
Returns:
TRUE if rendered ok; FALSE if not.

Definition at line 5691 of file cameleps.cpp.

05692 {
05693     // Get a device context
05694     KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
05695 
05696     // What we do is: export the path, save the graphics context, use the path as a clipping 
05697     // region, render the bitmap, restore the graphics context, and optionally stroke the
05698     // path, if necessary.
05699 
05700     // make sure the eps-rr is set up with the correct path attributes,
05701     // as ExportPath() will only be rendering pure path information.
05702     GetValidPathAttributes();
05703 
05704     // export our path.
05705     ExportPath(DrawPath, TRUE, TRUE);
05706 
05707     // Save the context
05708     pDC->OutputToken(_T("gs"));
05709 
05710     // export a 'clip' command. note that if our current winding rule is for even-odd
05711     // winding, we must export an 'eoclip' command instead.
05712     if (RR_WINDINGRULE() == EvenOddWinding)
05713         pDC->OutputToken(TEXT("eoclip"));
05714     else
05715         pDC->OutputToken(TEXT("clip"));
05716 
05717     // Render the bitmap - first, set up the parallelogram to render into.
05718     BitmapFillAttribute* pFillAttr = (BitmapFillAttribute*) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
05719     DocCoord Coords[4];
05720     Coords[3] = *(pFillAttr->GetStartPoint());
05721     Coords[2] = *(pFillAttr->GetEndPoint());
05722     Coords[0] = *(pFillAttr->GetEndPoint2());
05723 
05724     // Deduce the other co-ordinate (not used by DrawParalleogramBitmap(), but calculate
05725     // it just in case...)
05726     Coords[1].x = Coords[0].x + (Coords[2].x - Coords[3].x);
05727     Coords[1].y = Coords[0].y + (Coords[2].y - Coords[3].y);
05728 
05729     // Get the bitmap
05730     KernelBitmap *pKernelBitmap = pFillAttr->GetBitmap();
05731     if (pKernelBitmap == NULL)
05732         return FALSE;
05733 
05734     // Render it.
05735     if (!DrawParallelogramBitmap(Coords, pKernelBitmap->ActualBitmap, GetFillEffect(),
05736                                  pFillAttr->GetStartColour(), pFillAttr->GetEndColour()))
05737         return FALSE;
05738 
05739     // Restore the context
05740     pDC->OutputToken(_T("gr"));
05741 
05742     // Work out if we should stroke the path
05743     TCHAR PathType[2] = _T("N");
05744 
05745     if (!RR_STROKECOLOUR().IsTransparent())
05746     {
05747         // Stroke path, leaving it open
05748         PathType[0] = 'S';
05749     }
05750 
05751     PathVerb* Verbs = DrawPath->GetVerbArray();
05752     INT32 NumCoords = DrawPath->GetNumCoords();
05753 
05754     if (Verbs[NumCoords - 1] & PT_CLOSEFIGURE)
05755         // Path should be closed
05756         PathType[0] = tolower(PathType[0]);
05757 
05758     // Do the stroke command
05759     pDC->OutputToken(PathType);
05760     pDC->OutputNewLine();
05761 
05762     // Ok if we got to here
05763     return TRUE;
05764 }

SlowJobResult CamelotEPSRenderRegion::DrawMaskedBitmap const DocRect Rect,
KernelBitmap pBitmap,
MaskedRenderRegion pMask,
ProgressDisplay Progress
[virtual]
 

Plots the bitmap using the mask supplied.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/5/95
Parameters:
Point - the position to plot the bitmap [INPUTS] pBitmap - The bitmap that needs plotting pMask - The mask render region to use to indicate which bits of pBitmap needs to be plotted
Notes:

Reimplemented from RenderRegion.

Definition at line 4299 of file cameleps.cpp.

04302 {
04303 #ifndef STANDALONE
04304 
04305     KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
04306 
04307     // Make sure the world is in one piece
04308     if ((pBitmap==NULL) || (pMask==NULL))
04309         return SLOWJOB_FAILURE;
04310 
04311     // Are we doing actual EPS? If so, then we need to do some special stuff
04312     BOOL IsCamelotEPS = IS_A(this, CamelotEPSRenderRegion);
04313 
04314     // If mask coverage is 0% we do not need to do anything. The TRUE param indicates
04315     // that we don't care about exact coverage, which makes it return as soon as it realises
04316     // that there are pixel(s) that we'll have to plot
04317     if (pMask->FindCoverage(TRUE) == 0)
04318         return SLOWJOB_SUCCESS;
04319 
04320     // Guess we will need to be doing something...
04321     if (pBitmap->ActualBitmap == NULL)
04322         return SLOWJOB_FAILURE;
04323 
04324     // Get the 'Actual' windows Bitmap
04325     CWxBitmap *WinBM = (CWxBitmap*)pBitmap->ActualBitmap;
04326 
04327     // Is it valid ?
04328     if ((WinBM->BMInfo==NULL) || (WinBM->BMBytes==NULL))
04329         return SLOWJOB_FAILURE;
04330 
04331     // Remember the Size of the Bitmap (in pixels)
04332     INT32 Width  = WinBM->GetWidth();
04333     INT32 Height = WinBM->GetHeight();
04334 
04335     if ((Width == 0) || (Height == 0))
04336         // Error - bitmap has no dimension
04337         return SLOWJOB_FAILURE;
04338 
04339     // Hideous WINOILY code in the kernel. I get the feeling this was a rush job!
04340     // Convert the bitmap from a 32bpp bitmap to a 24bpp bitmap
04341     INT32 BitmapDepth = WinBM->GetBPP();
04342     if (BitmapDepth == 32)
04343     {
04344         // Can't plot 32bpp bitmaps to GDI as 16-bit GDI doesn't understand them,
04345         // so we convert to 24bpp bitmap in-situ and render that...
04346 
04347         // How many bytes to a source scanline?
04348         const INT32 ScanlineBytes = WinBM->GetScanlineSize();
04349 
04350         // How many bytes to a destination scanline
04351         const INT32 DestlineBytes = DIBUtil::ScanlineSize(Width, 24);
04352 
04353         // Now convert the bitmap in-situ
04354         LPBYTE OriginalBuffer  = WinBM->BMBytes;
04355         LPBYTE ConvertedBuffer = WinBM->BMBytes;
04356 
04357         INT32 i;
04358         for (i=0; i<Height; i++)
04359         {
04360             DIBUtil::Convert32to24(Width, OriginalBuffer, ConvertedBuffer);
04361             OriginalBuffer += ScanlineBytes;
04362             ConvertedBuffer += DestlineBytes;
04363         }
04364 
04365         // Update bitmap info to show it is now a 24bpp bitmap...
04366         WinBM->BMInfo->bmiHeader.biSizeImage = DestlineBytes * Height;
04367         WinBM->BMInfo->bmiHeader.biBitCount  = 24;
04368         BitmapDepth = 24;
04369 
04370         // Now swap the R and B bytes around as they are in BGR format in DIBS, and
04371         // we need RGB format for PostScript.
04372         OriginalBuffer = WinBM->BMBytes;
04373 
04374         for (i=0; i<Height; i++)
04375         {
04376             ConvertedBuffer = OriginalBuffer;
04377             for (INT32 j=0; j<Width; j++)
04378             {
04379                 // Swap R and B bytes around
04380                 BYTE Temp = ConvertedBuffer[0];
04381                 ConvertedBuffer[0] = ConvertedBuffer[2];
04382                 ConvertedBuffer[2] = Temp;
04383                 ConvertedBuffer += 3;
04384             }
04385 
04386             OriginalBuffer += DestlineBytes;
04387         }
04388     }
04389 
04390     // make sure we have a 24bpp bitmap
04391     ERROR3IF(BitmapDepth!=24, _T("Non 24bpp bitmap found in DrawMaskedBitmap"));
04392 
04393     // Work out the coords to blit to, taking into acount the differnt dpis of the
04394     // source and destination bitmaps.
04395     INT32 SrcDpi = pMask->FindMaskDpi();
04396     INT32 DestDpi = SrcDpi;
04397     BOOL UseLevel2 = FALSE;
04398 
04399     if (IsCamelotEPS)
04400     {
04401         // EPS is output in points, so it's always 72dpi.
04402         DestDpi = 72000;
04403 
04404         // Find out if we should do level 2 output.
04405         if (EPSFilter::XSEPSExportPSType == 2)
04406             UseLevel2 = TRUE;
04407     }
04408     else
04409     {
04410         // Find destination device resolution (e.g. PostScript printer)
04411         if (RenderDC!=NULL)
04412             DestDpi = RenderDC->GetPPI().GetWidth();
04413 //  WEBSTER-ranbirr-12/11/96
04414 #ifndef WEBSTER
04415         // If printing, then see if we should do level 2.
04416         if (IsPrinting())
04417         {
04418             // Get the print info for this job.
04419             CCPrintInfo *pInfo = CCPrintInfo::GetCurrent();
04420             if (pInfo != NULL)
04421             {
04422                 PrintControl *pPrCtrl = pInfo->GetPrintControl();
04423                 ERROR3IF(pPrCtrl == NULL, _T("Unexpected NULL pointer"));
04424 
04425                 if (pPrCtrl->GetPSLevel() == PSLEVEL_2)
04426                     // Printing to a level 2 device - party on!
04427                     UseLevel2 = TRUE;
04428             }
04429         }
04430 #endif  //webster
04431     }
04432 
04433     // Work out the ratio between to two
04434     double Ratio = DestDpi;
04435     Ratio = Ratio/SrcDpi;
04436     TRACEUSER( "Rik", _T("Src = %ld, Dest = %ld, Ratio = %f\n"), SrcDpi, DestDpi, Ratio);
04437 
04438     // Convert the DocCoord into a windows coord
04439     DocRect ClipRect = pMask->GetClipRect();
04440     POINT Origin;
04441 
04442     if (IsCamelotEPS)
04443     {
04444         // No GDI conversion needed for EPS - we need to convert to points later on.
04445         Origin.x = ClipRect.lo.x;
04446         Origin.y = ClipRect.lo.y;
04447     }
04448     else
04449     {
04450         // Usual GDI conversion (used for PostScript printers)
04451         WinRect WinClipRect = OSRenderRegion::DocRectToWin(RenderMatrix, ClipRect, DestDpi);
04452         Origin.x = WinClipRect.GetLeft();
04453         Origin.y = WinClipRect.GetBottom();
04454     }
04455 
04456     // Inform progress object how high this band is
04457     if (Progress!=NULL)
04458         Progress->StartBitmapPhaseBand(Height);
04459 
04460     // We need to create a tempory bitmap that we use to render each scan line
04461     LPBITMAPINFO    TempBitmapInfo = NULL;
04462     LPBYTE          TempBitmapBytes = NULL;
04463 
04464     // Get some memory for a tempory bmp 1 pixel high
04465     TempBitmapInfo = AllocDIB(Width, 1, BitmapDepth, &TempBitmapBytes);
04466     if (TempBitmapInfo==NULL)
04467         return SLOWJOB_FAILURE;
04468 
04469     // Get a buffer for RGB channel separation (for level 2) and colour separation
04470     BYTE *pRGBBuf = (BYTE *) CCMalloc(Width);
04471     ERROR2IF(pRGBBuf == NULL, SLOWJOB_FAILURE, _T("No memory for RGB buffer"));
04472 
04473     // How many bytes to a destination scanline
04474     INT32 ScanLineBytes = DIBUtil::ScanlineSize(Width, BitmapDepth);
04475     INT32  BytesPerPixel = 3;
04476 
04477     // Now convert the bitmap in-situ
04478     LPBYTE SrcBuffer  = WinBM->BMBytes;
04479     LPBYTE DestBuffer = TempBitmapBytes;
04480 
04481     // If we're colour separating, make sure we've got some sep tables to work with.
04482     // We cache them once we've used them. I would do this sort of set-up in StartRender
04483     // but of course all the derived classes just override that behaviour and we're stuffed
04484     if (SepTables == NULL && RenderView->GetColourPlate() != NULL && !RenderView->GetColourPlate()->IsDisabled())
04485     {
04486         // We are doing a colour separation - find the sep tables
04487 
04488         ColourContextCMYK *cc = (ColourContextCMYK *)RenderView->GetColourContext(COLOURMODEL_CMYK);
04489         if (cc != NULL)
04490         {
04491             SepTables = (BYTE *) CCMalloc(5 * 256 * sizeof(BYTE));
04492             if (SepTables != NULL)
04493             {
04494                 if (!cc->GetProfileTables(SepTables))
04495                 {
04496                     CCFree(SepTables);
04497                     SepTables = NULL;
04498                 }
04499             }
04500         }
04501 
04502         ERROR3IF(SepTables == NULL, _T("Can't generate separation tables in CamelotEPSRenderRegion"));
04503     }
04504 
04505     // Now copy the Bits from our Kernel Bitmap into the Memory DC, scan line at a time
04506     MaskRegion MaskInfo;
04507     pMask->GetFirstMaskRegion(&MaskInfo);
04508     try
04509     {
04510         while (MaskInfo.Length!=0)
04511         {
04512             // Calculate the source buffer address from the x and y position
04513             SrcBuffer = WinBM->BMBytes;
04514             SrcBuffer += ScanLineBytes * MaskInfo.y;
04515             SrcBuffer += MaskInfo.x*BytesPerPixel;
04516             INT32 RegionWidth = MaskInfo.Length;
04517 
04518             // Update bitmap info to show the new scan line size
04519             TempBitmapInfo->bmiHeader.biWidth = RegionWidth;
04520             TempBitmapInfo->bmiHeader.biSizeImage = (RegionWidth*BytesPerPixel);
04521 
04522             // copy the scan line into the temporary bmp
04523             if (SepTables == NULL)
04524             {
04525                 // We are not colour separating, so just do a quick memcpy
04526                 memcpy(DestBuffer, SrcBuffer, RegionWidth*BytesPerPixel);
04527             }
04528             else
04529             {
04530                 // We are doing some sort of colour separation, so copy the data across, colour
04531                 // separating it as we go
04532                 ERROR3IF(BytesPerPixel != 3, _T("non-24bpp scanline unsupported"));
04533                 ColourSeparateScanline24(DestBuffer, SrcBuffer, RegionWidth);
04534             }
04535 
04536             // Work out the coords of the destination rectangle
04537             INT32 DestX = Origin.x + INT32(ceil(MaskInfo.x*Ratio));
04538             INT32 DestY = Origin.y;
04539 
04540             // Y direction is different for our EPS and GDI PostScript, as GDI preserves
04541             // the Y +ve <=> downwards model of windows.
04542             if (IsCamelotEPS)
04543                 DestY += INT32(ceil((MaskInfo.y+1)*Ratio));
04544             else
04545                 DestY -= INT32(ceil((MaskInfo.y+1)*Ratio));
04546 
04547             INT32 DestWidth = INT32(ceil(RegionWidth*Ratio));
04548             INT32 DestHeight = INT32(ceil(1*Ratio));
04549 
04550             pDC->OutputToken(_T("sv"));
04551             pDC->OutputValue(RegionWidth);
04552             pDC->OutputToken(_T("1"));
04553 
04554 
04555             if (IsCamelotEPS)
04556             {
04557                 // Convert to points.
04558                 pDC->OutputUserSpaceValue(DestWidth);
04559                 pDC->OutputUserSpaceValue(DestHeight);
04560 
04561                 DocCoord Dest(DestX, DestY);
04562                 pDC->OutputCoord(Dest);
04563             }
04564             else
04565             {
04566                 // Pass straight through
04567                 pDC->OutputValue(DestWidth);
04568                 pDC->OutputValue(DestHeight);
04569                 pDC->OutputValue(DestX);
04570                 pDC->OutputValue(DestY);
04571             }
04572 
04573             // Tell the proc whether this is L1 or L2 compatible data
04574             if (UseLevel2)
04575                 pDC->OutputToken(_T("2"));
04576             else
04577                 pDC->OutputToken(_T("1"));
04578 
04579             // Rendering primitive.
04580             if (SepTables == NULL)
04581                 pDC->OutputToken(_T("cbsl"));       // 24-bpp colour scanline
04582             else
04583                 pDC->OutputToken(_T("gbsl"));       // 8-bpp greyscale scanline
04584 
04585 
04586             // Output bitmap data - format depends on whether we can do Level 2 or not
04587             if (UseLevel2)
04588             {
04589                 // Separate into 3 RGB streams (because it is much more likely to compress well
04590                 // with RLE if we compress each component individually), and send as RLE
04591                 // compressed ASCII85 data.
04592 
04593                 // If we're colour separating, then it's greyscale (R=G=B) data, so we just dump
04594                 // only the first channel to the gbsl operator
04595                 const INT32 NumStreams = (SepTables == NULL) ? 3 : 1;
04596 
04597                 for (INT32 i = 0; i < NumStreams; i++)
04598                 {
04599                     ERROR3IF(RegionWidth > Width, _T("I didn't allocate enough memory!"));
04600 
04601                     // Copy this component into the buffer
04602                     for (INT32 j = 0; j < RegionWidth; j++)
04603                     {
04604                         pRGBBuf[j] = TempBitmapBytes[(j * 3) + i];
04605                     }
04606 
04607                     // We are going to do ASCII85, so get ready for it.
04608                     if (!pDC->StartASCII85Output(TRUE))  // TRUE => RLE please
04609                         // Error
04610                         return SLOWJOB_FAILURE;
04611 
04612                     // Send to output stream as RLE encoded ASCII85 data.
04613                     /*INT32 nBytes =*/ pDC->OutputASCII85(pRGBBuf, RegionWidth);
04614 
04615                     if (!pDC->EndASCII85Output())
04616                         // Error
04617                         return SLOWJOB_FAILURE;
04618                 }
04619             }
04620             else
04621             {
04622                 // Just output as L1 ASCIIHex encoded data
04623                 if (SepTables != NULL)
04624                 {
04625                     // Colour separating, so reduce the 24-bit (R=G=B) greyscale to 8bpp by getting the _T("red") channel
04626                     for (INT32 j = 0; j < RegionWidth; j++)
04627                         pRGBBuf[j] = TempBitmapBytes[j * 3];
04628                     pDC->OutputRawBinary(pRGBBuf, RegionWidth, 1);
04629                 }
04630                 else
04631                 {
04632                     // Normal 24bpp colour output
04633                     pDC->OutputRawBinary(TempBitmapBytes, RegionWidth * 3, 1);
04634                 }
04635             }
04636 
04637             pDC->OutputToken(_T("rs"));
04638             pDC->OutputNewLine();
04639 
04640             // Update the progress display if necessary.
04641             if ((Progress!=NULL) && (!Progress->BitmapPhaseBandRenderedTo(MaskInfo.y)))
04642             {
04643                 // Free up the tempory DIB I made
04644                 FreeDIB(TempBitmapInfo, TempBitmapBytes);
04645 
04646                 return SLOWJOB_USERABORT;
04647             }
04648 
04649             // Find the next bit of scan line to plot
04650             pMask->GetNextMaskRegion(&MaskInfo);
04651         }
04652     }
04653     catch(CFileException)
04654     {
04655         FreeDIB(TempBitmapInfo, TempBitmapBytes);
04656 
04657         if (UseLevel2)
04658             CCFree(pRGBBuf);
04659 
04660         return SLOWJOB_FAILURE;
04661     }
04662 
04663 
04664     // Update bitmap info to what it was before we started
04665     TempBitmapInfo->bmiHeader.biSizeImage = (Width*3);
04666     TempBitmapInfo->bmiHeader.biWidth = Width;
04667 
04668     // Free up the tempory DIB I made
04669     FreeDIB(TempBitmapInfo, TempBitmapBytes);
04670 
04671     // Free up the buffer used for separating RGB components
04672     CCFree(pRGBBuf);
04673 #endif
04674 
04675     // All ok
04676     return SLOWJOB_SUCCESS;
04677 }

BOOL CamelotEPSRenderRegion::DrawParallelogramBitmap DocCoord Coords,
OILBitmap pBitmap,
EFFECTTYPE  Effect = EFFECT_RGB,
DocColour StartCol = NULL,
DocColour EndCol = NULL
[virtual]
 

Plot an arbitrarily transformed bitmap in the position specified.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/7/95
Parameters:
Coords - the parallelogram to plot the bitmap into (should be an array of [INPUTS] 4 co-ordinates) pBitmap - the bitmap to render! Effect - if contone colours are supplied, this is how the colours should fade. StartCol, EndCol - optional colours, if non-NULL, this indicates that the bitmap is a contoned bitmap and should be rendered using these colours.
Returns:
TRUE if the bitmap could be rendered as specified; FALSE if it could not be (and hence wasn't).
For a normal untransformed rectangle, the Coords array should start specify the parallelogram as follows:

Coords[0] Coords[1] +---------------+ | | | | | | | | +---------------+ Coords[3] Coords[2]

See also:
NodeBitmap::Render; CamelotEPSRenderRegion::DrawTransformedBitmap

Definition at line 5165 of file cameleps.cpp.

05168 {
05169     // If we are not drawing complex shapes and this shape is, then return
05170     if ((!RenderComplexShapes) && (TestForComplexShape(&Caps)))
05171         return TRUE;
05172 
05173     // If it's contoned between two no-colours, it is invisible (on this plate) so don't render anything
05174     if (StartCol != NULL && StartCol->IsTransparent() && EndCol != NULL && EndCol->IsTransparent())
05175         return(TRUE);
05176 
05177     // Get information about the bitmap to be rendered.
05178     BitmapInfo BMInfo;
05179     if (!pBitmap->GetInfo(&BMInfo))
05180     {
05181         ERROR3("Bitmap GetInfo failed");
05182         // Error getting bitmap info
05183         return FALSE;
05184     }
05185 
05186     // Remember the Size of the Bitmap (in pixels)
05187     INT32 Width  = BMInfo.PixelWidth;
05188     INT32 Height = BMInfo.PixelHeight;
05189 
05190     if ((Width == 0) || (Height == 0))
05191     {
05192         // Error - bitmap has no dimension
05193         ERROR3("Bitmap width/height is 0");
05194         return FALSE;
05195     }
05196 
05197     // Find out if this is real renderable EPS.
05198     BOOL IsCamelotEPS = IS_A(this, CamelotEPSRenderRegion);
05199 
05200     // Is it contoned?
05201     BOOL IsContoned = (StartCol != NULL) && (EndCol != NULL);
05202     if (IsContoned)
05203     {
05204         if (pBitmap->GetGreyscaleVersion() != NULL)
05205         {
05206             pBitmap = pBitmap->GetGreyscaleVersion();
05207             if (!pBitmap->GetInfo(&BMInfo))
05208             {
05209                 ERROR3("Bitmap GetInfo failed");
05210                 // Error getting bitmap info
05211                 return FALSE;
05212             }
05213         }
05214     }
05215 
05216     // Find out if we can use Level 2 features.
05217     BOOL UseLevel2 = FALSE;
05218 
05219     if (IsCamelotEPS)
05220     {
05221         // Use the EPS preference.
05222         if (EPSFilter::XSEPSExportPSType == 2)
05223             UseLevel2 = TRUE;
05224     }
05225 //  WEBSTER-ranbirr-12/11/96
05226 #ifndef WEBSTER
05227     else if (IsPrinting())
05228     {
05229 #ifndef STANDALONE
05230         // Get the print info for this job.
05231         CCPrintInfo *pInfo = CCPrintInfo::GetCurrent();
05232         if (pInfo != NULL)
05233         {
05234             PrintControl *pPrCtrl = pInfo->GetPrintControl();
05235             if (pPrCtrl->GetPSLevel() == PSLEVEL_2)
05236                 // Printing to a level 2 device - party on!
05237                 UseLevel2 = TRUE;
05238         }
05239 #else
05240     ERROR2(FALSE,"CamelotEPSRenderRegion::DrawParallelogramBitmap trying to print in Viewer version!")
05241 #endif
05242     }
05243 
05244 #endif //webster
05245 
05246     // Work out the coords of the destination rectangle
05247 //  INT32 DestX = 0;
05248 //  INT32 DestY = 0;
05249 
05250     KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
05251 
05252     pDC->OutputToken(_T("sv"));
05253 
05254     // Dimensions of bitmap
05255     pDC->OutputValue(Width);
05256     pDC->OutputValue(Height);
05257 
05258     // Number of bits per component sample
05259     INT32 BytesPerScanline;
05260 
05261     // Are we colour separating? Get SepTables if we need them
05262     // NOTE that we get them even if we have a <= 8bpp bitmap, as the pointer is also used 
05263     // as a "we are separating" flag. Note also that we don't try to separate contoned bitmaps
05264     // via the normal system- we just let the old contone bitmap code output it, and separate the palette
05265     if (!IsContoned && SepTables == NULL && RenderView->GetColourPlate() != NULL)
05266     {
05267         ColourContextCMYK *cc = (ColourContextCMYK *)RenderView->GetColourContext(COLOURMODEL_CMYK);
05268         if (cc != NULL)
05269         {
05270             SepTables = (BYTE *) CCMalloc(5 * 256 * sizeof(BYTE));
05271             if (SepTables != NULL)
05272             {
05273                 if (!cc->GetProfileTables(SepTables))
05274                 {
05275                     CCFree(SepTables);
05276                     SepTables = NULL;
05277                 }
05278             }
05279         }
05280 
05281         ERROR3IF(SepTables == NULL, "Can't generate separation tables in CamelotEPSRenderRegion");
05282     }
05283 
05284     if (SepTables != NULL && !IsContoned)
05285     {
05286         // ALL colour separated bitmaps go out as simple 8bpp greyscales (yay! no special cases!)
05287         pDC->OutputValue((INT32)8);
05288         BytesPerScanline = Width;
05289     }
05290     else
05291     {
05292         // It's not colour separated, so output the right values for the bitmap's BPP.
05293         switch (BMInfo.PixelDepth)
05294         {
05295             case 1:
05296             case 8:
05297                 pDC->OutputValue((INT32) BMInfo.PixelDepth);
05298                 BytesPerScanline = ((BMInfo.PixelDepth * Width) + 7) / 8;   // Round 1bpp up to multiple of bytes
05299                 break;
05300 
05301             case 4:
05302                 // 4bpp images get converted to 8bpp because Adobe SDK image library can't
05303                 // do 4bpp on some PS printers (e.g. Canon LBP4-PS).
05304                 pDC->OutputValue((INT32) 8);
05305                 BytesPerScanline = Width;
05306                 break;
05307 
05308             case 24:
05309             case 32:            // 32bpp images are output as 24bpp to postscript
05310                 // Output will be standard 24bpp
05311                 pDC->OutputValue((INT32) 24);
05312                 BytesPerScanline = 3 * Width;
05313                 break;
05314 
05315             default:
05316                 // Unknown bitmap depth
05317                 ERROR3("Unsupported bitmap depth in CamelotEPSRenderRegion::DrawParallelogramBitmap");
05318                 return FALSE;
05319         }
05320     }
05321 
05322     // Now, output how many bytes per scanline will be used.
05323     pDC->OutputValue(BytesPerScanline);
05324 
05325     // Now output the matrix - colorimage expects the inverse of this matrix, i.e.
05326     // it needs the matrix which maps the destination area to the 1-1 rectangle at
05327     // the origin (cos PostScript is weird like that).
05328     pDC->OutputToken(_T("["));
05329 
05330     // NB. We have to do some 'bespoke' matrix maths here, because we need to work
05331     //     in points, and our Matrix class is not accurate enough (notably the e and 
05332     //     f components are integer only, and we need fractional points).
05333     double a[2],b[2],c[2],d[2], e[2], f[2];
05334 
05335     // Find out the size of one unit, in MILLIPOINTS.
05336     double UnitSize;
05337     if (IsCamelotEPS)
05338     {
05339         // Unit is 1000 millipoints, as we always use 1 point as unit in user space
05340         // in Camelot EPS.
05341         UnitSize = 1000;
05342     }
05343     else
05344     {
05345         // Find the size of a pixel, because Windows maps a unit to a pixel.
05346         FIXED16 fxPixelSize;
05347         RenderView->GetPixelSize(&fxPixelSize, &fxPixelSize);
05348         UnitSize = fxPixelSize.MakeDouble();
05349     }
05350 
05351     // Work out the width and height of the bitmap, assuming each pixel corresponds to
05352     // one unit.
05353     double dWidth = (double) Width;
05354     double dHeight = (double) Height;
05355 
05356     DocCoord DCOrigin = pDC->GetOrigin();
05357 
05358     if (IsCamelotEPS)
05359     {
05360         dWidth *= UnitSize;
05361         dHeight *= UnitSize;
05362         a[0] = ((double) (Coords[2].x - Coords[3].x)) / dWidth;
05363         b[0] = ((double) (Coords[2].y - Coords[3].y)) / dWidth;
05364         c[0] = ((double) (Coords[0].x - Coords[3].x)) / dHeight;
05365         d[0] = ((double) (Coords[0].y - Coords[3].y)) / dHeight;
05366         e[0] = ((double) (Coords[3].x - DCOrigin.x)) / UnitSize;
05367         f[0] = ((double) (Coords[3].y - DCOrigin.y)) / UnitSize;
05368     }
05369     else
05370     {
05371         ERROR3IF(!pDC->IsKindOf(CC_RUNTIME_CLASS(PSPrintDC)), "KernelDC is not a PSPrintDC - how did that happen?");
05372         // Printing to PostScript - convert to Window co-ordinates, using the DC.
05373         PSPrintDC *pPSDC = (PSPrintDC *) pDC;
05374 
05375         WinCoord PSCoords[3];
05376         for (INT32 i = 0; i <= 3; i++)
05377             PSCoords[i] = pPSDC->TransformCoord(Coords[i]);
05378 
05379         a[0] = ((double) (PSCoords[2].x - PSCoords[3].x)) / dWidth;
05380         b[0] = ((double) (PSCoords[2].y - PSCoords[3].y)) / dWidth;
05381         c[0] = ((double) (PSCoords[0].x - PSCoords[3].x)) / dHeight;
05382         d[0] = ((double) (PSCoords[0].y - PSCoords[3].y)) / dHeight;
05383         e[0] = (double) PSCoords[3].x;
05384         f[0] = (double) PSCoords[3].y;
05385     }
05386 
05387     // Calculate the inverse of the above.
05388     double Det = a[0] * d[0] - b[0] * c[0];
05389 
05390     if (Det==0.0)
05391     {
05392         // There is no inversion of this matrix
05393         // return the identity matrix
05394         ERROR3("Matrix Inversion Failed - Tried to Invert a non-invertable matrix" );
05395         return FALSE;
05396     }
05397 
05398     // this section calculates the inverse of the matrix. As it takes into
05399     // account that our 3x3 matrix always has 0,0,1 down its right hand side
05400     // it has been greatly simplified. The operations combine the calculation
05401     // of the adjoint matrix and scaling it by the Determinent with a matrix
05402     // transpose (the inverse is the transpose of the adjoint scaled by the 
05403     // determinent)
05404     a[1] =  d[0] / Det;
05405     b[1] = -b[0] / Det;
05406     c[1] = -c[0] / Det;
05407     d[1] =  a[0] / Det;
05408     e[1] =   ((c[0] * f[0]) - (e[0] * d[0])) / Det ;
05409     f[1] = -(((a[0] * f[0]) - (e[0] * b[0])) / Det);
05410 
05411     pDC->OutputReal(a[1]);
05412     pDC->OutputReal(b[1]);
05413     pDC->OutputReal(c[1]);
05414     pDC->OutputReal(d[1]);
05415 
05416     if (IsCamelotEPS)
05417     {
05418         // Convert to points.
05419         pDC->OutputUserSpaceValue((MILLIPOINT) (e[1] * 1000.0));
05420         pDC->OutputUserSpaceValue((MILLIPOINT) (f[1] * 1000.0));
05421     }
05422     else
05423     {
05424         // Pass straight through
05425         pDC->OutputReal(e[1]);
05426         pDC->OutputReal(f[1]);
05427     }
05428 
05429     pDC->OutputToken(_T("]"));
05430 
05431     // Default values for smoothing and polarity
05432     pDC->OutputToken(_T("false"));
05433     pDC->OutputToken(_T("false"));
05434 
05435     // Normally we use ASCII Hex encoding, but for Level 2 specific output, we use ASCII85.
05436     if (UseLevel2)
05437         // Run length encoded and ASCII85 encoded
05438         pDC->OutputToken(_T("3"));
05439     else
05440         // Simple level 1 compatible ASCII Hex encoding.
05441         pDC->OutputToken(_T("1"));
05442 
05443     // Set up the image procs
05444     pDC->OutputToken(_T("beginimage"));
05445 
05446     if (SepTables != NULL && !IsContoned)
05447     {
05448         // If we are colour-separating, then output always goes out as an 8bpp greyscale image
05449         // This may seem like a gross thing to do (especially for 1/4bpp), but as 4bpp is always
05450         // expanded to 8bpp anyway, it is much better to treat all images in a nice generic manner
05451         // and save ourselves lots of work, lots of confusion, and the potential for lots of
05452         // special cases which don't work (for examples of code like this, see the old composite
05453         // printing code below).
05454         if (!pBitmap->ExportSeparatedPalette(this))
05455         {
05456             ERROR3("ExportSeparatedPalette failed");
05457             return FALSE;
05458         }
05459 
05460         pDC->OutputToken(_T("doclutimage"));        // Colour separation to 8bpp greyscale image
05461 
05462         pDC->OutputNewLine();
05463 
05464         // Output bitmap (scanline) data as an 8bpp greyscale
05465         if (!pBitmap->ExportSeparatedData(this, SepTables))
05466         {
05467             ERROR3("ExportSeparatedData failed");
05468             return FALSE;
05469         }
05470     }
05471     else
05472     {
05473         // We've specified the size, depth and position of the bitmap, so now we work 
05474         // out which PostScript procedure we should render the image with.
05475         switch (BMInfo.PixelDepth)
05476         {
05477             case 1:
05478                 // It's a 1bpp image - should we output a palette with it?
05479                 if (IsContoned)
05480                 {
05481                     // (Jason here: I believe the postscript routine 1bitcopyimage doesn't work.
05482                     // This is probably OK, as I think all contoned bitmaps in camelot are made 8bpp.
05483                     // I've left this code in place, however, just in case it would break something)
05484 
05485                     // Convert colours to RGB and output for use with the special
05486                     // 1bpp contone operator.
05487                     Document *pDoc = RenderView->GetDoc();
05488                     if (pDoc == NULL)
05489                     {
05490                         ERROR3("No document when rendering");
05491                         // Panic!
05492                         return FALSE;
05493                     }
05494 
05495                     // Use the output context to convert the colours, and then output them...
05496                     ColourContext *pContext = CurrentColContext;
05497                     if (pContext == NULL)
05498                     {
05499                         ERROR3("No Colour context when rendering");
05500                         return(FALSE);      // Panic!
05501                     }
05502 
05503                     ERROR3IF(pContext->GetColourModel() != COLOURMODEL_RGBT,
05504                                 "RGB output context expected in EPS rendering");
05505                     ColourRGBT Result;
05506 
05507                     if (IsContoned)
05508                         pContext->ConvertColour((DocColour *) StartCol, (ColourGeneric *)&Result);
05509                     else
05510                     {
05511                         DocColour Black(0L, 0L, 0L);
05512                         pContext->ConvertColour(&Black, (ColourGeneric *)&Result);
05513                     }
05514 
05515                     pDC->OutputReal(Result.Red.MakeDouble());
05516                     pDC->OutputReal(Result.Green.MakeDouble());
05517                     pDC->OutputReal(Result.Blue.MakeDouble());
05518 
05519                     if (IsContoned)
05520                         pContext->ConvertColour((DocColour *) EndCol, (ColourGeneric *)&Result);
05521                     else
05522                     {
05523                         DocColour White(255L, 255L, 255L);
05524                         pContext->ConvertColour(&White, (ColourGeneric *)&Result);
05525                     }
05526 
05527                     pDC->OutputReal(Result.Red.MakeDouble());
05528                     pDC->OutputReal(Result.Green.MakeDouble());
05529                     pDC->OutputReal(Result.Blue.MakeDouble());
05530 
05531                     // Use special colour 1bpp operator
05532                     pDC->OutputToken(_T("1bitcopyimage"));
05533                 }
05534                 else
05535                 {
05536                     // Normal black and white image
05537                     pDC->OutputToken(_T("1bitbwcopyimage"));
05538                 }
05539                 break;
05540 
05541             case 4:
05542             case 8:
05543                 if (IsContoned)
05544                 {
05545                     // Contoned bitmap - generate and output the contone palette.
05546                     if (!pBitmap->BuildContonePalette(*StartCol, *EndCol, Effect, RenderView))
05547                     {
05548                         ERROR3("Contoned palette failed");
05549                         // Error while building palette (out of memory?)
05550                         return FALSE;
05551                     }
05552 
05553                     BOOL Success = pBitmap->ExportContonePalette(this);
05554 
05555                     // Clean up contone palette
05556                     pBitmap->DestroyContonePalette();
05557                 
05558                     // Did it work?
05559                     if (!Success)
05560                     {
05561                         ERROR3("Contoned palette export failed");
05562                         return FALSE;
05563                     }
05564 
05565                     // Use the procedure for rendering paletted images.
05566                     pDC->OutputToken(_T("doclutimage"));
05567                 }
05568                 else if (BMInfo.NumPaletteEntries > 0)
05569                 {
05570                     // It's a paletted image - export the palette
05571                     if (!pBitmap->ExportBitmapPalette(this))
05572                     {
05573                         ERROR3("ExportBitmapPalette failed");
05574                         return FALSE;
05575                     }
05576 
05577                     // Use the procedure for rendering paletted images.
05578                     pDC->OutputToken(_T("doclutimage"));
05579                 }
05580                 else
05581                 {
05582                     // It's a greyscale image - use the image operator.
05583                     // (Jason here: I reckon the postscript for doimage doesn't work. This is
05584                     // probably OK, because camelot can't theoretically have a non-paletted image?)
05585                     pDC->OutputToken(_T("doimage"));
05586                 }
05587                 break;
05588 
05589             case 24:
05590             case 32:                                    // 32bpp is output as 24bpp data
05591                 pDC->OutputToken(_T("do24image"));          // Normal composite colour 24bpp image
05592                 break;
05593 
05594             default:
05595                 // Unknown bitmap depth
05596                 ERROR3("Unsupported bitmap depth");
05597                 return FALSE;
05598         }
05599 
05600         pDC->OutputNewLine();
05601 
05602         // Output bitmap (scanline) data
05603         if (!pBitmap->ExportBitmapData(this))
05604         {
05605             ERROR3("ExportBitmapData failed");
05606             return FALSE;
05607         }
05608     }
05609 
05610     // Clean up image stuff
05611     pDC->OutputNewLine();
05612     pDC->OutputToken(_T("endimage"));
05613 
05614     pDC->OutputToken(_T("rs"));
05615     pDC->OutputNewLine();
05616 
05617     return TRUE;
05618 }

void CamelotEPSRenderRegion::DrawPathToOutputDevice Path DrawPath,
PathShape  shapePath = PATHSHAPE_PATH
[virtual]
 

Output all the commands required to render this path to the EPS file.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
DrawPath - the path to render. [INPUTS]
See also:
RenderRegion::DrawPath; EPSRenderRegion::GetValidPathAttributes EPSRenderRegion::ExportPath

Reimplemented from EPSRenderRegion.

Definition at line 5634 of file cameleps.cpp.

05635 {
05636     // If we are not drawing complex shapes and this shape is, then return
05637     if ((!RenderComplexShapes) && (TestForComplexShape(&Caps)))
05638         return;
05639 
05640     // Work out if we need to be renderable.
05641     BOOL Renderable = (IS_A(this, CamelotEPSRenderRegion) || IsPrinting());
05642 
05643     if (Renderable)
05644     {
05645         // Check for clipped (non-repeating) bitmaps...
05646 
05647         // Get the current fill attr
05648         ColourFillAttribute* pFillAttr = (ColourFillAttribute*) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
05649 
05650         // See if it is a simple non-repeating bitmap fill...
05651         if (pFillAttr->IS_KIND_OF(BitmapFillAttribute))
05652         {
05653             FillMappingAttribute* pMapAttr = (FillMappingAttribute*) CurrentAttrs[ATTR_FILLMAPPING].pAttr;
05654             if (pMapAttr->Repeat == 1)
05655             {
05656                 // Simple non-repeating clipped bitmap - we can do this!
05657                 DrawClippedBitmap(DrawPath);
05658                 return;
05659             }
05660         }
05661     }
05662 
05663     ExportPath(DrawPath, FALSE);
05664 
05665     // Now do the arrow heads if the render region can't do them directly
05666     if (!Caps.ArrowHeads)
05667     {
05668         // Doesn't support arrow heads directly so we render them as paths.
05669         DrawPathArrowHeads(DrawPath->GetCoordArray(),
05670                            DrawPath->GetVerbArray(),
05671                            DrawPath->GetNumCoords());
05672     }
05673 }

BOOL CamelotEPSRenderRegion::DrawTransformedBitmap NodeBitmap pNodeBitmap  )  [virtual]
 

Plot an arbitrarily transformed bitmap using a matrix and an offset. The bitmap is assumed to occupy a rectangle at the origin, which has pixels 1 point across, and the matrix supplied transforms this area to the correct place. The Point parameter supplies an optional offset which can be applied after the transform. If the offset is 0,0, this means there is no offset (surprise, surprise!).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/6/95
Parameters:
pNodeBitmap - the bitmap node to render! [INPUTS]
Returns:
TRUE if the bitmap could be rendered as specified; FALSE if it could not be (and hence wasn't).
See also:
NodeBitmap::Render

Reimplemented from RenderRegion.

Definition at line 5098 of file cameleps.cpp.

05099 {
05100     // If we are not drawing complex shapes and this shape is, then return
05101     if ((!RenderComplexShapes) && (TestForComplexShape(&Caps)))
05102         return TRUE;
05103 
05104     if ((!RenderComplexShapes) && (pNodeBitmap->NeedsTransparency()))
05105         return TRUE;
05106 
05107     DocCoord *Coords = pNodeBitmap->InkPath.GetCoordArray();
05108 
05109     // Get the 'actual' OIL Bitmap
05110     OILBitmap *TheBitmap = pNodeBitmap->GetBitmap()->ActualBitmap;
05111 
05112     // Is it contoned?
05113     DocColour *StartCol = NULL, 
05114               *EndCol =   NULL;
05115 
05116     if (!RR_STROKECOLOUR().IsTransparent())
05117     {
05118         // It has a line colour, so it is contoned!
05119         StartCol = &(RR_STROKECOLOUR());
05120         EndCol   = &(RR_FILLCOLOUR());
05121     }
05122 
05123     // Render it
05124     return DrawParallelogramBitmap(Coords, TheBitmap, GetFillEffect(), StartCol, EndCol);
05125 }

BOOL CamelotEPSRenderRegion::GetCurrFillEffect UINT32 EffectType  )  [protected]
 

Return the state of the current fill effect in the EPS attributes stack.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/06/96
Parameters:
- [INPUTS]
The current type of fill effect [OUTPUTS]
Returns:
TRUE if a fill effect exists in the current attrs stack FALSE if not

Definition at line 3844 of file cameleps.cpp.

03845 {
03846     // set default
03847     EffectType = FILLEFFECT_FADE;
03848 
03849     FillEffectAttribute *pFillAttr = (FillEffectAttribute *) CurrentAttrs[ATTR_FILLEFFECT].pAttr;
03850     if (pFillAttr==NULL)
03851         return FALSE;   
03852 
03853     if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(FillEffectFadeAttribute)))
03854     {
03855         EffectType = FILLEFFECT_FADE;
03856     }
03857     else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(FillEffectRainbowAttribute)))
03858     {
03859         EffectType = FILLEFFECT_RAINBOW;
03860     }
03861     else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(FillEffectAltRainbowAttribute)))
03862     {
03863         EffectType = FILLEFFECT_ALTRAINBOW;
03864     }
03865     else
03866     {
03867         ERROR3("Illegal fill effect type!");
03868     }
03869     
03870     return TRUE;
03871 }

void CamelotEPSRenderRegion::GetRenderRegionCaps RRCaps pCaps  )  [virtual]
 

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.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
10/4/95
Parameters:
pCaps - The details about what types of thing this render region can render [OUTPUTS]

Reimplemented from EPSRenderRegion.

Reimplemented in NativeRenderRegion.

Definition at line 3311 of file cameleps.cpp.

03312 {
03313     // We can do grad fills, and most kinds of bitmaps.
03314     pCaps->CanDoNothing();
03315     pCaps->GradFills = TRUE;
03316     pCaps->SimpleBitmaps = TRUE;
03317     pCaps->ArbitraryBitmaps = TRUE;
03318     pCaps->ClippedSimpleBitmaps = TRUE;
03319     pCaps->ClippedArbitraryBitmaps = TRUE;
03320     pCaps->ClippedOutput = TRUE;
03321 }

void CamelotEPSRenderRegion::GetValidPathAttributes  )  [virtual]
 

See EPSRenderRegion::GetValidPathAttributes. This version checks and handles grad fill colours before calling the base class version.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
See also:
EPSRenderRegion::GetValidPathAttributes

Reimplemented from ArtWorksEPSRenderRegion.

Reimplemented in NativeRenderRegion.

Definition at line 3336 of file cameleps.cpp.

03337 {
03338     KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
03339 
03340     FillGeometryAttribute *pFillAttr = 
03341         (FillGeometryAttribute *) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
03342 
03343     if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(GradFillAttribute)) &&
03344         SetLastOutputAttribute(ATTR_FILLGEOMETRY))
03345     {
03346         // If the fill is square
03347         if (!pFillAttr->IsASquareFill() && !pFillAttr->IsAThreeColFill())
03348         {
03349             // Get the correct brush - may be a grad fill.
03350             if (//pFillAttr->IsKindOf(CC_RUNTIME_CLASS(GradFillAttribute)) &&
03351                 !pFillAttr->IsKindOf(CC_RUNTIME_CLASS(BitmapFillAttribute)) )
03352             {
03353                 // Output a grad fill command...
03354 
03355                 // Get the start colour and end colour in CMYK, and output them.
03356                 GradFillAttribute *pGradFillAttr = (GradFillAttribute *) pFillAttr;
03357 
03358                 // Check if the colours are named or not.
03359                 BOOL UnnamedColours = FALSE;
03360                 BOOL GreyFill = FALSE;
03361 
03362                 // During a normal CamEPS export we will not be separating, hence
03363                 // pSeparation will always return NULL here. If however we are
03364                 // currently printing we need to perform some giggery pokery with
03365                 // grad fills in order to separate them correctly. 
03366                 
03367                 // We have two fill operators we can use in Postscript, these
03368                 // are cax, a colour fill op and cag a grey fill op. 
03369                 // There are three items of interest to us which we need to consider
03370                 // before choosing to use one of the postscript fill operators, these
03371                 // are
03372                 // (1) the end colours of the fill (the model etc)
03373                 // (2) the fill effect across the grad fill
03374                 // (3) the output plate we're rendering to.
03375                 //
03376                 // We need to work out what happens on both cmyk and spot plates when
03377                 // using one of these operators. For instance when using a grey fill
03378                 // operator, the fill effect will not be used. It may go out in the 
03379                 // output stream, but it will be ignored in Postscript (because you
03380                 // are using a grey fill of course!).
03381                 // You also need to consider that if you use the colour fill operator
03382                 // you are in effect restricting output to the process colour plates.
03383                 // Nothing will appear on spot plates. The colour operator works by
03384                 // performing a separation itself, using the current fill effect and
03385                 // wandering about in rgb space.
03386                 // You also need to know the rules for interaction between mixed colours
03387                 // during a separation, ie if we have a rgb colour to spot colour fill
03388                 // with a rainbow fill effect, question which should immediately leap/
03389                 // to mind are
03390                 // (1) do we use the fill effect
03391                 // (2) what fill is used on the spot plate
03392                 // (3) what fill is used on the process plates
03393                 // (4) how will this all look, is it sensible?
03394 
03395                             
03396                 // We should really define a virtual function for this operation and
03397                 // override it in PrintPSRenderRegion.
03398 
03399                 ColourContext* pContext;
03400                 ColourPlate* pSeparation;
03401                 GetOutputColourPlate(COLOURMODEL_CMYK, &pContext, &pSeparation);
03402 
03403                 if (pSeparation!=NULL)
03404                 {
03405                     DocColour *Start, *End;
03406                     Start = &(pGradFillAttr->Colour);
03407                     End   = &(pGradFillAttr->EndColour);
03408                     BOOL StartIsSpot = (Start->GetSpotParent() != NULL);
03409                     BOOL EndIsSpot   = (End->GetSpotParent() != NULL);
03410 
03411                     // If we are rendering a spot plate 
03412                     GreyFill = (pSeparation->GetType() == COLOURPLATE_SPOT);
03413                     // or either end of this fill are spot... use the gray fill operator
03414                     // This will mean process colour will be separated and provide a linear
03415                     // fill to white on none spot plates.
03416                     GreyFill = (GreyFill || StartIsSpot || EndIsSpot);
03417 
03418                     if (!GreyFill)
03419                     {
03420                         // ok we're on a process plate, and both ends are not spot
03421                         // are both ends CMYK colours with a simple fill effect?
03422                         GreyFill = ( Start->GetColourModel() == COLOURMODEL_CMYK ) && 
03423                                    (   End->GetColourModel() == COLOURMODEL_CMYK );
03424 
03425                         if (GreyFill)
03426                         {
03427                             // Is there a crazy fill effect pending?
03428                             UINT32 filleffect;
03429                             BOOL exists = GetCurrFillEffect(filleffect);
03430                             GreyFill = (!exists || filleffect == FILLEFFECT_FADE);
03431                         }
03432                     }
03433                 }
03434 
03435                 // if GreyFill is true we output this fill as a single plate gray fill
03436                 // otherwise we splunge it across the process plates.
03437                     
03438                 if (GreyFill)
03439                 {
03440                     UnnamedColours = TRUE;
03441                     // both of these colours are cmyk so we need to handle the separation
03442                     // slightly differently. The user will expect these colours to spread
03443                     // without going through rgb=>devcmyk to do so.
03444                     PColourCMYK sCMYK, eCMYK;
03445 
03446                     pGradFillAttr->Colour.GetCMYKValue(pContext, &sCMYK);
03447                     pGradFillAttr->EndColour.GetCMYKValue(pContext, &eCMYK);
03448 
03449                     // Sanity check on this plate
03450                     ERROR3IF( (sCMYK.Cyan!=0 || sCMYK.Magenta!=0 || sCMYK.Yellow!=0 ||
03451                                eCMYK.Cyan!=0 || eCMYK.Magenta!=0 || eCMYK.Yellow!=0) , 
03452                              "Not a mono plate during export of CMYK gradfills (CAMEPSRndRgn::GetValidPathAttributes())" );
03453 
03454                     // output a linear key fill.
03455                     BOOL ok = pDC->OutputColourValue(255 - sCMYK.Key);
03456                     ok = ok && pDC->OutputColourValue(255 - eCMYK.Key);
03457                     // This entire function seems to ignore disc failure which is a bit rampant!
03458                     ERROR3IF(!ok, "Disc buffer failure during gradfill output in GetValidPathAttributes");
03459                 }
03460                 else
03461                 {
03462                     // This is a mixture of colour spaces so simply output the
03463                     // who lot as normal. Postscript will spread the colour
03464                     UnnamedColours = OutputGradFillColours( &(pGradFillAttr->Colour), &(pGradFillAttr->EndColour) );
03465                 }
03466 
03467                 // Output the start and end points of the grad fill
03468                 pDC->OutputCoord(pGradFillAttr->StartPoint);
03469                 pDC->OutputCoord(pGradFillAttr->EndPoint);
03470 
03471 
03472                 // Output the fill type
03473                 if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(LinearFillAttribute)))
03474                 {
03475                     LinearFillAttribute *pLinearFillAttr = (LinearFillAttribute *) pFillAttr;
03476 
03477                     DocCoord* Start = pFillAttr->GetStartPoint();
03478                     DocCoord* End   = pFillAttr->GetEndPoint();
03479                     DocCoord* End2  = pFillAttr->GetEndPoint2();
03480 
03481                     if (AreLinesPerpendicular(Start, End, End2))
03482                     {
03483                         TRACEUSER( "Will", _T("Exporting Simple Linear Fill\n"));
03484                         pDC->OutputValue((INT32) CAMEPS_FILL_LINEAR);
03485                     }
03486                     else
03487                     {
03488                         TRACEUSER( "Will", _T("Exporting New Style Linear Fill\n"));
03489                         pDC->OutputCoord(pLinearFillAttr->EndPoint2);
03490                         pDC->OutputValue((INT32) CAMEPS_FILL_NEWLINEAR);
03491                     }
03492                 }
03493                 else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(RadialFillAttribute)))
03494                 {
03495                     // Is it circular or elliptical?
03496                     RadialFillAttribute *pRadialFillAttr = (RadialFillAttribute *) pFillAttr;
03497                     if (pRadialFillAttr->IsElliptical())
03498                     {
03499                         // Elliptical fill - output the second end point.
03500                         pDC->OutputCoord(pRadialFillAttr->EndPoint2);
03501                         pDC->OutputValue((INT32) CAMEPS_FILL_ELLIPTICAL);
03502                     }
03503                     else
03504                     {
03505                         // Circular fill
03506                         pDC->OutputValue((INT32) CAMEPS_FILL_CIRCULAR);
03507                     }
03508                 }
03509                 else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(ConicalFillAttribute)))
03510                 {
03511                     pDC->OutputValue((INT32) CAMEPS_FILL_CONICAL);
03512                 }
03513                 else
03514                 {
03515                     // Bodge: ought to handle this more gracefully soon...
03516                     ENSURE(FALSE, "Unsupported grad fill encountered while exporting");
03517                     EPSRenderRegion::GetValidPathAttributes();
03518                     return;
03519                 }
03520 
03521                 // Output the grad fill token
03522                 if (UnnamedColours)
03523                 {
03524                     if (GreyFill)
03525                         pDC->OutputToken(_T("cag"));
03526                     else
03527                         pDC->OutputToken(_T("caz"));
03528                 }
03529                 else
03530                 {
03531                     pDC->OutputToken(_T("cax"));
03532                 }
03533                 pDC->OutputNewLine();
03534             }
03535             else if (   // Utterly awful code by WillC
03536                         (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(FractalFillAttribute)) ||
03537                          pFillAttr->IsKindOf(CC_RUNTIME_CLASS(NoiseFillAttribute))) &&
03538                          Caps.BitmapFills
03539                     )
03540             {
03541                 // Fractal fill - output fractal fill command...
03542 
03543                 //*************************************************************************
03544                 // this piece of code is copied from the bitmap export but differs
03545                 // only very slightly. Is this difference a bug or intended? We will never
03546                 // know.
03547 
03548                 // first output the base class fill stuff...
03549                 BitmapFillAttribute *pFill = (BitmapFillAttribute *) pFillAttr;
03550 
03551                 // Get the start colour and end colour in CMYK, and output them.
03552                 // Check if the colours are named or not.
03553                 BOOL UnnamedColours = FALSE;
03554                 ColourContext *cc = NULL;
03555                 
03556                 // (ChrisG 8/12/00) All non-grey grad fill colours are now exported by the 
03557                 // OutputGradFillColours function.
03558                 if ((pFill->Colour.FindParentIndexedColour() == NULL) &&
03559                     (pFill->EndColour.FindParentIndexedColour() == NULL))
03560                 {
03561                     // Neither colour is named...use unnamed colour syntax.
03562                     cc = ColourManager::GetColourContext(COLOURMODEL_CMYK, GetRenderView());
03563                     ERROR3IF(cc == NULL, "No CMYK colour context - somethings' seriously broken");
03564                 }
03565                 else
03566                 {
03567                     cc = NULL;
03568                 }
03569 
03570                 // Output the colours (and names)
03571                 UnnamedColours = OutputGradFillColours (&(pFill->Colour), &(pFill->EndColour), cc);
03572 
03573                 // Next the coords of the fill
03574                 pDC->OutputCoord(pFill->StartPoint);
03575                 pDC->OutputCoord(pFill->EndPoint);
03576                 pDC->OutputCoord(pFill->EndPoint2);
03577 
03578                 //*************************************************************************
03579                 // ok NoiseFillAttributes are saved as FractalFillAttributes. Strange you
03580                 // might say, aha! but NoiseFillAttributes are new objects not supported by
03581                 // camelot 1.1 so what else should we do? Hmm not sure at this point.
03582 
03583                 // Save the fractal parameters out.
03584                 pDC->OutputValue(pFill->GetSeed());
03585                 pDC->OutputReal(pFill->GetGraininess().MakeDouble());
03586                 pDC->OutputReal(pFill->GetGravity().MakeDouble());
03587                 pDC->OutputReal(pFill->GetSquash().MakeDouble());
03588 
03589                 // And now the DPI of the fractal bitmap
03590                 UINT32 DPI = pFill->GetFractalDPI();
03591                 pDC->OutputValue(DPI);
03592 
03593                 // And now the 'tileable' flag
03594                 pDC->OutputValue((INT32) (pFill->GetTileable()));
03595 
03596                 // Always Fractal type 1 at present
03597                 pDC->OutputToken(_T("1"));
03598 
03599                 // This is a fractal fill
03600                 pDC->OutputValue((INT32) CAMEPS_FILL_FRACTAL);
03601 
03602                 if (UnnamedColours)
03603                     pDC->OutputToken(_T("caz"));
03604                 else
03605                     pDC->OutputToken(_T("cax"));
03606                 pDC->OutputNewLine();
03607             }
03608             else if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(BitmapFillAttribute)) && Caps.BitmapFills)
03609             {
03610                 // Bitmap fill - output bitmap fill command...
03611                 BitmapFillAttribute *pBitmapFill = (BitmapFillAttribute *) pFillAttr;
03612                 ERROR3IF(pBitmapFill->GetBitmap() == NULL, "Bitmap fill has no bitmap");
03613 
03614                 if (pBitmapFill->GetBitmap())
03615                 {
03616                     // Get the start colour and end colour in CMYK, and output them.
03617                     // Check if the colours are named or not.
03618                     BOOL UnnamedColours = FALSE;
03619                     BOOL HasColours = ((pBitmapFill->GetStartColour() != NULL) &&
03620                                        (pBitmapFill->GetEndColour() != NULL));
03621 
03622                     if (HasColours)
03623                     {
03624                         // (ChrisG 8/12/00) All non-grey grad fill colours are now exported by the 
03625                         // OutputGradFillColours function.
03626                         ColourContext *cc = NULL;
03627 
03628                         if ((pBitmapFill->Colour.FindParentIndexedColour() == NULL) &&
03629                             (pBitmapFill->EndColour.FindParentIndexedColour() == NULL))
03630                         {
03631                             // Neither colour is named...use unnamed colour syntax.
03632                             cc = ColourManager::GetColourContext(COLOURMODEL_CMYK, GetRenderView());
03633                             ERROR3IF(cc == NULL, "No CMYK colour context - somethings' seriously broken");
03634                         }
03635                         else
03636                         {
03637                             // One or two of the colours are named, so use the named colour syntax.
03638                             cc = NULL;
03639                         }
03640 
03641                         // Write out the colours themselves.
03642                         UnnamedColours = OutputGradFillColours (&(pBitmapFill->Colour),
03643                                                                 &(pBitmapFill->EndColour),
03644                                                                 cc);
03645                     }
03646 
03647                     pDC->OutputCoord(pBitmapFill->StartPoint);
03648                     pDC->OutputCoord(pBitmapFill->EndPoint);
03649                     pDC->OutputCoord(pBitmapFill->EndPoint2);
03650 
03651                     if (HasColours)
03652                         pDC->OutputValue((INT32) CAMEPS_FILL_NEWBITMAP);
03653                     else
03654                         pDC->OutputValue((INT32) CAMEPS_FILL_BITMAP);
03655 
03656                     if (UnnamedColours)
03657                         pDC->OutputToken(_T("caz"));
03658                     else
03659                         pDC->OutputToken(_T("cax"));
03660 
03661                     pDC->OutputNewLine();
03662 
03663                     // ...and then the bitmap itself.
03664                     ExportDC *pExportDC = (ExportDC *) pDC;
03665                     pExportDC->GetParentFilter()->ExportBitmap(*pBitmapFill->GetBitmap());
03666                 }
03667             }
03668         }
03669     }
03670 
03671     if (SetLastOutputAttribute(ATTR_FILLEFFECT))
03672     {
03673         UINT32 EffectType;
03674         GetCurrFillEffect(EffectType);
03675 
03676         // Output fill effect
03677         pDC->OutputValue(EffectType);
03678     
03679         // Output the fill effect token
03680         pDC->OutputToken(_T("cxe"));
03681         pDC->OutputNewLine();
03682     }
03683 
03684     if (SetLastOutputAttribute(ATTR_FILLMAPPING))
03685     {
03686         // Now do the chromatic fill mapping
03687         FillMappingAttribute *pFillAttr = 
03688             (FillMappingAttribute *) CurrentAttrs[ATTR_FILLMAPPING].pAttr;
03689 
03690         // Get the correct mapping
03691         INT32 MappingType = pFillAttr->Repeat;
03692 //Mark Howitt, 9/10/97. If we are exporting, make sure that repeating grad fill is saved as simple.
03693 #ifdef _DEBUG
03694         if(MappingType == 4) MappingType = 2;
03695 #endif
03696         ERROR3IF((MappingType < 1) || (MappingType > 3), "Illegal fill mapping value!");
03697         
03698         // Output fill mapping
03699         pDC->OutputValue((UINT32) MappingType);
03700 
03701         // Allow for future extension of fill mappings. 
03702         pDC->OutputToken(_T("0"));
03703 
03704         // Output the fill mapping token
03705         pDC->OutputToken(_T("cxm"));
03706         pDC->OutputNewLine();
03707     }
03708 
03709     if (SetLastOutputAttribute(ATTR_WINDINGRULE))
03710     {
03711         WindingRuleAttribute *pWindingRuleAttr = 
03712             (WindingRuleAttribute *) CurrentAttrs[ATTR_WINDINGRULE].pAttr;
03713 
03714         switch (pWindingRuleAttr->WindingRule)
03715         {
03716             case NonZeroWinding:
03717                 // Change winding rule to 0, which means non-zero in Camelot EPS.
03718                 pDC->OutputToken(_T("0"));
03719                 pDC->OutputToken(_T("awr"));
03720                 pDC->OutputNewLine();
03721                 break;
03722 
03723             case EvenOddWinding:
03724                 // Change winding rule to 1, which means even-odd in Camelot EPS.
03725                 pDC->OutputToken(_T("1"));
03726                 pDC->OutputToken(_T("awr"));
03727                 pDC->OutputNewLine();
03728                 break;
03729 
03730             case NegativeWinding:
03731             case PositiveWinding:
03732                 // Not supported in Camelot EPS - ignore.
03733                 break;
03734 
03735             default:
03736                 ERROR3("Unknown winding rule encountered while exporting.");
03737                 break;
03738                 
03739         }
03740     }
03741 
03742     // Leave arrows/dash patterns to the base class.
03743 
03744     // Handle usual pens/brushes
03745     EPSRenderRegion::GetValidPathAttributes();
03746 }

BOOL CamelotEPSRenderRegion::NeedsPrintComponents void   )  [virtual]
 

Lets the print component class know that they are needed in this format's export.

Author:
Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/2/00
Parameters:
- [INPUTS]
Returns:
TRUE - the print components are needed.

Definition at line 4864 of file cameleps.cpp.

04865 {
04866     // We want print components!
04867     return TRUE;
04868 }

void CamelotEPSRenderRegion::OutputFillColour void   )  [virtual]
 

This simply calls EPSRenderRegion::OutputFillColour, otherwise this render region uses the overridden version found in ArtWorksEPSRenderRegion.

Author:
Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com>
Date:
8/12/00
Parameters:
- [INPUTS]
Returns:
-
See also:
EPSRenderRegion::OutputStrokeColour

Reimplemented from ArtWorksEPSRenderRegion.

Reimplemented in NativeRenderRegion.

Definition at line 5822 of file cameleps.cpp.

05823 {
05824     EPSRenderRegion::OutputFillColour ();
05825 }

BOOL CamelotEPSRenderRegion::OutputGradFillColours DocColour StartCol,
DocColour EndCol,
ColourContext pContext = NULL
[protected, virtual]
 

Reimplemented in NativeRenderRegion.

Definition at line 3770 of file cameleps.cpp.

03771 {
03772     KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
03773     bool outputNames = FALSE;
03774 
03775     if ((StartCol->FindParentIndexedColour() == NULL) &&
03776         (EndCol->FindParentIndexedColour() == NULL))
03777     {
03778         // Neither colour is named...use unnamed colour syntax.
03779         outputNames = FALSE;
03780     }
03781     else
03782     {
03783         // One or two of the colours are named, so use the named colour syntax.
03784         outputNames = TRUE;
03785     }
03786 
03787     // Start writing stuff to the EPS file.
03788     INT32 red = 0;
03789     INT32 green = 0;
03790     INT32 blue = 0;
03791 
03792     // Write out the start colour
03793     StartCol->GetRGBValue (&red, &green, &blue);
03794     pDC->OutputColourValue (red);
03795     pDC->OutputColourValue (green);
03796     pDC->OutputColourValue (blue);
03797 
03798     if (outputNames)
03799     {
03800         // Write out the name
03801         pDC->OutputColourName (StartCol);
03802 
03803         // Write out the tint value. This isn't actually used at the moment, but is left 
03804         //  for possible future expansion
03805         pDC->OutputValue ((INT32)0);
03806     }
03807 
03808     // And the End colour.
03809     EndCol->GetRGBValue (&red, &green, &blue);
03810     pDC->OutputColourValue(red);
03811     pDC->OutputColourValue(green);
03812     pDC->OutputColourValue(blue);
03813 
03814     if (outputNames)
03815     {
03816         // Write out the name
03817         pDC->OutputColourName (EndCol);
03818 
03819         // Write out the tint value. This isn't actually used at the moment, but is left 
03820         //  for possible future expansion
03821         pDC->OutputValue ((INT32)0);
03822     }
03823 
03824     // Return TRUE for no names used, FALSE for names used.
03825     return (!outputNames);
03826 }

void CamelotEPSRenderRegion::OutputStrokeColour  )  [virtual]
 

This simply calls EPSRenderRegion::OutputStrokeColour, as otherwise the ArtWorks version is used (which can't cope with the RGB colour tokens).

Author:
Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com>
Date:
8/12/00
Parameters:
- [INPUTS]
Returns:
-
See also:
EPSRenderRegion::OutputStrokeColour

Reimplemented from ArtWorksEPSRenderRegion.

Reimplemented in NativeRenderRegion.

Definition at line 5802 of file cameleps.cpp.

05803 {
05804     EPSRenderRegion::OutputStrokeColour ();
05805 }

BOOL CamelotEPSRenderRegion::RenderChar WCHAR  ch,
Matrix pMatrix
[virtual]
 

Render a character, using the specified transform and current attributes in the render region.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/4/95
Parameters:
ch - unicode value of char [INPUTS] pMatrix - matrix specifying transforms to place char correctly in document
Returns:
FALSE if fails

Reimplemented from EPSRenderRegion.

Reimplemented in NativeRenderRegion, and PrintPSRenderRegion.

Definition at line 4695 of file cameleps.cpp.

04696 {
04697 #ifndef STANDALONE
04698 
04699     // Should we render it as curves? (We do for non-ASCII characters)
04700     if ((ch > 255) || EPSFilter::XSEPSExportTextAsCurves)
04701         return RenderRegion::RenderChar(ch, pMatrix);
04702 
04703     // Make sure we have the right attributes for rendering as paths.
04704     GetValidPathAttributes();
04705 
04706     // get overall matrix - attribute matrix concatenated with given matrix if supplied
04707     Matrix matrix;
04708     if (GetCharAttributeMatrix(&matrix)==FALSE)
04709         return FALSE;
04710     if (pMatrix)
04711         matrix*=*pMatrix;
04712 
04713     // Can we do this using a GDI font?
04714     // We can if the matrix only specifies scaling and translation, with no aspect ratio.
04715     FIXED16 abcd[4];
04716     INT32   ef[2];
04717     matrix.GetComponents(abcd, ef);
04718 
04719     if ((abcd[1] == FIXED16(0)) && (abcd[2] == FIXED16(0)) && (abcd[0] == abcd[3]))
04720     {
04721         // Simple transformation - we can do this with an untransformed PostScript font
04722 
04723         // Work out required height of the font
04724         MILLIPOINT ReferenceSize = TextManager::GetDefaultHeight();
04725         MILLIPOINT Height = ReferenceSize * abcd[3];
04726 
04727         if (!SelectNewFont(RR_TXTFONTTYPEFACE(), RR_TXTBOLD(), RR_TXTITALIC(), Height))
04728         {
04729             // Could not select font
04730             return FALSE;
04731         }
04732     }
04733     else
04734     {
04735         // Transformation is complex - we need to use a matrix when selecting the font.
04736         if (!SelectNewFont(RR_TXTFONTTYPEFACE(), RR_TXTBOLD(), RR_TXTITALIC(), abcd))
04737         {
04738             // Could not select font
04739             return FALSE;
04740         }
04741     }
04742 
04743     // Render the character in the specified position...
04744     KernelDC *pKernelDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
04745 
04746     // Output character
04747 
04748     // Graham 5/8/96: Changed this to work with MBCS
04749     // Set up a string buffer for the output character
04750     char cBuffer[3];
04751 
04752     //Convert the character over to a MBCS index number
04753     UINT32 uiCharNumber = UnicodeManager::UnicodeToMultiByte(ch);
04754 
04755     //DecomposeMultiBytes takes that index number and creates a
04756     //two-byte character from it. We put that two-byte character
04757     //in cBuffer.
04758     UnicodeManager::DecomposeMultiBytes(uiCharNumber, (BYTE*) &cBuffer[0], (BYTE*) &cBuffer[1]);
04759     
04760     //And let's null-terminate cBuffer
04761     cBuffer[2]=0;
04762 
04763     //Now, if the character was a standard one-byte ASCII character, the ASCII
04764     //value will be in the second byte of cBuffer - cBuffer[1] - and cBuffer[0]
04765     //will be zero.
04766 
04767     //Note that we have set cBuffer[2] to zero. That means that cBuffer is null
04768     //terminated whether it contains a one or a two byte character.
04769 
04770     //So let's check if we've got a one-byte or a two-byte character. We do this
04771     //by saying...is cBuffer[0] zero?
04772 
04773     // First we copy it byte by byte into a TCHAR buffer
04774     TCHAR tcBuffer[3];
04775     tcBuffer[0]=cBuffer[0];
04776     tcBuffer[1]=cBuffer[1];
04777     tcBuffer[2]=cBuffer[2];
04778 
04779     if (tcBuffer[0]==0)
04780         //It's a standard ASCII character, one byte long.
04781         //So we only want to pass the second byte of cBuffer - cBuffer[1] -
04782         //to OutputString
04783         pKernelDC->OutputString(&tcBuffer[1]);
04784     else
04785         //The character is two bytes long (that is, it's a foreign character).
04786         //So we want to pass the whole of cBuffer - starting from cBuffer[0] -
04787         //to OutputString
04788         pKernelDC->OutputString(&tcBuffer[0]);
04789 
04790     //And that's the end of Graham's MBCS code. Now back to Tim.
04791 
04792     // Output position
04793     DocCoord DocPos(ef[0], ef[1]);
04794     pKernelDC->OutputCoord(DocPos);
04795 
04796     // Work out how to render the character..
04797     BOOL FlatFill = IS_A(CurrentAttrs[ATTR_FILLGEOMETRY].pAttr, FlatFillAttribute);
04798     BOOL Stroked = !RR_STROKECOLOUR().IsTransparent();
04799 
04800     // The character is filled if the fill is not a simple flat fill, or if it is,
04801     // but the fill colour is not transparent.
04802     BOOL Filled = !FlatFill || (!RR_FILLCOLOUR().IsTransparent());
04803 
04804     if (FlatFill && Filled && !Stroked)
04805     {
04806         // Simple flat filled text with no outline, so render normally.
04807         pKernelDC->OutputToken(_T("t"));
04808     }
04809     else
04810     {
04811         // Need to do something special...
04812         if (Stroked)
04813         {
04814             if (Filled)
04815                 // Stroke and fill it
04816                 pKernelDC->OutputToken(_T("tb"));
04817             else
04818                 // Just stroke it
04819                 pKernelDC->OutputToken(_T("ts"));
04820         }
04821         else
04822         {
04823             // Just fill it
04824             pKernelDC->OutputToken(_T("tf"));
04825         }
04826     }
04827 
04828 #endif
04829 
04830     return TRUE;
04831 }

BOOL CamelotEPSRenderRegion::SelectNewFont WORD  Typeface,
BOOL  Bold,
BOOL  Italic,
FIXED16 abcd
[protected]
 

Definition at line 4979 of file cameleps.cpp.

04980 {
04981 #ifndef STANDALONE
04982 
04983     // BODGE: This is mingled with horrible OIL code that should be moved to the OIL RSN...
04984 
04985     // Check to see if it is cached
04986     if ((FontInfo.Valid && FontInfo.Complex) &&
04987         (FontInfo.Typeface == Typeface) &&
04988         (FontInfo.Bold == Bold) &&
04989         (FontInfo.Italic == Italic) &&
04990         (FontInfo.a == abcd[0]) &&
04991         (FontInfo.b == abcd[1]) &&
04992         (FontInfo.c == abcd[2]) &&
04993         (FontInfo.d == abcd[3]))
04994     {
04995         // It is the same as the currently selected/cached font
04996         TRACEUSER( "Tim", _T("Using the cached font\n"));
04997         return TRUE;
04998     }
04999 
05000     // Cache is invalid - map the TrueType name to a PostScript font.
05001 
05002     // Get the typeface name of the font
05003     //  ENUMLOGFONT *pEnumLogFont = TextInfoBarOp::GetCachedLogFont(Typeface);
05004     //  String_64 FontName(pEnumLogFont->elfLogFont.lfFaceName);
05005     // Changed by Mike (2/8/95)
05006     String_64 FontName;
05007     if (!FONTMANAGER->GetFontName(Typeface, FontName))
05008         return FALSE;
05009 
05010     // Transform to a INI-file friendly format
05011     String_64 Encoded;
05012     INT32 Styles = 0;
05013     if (Bold)
05014         Styles += 1;
05015     if (Italic)
05016         Styles += 2;
05017     FONTMANAGER->EncodeFontName(FontName, Encoded, Styles);
05018 
05019     // Look up font in INI file.
05020     String_256 MappedFontName;
05021     if (!Camelot.GetPrefDirect(_T("EPSFontMapping"), (TCHAR *) Encoded, &MappedFontName))
05022     {
05023         // No preference - map to Times-Roman variant
05024         if (Bold)
05025         {
05026             if (Italic)
05027                 MappedFontName.Load(_R(IDS_K_CAMEPS_MAPFNAMEBI2));
05028             else
05029                 MappedFontName.Load(_R(IDS_K_CAMEPS_MAPFNAMEB2));
05030         }
05031         else
05032         {
05033             if (Italic)
05034                 MappedFontName.Load(_R(IDS_K_CAMEPS_MAPFNAMEI2));
05035             else
05036                 MappedFontName.Load(_R(IDS_K_CAMEPS_MAPFNAME2));
05037         }           
05038     }
05039 
05040     // Select this font by prefixing with a forward slash to make it into a name.
05041     KernelDC *pKernelDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
05042     String_8 Slash(TEXT("/"));
05043     MappedFontName.Insert(Slash, 0);
05044     pKernelDC->OutputToken((TCHAR *) MappedFontName);
05045 
05046     // Get the default text height, and work out how to scale to PostScript's default of
05047     // 1 user space unit (i.e. 1 pt)
05048     double ScaleFactor = TextManager::GetDefaultHeight() / 1000.0;
05049     TCHAR MatrixBuf[100];
05050     camSprintf(MatrixBuf, _T("[%.3f %.3f %.3f %.3f 0 0]"), 
05051             (double) (abcd[0].MakeDouble() * ScaleFactor),
05052             (double) (abcd[1].MakeDouble() * ScaleFactor),
05053             (double) (abcd[2].MakeDouble() * ScaleFactor),
05054             (double) (abcd[3].MakeDouble() * ScaleFactor));
05055 
05056     pKernelDC->OutputToken(MatrixBuf);
05057     
05058     // Select the complex font
05059     pKernelDC->OutputToken(_T("sf"));
05060 
05061     // Font cache is now valid
05062     FontInfo.Valid    = TRUE;
05063     FontInfo.Complex  = TRUE;
05064     FontInfo.Typeface = Typeface;
05065     FontInfo.Bold     = Bold;
05066     FontInfo.Italic   = Italic;
05067     FontInfo.a = abcd[0];
05068     FontInfo.b = abcd[1];
05069     FontInfo.c = abcd[2];
05070     FontInfo.d = abcd[3];
05071 
05072 #endif
05073     
05074     // All ok
05075     return TRUE;    
05076 }

BOOL CamelotEPSRenderRegion::SelectNewFont WORD  Typeface,
BOOL  Bold,
BOOL  Italic,
MILLIPOINT  Size
[protected]
 

Get the font name being used by the Camelot EPS exporter.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/4/95
Parameters:
Typeface - The font's ID. [INPUTS] Bold - Is it bold? Italic - Is it italic? Size - The font size in millipoints.
Returns:
TRUE - Success. FALSE - Failure / an error occured.

Definition at line 4889 of file cameleps.cpp.

04893 {
04894 #ifndef STANDALONE
04895     // BODGE: This is mingled with horrible OIL code that should be moved to the OIL RSN...
04896 
04897     // Check to see if it is cached
04898     if ((FontInfo.Valid && !FontInfo.Complex) &&
04899         (FontInfo.Typeface == Typeface) &&
04900         (FontInfo.Bold == Bold) &&
04901         (FontInfo.Italic == Italic) &&
04902         (FontInfo.Size == Size))
04903     {
04904         // It is the same as the currently selected/cached font
04905         TRACEUSER( "Tim", _T("Using the cached font\n"));
04906         return TRUE;
04907     }
04908 
04909     // Cache is invalid - map the TrueType name to a PostScript font.
04910 
04911     // Get the typeface name of the font
04912     String_64 FontName;
04913     if (!FONTMANAGER->GetFontName(Typeface, FontName))
04914         return FALSE;
04915 
04916     // Transform to a INI-file friendly format
04917     String_64 Encoded;
04918     INT32 Styles = 0;
04919     if (Bold)
04920         Styles += 1;
04921     if (Italic)
04922         Styles += 2;
04923     FONTMANAGER->EncodeFontName(FontName, Encoded, Styles);
04924 
04925     // Look up font in INI file.
04926     String_256 MappedFontName;
04927     if (!Camelot.GetPrefDirect(_T("EPSFontMapping"), (TCHAR *) Encoded, &MappedFontName))
04928     {
04929         // No preference - map to Times-Roman variant
04930         if (Bold)
04931         {
04932             if (Italic)
04933                 MappedFontName.Load(_R(IDS_K_CAMEPS_MAPFNAMEBI));
04934             else
04935                 MappedFontName.Load(_R(IDS_K_CAMEPS_MAPFNAMEB));
04936         }
04937         else
04938         {
04939             if (Italic)
04940                 MappedFontName.Load(_R(IDS_K_CAMEPS_MAPFNAMEI));
04941             else
04942                 MappedFontName.Load(_R(IDS_K_CAMEPS_MAPFNAME));
04943         }           
04944     }
04945 
04946     // Due to inaccuracies, point sizes like 16pt come out as 15.999pt, so we check
04947     // for trailing digit errors and round to nearest integer point size if necessary.
04948     // (NB we have to use another variable for this otherwise the cache values don't match)
04949     MILLIPOINT CorrectedSize = Size;
04950     MILLIPOINT Remainder = Size % 1000;
04951     if ((Remainder <= 2) || (Remainder >= 998))
04952         // Lose the inaccuracy.
04953         CorrectedSize = ((Size + 500) / 1000) * 1000;
04954 
04955     // Select this font by prefixing with a forward slash to make it into a name.
04956     KernelDC *pKernelDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
04957     String_8 Slash(TEXT("/"));
04958     MappedFontName.Insert(Slash, 0);
04959     pKernelDC->OutputToken((TCHAR *) MappedFontName);
04960     pKernelDC->OutputUserSpaceValue(CorrectedSize);
04961     pKernelDC->OutputToken(_T("sf"));
04962 
04963     // Font cache is now valid
04964     FontInfo.Valid    = TRUE;
04965     FontInfo.Complex  = FALSE;
04966     FontInfo.Typeface = Typeface;
04967     FontInfo.Bold     = Bold;
04968     FontInfo.Italic   = Italic;
04969     FontInfo.Size     = Size;
04970     
04971 #endif
04972 
04973     // All ok
04974     return TRUE;    
04975 }

BOOL CamelotEPSRenderRegion::StartRender void   )  [virtual]
 

Prepare the render region for rendering (exporting).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Returns:
TRUE if worked, FALSE if failed.
See also:
EPSRenderRegion::Initialise; EPSRenderRegion::StopRender

Reimplemented from ArtWorksEPSRenderRegion.

Reimplemented in PrintPSRenderRegion.

Definition at line 3239 of file cameleps.cpp.

03240 {
03241     // (ChrisG 3/1/01) - We no longer write out the restore/save pair, so that multiple objects
03242     //  (both simple and complex) can be clipped together. This now works the same as the 
03243     //  printing (see PrintPSRenderRegion::StartRender)
03244 
03245     // This should only be done around areas where there is a possibility of the VM being 
03246     //  modified without our knowledge, e.g. when including EPS files inside this file, using
03247     //  third-party functions, etc..., and the save should be done immediately before the 
03248     //  suspect block, and the restore immediately after.
03249 
03250     // Call base class first
03251     if (!EPSRenderRegion::StartRender())
03252         return FALSE;
03253 
03254     InitAttributes ();
03255 
03256     return TRUE;
03257 }

BOOL CamelotEPSRenderRegion::StopRender void   )  [virtual]
 

Deinitialise the render region after rendering (exporting).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
See also:
EPSRenderRegion::Deinitialise; EPSRenderRegion::StartRender

Reimplemented from VectorFileRenderRegion.

Reimplemented in PrintPSRenderRegion.

Definition at line 3270 of file cameleps.cpp.

03271 {
03272     // (ChrisG 3/1/01) - We no longer write out the restore/save pair, so that multiple objects
03273     //  (both simple and complex) can be clipped together. This now works the same as the 
03274     //  printing (see CamelotEPSRenderRegion::StartRender for more info)
03275 
03276     if (!IS_A(this, NativeRenderRegion))
03277     {
03278         // Since we're clearing the the current attributes in the postscript file (using 
03279         //  restore), we'd better clear them in the exporter, so that they are re-exported
03280         //  if needed. NOTE: This only seems to affect font info.
03281 
03282         FontInfo.Valid = 0;
03283     }
03284 
03285     if (SepTables != NULL)
03286     {
03287         CCFree(SepTables);
03288         SepTables = NULL;
03289     }
03290 
03291     DeInitAttributes ();
03292 
03293     return TRUE;
03294 }

BOOL CamelotEPSRenderRegion::WriteEPSBoundingBox void   )  [protected, virtual]
 

Calls the base EPS bounding box function.

Author:
Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/5/00
Parameters:
- [INPUTS]
Returns:
TRUE if ok; FALSE if error (e.g. file/disk error or printer driver error)
See also:
EPSRenderRegion::WriteEPSBoundingBox

Reimplemented from ArtWorksEPSRenderRegion.

Definition at line 3887 of file cameleps.cpp.

03888 {
03889     // Call the base class function.
03890     return EPSRenderRegion::WriteEPSBoundingBox ();
03891 }

BOOL CamelotEPSRenderRegion::WriteEPSTrailerComments void   )  [protected, virtual]
 

Writes out an EPS trailer by calling the base class function.

Author:
Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/5/000
Parameters:
- [INPUTS]
Returns:
TRUE if ok; FALSE if error (e.g. file/disk error or printer driver error)
See also:
EPSRenderRegion::CloseDown

Reimplemented from ArtWorksEPSRenderRegion.

Definition at line 4024 of file cameleps.cpp.

04025 {
04026     // (ChrisG 3/1/01) - Output some code so that we stop using our dictionary, Since
04027     //  this is no longer controlled by Start- and StopRender, we have restore here. This should 
04028     //  be done to close the 'save-restore' block started in WriteSetup.
04029     KernelDC *pDC = (KernelDC*)CCDC::ConvertFromNativeDC(RenderDC);
04030     pDC->OutputToken(_T("end restore"));
04031     pDC->OutputNewLine();
04032 
04033     // Call the base class to over-ride the native render region version.
04034     return EPSRenderRegion::WriteEPSTrailerComments ();
04035 }

BOOL CamelotEPSRenderRegion::WriteNewLine void   )  [virtual]
 

Outputs a new line tag to the file.

Author:
Chris_Gallimore (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/11/00
Parameters:
- [INPUTS]
Returns:
TRUE - Success. FALSE - Failure.

Reimplemented from EPSRenderRegion.

Definition at line 5780 of file cameleps.cpp.

05781 {
05782     // Since the positions of the characters are explicitly given in the EPS file, newline
05783     //  (/r) characters are not required. And they 
05784     return TRUE;
05785 }

BOOL CamelotEPSRenderRegion::WriteProlog KernelDC pDC  )  [protected, virtual]
 

Output any PostScript prolog for this render region. For EPS and printing, this means output of our PostScript rendering procedures; for Native files we do nothing.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/04/95
Parameters:
pDC - the device context to output to. [INPUTS]
- [OUTPUTS]
Returns:
TRUE if ok; FALSE if error (e.g. file/disk error or printer driver error)
See also:
EPSRenderRegion::WriteSetup

Reimplemented from EPSRenderRegion.

Reimplemented in NativeRenderRegion, and PrintPSRenderRegion.

Definition at line 3910 of file cameleps.cpp.

03911 {
03912     // Get hold of our PostScript prolog resource...
03913     CCResTextFile PrologFile;
03914 
03915     // Open the file
03916     if (!PrologFile.open(_R(IDM_PS_PROLOG), _R(IDT_PS_RES)))
03917     {
03918         // Failed to open the file...
03919         ERROR2(FALSE, "Could not get at PostScript resource!");
03920     } 
03921 
03922     // Put some comments out to mark our procset
03923     pDC->OutputNewLine();
03924     pDC->OutputToken(_T("%%BeginResource: procset XaraStudio1Dict"));
03925     pDC->OutputNewLine();
03926     pDC->OutputToken(_T("% Copyright (c) 1995,1996 Xara Ltd"));
03927     pDC->OutputNewLine();
03928 
03929     // Start a new dictionary to avoid clashes...
03930     pDC->OutputToken(_T("/XaraStudio1Dict 300 dict def XaraStudio1Dict begin"));
03931     pDC->OutputNewLine();
03932 
03933     // Read each line from the file and output it to the DC.
03934     String_256 LineBuf;
03935     TCHAR *pBuf = (TCHAR *) LineBuf;
03936 
03937     while (!PrologFile.read(&LineBuf).eof())
03938     {
03939         // Copy this line to output.
03940         pDC->OutputTCHARAsChar(pBuf, LineBuf.Length());
03941         pDC->OutputNewLine();
03942     }
03943 
03944     // All done
03945     PrologFile.close();
03946 
03947     // Write out any separation functions in this prolog if we
03948     // need to. Note this is a bool function
03949     WriteSepFunctions(pDC);
03950 
03951     // Put some comments/code out to mark our procset end
03952     pDC->OutputToken(_T("end"));
03953     pDC->OutputNewLine();
03954     pDC->OutputToken(_T("%%EndResource"));
03955     pDC->OutputNewLine();
03956 
03957     return TRUE;
03958 }

BOOL CamelotEPSRenderRegion::WriteSetup KernelDC pDC  )  [protected, virtual]
 

Output any PostScript setup for this render region. For EPS and printing, this means output of our PostScript code to initialise the context for rendering; for Native files we do nothing.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/04/95
Parameters:
pDC - the device context to output to. [INPUTS]
- [OUTPUTS]
Returns:
TRUE if ok; FALSE if error (e.g. file/disk error or printer driver error)
See also:
EPSRenderRegion::WriteSetup

Reimplemented from EPSRenderRegion.

Reimplemented in NativeRenderRegion, and PrintPSRenderRegion.

Definition at line 3977 of file cameleps.cpp.

03978 {
03979     // Get hold of our PostScript setup resource...
03980     CCResTextFile SetupFile;
03981 
03982     // Open the file
03983     if (!SetupFile.open(_R(IDM_PS_SETUP), _R(IDT_PS_RES)))
03984     {
03985         // Failed to open the file...
03986         ERROR2(FALSE, "Could not get at PostScript resource!");
03987     } 
03988 
03989     // Output some code so that we use our dictionary
03990     pDC->OutputToken(_T("save XaraStudio1Dict begin"));
03991     pDC->OutputNewLine();
03992 
03993     // Read each line from the file and output it to the DC.
03994     String_256 LineBuf;
03995     TCHAR *pBuf = (TCHAR *) LineBuf;
03996 
03997     while (!SetupFile.read(&LineBuf).eof())
03998     {
03999         // Copy this line to output.
04000         pDC->OutputTCHARAsChar(pBuf, LineBuf.Length());
04001         pDC->OutputNewLine();
04002     }
04003 
04004     // All done
04005     SetupFile.close();
04006 
04007     return TRUE;
04008 }


Member Data Documentation

EPSFontCache CamelotEPSRenderRegion::FontInfo [protected]
 

Definition at line 433 of file cameleps.h.

BYTE* CamelotEPSRenderRegion::SepTables [protected]
 

Definition at line 440 of file cameleps.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:51:46 2007 for Camelot by  doxygen 1.4.4