00001 // $Id: psrndrgn.cpp 1365 2006-06-25 20:29:01Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 // Render region for rendering to PostScript devices. 00100 00101 /* 00102 */ 00103 00104 #include "camtypes.h" 00105 00106 #include "psrndrgn.h" 00107 #include "psdc.h" 00108 #include "page.h" 00109 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 #include "textfuns.h" 00113 #include "devcolor.h" 00114 #include "camelot.h" 00115 #include "colplate.h" 00116 //#include "isetres.h" 00117 //#include "tim.h" 00118 #include "oilfiles.h" 00119 #include "unicdman.h" //For MBCS support 00120 //#include "xaracms.h" 00121 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00122 #include "printctl.h" 00123 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00124 00125 DECLARE_SOURCE("$Revision: 1365 $"); 00126 00127 CC_IMPLEMENT_DYNAMIC(PrintPSRenderRegion, CamelotEPSRenderRegion) 00128 00129 #define new CAM_DEBUG_NEW 00130 00131 00132 /******************************************************************************************** 00133 00134 > PrintPSRenderRegion(DocRect ClipRect, Matrix ConvertMatrix, FIXED16 ViewScale) 00135 00136 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00137 Created: 15/04/94 00138 Purpose: Initialise a render region for printing PostScript. 00139 SeeAlso: CamelotEPSRenderRegion::CamelotEPSRenderRegion 00140 00141 ********************************************************************************************/ 00142 00143 PrintPSRenderRegion::PrintPSRenderRegion(DocRect ClipRect, 00144 Matrix ConvertMatrix, 00145 FIXED16 ViewScale) 00146 : CamelotEPSRenderRegion(ClipRect, ConvertMatrix, ViewScale) 00147 { 00148 // We're a printing render region. 00149 RenderFlags.Printing = TRUE; 00150 } 00151 00152 /******************************************************************************************** 00153 00154 > PrintPSRenderRegion::~PrintPSRenderRegion() 00155 00156 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00157 Created: 15/04/94 00158 Purpose: Delete the region, flushing the PostScript output DC beforehand. 00159 SeeAlso: PSPrintDC::Flush 00160 00161 ********************************************************************************************/ 00162 00163 PrintPSRenderRegion::~PrintPSRenderRegion() 00164 { 00165 PSPrintDC *pPSPrintDC = (PSPrintDC *) CCDC::ConvertFromNativeDC(RenderDC); 00166 00167 // Restore OS context - just pretend we want to do some OS output 00168 pPSPrintDC->StartOSOutput(); 00169 00170 // Flush the DC 00171 pPSPrintDC->FlushDC(); 00172 00173 pPSPrintDC->EndOSOutput(); 00174 00175 // Karim 06/06/2000 - free the memory! (hope this doesn't blow up something else...) 00176 // AB: Don't do this. RenderRegion's destructor deletes RenderDC 00177 // delete pPSPrintDC; 00178 // pPSPrintDC = NULL; 00179 } 00180 00181 00182 00183 /******************************************************************************************** 00184 00185 > BOOL PrintPSRenderRegion::InitDevice() 00186 00187 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00188 Created: 27/05/94 00189 Returns: TRUE if the device context is initialised ok; 00190 FALSE if not. 00191 Purpose: Initialise the device specific mechanisms for this render region. 00192 For a PrintPSRenderRegion we need to change the DC slightly - we use the 00193 existing RenderDC to make a PSPrintDC, which allows us to output PostScript 00194 directly to the device. 00195 Errors: Same as base class. 00196 SeeAlso: RenderRegion::InitDevice 00197 00198 ********************************************************************************************/ 00199 00200 BOOL PrintPSRenderRegion::InitDevice() 00201 { 00202 // Ensure the current DC is suitable for postscript rendering 00203 00204 CCDC *pCCDC = CCDC::ConvertFromNativeDC( RenderDC ); 00205 ERROR2IF(!pCCDC || !pCCDC->IsKindOf(CC_RUNTIME_CLASS(PSPrintDC)), FALSE, "Trying to InitDevice on a non-Postscript CCDC"); 00206 00207 PSPrintDC *pPSPrintDC = (PSPrintDC *) pCCDC; 00208 00209 pPSPrintDC->SetDCTransforms(RenderMatrix, RenderView); 00210 00211 // Call base class - note that unlike other InitDevice() implementations, we don't 00212 // call this as the very first thing in the function - this is because we need to switch 00213 // the DC beforehand, as seen above. 00214 if (!RenderRegion::InitDevice()) 00215 return FALSE; 00216 00217 // Find out what this region can do 00218 GetRenderRegionCaps(&Caps); 00219 00220 // All ok 00221 return TRUE; 00222 } 00223 00224 /******************************************************************************************** 00225 00226 > BOOL PrintPSRenderRegion::StartRender() 00227 00228 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00229 Created: 30/03/94 00230 Returns: TRUE if worked, FALSE if failed. 00231 Purpose: Prepare the render region for rendering (exporting). 00232 SeeAlso: EPSRenderRegion::Initialise; EPSRenderRegion::StopRender 00233 00234 ********************************************************************************************/ 00235 00236 BOOL PrintPSRenderRegion::StartRender() 00237 { 00238 // If we are being restarted, reinstate our dictionary on the stack 00239 // BOOL Restarted = RenderFlags.ValidDevice; 00240 00241 // Call base class first 00242 if (!EPSRenderRegion::StartRender()) 00243 return FALSE; 00244 00245 // Attach the DC to this render region. 00246 PSPrintDC *pPSPrintDC = (PSPrintDC *) CCDC::ConvertFromNativeDC(RenderDC); 00247 pPSPrintDC->SetDCTransforms(RenderMatrix, RenderView); 00248 pPSPrintDC->AttachRenderRegion(this); 00249 00250 Initialise(); 00251 00252 return TRUE; 00253 } 00254 00255 00256 00257 /******************************************************************************************** 00258 00259 > BOOL PrintPSRenderRegion::StopRender() 00260 00261 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00262 Created: 11/5/93 00263 Inputs: RenderState is a Node* pointing at the current rendering node in the tree, 00264 or NULL if all objects rendered. 00265 Purpose: Stops the rendering of a OSRenderRegion, saving it's current renderstate so 00266 that rendering can continue where it left off, later on. If the RenderState 00267 passed is NULL then the RenderRegion will be unlinked from the list and will 00268 then delete itself. 00269 SeeAlso: OSRenderRegion::StartRender() 00270 00271 ********************************************************************************************/ 00272 00273 BOOL PrintPSRenderRegion::StopRender() 00274 { 00275 // Call base class 00276 BOOL bHaveRendered = EPSRenderRegion::StopRender(); 00277 00278 // Flush our buffered PostScript device context. 00279 PSPrintDC *pPSPrintDC = (PSPrintDC *) CCDC::ConvertFromNativeDC(RenderDC); 00280 pPSPrintDC->FlushDC(); 00281 00282 // Detach the DC from this render region. 00283 pPSPrintDC->DetachRenderRegion(); 00284 00285 return bHaveRendered; 00286 } 00287 00288 /******************************************************************************************** 00289 00290 > BOOL PrintPSRenderRegion::CloseDown() 00291 00292 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00293 Created: 05/09/95 00294 Returns: TRUE (always) 00295 Purpose: Close down a PostScript render region - in fact we do nothing as the 00296 printer driver is responsible for tidying up, and we will already have 00297 cleared our dictionary from the dict stack in StopRender() 00298 SeeAlso: CamelotEPSRenderRegion::StopRender 00299 00300 ********************************************************************************************/ 00301 00302 BOOL PrintPSRenderRegion::CloseDown() 00303 { 00304 // Do nothing - the printer driver should do it all for us... 00305 return TRUE; 00306 } 00307 00308 /******************************************************************************************** 00309 00310 > virtual void PrintPSRenderRegion::ConditionalSuicide ( void ) 00311 00312 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00313 Created: 24/2/00 00314 Inputs: - 00315 Returns: - 00316 Purpose: Causes the object to commit suicide. This is to get around using a few 00317 if IS_A calls elsewhere in Camelot. 00318 00319 ********************************************************************************************/ 00320 00321 void PrintPSRenderRegion::ConditionalSuicide ( void ) 00322 { 00323 // Delete the object. 00324 delete this; 00325 } 00326 00327 /******************************************************************************************** 00328 00329 > BOOL PrintPSRenderRegion::WriteProlog(KernelDC *pDC) 00330 00331 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00332 Created: 24/04/95 00333 Inputs: pDC - the device context to output to. 00334 Outputs: - 00335 Returns: TRUE if ok; 00336 FALSE if error (e.g. file/disk error or printer driver error) 00337 Purpose: Output any PostScript prolog for this render region. For EPS and printing, 00338 this means output of our PostScript rendering procedures; for Native 00339 files we do nothing. 00340 SeeAlso: EPSRenderRegion::WriteSetup 00341 00342 ********************************************************************************************/ 00343 00344 BOOL PrintPSRenderRegion::WriteProlog(KernelDC *pDC) 00345 { 00346 // Call base class to output our dictionary 00347 if (!CamelotEPSRenderRegion::WriteProlog(pDC)) 00348 // Error 00349 return FALSE; 00350 00351 // All done 00352 return TRUE; 00353 } 00354 00355 /******************************************************************************************** 00356 00357 > BOOL PrintPSRenderRegion::WriteSetup(KernelDC *pDC) 00358 00359 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00360 Created: 24/04/95 00361 Inputs: pDC - the device context to output to. 00362 Outputs: - 00363 Returns: TRUE if ok; 00364 FALSE if error (e.g. file/disk error or printer driver error) 00365 Purpose: Output any PostScript setup for this render region. For EPS and printing, 00366 this means output of our PostScript code to initialise the context for 00367 rendering; for Native files we do nothing. 00368 SeeAlso: EPSRenderRegion::WriteSetup 00369 00370 ********************************************************************************************/ 00371 00372 BOOL PrintPSRenderRegion::WriteSetup(KernelDC *pDC) 00373 { 00374 // Call base class to output our setup code 00375 if (!CamelotEPSRenderRegion::WriteSetup(pDC)) 00376 // Error 00377 return FALSE; 00378 00379 // All ok 00380 return TRUE; 00381 } 00382 00383 00384 /******************************************************************************************** 00385 00386 > virtual BOOL PrintPSRenderRegion::WriteSepTables(KernelDC *pDC) 00387 00388 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00389 Created: 19/06/96 00390 Inputs: pDC - the device context to output to. 00391 Outputs: - 00392 Returns: TRUE if ok; 00393 FALSE if error (e.g. file/disk error or printer driver error) 00394 Purpose: Output the current set of device printer profiles as Postscript hex 00395 arrays. Our Postscript prolog functions will use these arrays when 00396 creating separations. (if we are not separating, we do nothing) 00397 SeeAlso: 00398 00399 ********************************************************************************************/ 00400 00401 BOOL PrintPSRenderRegion::WriteSepTables(KernelDC *pDC) 00402 { 00403 ColourContext* pContext; 00404 ColourPlate* pSeparation; 00405 GetOutputColourPlate(COLOURMODEL_CMYK, &pContext, &pSeparation); 00406 00407 // Note, we return true to all but the token output 00408 // functions. We will terminate the output only if 00409 // we receive a disc failure. 00410 00411 // do nothing if we are not separating 00412 if (pSeparation==NULL) 00413 return TRUE; 00414 00415 // check that we've got a colour context attached to us. 00416 if (pContext==NULL) 00417 { 00418 ERROR3("There is no current colour context in this render region!"); 00419 return TRUE; 00420 } 00421 00422 // Whip out the physical tables we will use to separate. 00423 BYTE Table[5*256]; 00424 if (!pContext->GetProfileTables(Table)) 00425 return TRUE; 00426 00427 // output cyan 00428 BOOL ok = pDC->OutputToken(_T("/ccurve [")); 00429 ok = ok && WriteSepTablesHelper(pDC, Table); 00430 ok = ok && pDC->OutputToken(_T("] def")); 00431 ok = ok && pDC->OutputNewLine(); 00432 00433 // output magenta 00434 ok = ok && pDC->OutputToken(_T("/mcurve [")); 00435 ok = ok && WriteSepTablesHelper(pDC, Table+256); 00436 ok = ok && pDC->OutputToken(_T("] def")); 00437 ok = ok && pDC->OutputNewLine(); 00438 00439 // output yellow 00440 ok = ok && pDC->OutputToken(_T("/ycurve [")); 00441 ok = ok && WriteSepTablesHelper(pDC, Table+512); 00442 ok = ok && pDC->OutputToken(_T("] def")); 00443 ok = ok && pDC->OutputNewLine(); 00444 00445 // output ucr 00446 ok = ok && pDC->OutputToken(_T("/ucurve [")); 00447 ok = ok && WriteSepTablesHelper(pDC, Table+768); 00448 ok = ok && pDC->OutputToken(_T("] def")); 00449 ok = ok && pDC->OutputNewLine(); 00450 00451 // output black generation 00452 ok = ok && pDC->OutputToken(_T("/bcurve [")); 00453 ok = ok && WriteSepTablesHelper(pDC, Table+1024); 00454 ok = ok && pDC->OutputToken(_T("] def")); 00455 ok = ok && pDC->OutputNewLine(); 00456 00457 // Enable separations 00458 ok = ok && pDC->OutputToken(_T("1 setseps")); 00459 ok = ok && pDC->OutputNewLine(); 00460 00461 // Is this a mono plate? 00462 BOOL mono = pSeparation->IsMonochrome(); 00463 00464 // find what type of separation plate we are using 00465 ColourPlateType Type = pSeparation->GetType(); 00466 switch (Type) 00467 { 00468 case COLOURPLATE_CYAN: 00469 ok = ok && pDC->OutputToken(_T("v_cpcy setplate")); 00470 ok = ok && pDC->OutputNewLine(); 00471 break; 00472 case COLOURPLATE_MAGENTA: 00473 ok = ok && pDC->OutputToken(_T("v_cpmg setplate")); 00474 ok = ok && pDC->OutputNewLine(); 00475 break; 00476 case COLOURPLATE_YELLOW: 00477 ok = ok && pDC->OutputToken(_T("v_cpyl setplate")); 00478 ok = ok && pDC->OutputNewLine(); 00479 break; 00480 case COLOURPLATE_KEY: 00481 ok = ok && pDC->OutputToken(_T("v_cpky setplate")); 00482 ok = ok && pDC->OutputNewLine(); 00483 break; 00484 case COLOURPLATE_SPOT: 00485 // Force mono to be true here, all spot colour will 00486 // be going out as weights of key, and hence are 00487 // really the same as mono c,m,y,k 00488 mono=TRUE; 00489 break; 00490 default: 00491 ERROR3("What kind of a plate is that?"); 00492 break; 00493 00494 } 00495 00496 // Output the mono setting. This determins whether our postscript 00497 // colour fill and stroke functions will set colour using the 00498 // setgray function or setcmyk 00499 if (mono) 00500 ok = ok && pDC->OutputToken(_T("1 setmono")); 00501 else 00502 ok = ok && pDC->OutputToken(_T("0 setmono")); 00503 ok = ok && pDC->OutputNewLine(); 00504 00505 // All ok 00506 return ok; 00507 } 00508 00509 00510 /******************************************************************************************** 00511 00512 > BOOL PrintPSRenderRegion::WriteSepTablesHelper(KernelDC *pDC, BYTE* Table) 00513 00514 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00515 Created: 19/06/96 00516 Inputs: pDC - the device context to output to. 00517 Table = a pointer to a 256 byte entry table 00518 Outputs: - 00519 Returns: TRUE if ok; 00520 FALSE if error (e.g. file/disk error or printer driver error) 00521 Purpose: Output the table of 256 values to the output stream 00522 00523 ********************************************************************************************/ 00524 00525 BOOL PrintPSRenderRegion::WriteSepTablesHelper(KernelDC *pDC, BYTE* Table) 00526 { 00527 BOOL ok; 00528 UINT32 val; 00529 for (INT32 i=0; i<256; i++) 00530 { 00531 val = (UINT32) (Table[i]); 00532 ok = pDC->OutputValue(val); 00533 if (!ok) 00534 return FALSE; 00535 } 00536 return TRUE; 00537 } 00538 00539 00540 00541 /******************************************************************************************** 00542 00543 > BOOL PrintPSRenderRegion::WritePlateName(KernelDC *pDC) 00544 00545 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00546 Created: 24/06/96 00547 Inputs: pDC - the device context to output to. 00548 Outputs: - 00549 Returns: TRUE if ok; 00550 FALSE if error (e.g. file/disk error or printer driver error) 00551 Purpose: Output the current plate name for this print separation, if there is one. 00552 00553 ********************************************************************************************/ 00554 00555 BOOL PrintPSRenderRegion::WritePlateName(KernelDC *pDC) 00556 { 00557 ColourPlate* pSeparation; 00558 GetOutputColourPlate(COLOURMODEL_CMYK, NULL, &pSeparation); 00559 00560 // do nothing if we are not separating 00561 if (pSeparation==NULL) 00562 return TRUE; 00563 00564 // Get and output the plate name, cheers 00565 String_64 platename; 00566 pSeparation->GetDescription(&platename); 00567 TCHAR* pPlate = (TCHAR*)platename; 00568 // ok output the textural name 00569 BOOL ok = pDC->OutputToken(_T("%%PlateColor :")); 00570 ok = ok && pDC->OutputToken(pPlate); 00571 ok = ok && pDC->OutputNewLine(); 00572 00573 return ok; 00574 } 00575 00576 00577 00578 00579 /******************************************************************************************** 00580 00581 > BOOL PrintPSRenderRegion::WritePlateScreen(KernelDC *pDC) 00582 00583 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00584 Created: 24/06/96 00585 Inputs: pDC - the device context to output to. 00586 Outputs: - 00587 Returns: TRUE if ok; 00588 FALSE if error (e.g. file/disk error or printer driver error) 00589 Purpose: Output the setscreen function for this plate. 00590 00591 ********************************************************************************************/ 00592 00593 BOOL PrintPSRenderRegion::WritePlateScreen(KernelDC *pDC) 00594 { 00595 PrintControl *pPrintCtl=NULL; 00596 View *pView = GetRenderView(); 00597 if (pView) pPrintCtl = pView->GetPrintControl(); 00598 if (!pPrintCtl) 00599 return TRUE; 00600 00601 // Get a pointer to the typeset info structure 00602 TypesetInfo *pInfo = pPrintCtl->GetTypesetInfo(); 00603 00604 double ang,freq; 00605 String_256 ScreenName; 00606 ScreenType scrtype; 00607 00608 // If separating then interogate the current plate 00609 if (pInfo->AreSeparating()) 00610 { 00611 ColourPlate* pSeparation; 00612 GetOutputColourPlate(COLOURMODEL_CMYK, NULL, &pSeparation); 00613 00614 // do nothing if we are not separating 00615 if (pSeparation==NULL) 00616 return TRUE; 00617 00618 // Make sure screening is on in this plate 00619 if (!pSeparation->ActiveScreening()) 00620 return TRUE; 00621 00622 // Get the screen type if enabled. 00623 scrtype = pSeparation->GetScreenFunction(); 00624 if (scrtype==SCRTYPE_NONE) 00625 return TRUE; 00626 00627 // ok we can get the angle and frequency 00628 ang = pSeparation->GetScreenAngle(); 00629 freq = pSeparation->GetScreenFrequency(); 00630 } 00631 else 00632 { 00633 // Is screening off? 00634 if (!pInfo->AreScreening()) 00635 return TRUE; 00636 00637 scrtype = pInfo->GetScreenFunction(); 00638 if (scrtype==SCRTYPE_NONE) 00639 return TRUE; 00640 00641 ang = 45.0; 00642 freq = pInfo->GetDefaultScreenFrequency(); 00643 } 00644 00645 // read the name of this screen 00646 pInfo->GetScreenName(scrtype, &ScreenName); 00647 00648 String_256 fred; 00649 fred += String_8(_T("{")); 00650 fred += ScreenName; 00651 fred += String_8(_T("}")); 00652 00653 // ok output 'freq ang screenfunc setscreen' 00654 BOOL ok = pDC->OutputFloat(freq, 4); 00655 ok = ok && pDC->OutputFloat(ang, 4); 00656 ok = ok && pDC->OutputToken(fred); 00657 ok = ok && pDC->OutputToken(_T("setscreen")); 00658 ok = ok && pDC->OutputNewLine(); 00659 00660 return ok; 00661 } 00662 00663 00664 00665 /******************************************************************************************** 00666 00667 > BOOL PrintPSRenderRegion::WriteSepFunctions(KernelDC *pDC) 00668 00669 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00670 Created: 26/06/96 00671 Inputs: pDC - the device context to output to. 00672 Outputs: - 00673 Returns: TRUE if ok; 00674 FALSE if error (e.g. file/disk error or printer driver error) 00675 Purpose: Output the setscreen functions file for this separation. 00676 SeeAlso: WriteProlog 00677 00678 ********************************************************************************************/ 00679 00680 BOOL PrintPSRenderRegion::WriteSepFunctions(KernelDC *pDC) 00681 { 00682 PrintControl *pPrintCtl=NULL; 00683 View *pView = GetRenderView(); 00684 if (pView) pPrintCtl = pView->GetPrintControl(); 00685 if (!pPrintCtl) 00686 return TRUE; 00687 00688 // Get a pointer to the typeset info structure 00689 TypesetInfo *pInfo = pPrintCtl->GetTypesetInfo(); 00690 // Is screening off? 00691 if (!pInfo->AreScreening()) 00692 return TRUE; 00693 00694 // Get hold of our PostScript prolog resource... 00695 CCResTextFile ScreenFile; 00696 00697 // Open the file 00698 if (!ScreenFile.open(_R(IDM_PS_SPOTFUNCS), _R(IDT_PS_RES))) 00699 { 00700 // Failed to open the file... 00701 ERROR2(FALSE, "Could not get at PostScript resource!"); 00702 } 00703 00704 // Read each line from the file and output it to the DC. 00705 String_256 LineBuf; 00706 TCHAR *pBuf = (TCHAR *) LineBuf; 00707 00708 while (!ScreenFile.eof()) 00709 { 00710 // Copy this line to output. 00711 ScreenFile.read(&LineBuf); 00712 pDC->OutputTCHARAsChar(pBuf, LineBuf.Length()); 00713 pDC->OutputNewLine(); 00714 } 00715 00716 // All done 00717 ScreenFile.close(); 00718 00719 return TRUE; 00720 } 00721 00722 00723 00724 00725 /******************************************************************************************** 00726 00727 > BOOL PrintPSRenderRegion::PushClipRegion(KernelDC *pDC, const DocRect& Rect) 00728 00729 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00730 Created: 02/09/96 00731 Inputs: pDC - the device context to output to. 00732 Rect - the clipping rect to create. 00733 Outputs: - 00734 Returns: TRUE if ok; 00735 FALSE if error (e.g. file/disk error or printer driver error) 00736 Purpose: Stack the PostScript clipping rectangle. The clipping rectangle will be 00737 active until our context is reset. 00738 SeeAlso: PopClipRegion 00739 00740 ********************************************************************************************/ 00741 00742 BOOL PrintPSRenderRegion::PushClipRegion(KernelDC *pDC, const DocRect& Rect) 00743 { 00744 BOOL ok = pDC->OutputToken(_T("gs")); 00745 ok = ok && pDC->OutputNewLine(); 00746 ok = ok && WriteClipRegion(pDC,Rect); 00747 return ok; 00748 } 00749 00750 00751 /******************************************************************************************** 00752 00753 > BOOL PrintPSRenderRegion::PopClipRegion(KernelDC *pDC) 00754 00755 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00756 Created: 02/09/96 00757 Inputs: pDC - the device context to output to. 00758 Outputs: - 00759 Returns: TRUE if ok; 00760 FALSE if error (e.g. file/disk error or printer driver error) 00761 Purpose: Unstack the current PostScript clip region. We simply pop the graphics state 00762 here to return to the previous clipping region. 00763 SeeAlso: PushClipRegion 00764 00765 ********************************************************************************************/ 00766 00767 BOOL PrintPSRenderRegion::PopClipRegion(KernelDC *pDC) 00768 { 00769 BOOL ok = pDC->OutputToken(_T("gr")); 00770 ok = ok && pDC->OutputNewLine(); 00771 return ok; 00772 } 00773 00774 00775 00776 00777 /******************************************************************************************** 00778 00779 > BOOL PrintPSRenderRegion::WriteClipRegion(KernelDC *pDC, const DocRect& Rect) 00780 00781 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00782 Created: 02/09/96 00783 Inputs: pDC - the device context to output to. 00784 Rect - the clipping rect to create. 00785 Outputs: - 00786 Returns: TRUE if ok; 00787 FALSE if error (e.g. file/disk error or printer driver error) 00788 Purpose: Set up a PostScript clipping rectangle. The clipping rectangle will be 00789 active until our context is reset. 00790 00791 ********************************************************************************************/ 00792 00793 BOOL PrintPSRenderRegion::WriteClipRegion(KernelDC *pDC, const DocRect& Rect) 00794 { 00795 if (!Rect.IsValid() || Rect.IsEmpty()) 00796 return TRUE; 00797 00798 DocCoord c0,c1; 00799 c0=Rect.lo; 00800 c1=Rect.hi; 00801 BOOL ok = pDC->OutputCoord(c0); 00802 ok = ok && pDC->OutputCoord(c1); 00803 ok = ok && pDC->OutputToken(TEXT("Cp")); 00804 ok = ok && pDC->OutputNewLine(); 00805 00806 return ok; 00807 } 00808 00809 00810 /******************************************************************************************** 00811 00812 > BOOL PrintPSRenderRegion::WritePhotoNegative(KernelDC *pDC) 00813 00814 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00815 Created: 29/08/96 00816 Inputs: pDC - the device context to output to. 00817 Outputs: - 00818 Returns: TRUE if ok; 00819 FALSE if error (e.g. file/disk error or printer driver error) 00820 Purpose: Start photo negative rendering. All rendering will be photo-negated. 00821 00822 ********************************************************************************************/ 00823 00824 BOOL PrintPSRenderRegion::WritePhotoNegative(KernelDC *pDC) 00825 { 00826 /* 00827 ColourPlate* pSeparation; 00828 GetOutputColourPlate(COLOURMODEL_CMYK, NULL, &pSeparation); 00829 00830 // do nothing if we are not separating 00831 if (pSeparation==NULL) 00832 return TRUE; 00833 00834 // if this plate says negative lets do it 00835 if (pSeparation->IsEPSNegative()) 00836 return WriteSetTransfer(pDC); 00837 */ 00838 // Find the print control structure. 00839 PrintControl *pControl = GetRenderView()->GetPrintControl(); 00840 if (pControl) 00841 { 00842 TypesetInfo *pTypeset = pControl->GetTypesetInfo(); 00843 if (pTypeset && pTypeset->PrintPhotoNegative()) 00844 return WriteSetTransfer(pDC); 00845 } 00846 00847 return TRUE; 00848 } 00849 00850 BOOL PrintPSRenderRegion::WriteSetTransfer(KernelDC *pDC) 00851 { 00852 BOOL ok = pDC->OutputToken(_T("{1 exch sub} settransfer")); 00853 ok = ok && pDC->OutputNewLine(); 00854 return ok; 00855 } 00856 00857 00858 /******************************************************************************************** 00859 00860 > BOOL PrintPSRenderRegion::WriteRenderPaper(KernelDC *pDC) 00861 00862 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00863 Created: 29/08/96 00864 Inputs: pDC - the device context to output to. 00865 Outputs: - 00866 Returns: TRUE if ok; 00867 FALSE if error (e.g. file/disk error or printer driver error) 00868 Purpose: Fill the entire renderable area with white 00869 00870 ********************************************************************************************/ 00871 00872 BOOL PrintPSRenderRegion::WriteRenderPaper(KernelDC *pDC) 00873 { 00874 /* 00875 ColourPlate* pSeparation; 00876 GetOutputColourPlate(COLOURMODEL_CMYK, NULL, &pSeparation); 00877 00878 // do nothing if we are not separating 00879 if (pSeparation==NULL) 00880 return TRUE; 00881 00882 // if this plate says negative lets do it 00883 if (pSeparation->IsEPSNegative()) 00884 return WriteFillPaper(pDC); 00885 */ 00886 // Find the print control structure. 00887 PrintControl *pControl = GetRenderView()->GetPrintControl(); 00888 if (pControl) 00889 { 00890 TypesetInfo *pTypeset = pControl->GetTypesetInfo(); 00891 if (pTypeset && pTypeset->PrintPhotoNegative()) 00892 return WriteFillPaper(pDC); 00893 } 00894 00895 return TRUE; 00896 } 00897 00898 00899 BOOL PrintPSRenderRegion::WriteFillPaper(KernelDC *pDC) 00900 { 00901 BOOL ok = pDC->OutputToken(_T("gsave clippath 1 setgray fill grestore")); 00902 ok = ok && pDC->OutputNewLine(); 00903 return ok; 00904 } 00905 00906 00907 00908 00909 00910 00911 00912 /******************************************************************************************** 00913 00914 > BOOL PrintPSRenderRegion::OutputPSHeader() 00915 00916 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> & JustinF 00917 Created: 04/29/95 00918 Returns: TRUE if ok; 00919 FALSE if file/printer error occured. 00920 Purpose: Output the PostScript header that Camelot needs in order for its PostScript 00921 code to work. NB. the original version of this function has been commented 00922 out and moved to the end of this source file. 00923 00924 ********************************************************************************************/ 00925 00926 BOOL PrintPSRenderRegion::OutputPSHeader() 00927 { 00928 PORTNOTE("printing", "Don't output strange rectangles") 00929 #ifndef EXCLUDE_FROM_XARALX 00930 // If running under Win95 or Win31, but not any flavour of WinNT, then begin with some 00931 // fake GDI output to force the buggy Postscript driver to flush its output buffer. 00932 if (IsWin32s()) 00933 { 00934 // Justin says: please *don't* change this to *anything* else until you've 00935 // spoken to me or Phil. 00936 CBrush br; 00937 br.CreateStockObject(WHITE_BRUSH); 00938 CBrush* pOldBr = RenderDC->SelectObject(&br); 00939 00940 CPen pn; 00941 pn.CreateStockObject(WHITE_PEN); 00942 CPen* pOldPn = RenderDC->SelectObject(&pn); 00943 00944 // Draw a tiny white rectangle with a white outline. 00945 TRACEUSER( "JustinF", _T("Postscript pixel fix in action ...\n")); 00946 RenderDC->Rectangle(&CRect(0, 0, 1, 1)); 00947 00948 RenderDC->SelectObject(pOldPn); 00949 RenderDC->SelectObject(pOldBr); 00950 } 00951 #endif 00952 00953 // Use the current DC to make a new one that is suitable for rendering 00954 // PostScript to directly. 00955 PSPrintDC* pPSPrintDC = new PSPrintDC(RenderDC); 00956 if (pPSPrintDC == NULL) return FALSE; 00957 00958 // Set up this - don't need it but the DC might get upset if it has no view. 00959 RenderDC = pPSPrintDC->GetDC(); 00960 pPSPrintDC->SetDCTransforms(RenderMatrix, RenderView); 00961 00962 // Tell the DC (i) we want to do OS output - this prevents it from outputting a 00963 // reference to our dictionary before we have defined it (because it's trying to 00964 // set up the PostScript C ready for Camelot EPS commands); (ii) we have finished 00965 // doing our 'OS' output. :-) 00966 return pPSPrintDC->StartOSOutput() && pPSPrintDC->EndOSOutput(); 00967 } 00968 00969 00970 00971 /******************************************************************************************** 00972 00973 > void PrintPSRenderRegion::Initialise() 00974 00975 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00976 Created: 04/29/95 00977 Purpose: Over-rides the EPS header output code - we don't want to do this everytime 00978 we start a PostScript render region, only every time we start a print job. 00979 SeeAlso: PrintPSRenderRegion::OutputPSHeader 00980 00981 ********************************************************************************************/ 00982 00983 void PrintPSRenderRegion::Initialise() 00984 { 00985 // Set up render region 00986 InitClipping(); 00987 InitAttributes(); 00988 } 00989 00990 /******************************************************************************************** 00991 00992 > void PrintPSRenderRegion::DeInitialise() 00993 00994 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00995 Created: 04/29/95 00996 Purpose: Over-rides the EPS trailer output code - we don't want to do this everytime 00997 we delete a PostScript render region - the printer driver should do it for 00998 us. 00999 SeeAlso: PrintPSRenderRegion::OutputPSHeader 01000 01001 ********************************************************************************************/ 01002 01003 void PrintPSRenderRegion::DeInitialise() 01004 { 01005 // Clear up 01006 DeInitAttributes(); 01007 } 01008 01009 01010 BOOL PrintPSRenderRegion::InitPSDevice(CNativeDC *pDC, PrintView *pPrintView) 01011 { 01012 // Make a new PSRenderRegion, and use it to output out PostScript header. 01013 DocRect DummyRect; 01014 Matrix DummyMatrix; 01015 FIXED16 DummyScale(0); 01016 PrintPSRenderRegion *pRegion = new PrintPSRenderRegion(DummyRect, DummyMatrix, DummyScale); 01017 if (pRegion == NULL) 01018 return FALSE; 01019 01020 // Attach new region to the DC. 01021 pRegion->AttachDevice((View *) pPrintView, pDC, Document::GetSelectedSpread()); 01022 01023 // Output the header 01024 if (!pRegion->OutputPSHeader()) 01025 return FALSE; 01026 01027 delete pRegion; 01028 01029 return TRUE; 01030 } 01031 01032 01033 /******************************************************************************************** 01034 01035 > BOOL PrintPSRenderRegion::RenderChar(WCHAR ch, Matrix* pMatrix) 01036 01037 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01038 Created: 30/4/95 01039 Inputs: ch - unicode value of char 01040 pMatrix - matrix specifying transforms to place char correctly in document 01041 Returns: FALSE if fails 01042 Purpose: Render a character, 01043 using the specified transform and current attributes in the render region. 01044 01045 ********************************************************************************************/ 01046 01047 BOOL PrintPSRenderRegion::RenderChar(WCHAR ch, Matrix* pMatrix) 01048 { 01049 PORTNOTE("printing", "Disabled PS text rendering") 01050 #ifndef EXCLUDE_FROM_XARALX 01051 // If it is stroked or not simple flat fill, or not a standard ASCII character then we 01052 // must do this as paths. 01053 BOOL FlatFill = IS_A(CurrentAttrs[ATTR_FILLGEOMETRY].pAttr, FlatFillAttribute); 01054 01055 if (!FlatFill || 01056 !RR_STROKECOLOUR().IsTransparent() || 01057 (FlatFill & RR_FILLCOLOUR().IsTransparent()) || 01058 (ch > 255)) 01059 return RenderRegion::RenderChar(ch, pMatrix); 01060 01061 // Check for emulsion down printing 01062 PrintControl *pPrintCtl; 01063 View *pView = GetRenderView(); 01064 if (pView && (pPrintCtl=pView->GetPrintControl())) 01065 { 01066 if (pPrintCtl->GetTypesetInfo()->PrintEmulsionDown()) 01067 return RenderRegion::RenderChar(ch, pMatrix); 01068 } 01069 01070 // get overall matrix - attribute matrix concatenated with given matrix if supplied 01071 Matrix matrix; 01072 if (GetCharAttributeMatrix(&matrix)==FALSE) 01073 return FALSE; 01074 if (pMatrix) 01075 matrix*=*pMatrix; 01076 01077 // Can we do this using a GDI font? 01078 // We can if the matrix only specifies scaling and translation 01079 FIXED16 abcd[4]; 01080 INT32 ef[2]; 01081 matrix.GetComponents(abcd, ef); 01082 01083 // GDI can't do y-axis flips, so we do it as shapes if this is detected (and x-axis 01084 // flips, for consistency). 01085 if ((abcd[0] < FIXED16(0)) || (abcd[3] < FIXED16(0))) 01086 { 01087 // Flipped in one or both axes - render as a path. 01088 return RenderRegion::RenderChar(ch, pMatrix); 01089 } 01090 01091 // Work out how complex the transformation is. 01092 FIXED16 ScaleX, ScaleY; 01093 ANGLE Rotation, Shear; 01094 01095 if ((abcd[1] == FIXED16(0)) && (abcd[2] == FIXED16(0))) 01096 { 01097 // Simple scaling transformation. 01098 ScaleX = abcd[0]; 01099 ScaleY = abcd[3]; 01100 Rotation = FIXED16(0); 01101 Shear = FIXED16(0); 01102 } 01103 else 01104 { 01105 // Decompose the matrix to find out how complex it is. 01106 // Pass in NULL for translation as we already know it is in 'ef'. 01107 FIXED16 Aspect; 01108 BOOL Result = matrix.Decompose(&ScaleY, &Aspect, &Rotation, &Shear, NULL); 01109 01110 if (!Result || (Shear != FIXED16(0))) 01111 // Either there was a problem, or the character is sheared, in which case 01112 // we can't do it with GDI. 01113 return RenderRegion::RenderChar(ch, pMatrix); 01114 01115 // Set up the ScaleX based on the aspect ratio 01116 ScaleX = ScaleY * Aspect; 01117 } 01118 01119 // Check for sideways printing - if the render matrix has rotation, then we are 01120 // printing at 270 degrees rotation, so adjust the rotation accordingly. 01121 #if 1 01122 FIXED16 RenderABCD[4]; 01123 INT32 RenderEF[2]; 01124 RenderMatrix.GetComponents(RenderABCD, RenderEF); 01125 if ((RenderABCD[1] != FIXED16(0)) || (RenderABCD[2] != FIXED16(0))) 01126 // Rotate by 270 degrees (angle is in radians) 01127 Rotation += FIXED16(1.5 * PI); 01128 #endif 01129 // Simple transformation - we can do this with a GDI font. 01130 PSPrintDC *pPSDC = (PSPrintDC *) CCDC::ConvertFromNativeDC(RenderDC); 01131 if (!pPSDC->StartOSOutput()) 01132 return FALSE; 01133 01134 01135 // Work out required width and height of the font 01136 MILLIPOINT ReferenceSize = TextManager::GetDefaultHeight(); 01137 MILLIPOINT Width = ReferenceSize * ScaleX; 01138 MILLIPOINT Height = ReferenceSize * ScaleY; 01139 01140 if (!pPSDC->SelectNewFont(RR_TXTFONTTYPEFACE(), RR_TXTBOLD(), RR_TXTITALIC(), 01141 Width, Height, Rotation)) 01142 { 01143 // Could not select font (maybe because device can't rotate fonts) 01144 pPSDC->EndOSOutput(); 01145 return RenderRegion::RenderChar(ch, pMatrix); 01146 } 01147 01148 // Ok, so the OS might screw up our attributes/graphics state, so we force 01149 // attributes to be output specifically the next time we do some Camelot output. 01150 ResetOutputAttributes(); 01151 01152 // First, set up the text attributes that are not encoded in the font. 01153 UINT32 OldTextAlign = RenderDC->SetTextAlign(TA_BASELINE); 01154 INT32 OldBKMode = RenderDC->SetBkMode(TRANSPARENT); 01155 COLORREF TextColour = ConvertColourToScreenWord(CurrentColContext, &RR_FILLCOLOUR()); 01156 01157 // check for completely black text 01158 if (TextColour==0 && IsWindowsNT()) 01159 { 01160 // All components are 0! 01161 // BODGE TEXT - The driver decides its a good idea not to ouput 01162 // 0 g when black is (it thinks) already set. 01163 // Hence we get the colour previously set. So, we 01164 // output a dummy black here, which it doesn't ignore. 01165 // Done by Mike (04/07/96). It would be nice to find 01166 // out why the driver is ignoring us but time is fleating 01167 01168 TextColour = (DWORD)(0x00010101); 01169 01170 /* 01171 This really is majorly dangerous! (Read comments in OutputDirect for why) 01172 We could use the following but we will destroy the graphics state of 01173 gdi for colour. ie if GDI does a 'save char col fill restore' we will 01174 end up doing this 01175 col save char col fill restore 01176 and will have mucked up the graph state. 01177 01178 String_32 LineBuf("0 g"); 01179 LineBuf += '\n'; 01180 TCHAR *pBuf = (TCHAR *) LineBuf; 01181 pPSDC->OutputTCHARAsChar(pBuf, LineBuf.Length()); 01182 */ 01183 } 01184 01185 COLORREF OldTextColour = RenderDC->SetTextColor(TextColour); 01186 01187 // Render the character in the specified position 01188 DocCoord DocPos(ef[0], ef[1]); 01189 01190 // Convert DocCoord to WinCoord 01191 OilCoord OilPoint; 01192 RenderMatrix.GetComponents(abcd, ef); 01193 OilPoint.x = MatrixCalc(abcd[0], DocPos.x, abcd[2], DocPos.y) + ef[0]; 01194 OilPoint.y = MatrixCalc(abcd[1], DocPos.x, abcd[3], DocPos.y) + ef[1]; 01195 WinCoord WinPos = OilPoint.ToWin(RenderView); 01196 01197 // Graham 5/8/96: "ch" is presently in UNICODE or ASCII 01198 // We need to convert it over to MBCS to deal with Japanese strings 01199 //So convert ch, which is of form WCHAR, over to a MBCS UINT32 character index 01200 01201 UINT32 uiCharNumber = UnicodeManager::UnicodeToMultiByte(ch); 01202 01203 //Now we want to put that UINT32 value into an array of char ready to pass to 01204 //RenderDC->TextOut. We do this using UnicodeManager::DecomposeMultiBytes 01205 01206 BYTE bCharArray[2]; 01207 01208 UnicodeManager::DecomposeMultiBytes(uiCharNumber, &bCharArray[0], &bCharArray[1]); 01209 01210 //Now, is the character in bCharArray one or two bytes long? 01211 //If it is one byte long, the first byte in bCharArray will be zero. 01212 if (bCharArray[0]==0) 01213 //It's a standard ASCII character, one byte long 01214 //So pass that character (bCharArray[1]) to the TextOut function. 01215 //The last parameter in text out is the number of bytes - in this case 1. 01216 RenderDC->TextOut(WinPos.x, WinPos.y, (CHAR*) &bCharArray[1], 1); 01217 else 01218 //The character is two bytes long (that is, it's a foreign character) 01219 //So we pass bCharArray[0] to TextOut and tell TextOut that it should 01220 //use two bytes from that address. We do this by setting the last 01221 //parameter to 2. 01222 RenderDC->TextOut(WinPos.x, WinPos.y, (CHAR*) &bCharArray[0], 2); 01223 01224 // Clean up text attributes 01225 RenderDC->SetTextAlign(OldTextAlign); 01226 RenderDC->SetBkMode(OldBKMode); 01227 RenderDC->SetTextColor(OldTextColour); 01228 01229 // Finished doing GDI output 01230 if (!pPSDC->EndOSOutput()) 01231 return FALSE; 01232 return TRUE; 01233 #else 01234 return RenderRegion::RenderChar(ch, pMatrix); 01235 #endif 01236 } 01237