#include <cameleps.h>
Inheritance diagram for CamelotEPSRenderRegion:
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 |
Definition at line 375 of file cameleps.h.
|
Initialise a render region for exporting Camelot EPS. Sets up the string to put in the %Creator comment.
Definition at line 3194 of file cameleps.cpp. 03197 : ArtWorksEPSRenderRegion(ClipRect, ConvertMatrix, ViewScale) 03198 { 03199 CreatorString = _T("Xara X"); 03200 03201 SepTables = NULL; 03202 }
|
|
destructor
Definition at line 3216 of file cameleps.cpp. 03217 { 03218 if (SepTables != NULL) 03219 { 03220 CCFree(SepTables); 03221 SepTables = NULL; 03222 } 03223 }
|
|
Copies the scanline of 24bpp RGB values from SrcBuffer to DestBuffer, running the pixels through colour separation tables en route.
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 }
|
|
Doesn't delete the object when invoked. This is to get around using a few if IS_A calls elsewhere in Camelot.
Reimplemented from RenderRegion. Reimplemented in NativeRenderRegion, and PrintPSRenderRegion. Definition at line 4846 of file cameleps.cpp.
|
|
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).
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 }
|
|
Plots the bitmap using the mask supplied.
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 }
|
|
Plot an arbitrarily transformed bitmap in the position specified.
Coords[0] Coords[1] +---------------+ | | | | | | | | +---------------+ Coords[3] Coords[2]
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 }
|
|
Output all the commands required to render this path to the EPS file.
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 }
|
|
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!).
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 }
|
|
Return the state of the current fill effect in the EPS attributes stack.
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 }
|
|
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.
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 }
|
|
See EPSRenderRegion::GetValidPathAttributes. This version checks and handles grad fill colours before calling the base class version.
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 }
|
|
Lets the print component class know that they are needed in this format's export.
Definition at line 4864 of file cameleps.cpp. 04865 { 04866 // We want print components! 04867 return TRUE; 04868 }
|
|
This simply calls EPSRenderRegion::OutputFillColour, otherwise this render region uses the overridden version found in ArtWorksEPSRenderRegion.
Reimplemented from ArtWorksEPSRenderRegion. Reimplemented in NativeRenderRegion. Definition at line 5822 of file cameleps.cpp. 05823 { 05824 EPSRenderRegion::OutputFillColour (); 05825 }
|
|
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 }
|
|
This simply calls EPSRenderRegion::OutputStrokeColour, as otherwise the ArtWorks version is used (which can't cope with the RGB colour tokens).
Reimplemented from ArtWorksEPSRenderRegion. Reimplemented in NativeRenderRegion. Definition at line 5802 of file cameleps.cpp. 05803 { 05804 EPSRenderRegion::OutputStrokeColour (); 05805 }
|
|
Render a character, using the specified transform and current attributes in the render region.
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 }
|
|
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 }
|
|
Get the font name being used by the Camelot EPS exporter.
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 }
|
|
Prepare the render region for rendering (exporting).
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 }
|
|
Deinitialise the render region after rendering (exporting).
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 }
|
|
Calls the base EPS bounding box function.
Reimplemented from ArtWorksEPSRenderRegion. Definition at line 3887 of file cameleps.cpp. 03888 { 03889 // Call the base class function. 03890 return EPSRenderRegion::WriteEPSBoundingBox (); 03891 }
|
|
Writes out an EPS trailer by calling the base class function.
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 }
|
|
Outputs a new line tag to the file.
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 }
|
|
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.
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 }
|
|
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.
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 }
|
|
Definition at line 433 of file cameleps.h. |
|
Definition at line 440 of file cameleps.h. |