printctl.cpp

Go to the documentation of this file.
00001 // $Id: printctl.cpp 1454 2006-07-17 11:52:51Z 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 // Implementation of the print control class
00100 
00101 /*
00102 */
00103 
00104 #include "camtypes.h"
00105 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 #include "colcontx.h"
00107 #include "colourix.h"
00108 #include "colormgr.h"
00109 #include "colplate.h"
00110 #include "camelot.h"
00111 //#include "convert.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 //#include "justin2.h"
00115 //#include "markn.h"
00116 #include "osrndrgn.h"
00117 #include "prdlgctl.h"
00118 #include "princomp.h"
00119 #include "printctl.h"
00120 #include "prntview.h"
00121 //#include "resource.h"
00122 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00123 //#include "simon.h"
00124 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00125 //#include "tim.h"
00126 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00127 #include "prnmks.h"
00128 //#include "isetres.h"
00129 
00130 CC_IMPLEMENT_MEMDUMP(PrintControl,  CC_CLASS_MEMDUMP)
00131 CC_IMPLEMENT_MEMDUMP(PrintPatchInfo,CC_CLASS_MEMDUMP)
00132 CC_IMPLEMENT_MEMDUMP(TypesetInfo,   CC_CLASS_MEMDUMP)
00133 
00134 // This is not compulsory, but you may as well put it in so that the correct version
00135 // of your file can be registered in the .exe
00136 DECLARE_SOURCE("$Revision: 1454 $");
00137 
00138 #define Swap(a,b)       { (a)^=(b), (b)^=(a), (a)^=(b); }
00139 
00140 // This is the max DPI at which bitmaps will be printed when using automatic DPI calculations
00141 #define MAXAUTOBITMAPDPI 200
00142 
00143 // These two values determine the range of values that the bitmap DPI will lie within
00144 #define MINBITMAPDPI 10
00145 #define MAXBITMAPDPI 600
00146 
00147 // Constants used for initialisation
00148 #define A4_WIDTH    (INT32(MM_MP_VAL*210))  // 210 mm - A4 width
00149 #define A4_HEIGHT   (INT32(MM_MP_VAL*297))  // 297 mm - A4 height
00150 
00151 //----------------------------------------------------------------
00152 
00153 static INT32 MinPrintScale = 5;
00154 static INT32 MaxPrintScale = 999;
00155 
00156 PrintMethodType PrintControl::AppPrintMethod = PRINTMETHOD_NORMAL;  // ini file entry declared in princomp.cpp
00157 
00158 //  if ( Camelot.DeclareSection(TEXT("Preferences"), 3) )
00159 //  {
00160         // section declared ok so now define the preference option  
00161         //  Camelot.DeclarePref(TEXT("Preferences"), TEXT("MinPrintScale"), &MinPrintScale, 1);
00162         //  Camelot.DeclarePref(TEXT("Preferences"), TEXT("MaxPrintScale"), &MaxPrintScale, 1);
00163 
00164 /******************************************************************************************
00165 
00166 >   PrintControl::PrintControl()
00167 
00168     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00169     Created:    27/3/95
00170     Inputs:     -
00171     Outputs:    -
00172     Returns:    -
00173     Purpose:    Default constructor
00174     Errors:     -
00175     SeeAlso:    -
00176 
00177 ******************************************************************************************/
00178 
00179 PrintControl::PrintControl()
00180 {
00181     PrintAreaSetUp = FALSE; // We haven't set the control up with a print area yet
00182     SetUpFailed    = FALSE; // We haven't called SetUp yet, so we haven't failed yet
00183     pSpread = NULL;
00184 
00185     TotalPrintArea  = DocRect(0,0,A4_WIDTH,A4_HEIGHT);
00186     PrintableArea   = TotalPrintArea;
00187     PALeftMargin    = 0;
00188     PATopMargin     = 0;
00189 
00190     Origin          = DocCoord(0,A4_HEIGHT);
00191 
00192     PageWidth   = A4_WIDTH;
00193     PageHeight  = A4_HEIGHT;
00194     PaperWidth  = A4_WIDTH;
00195     PaperHeight = A4_HEIGHT;
00196 
00197     DPS             = FALSE;
00198     Bleed           = 0;
00199     CropArea        = CROPAREA_SIZE+OUTSIDEBLEEDWIDTH;
00200     CropTopMargin   = 0;
00201     CropLeftMargin  = 0;
00202 
00203     // Print layout vars
00204     WholeSpread = FALSE;
00205 
00206     Scale   = FIXED16(100);
00207     Orient  = PRINTORIENTATION_UPRIGHT;
00208 
00209     FitType = PRINTFIT_BESTPAPER;
00210 
00211     TopMargin   = 0;
00212     LeftMargin  = 0;
00213     ScaledWidth = A4_WIDTH;
00214     ScaledHeight= A4_HEIGHT;
00215 
00216     Rows    = 1;
00217     Columns = 1;
00218     Gutter  = 0;
00219 
00220     // Print output vars
00221     Layers                  = PRINTLAYERS_VISIBLEFOREGROUND;
00222     // Job 10463: remove PS Level bits - default to Level 2
00223     PSLangLevel             = PSLEVEL_2;
00224 //  PrintMethod             = CurrentPrintMethod;
00225     BitmapResolutionMethod  = BITMAPRES_AUTO;
00226     DotsPerInch             = 150;
00227     FillQuality             = PRINTFILLQUALITY_MEDIUM;
00228     TextOptions             = PRINTTEXTOPTIONS_NORMAL;
00229 
00230     // General print vars
00231     Collated        = FALSE;
00232     NumCopies       = 1;
00233     PrintToFile     = FALSE;
00234     ObjPrintRange   = PRINTRANGEOBJ_ALL;
00235     DPSPrintRange   = PRINTRANGEDPS_BOTH;
00236 
00237     // Misc
00238     UpdateDependants = TRUE;
00239 
00240     // Print layout var initialisation
00241     Printing = FALSE;
00242 };
00243 
00244 /******************************************************************************************
00245 
00246 >   PrintControl::~PrintControl()
00247 
00248     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00249     Created:    27/3/95
00250     Inputs:     -
00251     Outputs:    -
00252     Returns:    -
00253     Purpose:    Default deconstructor
00254     Errors:     -
00255     SeeAlso:    PrintControl()::PrintControl()
00256 
00257 ******************************************************************************************/
00258 
00259 PrintControl::~PrintControl()
00260 {
00261     // Does nowt as yet
00262 }
00263 
00264 /******************************************************************************************
00265 
00266 >   String_256 PrintControl::BuildPrintInfoStr()
00267 
00268     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00269     Created:    7/4/95
00270     Inputs:     -
00271     Outputs:    -
00272     Returns:    Returns the print info string 
00273     Purpose:    This uses the print control's settings to build the string displayed in the print info
00274                 field of a print dlg
00275     Errors:     -
00276     SeeAlso:    -
00277 
00278 ******************************************************************************************/
00279 
00280 String_256 PrintControl::BuildPrintInfoStr()
00281 {
00282     String_256 Str;
00283 
00284     switch (FitType)
00285     {
00286         case PRINTFIT_BEST:     Str = String_256(_R(IDS_PRINT_BESTFIT));    break;
00287         case PRINTFIT_CUSTOM:   Str = String_256(_R(IDS_PRINT_CUSTOMFIT));  break;
00288         case PRINTFIT_MULTIPLE: Str = String_256(_R(IDS_PRINT_MULTIPLEFIT));break;
00289         case PRINTFIT_BESTPAPER:Str = String_256(_R(IDS_PRINT_BESTFITPAPER));   break;
00290         default: ERROR3_PF(("Unknown fit type (%d)",FitType)); break;
00291     }
00292 
00293     TCHAR* format = _T("%.2lf%%");
00294     double fScale = Scale.MakeDouble();
00295     INT32 n = INT32((fScale*100)+0.5);
00296 
00297     if (n % 100 == 0)
00298         format = _T("%.0lf%%");
00299     else if (n % 10 == 0)
00300         format = _T("%.1lf%%");
00301 
00302     TCHAR s[100];
00303     camSprintf(s,format,fScale);
00304     Str += s;
00305 
00306     switch (Orient)
00307     {
00308         case PRINTORIENTATION_UPRIGHT:  Str += String_256(_R(IDS_PRINT_UPRIGHT));   break;
00309         case PRINTORIENTATION_SIDEWAYS: Str += String_256(_R(IDS_PRINT_SIDEWAYS));  break;
00310         default: ERROR3_PF(("Unknown orientation (%d)",Orient)); break;
00311     }
00312 
00313     // If no print area set up, then assume we have no printer connected
00314     if (!PrintAreaSetUp)
00315     {
00316         Str += String_256(_R(IDS_PRINT_NOPRINTER));
00317         return Str;
00318     }
00319 
00320     // Work out how many pages will get completely printed
00321     UINT32 NumPages = 1;
00322     UINT32 IDSPlural   = _R(IDS_PRINT_PAGES);
00323     UINT32 IDSSingular = _R(IDS_PRINT_PAGE);
00324 
00325     switch (FitType)
00326     {
00327         case PRINTFIT_BEST:
00328         case PRINTFIT_BESTPAPER:
00329             NumPages = 1;
00330             break;
00331 
00332         case PRINTFIT_MULTIPLE:
00333             NumPages = 0;
00334             if (StartPrinting())
00335             {
00336                 GetNextPaper();
00337 
00338                 PrintPatchInfo PatchInfo;
00339                 while (GetNextPatch(&PatchInfo))
00340                 {
00341                     DocRect Rect = PatchInfo.GetClipRect(FALSE,FALSE);
00342                     double ScaleFactor = PatchInfo.Scale.MakeDouble() / 100;
00343 
00344                     INT32 w = Rect.Width();
00345                     INT32 h = Rect.Height();
00346 
00347                     if (PatchInfo.Rotate)
00348                     {   INT32 t = w;    w = h;  h = t;  }
00349 
00350                     Rect.lo.x = PatchInfo.XTrans;
00351                     Rect.lo.y = PatchInfo.YTrans;
00352 
00353                     Rect.hi.x = Rect.lo.x + (INT32((double(w) * ScaleFactor)+0.5));
00354                     Rect.hi.y = Rect.lo.y + (INT32((double(h) * ScaleFactor)+0.5));
00355 
00356                     if (PrintableArea.ContainsRect(Rect))
00357                         NumPages++;
00358                 }
00359 
00360                 EndPrinting();
00361             }
00362             IDSPlural   = _R(IDS_PRINT_TILES);
00363             IDSSingular = _R(IDS_PRINT_TILE);
00364             break;
00365 
00366         case PRINTFIT_CUSTOM:
00367             {
00368                 DocRect Rect(0,PaperHeight-ScaledHeight,ScaledWidth,PaperHeight);
00369                 
00370                 INT32 CropAdj = GetCropAdjust();
00371                 INT32 TransX = LeftMargin + CropAdj;
00372                 INT32 TransY = TopMargin + CropAdj;
00373                 
00374                 Rect.Translate(TransX,-TransY);
00375                 if (PrintableArea.ContainsRect(Rect))
00376                     NumPages = 1;
00377                 else
00378                     NumPages = 0;
00379             }
00380             break;
00381     }
00382 
00383     if (NumPages >= 1)
00384     {
00385         camSprintf(s, TEXT("%ld") ,NumPages);
00386         Str += s;
00387 
00388         if (NumPages == 1)
00389             Str += String_256(IDSSingular);
00390         else
00391             Str += String_256(IDSPlural);
00392     }
00393     else
00394         Str += String_256(_R(IDS_PRINT_NOPAGESFIT));
00395 
00396     return Str;
00397 }
00398 
00399 /******************************************************************************************
00400 
00401 >   String_256 PrintControl::BuildPaperSizeStr()
00402 
00403     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00404     Created:    7/4/95
00405     Inputs:     -
00406     Outputs:    -
00407     Returns:    Returns the paper size string 
00408     Purpose:    This uses the printer settings to build the string displayed in the paper size
00409                 field of a print options tab
00410     Errors:     -
00411     SeeAlso:    -
00412 
00413 ******************************************************************************************/
00414 
00415 String_256 PrintControl::BuildPaperSizeStr()
00416 {
00417     String_256 Str = TEXT("");
00418     String_256 TempStr = TEXT("");
00419 
00420     // If no print area set up, then assume we have no printer connected
00421     if (!PrintAreaSetUp)
00422         return Str;
00423 
00424     DimScale* pDimScale = NULL;
00425     if (pSpread != NULL)
00426         pDimScale = DimScale::GetPtrDimScale(pSpread);
00427 
00428     if (pDimScale != NULL)
00429     {
00430         BOOL ActiveState = pDimScale->IsActive();
00431         pDimScale->SetActiveState(FALSE);
00432 
00433         pDimScale->ConvertToUnits(PaperWidth,&TempStr);
00434         Str += TempStr;
00435 
00436         Str += String_32(_R(IDS_NUM_BY_NUM));
00437 
00438         pDimScale->ConvertToUnits(PaperHeight,&TempStr);
00439         Str += TempStr;
00440 //  WEBSTER-ranbirr-13/11/96
00441 #ifndef WEBSTER
00442         INT32 PrScale;
00443         if (CCPrintDialog::GetScale(&PrScale))
00444         {
00445             if (PrScale != 100)
00446             {
00447                 Str += String_256(_R(IDS_PRINT_PRINTERSCALING));
00448 
00449                 TCHAR s[100];
00450                 String_32 jcf(_R(IDS_PERCENT_FORMAT));
00451                 camSprintf(s, jcf, (INT32) PrScale);
00452                 Str += s;
00453             }
00454         }
00455 #endif //webster
00456         pDimScale->SetActiveState(ActiveState);
00457     }
00458 
00459     return Str;
00460 }
00461 
00462 /******************************************************************************************
00463 
00464 >   PrintControl& PrintControl::operator=(PrintControl& other)
00465 
00466     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00467     Created:    27/3/95
00468     Inputs:     the object to copy
00469     Outputs:    -
00470     Returns:    ref to copy of other
00471     Purpose:    The assignment operator for PrintControl
00472     Errors:     -
00473     SeeAlso:    -
00474 
00475 ******************************************************************************************/
00476 
00477 PrintControl& PrintControl::operator=(PrintControl& other)
00478 {
00479     PrintAreaSetUp  = other.PrintAreaSetUp;
00480     SetUpFailed     = other.SetUpFailed;
00481     pSpread         = other.pSpread;
00482 
00483     TotalPrintArea  = other.TotalPrintArea;
00484     PrintableArea   = other.PrintableArea;
00485     PALeftMargin    = other.PALeftMargin;
00486     PATopMargin     = other.PATopMargin;
00487 
00488     Origin          = other.Origin;
00489     PaperWidth      = other.PaperWidth;
00490     PaperHeight     = other.PaperHeight;
00491     PageWidth       = other.PageWidth;
00492     PageHeight      = other.PageHeight; 
00493     OrigPageWidth   = other.OrigPageWidth;
00494     OrigPageHeight  = other.OrigPageHeight;
00495 
00496     // Print layout vars
00497     WholeSpread     = other.WholeSpread;
00498     DPS             = other.DPS;
00499     Bleed           = other.Bleed;
00500 
00501     CropArea        = other.CropArea;
00502     CropTopMargin   = other.CropTopMargin;
00503     CropLeftMargin  = other.CropLeftMargin;
00504 
00505     Scale   = other.Scale;
00506     Orient  = other.Orient;
00507 
00508     FitType = other.FitType;
00509 
00510     TopMargin   = other.TopMargin;
00511     LeftMargin  = other.LeftMargin;
00512     ScaledWidth = other.ScaledWidth;
00513     ScaledHeight= other.ScaledHeight;
00514 
00515     Rows    = other.Rows;
00516     Columns = other.Columns;
00517     Gutter  = other.Gutter;
00518 
00519     // Print output vars
00520     Layers                  = other.Layers;
00521     PSLangLevel             = other.PSLangLevel;
00522 //  PrintMethod             = other.PrintMethod;
00523     BitmapResolutionMethod  = other.BitmapResolutionMethod;
00524     DotsPerInch             = other.DotsPerInch;
00525     FillQuality             = other.FillQuality;
00526     TextOptions             = other.TextOptions;
00527 
00528     // General print vars
00529     Collated        = other.Collated;
00530     NumCopies       = other.NumCopies;
00531     PrintToFile     = other.PrintToFile;
00532     ObjPrintRange   = other.ObjPrintRange;
00533     DPSPrintRange   = other.DPSPrintRange;
00534 
00535     // The TypesetInfo
00536     Typesetting = other.Typesetting;
00537 
00538     // Finally, make sure we have calculated all of the print settings like scaling properly
00539     if (pSpread != NULL)
00540         SetUp(pSpread);
00541 
00542     return *this;
00543 };
00544 
00545 //------------------------------------------------
00546 
00547 /******************************************************************************************
00548 
00549 >   BOOL PrintControl::SetUp(Spread* pThisSpread, BOOL RedrawPrintBorders = TRUE)
00550 
00551     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00552     Created:    4/4/95
00553     Inputs:     pThisSpread = ptr to a spread to print
00554                 RedrawPrintBorders - True if want a force redraw of associated docs (Defaults to TRUE)
00555     Outputs:    PrintAreaSetUp has same BOOL value as the return result
00556     Returns:    TRUE if able to set up print area OR already set up
00557     Purpose:    This function sets up the print control to print the given spread.
00558 
00559                 The entire spread area is used as the source area to print.  It can determine from the spread
00560                 whether it is a double page spread (DPS) or not.
00561 
00562                 Once it gets the source area for printing from the spread, it calcs the fit for the spread
00563                 using the current fit type.  I.e. it works out the scale factor and scaled page width
00564                 and height for each page printed, given the current settings.
00565 
00566     Errors:     -
00567     SeeAlso:    -
00568 
00569 ******************************************************************************************/
00570 
00571 BOOL PrintControl::SetUp(Spread* pThisSpread, BOOL RedrawPrintBorders)
00572 {
00573     ERROR2IF(pThisSpread == NULL,FALSE,"pThisSpread is NULL");
00574 
00575     pSpread = pThisSpread;
00576 
00577     // find out if it's a double page spread
00578     if (!pSpread->GetPageSize(NULL,NULL,NULL,&Bleed,&DPS,NULL))
00579         return FALSE;
00580 
00581     // Get a union of all the pages that represents the total printable area of the spread
00582     pSpread->GetPagesRect(&TotalPrintArea);
00583 
00584     PrintAreaSetUp = (CalcPrintAreaVars(RedrawPrintBorders) && CalcFit());
00585     SetUpFailed    = !PrintAreaSetUp;
00586 
00587     return PrintAreaSetUp;
00588 }   
00589 
00590 /******************************************************************************************
00591 
00592 >   BOOL PrintControl::CalcPrintAreaVars(BOOL RedrawPrintBorders = TRUE)
00593 
00594     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00595     Created:    11/4/95
00596     Inputs:     RedrawPrintBorders - True if want a force redraw of associated docs (Defaults to TRUE)
00597     Outputs:    -
00598     Returns:    TRUE if able to recalc
00599     Purpose:    This function calcs member vars dependant on the total print area.
00600                 The print area can be set up using SetUp().
00601 
00602                 Dependants are:
00603                     PageWidth
00604                     PageHeight
00605                     Origin
00606                     PrintableArea
00607 
00608                 It takes into account orientation, and whether its a double page spread (DPS).
00609                 If it's a DPS, it also takes the WholeSpread setting into account
00610 
00611                 NOTE: This func also finds out the width and height of the printer's paper using
00612                 CCPrintDialog::GetPaperSize(), and calcs the paper's area too
00613 
00614     Errors:     -
00615     SeeAlso:    SetUp()
00616 
00617 ******************************************************************************************/
00618 
00619 BOOL PrintControl::CalcPrintAreaVars(BOOL RedrawPrintBorders)
00620 {
00621     // Calc the print area origin
00622     Origin.x = TotalPrintArea.lo.x;
00623     Origin.y = TotalPrintArea.hi.y;
00624 
00625     //-------------------------
00626     // Find out the dimensions of the printer's paper (in MILLIPOINTS)
00627     wxSize PaperSize;
00628 //  WEBSTER-ranbirr-13/11/96
00629 #ifndef WEBSTER
00630     if (!CCPrintDialog::GetPaperSize(&PaperSize, RedrawPrintBorders))
00631         return FALSE;
00632 #endif //webster
00633     PaperWidth  = PaperSize.GetWidth();
00634     PaperHeight = PaperSize.GetHeight();
00635 
00636     // ------------------------
00637     // Get the printable area on the paper (defined relative to a origin at the bottom left of paper)
00638     // and the top & left margins of the printable area
00639 //  WEBSTER-ranbirr-13/11/96
00640 #ifndef WEBSTER
00641     if (!CCPrintDialog::GetPrintableArea(&PrintableArea))
00642         return FALSE;
00643     if (!CCPrintDialog::GetPrintMargins(&PALeftMargin,&PATopMargin))
00644         return FALSE;
00645 #endif //webster
00646     //-------------------------
00647     // Calc the width and height of the print area
00648     PageWidth  = TotalPrintArea.hi.x - TotalPrintArea.lo.x;
00649     PageHeight = TotalPrintArea.hi.y - TotalPrintArea.lo.y;
00650 
00651     // If double page spread AND printing single pages, half the width for each page printed
00652     if (DPS && !WholeSpread) 
00653         (PageWidth) /= 2;
00654 
00655     // Save the orig values in case PageWidth & PageHeight need to be swapped due to sideways orientation
00656     OrigPageWidth  = PageWidth;
00657     OrigPageHeight = PageHeight;
00658 
00659     // If printing sideways, the width and height of the printed page should be swapped
00660     if (Orient == PRINTORIENTATION_SIDEWAYS)
00661         Swap(PageWidth,PageHeight);
00662 
00663     return TRUE;
00664 }
00665 
00666 /******************************************************************************************
00667 
00668 >   void PrintControl::StartImport()
00669 
00670     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00671     Created:    10/4/95
00672     Inputs:     -
00673     Purpose:    Tells the object that it's data is being imported.
00674 
00675                 In this state, calling the Set functions just sets the aspect of the object,
00676                 rather than recalculation dependant aspects of the object.
00677 
00678                     e.g. calling SetScale() will recalc the width & height of the printed page
00679                     unless you call StartImport() first
00680 
00681                 You can call this func any time, not just for importing, if you need to alter
00682                 mmembers independently.
00683 
00684     SeeAlso:    EndImport()
00685 
00686 ******************************************************************************************/
00687 
00688 void PrintControl::StartImport()
00689 {
00690     UpdateDependants = FALSE;
00691 }
00692 
00693 /******************************************************************************************
00694 
00695 >   void PrintControl::StartImport()
00696 
00697     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00698     Created:    10/4/95
00699     Inputs:     -
00700     Purpose:    Tells the object that it's data is no longer being imported.
00701     SeeAlso:    StartImport()
00702 
00703 ******************************************************************************************/
00704 
00705 void PrintControl::EndImport()
00706 {
00707     UpdateDependants = TRUE;
00708 }
00709 
00710 //-------------------------
00711 
00712 
00713 /******************************************************************************************
00714 
00715 >   INT32 PrintControl::GetNumPrintablePages()
00716 
00717     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00718     Created:    12/4/95
00719     Inputs:     -
00720     Returns:    Number of printable pages (1 or 2)
00721     Purpose:    This tells you how many individual pages are printable, given the current settings
00722 
00723                 1 is returned:
00724                     If it's not a DPS
00725                     If it's a DPS, but we're printing the whole spread as one page
00726                     If it's a DPS, we're printing individual pages, but the print range is either Left or Right-only
00727 
00728                 2 is returned:
00729                     It's a DPS AND individual pages AND printing both pages
00730 
00731     SeeAlso:    -
00732 
00733 ******************************************************************************************/
00734 
00735 INT32 PrintControl::GetNumPrintablePages()
00736 {
00737     if (DPS && !WholeSpread && (DPSPrintRange == PRINTRANGEDPS_BOTH))
00738         return 2;
00739     else
00740         return 1;
00741 }
00742 
00743 //-------------------------
00744 
00745 /******************************************************************************************
00746 
00747 >   void PrintControl::SetScaleFactor(double ScaleFactor)
00748 
00749     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00750     Created:    10/4/95
00751     Inputs:     ScaleFactor = the scale factor
00752     Purpose:    Sets the scale percentage using the given scale factor
00753                 This alters dependants automatically (unless importing)
00754                 Dependants are:
00755                     ScaledWidth
00756                     ScaledHeight
00757     SeeAlso:    StartImport() & EndImport()
00758                                                     
00759 ******************************************************************************************/
00760 
00761 void PrintControl::SetScaleFactor(double ScaleFactor)
00762 {
00763     SetScale(FIXED16(100*ScaleFactor));
00764 }
00765 
00766 /******************************************************************************************
00767 
00768 >   void PrintControl::SetScale(FIXED16 NewScale)
00769 
00770     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00771     Created:    10/4/95
00772     Inputs:     NewScale = new scale factor
00773     Purpose:    Sets the scale percentage, altering dependants automatically (unless importing)
00774                 Dependants are:
00775                     ScaledWidth
00776                     ScaledHeight
00777     SeeAlso:    StartImport() & EndImport()
00778 
00779 ******************************************************************************************/
00780 
00781 void PrintControl::SetScale(FIXED16 NewScale)
00782 {
00783     Scale = NewScale;
00784     FIXED16 Min = FIXED16(MinPrintScale);
00785     FIXED16 Max = FIXED16(MaxPrintScale);
00786 
00787     if (Scale < Min) Scale = Min;
00788     if (Scale > Max) Scale = Max;
00789 
00790     if (UpdateDependants)
00791     {
00792         double ScaleFactor = (Scale.MakeDouble())/100;
00793 
00794         ScaledWidth  = INT32((double(PageWidth) *ScaleFactor)+0.5);
00795         ScaledHeight = INT32((double(PageHeight)*ScaleFactor)+0.5);
00796     }
00797 }
00798 
00799 /******************************************************************************************
00800 
00801 >   void PrintControl::SetPrintOrient(PrintOrient NewOrient)
00802 
00803     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00804     Created:    10/4/95
00805     Inputs:     NewOrient = new orientation
00806     Purpose:    Sets the print orientatio, altering dependants automatically (unless importing)
00807 
00808                 Dependants are:
00809                     ScaledWidth
00810                     ScaledHeight
00811                     PageWidth
00812                     PageHeight
00813                     Scale
00814 
00815                 and possibly:
00816                     Rows
00817                     Columns
00818 
00819     SeeAlso:    StartImport() & EndImport()
00820 
00821 ******************************************************************************************/
00822 
00823 void PrintControl::SetPrintOrient(PrintOrient NewOrient)
00824 {
00825     if (Orient != NewOrient)
00826     {
00827         Orient = NewOrient;
00828 
00829         if (UpdateDependants)
00830         {
00831             CalcPrintAreaVars();    // Update the page width and height (these get swapped)
00832             SetRows(Rows);          // Use SetRows() to recalc max rows and scale factor
00833             SetColumns(Columns);    // Use SetColumns() to recalc max columns and scale factor
00834 
00835             // This is a bodge fix.  Sometimes the gutter value can become -ve. In this case,
00836             // reset the multiple fit vars
00837             if (Gutter < 0)
00838             {
00839                 SetRows(1);         // Use SetRows() to recalc max rows and scale factor
00840                 SetColumns(1);      // Use SetColumns() to recalc max columns and scale factor
00841                 SetGutter(0);       
00842             }
00843         }
00844     }
00845 }
00846 
00847 /******************************************************************************************
00848 
00849 >   void PrintControl::SetWidth(INT32 NewVal)
00850 
00851     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00852     Created:    10/4/95
00853     Inputs:     NewVal = new width for the print area
00854     Purpose:    Sets the page width, altering dependants automatically (unless importing)
00855                 Dependants are:
00856                     Scale
00857                     ScaledHeight
00858     SeeAlso:    StartImport() & EndImport()
00859 
00860 ******************************************************************************************/
00861 
00862 void PrintControl::SetWidth(INT32 NewVal)
00863 {
00864     if (UpdateDependants)
00865     {
00866         double ScaleFactor = double(NewVal)/double(PageWidth);
00867         SetScaleFactor(ScaleFactor);        // Use SetScaleFactor() to recalc ScaledWidth and ScaledHeight
00868     }
00869     else
00870         ScaledWidth = NewVal;
00871 }
00872     
00873 
00874 /******************************************************************************************
00875 
00876 >   void PrintControl::SetHeight(INT32 NewVal)
00877 
00878     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00879     Created:    10/4/95
00880     Inputs:     NewVal = new height for the print area
00881     Purpose:    Sets the page height, altering dependants automatically (unless importing)
00882                 Dependants are:
00883                     Scale
00884                     ScaledWidth
00885     SeeAlso:    StartImport() & EndImport()
00886 
00887 ******************************************************************************************/
00888 
00889 void PrintControl::SetHeight(INT32 NewVal)
00890 {
00891     if (UpdateDependants)
00892     {
00893         double ScaleFactor = double(NewVal)/double(PageHeight);
00894         SetScaleFactor(ScaleFactor);        // Use SetScaleFactor() to recalc ScaledWidth and ScaledHeight
00895     }
00896     else
00897         ScaledHeight = NewVal;
00898 }
00899 
00900 //-------------------------
00901 //-------------------------
00902 //-------------------------
00903 
00904 /******************************************************************************************
00905 
00906 >   double PrintControl::CalcPatchWidth(INT32 Wd,INT32 NumColumns, INT32 GutterVal)
00907 
00908     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00909     Created:    11/4/95
00910     Inputs:     Wd          = Width of paper
00911                 NumColumns  = number of columns down the paper
00912                 Gutter      = gutter distance between each page
00913     Returns:    The width of each patch for multiple fit printing
00914     Purpose:    The patch width = (width of the paper / num columns) - gutter
00915     SeeAlso:    -
00916 
00917 ******************************************************************************************/
00918 
00919 double PrintControl::CalcPatchWidth(INT32 Wd,INT32 NumColumns,INT32 GutterVal)
00920 {
00921     return ((double(Wd) / double(NumColumns)) - double(GutterVal));
00922 }
00923 
00924 /******************************************************************************************
00925 
00926 >   double PrintControl::CalcPatchHeight(INT32 Ht,INT32 NumRows,INT32 GutterVal)
00927 
00928     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00929     Created:    11/4/95
00930     Inputs:     Ht          = Height of paper
00931                 NumRows = number of rows across the paper
00932                 Gutter  = gutter distance between each page
00933     Returns:    The Height of each patch for multiple fit printing
00934     Purpose:    The patch Height = (Height of the paper / num rows) - gutter
00935     SeeAlso:    -
00936 
00937 ******************************************************************************************/
00938 
00939 double PrintControl::CalcPatchHeight(INT32 Ht,INT32 NumRows,INT32 GutterVal)
00940 {
00941     return ((double(Ht) / double(NumRows)) - double(GutterVal));
00942 }
00943 
00944 /******************************************************************************************
00945 
00946 >   INT32 PrintControl::CalcMaxRows(INT32 GutterVal)
00947 
00948     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00949     Created:    11/4/95
00950     Inputs:     GutterVal = the gutter value to use
00951     Returns:    Max num rows for the current paper width and gutter setting
00952     Purpose:    Dynamically calcs the max num rows possible, given the current paper width
00953                 and gutter setting.
00954 
00955                 This is based on the min scale factor allowed
00956     SeeAlso:    -
00957 
00958 ******************************************************************************************/
00959 
00960 INT32 PrintControl::CalcMaxRows(INT32 GutterVal)
00961 {
00962     INT32 MaxRows = 0;
00963     double MinScaleFactor = double(MinPrintScale)/100;
00964     double PatchHeight,ScaleFactor;
00965 
00966     do
00967     {
00968         MaxRows += 1;
00969         PatchHeight = CalcPatchHeight(PaperHeight,MaxRows,GutterVal);
00970         ScaleFactor = PatchHeight / PageHeight;
00971     } while (ScaleFactor >= MinScaleFactor);
00972 
00973     if (MaxRows > 1)
00974         MaxRows -= 1;
00975 
00976     return MaxRows;
00977 }
00978 
00979 /******************************************************************************************
00980 
00981 >   INT32 PrintControl::CalcMaxColumns(INT32 GutterVal)
00982 
00983     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00984     Created:    11/4/95
00985     Inputs:     GutterVal = the gutter value to use
00986     Returns:    Max num columns for the current paper height and gutter setting
00987     Purpose:    Dynamically calcs the max num columns possible, given the current paper height 
00988                 and gutter setting.
00989 
00990                 This is based on the min scale factor allowed
00991     SeeAlso:    -
00992 
00993 ******************************************************************************************/
00994 
00995 INT32 PrintControl::CalcMaxColumns(INT32 GutterVal)
00996 {
00997     INT32 MaxColumns = 0;
00998     double MinScaleFactor = double(MinPrintScale)/100;
00999     double PatchWidth,ScaleFactor;
01000 
01001     do
01002     {
01003         MaxColumns += 1;
01004         PatchWidth = CalcPatchWidth(PaperWidth,MaxColumns,GutterVal);
01005         ScaleFactor = PatchWidth / PageWidth;
01006     } while (ScaleFactor >= MinScaleFactor);
01007 
01008     if (MaxColumns > 1)
01009         MaxColumns -= 1;
01010 
01011     return MaxColumns;
01012 }
01013 
01014 /******************************************************************************************
01015 
01016 >   INT32 PrintControl::CalcMaxGutter(INT32 NumRows,INT32 NumColumns)
01017 
01018     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01019     Created:    11/4/95
01020     Inputs:     NumRows     = num rows to base calc on
01021                 NumColumns  = num columns to base calc on
01022     Returns:    Max gutter value
01023     Purpose:    Dynamically calcs the max gutter value based on the given number of rows and columns, 
01024                 and the current paper size
01025     SeeAlso:    -
01026 
01027 ******************************************************************************************/
01028 
01029 INT32 PrintControl::CalcMaxGutter(INT32 NumRows,INT32 NumColumns)
01030 {
01031     double MinScaleFactor = double(MinPrintScale)/100;
01032 
01033     double PatchWidth  = CalcPatchWidth(PaperWidth,NumColumns,0);
01034     double PatchHeight = CalcPatchHeight(PaperHeight,NumRows,0);
01035 
01036     INT32 MaxGutterWidth  = INT32((PatchWidth  - (double(PageWidth) *MinScaleFactor))+0.5);
01037     INT32 MaxGutterHeight = INT32((PatchHeight - (double(PageHeight)*MinScaleFactor))+0.5);
01038 
01039     if (MaxGutterWidth < MaxGutterHeight)
01040         return MaxGutterWidth;
01041     else
01042         return MaxGutterHeight;
01043 }
01044 
01045 /******************************************************************************************
01046 
01047 >   void PrintControl::CalcMultipleFit(INT32 NumRows,INT32 NumColumns,INT32 GutterVal,INT32 Wd,INT32 Ht)
01048 
01049     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01050     Created:    11/4/95
01051     Inputs:     NumRows     = num rows to fit on paper
01052                 NumColumns  = num columns to fit on paper
01053                 GutterVal   = gutter distance between each page
01054                 Wd          = Width of paper
01055                 Ht          = Height of paper
01056                 Extra       = An adjustment made to the page size (usually 0)
01057     Returns:    -
01058     Purpose:    Recalcs the scale factor required for each page to fit the specified number of rows
01059                 and columns, and gutter distance, to the paper
01060 
01061                 Dependants are:
01062                     Scale
01063                     ScaledWidth
01064                     ScaledHeight
01065 
01066     SeeAlso:    StartImport() & EndImport()
01067 
01068 ******************************************************************************************/
01069 
01070 void PrintControl::CalcMultipleFit(INT32 NumRows,INT32 NumColumns,INT32 GutterVal,INT32 Wd,INT32 Ht,INT32 Extra)
01071 {
01072     // Calc the width and height of each patch on the page, taking into account the given gutter value
01073     double PatchWidth  = CalcPatchWidth(Wd,NumColumns,GutterVal);
01074     double PatchHeight = CalcPatchHeight(Ht,NumRows,GutterVal);
01075 
01076     // Work out the scale factor required to get the width of the page into this patch
01077     double ScaleFactor = PatchWidth / double(PageWidth+Extra);
01078 
01079     // Calc the new width and height of each page by applying the scale factor
01080     double NewWidth = PageWidth  * ScaleFactor;
01081     double NewHeight= PageHeight * ScaleFactor;
01082 
01083     // If the scale factor made using the page width and patch width means that the page does NOT entirely
01084     // fit into a multiple-fit patch, then use the scale factor generated using the patch height and page height
01085     //
01086     // (NB: We add 1.0 to these values so that the '>' comparisons don't fail due to insignificant floating point errors).
01087     //
01088     if ((NewWidth > (PatchWidth+1.0)) || (NewHeight > (PatchHeight+1.0)))
01089         ScaleFactor = PatchHeight / double(PageHeight+Extra);
01090     
01091     #ifdef _DEBUG
01092     {
01093         // In theory, when the scale factor is applied to the page width and height, the page will fit
01094         // entirely into a patch.  However, we still better check this is true when in debug builds
01095 
01096         NewWidth = PageWidth  * ScaleFactor;
01097         NewHeight= PageHeight * ScaleFactor;
01098 
01099         if ((NewWidth > (PatchWidth+1.0)) || (NewHeight > (PatchHeight+1.0)))
01100         {
01101             ERROR3("Multiple fit scale factor does not fit page into patch");
01102         }
01103     }
01104     #endif
01105     
01106     SetScaleFactor(ScaleFactor);        // Use SetScaleFactor() to recalc ScaledWidth and ScaledHeight
01107 }
01108 
01109 /******************************************************************************************
01110 
01111 >   BOOL PrintControl::CalcFit()
01112 
01113     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01114     Created:    11/4/95
01115     Inputs:     -
01116     Returns:    TRUE if a recalc took place, FALSE if nothing has been recalced
01117     Purpose:    Recalcs the scale factor needed to fit the current page in the specified
01118                 orientation, using the currently set fit type
01119 
01120                 This will only do anything when UpdateDependants is TRUE
01121 
01122     SeeAlso:    CalcMultipleFit()
01123 
01124 ******************************************************************************************/
01125 
01126 BOOL PrintControl::CalcFit()
01127 {
01128     static BOOL IgnoreCall = FALSE;
01129 
01130     if (!UpdateDependants)
01131         return FALSE;
01132 
01133     if (IgnoreCall)     // Stop re-entrant calls to this function
01134         return TRUE;
01135 
01136     IgnoreCall = TRUE;
01137 
01138     // Set these value to absolutely ziltch
01139     CropTopMargin=0;
01140     CropLeftMargin=0;
01141 
01142     switch (FitType)
01143     {
01144         case PRINTFIT_MULTIPLE:
01145             {
01146                 INT32 PAWidth  = PaperWidth;
01147                 INT32 PAHeight = PaperHeight;
01148 
01149                 INT32 CropAdjust = GetCropAdjust();
01150 
01151                 PAWidth -= (CropAdjust<<1);
01152                 PAHeight -= (CropAdjust<<1);
01153 
01154                 CalcMultipleFit(Rows,Columns,Gutter,PAWidth,PAHeight,0);
01155                 
01156                 // these settings just show to the user whats happening in the dialogue
01157                 // they do not get used explicitly to position the pages.
01158                 if ((Rows==1) && (Columns==1))
01159                 {
01160                     LeftMargin = (PaperWidth -ScaledWidth) /2;
01161                     TopMargin  = (PaperHeight-ScaledHeight)/2;
01162                 }
01163             }
01164             break;
01165 
01166         case PRINTFIT_BEST:
01167             {
01168                 INT32 PAWidth  = PrintableArea.Width();
01169                 INT32 PAHeight = PrintableArea.Height();
01170 
01171                 INT32 CropAdjust = GetCropAdjust();
01172 
01173                 PAWidth -= (CropAdjust<<1);
01174                 PAHeight -= (CropAdjust<<1);
01175 
01176                 BOOL PAOrient   = ((double(PAWidth)         / double(PAHeight))       <= 1.0);
01177                 BOOL PageOrient = ((double(OrigPageWidth)   / double(OrigPageHeight ))<= 1.0);
01178 
01179                 PrintOrient NewOrient;
01180 
01181                 if (PAOrient == PageOrient)
01182                     NewOrient = PRINTORIENTATION_UPRIGHT;
01183                 else
01184                     NewOrient = PRINTORIENTATION_SIDEWAYS;
01185 
01186                 if (NewOrient != Orient)
01187                     SetPrintOrient(NewOrient);
01188 
01189                 CalcMultipleFit(1,1,0,PAWidth,PAHeight,0);
01190 
01191                 PAWidth += (CropAdjust<<1);
01192                 PAHeight += (CropAdjust<<1);
01193 
01194                 LeftMargin = PALeftMargin+((PAWidth -ScaledWidth) /2);
01195                 TopMargin  = PATopMargin +((PAHeight-ScaledHeight)/2);
01196             }
01197             break;
01198 
01199         case PRINTFIT_CUSTOM:
01200             {
01201                 INT32 CropAdjust = GetCropAdjust();
01202                 CropLeftMargin = CropAdjust;
01203                 CropTopMargin = CropAdjust;
01204                 SetScale(Scale);
01205             }
01206             break;
01207 
01208         case PRINTFIT_BESTPAPER:
01209             // Best fit the document paper size onto the printed page
01210             // without scaling, distortion or clipping
01211             {
01212                 INT32 PAWidth  = PaperWidth;
01213                 INT32 PAHeight = PaperHeight;
01214 
01215                 INT32 CropAdjust = GetCropAdjust();
01216 
01217                 PAWidth -= (CropAdjust<<1);
01218                 PAHeight -= (CropAdjust<<1);
01219 
01220                 // Compute aspect of document and aspect of printed page
01221                 // TRUE means rect is portrait orientation, taller than it is wide...
01222                 BOOL PAOrient   = (double(PAWidth)          <= double(PAHeight));
01223                 BOOL PageOrient = (double(OrigPageWidth)    <= double(OrigPageHeight));
01224 
01225                 PrintOrient NewOrient;
01226 
01227                 if (PAOrient == PageOrient)
01228                     NewOrient = PRINTORIENTATION_UPRIGHT;
01229                 else
01230                     NewOrient = PRINTORIENTATION_SIDEWAYS;
01231 
01232                 if (NewOrient != Orient)
01233                     SetPrintOrient(NewOrient);
01234 
01235                 CropLeftMargin = CropAdjust;
01236                 CropTopMargin = CropAdjust;
01237                 SetScale(100.0);
01238 
01239 //              PAWidth += (CropAdjust<<1);
01240 //              PAHeight += (CropAdjust<<1);
01241 
01242                 // Centre document page within printed page
01243                 LeftMargin = (PAWidth - ScaledWidth) / 2;
01244                 TopMargin = (PAHeight - ScaledHeight) / 2;
01245             }
01246             break;
01247 
01248         default:
01249             ERROR3_PF(("Unknown fit type (%d)",FitType));
01250             IgnoreCall = FALSE;
01251             return FALSE;
01252     }
01253 
01254     IgnoreCall = FALSE;
01255 
01256     return TRUE;
01257 }
01258 
01259 /******************************************************************************************
01260 
01261 >   INT32 PrintControl::GetCropAdjust() const
01262 
01263     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01264     Created:    16/12/96
01265     Inputs:     -
01266     Returns:    An INT32, the width of the crop area
01267     Purpose:    Return the size of the extra area we need to take into account when fitting
01268                 pages onto the printable paper. Currently the bleed size and crop area size
01269                 is used.
01270     
01271 ******************************************************************************************/
01272 
01273 INT32 PrintControl::GetCropAdjust() const
01274 {
01275     INT32 CropAdjust = 0;
01276     
01277     PrintMarksMan *pMarksMan = GetApplication()->GetMarksManager();
01278     if (pMarksMan && Typesetting.OutputPrintersMarks())
01279         CropAdjust = CropArea+Bleed;
01280 
01281     return CropAdjust;
01282 }
01283 
01284 
01285 /******************************************************************************************
01286 
01287 >   void PrintControl::AdjustForTypesetting()
01288 
01289     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01290     Created:    16/12/96
01291     Inputs:     -
01292     Returns:    -
01293     Purpose:    Adjust the printing variables to allow for typesetting marks to be positioned
01294                 What happens here is that we adjust the X,Y translations so that we ensure
01295                 a patch is moved into a position where we can get the crop marks between the
01296                 patch and the papers edges.
01297 
01298 ******************************************************************************************/
01299 
01300 /*
01301 void PrintControl::AdjustForTypesetting()
01302 {
01303     // Used to do it like this but don't anymore.
01304 
01305 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
01306 #ifndef STANDALONE
01307     PrintMarksMan *pMarksMan = GetApplication()->GetMarksManager();
01308     if (pMarksMan && GetTypesetInfo()->OutputPrintersMarks())
01309     {
01310         switch (FitType)
01311         {
01312             case PRINTFIT_MULTIPLE:
01313             {
01314                 CropTopMargin = CropArea;
01315                 CropLeftMargin = CropArea;
01316                 // if the bleed is more than 1/2 of the gutter, then the
01317                 // bleed will overflow the edge of the page by the difference!
01318                 double sectw = CalcPatchWidth( PaperWidth, Columns,0);
01319                 double secth = CalcPatchHeight(PaperHeight,Rows   ,0);
01320                 // Translate to the bottom left of the current patch
01321                 double ovflx = Bleed - ((sectw - (double)ScaledWidth)/2);
01322                 double ovfly = Bleed - ((secth - (double)ScaledHeight)/2);
01323 
01324                 CropLeftMargin += (INT32)(ovflx+0.5);
01325                 CropTopMargin  += (INT32)(ovfly+0.5);
01326             }
01327             break;
01328 
01329             case PRINTFIT_BEST:
01330             {
01331                 // does nothing at the moment.
01332             }
01333             break;
01334 
01335             case PRINTFIT_CUSTOM:
01336             {
01337                 CropLeftMargin = CropArea+Bleed;
01338                  CropTopMargin = CropArea+Bleed;
01339             }
01340             break;
01341 
01342             default:
01343                 ERROR3_PF(("Unknown fit type (%d)",FitType));
01344                 break;
01345         }
01346     }
01347 #endif
01348 #endif
01349 }
01350 */
01351 
01352 
01353 /******************************************************************************************
01354 
01355 >   BOOL PrintControl::SetRows(INT32 NewVal)
01356 
01357     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01358     Created:    10/4/95
01359     Inputs:     NewVal = new number of coloumns of printed pages
01360     Returns:    TRUE if new row num == NewVal, FALSE if it's had to be altered because NewVal is out of range
01361     Purpose:    Sets the number of pages in each printed column, altering dependants automatically (unless importing)
01362                 Dependants are:
01363                     Scale
01364                     ScaledWidth
01365                     ScaledHeight
01366                     Columns
01367 
01368                 If not updating dependants, this will always return TRUE
01369 
01370     SeeAlso:    StartImport() & EndImport()
01371 
01372 ******************************************************************************************/
01373 
01374 BOOL PrintControl::SetRows(INT32 NewVal)
01375 {
01376     Rows = NewVal;
01377 
01378     if (UpdateDependants)
01379     {
01380         INT32 Max = CalcMaxRows(0);
01381 
01382         if (Rows < 1)   Rows = 1;
01383         if (Rows > Max) Rows = Max;
01384 
01385         INT32 MaxGutter = CalcMaxGutter(Rows,Columns);
01386         if (Gutter > MaxGutter)
01387             Gutter = MaxGutter;
01388 
01389         CalcFit();
01390     }
01391 
01392     return (Rows == NewVal);
01393 }
01394 
01395 /******************************************************************************************
01396 
01397 >   BOOL PrintControl::SetColumns(INT32 NewVal)
01398 
01399     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01400     Created:    10/4/95
01401     Inputs:     NewVal = new number of coloumns of printed pages
01402     Returns:    TRUE if new row num == NewVal, FALSE if it's had to be altered because NewVal is out of range
01403     Purpose:    Sets the number of pages in each printed column, altering dependants automatically (unless importing)
01404                 Dependants are:
01405                     Scale
01406                     ScaledWidth
01407                     ScaledHeight
01408                     Rows
01409 
01410                 If not updating dependants, this will always return TRUE
01411 
01412     SeeAlso:    StartImport() & EndImport()
01413 
01414 ******************************************************************************************/
01415 
01416 BOOL PrintControl::SetColumns(INT32 NewVal)
01417 {
01418     Columns = NewVal;
01419 
01420     if (UpdateDependants)
01421     {
01422         INT32 Max = CalcMaxColumns(0);
01423 
01424         if (Columns < 1)   Columns = 1;
01425         if (Columns > Max) Columns = Max;
01426 
01427         INT32 MaxGutter = CalcMaxGutter(Rows,Columns);
01428         if (Gutter > MaxGutter)
01429             Gutter = MaxGutter;
01430 
01431         CalcFit();
01432     }
01433 
01434     return (Columns == NewVal);
01435 }
01436 
01437 /******************************************************************************************
01438 
01439 >   BOOL PrintControl::SetGutter(INT32 NewVal)
01440 
01441     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01442     Created:    10/4/95
01443     Inputs:     NewVal = new gutter measurement between each page
01444     Returns:    TRUE if new row num == NewVal, FALSE if it's had to be altered because NewVal is out of range
01445     Purpose:    Sets the gutter measurement, altering dependants automatically (unless importing)
01446 
01447                 The gutter is the distance between each page when doing multiple fit printing.
01448                 Half the gutter width is used as a margin for each page next to the edge of the paper
01449 
01450                 Dependants are:
01451                     Scale
01452                     ScaledWidth
01453                     ScaledHeight
01454                     Rows
01455                     Colunmns
01456 
01457                 If not updating dependants, this will always return TRUE
01458 
01459     SeeAlso:    StartImport() & EndImport()
01460 
01461 ******************************************************************************************/
01462 
01463 BOOL PrintControl::SetGutter(INT32 NewVal)
01464 {
01465     Gutter = NewVal;
01466 
01467     if (UpdateDependants)
01468     {
01469         INT32 Max = CalcMaxGutter(1,1);
01470 
01471         if (Gutter < 0)     Gutter = 0;
01472         if (Gutter > Max)   Gutter = Max;
01473 
01474         INT32 MaxRows = CalcMaxRows(Gutter);
01475         if (Rows > MaxRows)
01476             Rows = MaxRows;
01477 
01478         INT32 MaxColumns = CalcMaxColumns(Gutter);
01479         if (Columns > MaxColumns)
01480             Columns = MaxColumns;
01481 
01482         CalcFit();
01483     }
01484 
01485     return (Gutter == NewVal);
01486 }
01487 
01488 /******************************************************************************************
01489 
01490 >   void PrintControl::SetWholeSpread(BOOL State)
01491 
01492     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01493     Created:    11/4/95
01494     Inputs:     State = new WholeSpread flag state
01495     Purpose:    Sets the WholeSpread state, altering dependants automatically (unless importing)
01496 
01497                 Dependants are:
01498                     Scale
01499                     ScaledWidth
01500                     ScaledHeight
01501                     PageWidth
01502                     PageHeight
01503                     Rows
01504                     Columns
01505     SeeAlso:    StartImport() & EndImport()
01506 
01507 ******************************************************************************************/
01508 
01509 void PrintControl::SetWholeSpread(BOOL State)
01510 {
01511     if (WholeSpread != State)
01512     {
01513         WholeSpread = State;
01514 
01515         if (UpdateDependants)
01516         {
01517             CalcPrintAreaVars();    // Update the page width & height (the page width either doubles or halves)
01518             SetRows(Rows);          // Use SetRows() to recalc max rows and scale factor
01519             SetColumns(Columns);    // Use SetColumns() to recalc max columns and scale factor
01520         }
01521     }
01522 }
01523 
01524 /******************************************************************************************
01525 
01526 >   void PrintControl::SetFitType(PrintFitType NewFitType)
01527 
01528     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01529     Created:    11/4/95
01530     Inputs:     NewFitType = page fit type
01531     Purpose:    Sets the fit type, altering dependants automatically (unless importing)
01532 
01533                 Dependants are:
01534                     ScaledWidth
01535                     ScaledHeight
01536                     Scale
01537     SeeAlso:    StartImport() & EndImport()
01538 
01539 ******************************************************************************************/
01540 
01541 void PrintControl::SetFitType(PrintFitType NewFitType)
01542 {
01543     FitType = NewFitType;
01544 
01545     if (UpdateDependants)
01546         CalcFit();
01547 }
01548 
01549 /******************************************************************************************
01550 
01551 >   INT32 PrintControl::GetDotsPerInch()
01552 
01553     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01554     Created:    18/4/95
01555     Inputs:     -
01556     Returns:    DPI value used to render bitmaps
01557     Purpose:    If the bitmap res setting is manual then the value the user entered is returned.
01558                 If the bitmap res setting is automatic, then base the DPI on the printer's DPI
01559 
01560                     Bitmap res = Half printer res
01561 
01562                     if (Bitmap res > MAXAUTOBITMAPDPI)
01563                         Bitmap res = MAXAUTOBITMAPDPI;
01564 
01565                     if (Bitmap res < MINBITMAPDPI)
01566                         Bitmap res = MINBITMAPDPI;
01567 
01568     SeeAlso:    SetDotsPerInch();
01569 
01570 ******************************************************************************************/
01571 
01572 INT32 PrintControl::GetDotsPerInch()
01573 {
01574     // MRH 11/9/00 - Tidied up code to make it more readable
01575     // Basically the code checks to see if the auto flag is set.
01576     // If NOT set then the DotsPerInch variable is left with the value in the manual edit box.
01577     // If it is set then it gets the current printer resolution and divides it by 2!
01578     if (BitmapResolutionMethod == BITMAPRES_AUTO)
01579     {
01580         // Choose the DPI automatically
01581         // This is based on the printer resolution
01582         // Set up the local variable to the max auto dpi!
01583         INT32 PrinterDPI = MAXAUTOBITMAPDPI;
01584 
01585         // Get the printer resolution (if this fails, choose the maximum setting)
01586         if (!CCPrintDialog::GetResolution(&PrinterDPI))
01587             PrinterDPI = MAXAUTOBITMAPDPI; // Failing could change the variable so reset it!
01588 
01589         // Make the DPI half the printer res
01590         DotsPerInch = PrinterDPI >> 1;
01591 
01592         // If this DPI value > MAXAUTOBITMAPDPI, then probably printing to a typesetter, in which case cap it as 
01593         // there's no point in printing at any higher DPI
01594         if (DotsPerInch > MAXAUTOBITMAPDPI)
01595             DotsPerInch = MAXAUTOBITMAPDPI;
01596 
01597         // Make sure that it doesn't dip below the min.
01598         // If it does, choose the printer DPI, so that we ensure good quality for low DPI settings
01599         if (DotsPerInch < MINBITMAPDPI)
01600             DotsPerInch = PrinterDPI;
01601     }
01602 
01603     // return the new value!
01604     return DotsPerInch;
01605 }
01606 
01607 
01608 /******************************************************************************************
01609 
01610 >   void PrintControl::SetDotsPerInch(INT32 NewVal)
01611 
01612     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01613     Created:    18/4/95
01614     Inputs:     NewVal = DPI value
01615     Returns:    -
01616     Purpose:    Ensures the NewVal is not < MINBITMAPDPI
01617 
01618                 If NewVal < MINBITMAP, the DPI is set to the printer's DPI
01619 
01620     SeeAlso:    GetDotsPerInch()
01621 
01622 ******************************************************************************************/
01623 
01624 void PrintControl::SetDotsPerInch(INT32 NewVal)
01625 { 
01626     DotsPerInch = NewVal;
01627 
01628     if (DotsPerInch > MAXBITMAPDPI)
01629         DotsPerInch = MAXBITMAPDPI;
01630 
01631     if (DotsPerInch < MINBITMAPDPI)
01632         DotsPerInch = MINBITMAPDPI;
01633 
01634 /*
01635     if (DotsPerInch < MINBITMAPDPI)
01636     {
01637         INT32 PrinterDPI;
01638 
01639         // Get the printer resolution (if this fails, choose the minimum setting)
01640         if (!CCPrintDialog::GetResolution(&PrinterDPI))
01641             PrinterDPI = MINBITMAPDPI;
01642 
01643         DotsPerInch = PrinterDPI;
01644     }
01645 */
01646 }
01647 
01648 /******************************************************************************************
01649 
01650 >   PrintMethodType PrintControl::GetPrintMethod(PrintMethodType NewVal)
01651 
01652     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01653     Created:    20/7/95
01654     Inputs:     -
01655     Returns:    The app's current print method
01656     Purpose:    Returns the app's print method.
01657                 This is stored in the global var AppPrintMethod
01658 
01659     SeeAlso:    SetPrintMethod()
01660 
01661 ******************************************************************************************/
01662 
01663 PrintMethodType PrintControl::GetPrintMethod()
01664 {
01665     return AppPrintMethod;
01666 }
01667 
01668 /******************************************************************************************
01669 
01670 >   void PrintControl::SetPrintMethod(PrintMethodType NewVal)
01671 
01672     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01673     Created:    20/7/95
01674     Inputs:     NewVal = new print method
01675     Returns:    -
01676     Purpose:    Sets the app's print method to be NewVal
01677                 This is stored in the global var AppPrintMethod
01678 
01679     SeeAlso:    GetPrintMethod()
01680 
01681 ******************************************************************************************/
01682 
01683 void PrintControl::SetPrintMethod(PrintMethodType NewVal)
01684 {
01685     AppPrintMethod = NewVal;
01686 }
01687 
01688 /******************************************************************************************
01689 
01690 >   void PrintControl::GetObjPrintRange()
01691 
01692     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01693     Created:    22/7/96
01694     Inputs:     -
01695     Returns:    PRINTRANGEOBJ_ALL or PRINTRANGEOBJ_SELECTED
01696     Purpose:    Find out the object range the user wants to print to.
01697 
01698                 This function has been modified (today 22/7/96) so that it reacts to the current selection.
01699                 This is to fix bug 4857, which meant if you selected "print selected objects" then
01700                 deselected all the objects, it would still print the selected objects, resulting in a 
01701                 blank page.
01702 
01703                 What's worse, the UI in the print dlg would grey out, so you couldn't switch it off.
01704 
01705                 This routine will mean that "print all" is on if the internal var is PRINTRANGEOBJ_ALL
01706                 OR there are no selected objects.
01707 
01708     SeeAlso:    GetPrintMethod()
01709 
01710 ******************************************************************************************/
01711 
01712 PrintRangeObj PrintControl::GetObjPrintRange()
01713 {
01714     // Find the selection
01715     SelRange* pSelRange = GetApplication()->FindSelection();
01716 
01717     if (pSelRange->FindFirst() != NULL)
01718         return ObjPrintRange;       // There are selected objects, so return the setting the user has made.
01719     else
01720         return PRINTRANGEOBJ_ALL;   // There's no selected objects, so always print all objects.
01721 }
01722 
01723 //--------------------------------------------------------------------------
01724 // Print layout funcs
01725 
01726 /******************************************************************************************
01727 
01728 >   BOOL PrintControl::CalcNumPaper()
01729 
01730     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01731     Created:    18/4/95
01732     Inputs:     -
01733     Outputs:    NumPaper = The number of pieces of paper we will print to
01734     Returns:    TRUE if it was able to cal num paper to print to, FALSE otherwise
01735 
01736     Purpose:    This works out how many pieces of paper we will print to.
01737                 NB: This can be different to the number of pieces of paper that comes out of the printer
01738                 when the printer can do multiple copies and we are in a position to exploit this
01739 
01740                 It takes into account DPS, whole spread & left or right-only settings.
01741                 It also takes into account the collated flag & the ability of the printer
01742                 to do multiple copies.
01743 
01744                 The number of pieces of paper that the printer will produce at the end of the print job
01745                     = number of printable pages * num copies
01746 
01747                 If the output is colla
01748 
01749     SeeAlso:    GetDotsPerInch()
01750 
01751 ******************************************************************************************/
01752 
01753 BOOL PrintControl::CalcNumPaper()
01754 {
01755     BOOL CanMultiCopy=TRUE;
01756 //  WEBSTER-ranbirr-13/11/96
01757 #ifndef WEBSTER 
01758     // Can the printer do multiple copies?
01759     if (!CCPrintDialog::CanMultiCopy(&CanMultiCopy))
01760         return FALSE;
01761 #endif //webster
01762     INT32 NumActualPiecesOfPaper = NumPrintablePages * NumCopies;   // Num pieces of paper that will come out of printer
01763 
01764     // NumPaper will be the number of pieces of paper we will print to
01765     // Default to the number printable of pages
01766     NumPaper = NumPrintablePages;
01767 
01768     if (NumPrintablePages == 1)
01769     {
01770         // If the printer can't cope with multiple copies, we'll have to do them all
01771         if (!CanMultiCopy)
01772             NumPaper = NumActualPiecesOfPaper;
01773     }
01774     else
01775     {
01776         // If the printer can't cope with multiple copies OR we need to collate the output
01777         // we'll have to do them all
01778         if (Collated || !CanMultiCopy)
01779             NumPaper = NumActualPiecesOfPaper;
01780     }   
01781 
01782     return TRUE;
01783 }
01784 
01785 /********************************************************************************************
01786 
01787 >   BOOL PrintControl::StartPrinting()
01788 
01789     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01790     Created:    25/4/95
01791     Inputs:     -
01792     Returns:    TRUE if all OK, FALSE otherwise
01793     Purpose:    This informs the print info object that you are about to do some printing.
01794 
01795                 This is purely to set up the print layout mechanism.  It will work out how many 
01796                 pieces of paper will be printed to, and how many times the page will be printed
01797                 on each piece of of paper (for multiple fit printing).
01798 
01799                 The mechanism works like this:
01800 
01801                 if (StartPrinting())
01802                 {
01803                     while (GetNextPaper())
01804                     {
01805                         while (GetNextPatch())
01806                         {
01807                             Use access funcs to get hold of data set up by GetNextPath(), e.g. scale, translation, etc
01808                         
01809                             if (SelectedOnly)
01810                                 print all selected objects that lie within the ClipRect area in the spread
01811                             else
01812                                 print all objects that lie within the ClipRect area in the spread
01813                         }
01814                     }
01815 
01816                     EndPrinting()
01817                 }
01818 
01819     SeeAlso:    GetNextPaper(), GetNextPath(), EndPrinting()
01820 
01821 ********************************************************************************************/
01822 
01823 BOOL PrintControl::StartPrinting()
01824 {
01825     ERROR2IF(Printing,FALSE,"Already printing - have you called EndPrinting()?");
01826     ERROR2IF(!PrintAreaSetUp,FALSE,"The print control hasn't been set up via SetUp()");
01827     ERROR2IF(pSpread == NULL,FALSE,"The print control pSpread is NULL");
01828 
01829     // Find out the number of printable pages
01830     NumPrintablePages = GetNumPrintablePages();             // This will be either 1 or 2
01831 
01832     // Init NumPaper member var with the number of pieces of paper we will print to.
01833     if (!CalcNumPaper())
01834         return FALSE;
01835 
01836     // PaperNumber is the number of the current piece of paper being printed to.
01837     // MaxPaperNumber is the total number of pieces of paper we will print to.
01838     PaperNumber     = 0;        // incremented at the start of GetNextPaper()
01839     MaxPaperNumber  = NumPaper;
01840     Reprint         = FALSE;    // Set to TRUE by ReprintPaper() to make GetNextPaper() to return 
01841                                 // the same paper again
01842 
01843     NumPatches = 0;
01844     Printing = TRUE;
01845 
01846     SelRange* pSelRange = GetApplication()->FindSelection();
01847     SelectionPresent    = (pSelRange->FindFirst() != NULL);
01848 
01849     // Now make sure that the list of printing plates is updated in case any spot colours
01850     // have been created or deleted recently...
01851     TypesetInfo* tpInfo = GetTypesetInfo();
01852     if (tpInfo != NULL && tpInfo->AreSeparating())
01853     {
01854         // Call CreatePlateList to ensure that the list of printing plates is set up
01855         // This will just update the list (if necessary) if it has been previously created,
01856         // to make sure that screening options and present plates are all hunky-dory.
01857         tpInfo->CreatePlateList();
01858     }
01859 
01860     return TRUE;
01861 }
01862 
01863 
01864 
01865 
01866 /********************************************************************************************
01867 
01868 >   BOOL PrintControl::EndPrinting()
01869 
01870     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01871     Created:    26/4/95
01872     Inputs:     -
01873     Returns:    TRUE if all OK, FALSE otherwise
01874     Purpose:    This informs the print info object that you have finished printing.
01875     SeeAlso:    StartPrinting();
01876 
01877 ********************************************************************************************/
01878 
01879 BOOL PrintControl::EndPrinting()
01880 {
01881     ERROR2IF(!Printing,FALSE,"Not printing - have you called StartPrinting()?");
01882     Printing = FALSE;
01883     return TRUE;
01884 }
01885 
01886 
01887 
01888 
01889 
01890 /********************************************************************************************
01891 
01892 >   BOOL PrintControl::GetNextPaper()
01893 
01894     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01895     Created:    26/4/95
01896     Inputs:     -
01897     Returns:    TRUE if you should print on another piece of paper
01898                 FALSE if the print job should end
01899     Purpose:    Call this for each piece of paper to be printed to.
01900                 NB: You must call StartPrinting() before calling this func as part of your print loop
01901 
01902                 If ReprintPaper() is called after GetNextPaper(), then the next time you call
01903                 GetNextPaper() you will actually be printing the previous piece of paper
01904                 e.g
01905                     while (GetNextPaper())      // Infinite loop
01906                         ReprintPaper();
01907 
01908 
01909     SeeAlso:    StartPrinting(),EndPrinting(), ReprintPaper()
01910 
01911 ********************************************************************************************/
01912 
01913 BOOL PrintControl::GetNextPaper()
01914 {
01915     ERROR2IF(!Printing,FALSE,"Not printing - have you called StartPrinting()?");
01916 
01917     // Do we need to reprint the same piece of paper?
01918     if (Reprint)
01919     {
01920         // Only re-jig the counters if we have called GetNextPaper() at least once
01921         if (NumPaper < MaxPaperNumber)
01922         {
01923             NumPaper++;
01924             PaperNumber--;
01925         }
01926         // Reprinting, so set flag to FALSE
01927         Reprint = FALSE;
01928     }
01929 
01930     if (NumPaper > 0)
01931     {
01932         NumPaper--;
01933         PaperNumber++;
01934 
01935         // Calc the number of patches we'll have to print on this next piece of paper
01936         if (FitType == PRINTFIT_MULTIPLE)
01937         {
01938             NumPatches  = Rows*Columns;
01939 
01940             // PatchRow & PatchColumn form a coordinate specifying which patch to print next
01941             PatchRow    = 0;
01942             PatchColumn = 0;
01943 
01944             // Section width and height define the size of the areas of the page patches will fit into.
01945             // Effectively these are the patch sizes ignoring the gutter value.
01946             // Each patch is centred within a section of the page.
01947             INT32 CropAdjust = GetCropAdjust();
01948             INT32 PAWidth    = PaperWidth - (CropAdjust<<1);
01949             INT32 PAHeight   = PaperHeight - (CropAdjust<<1);
01950             SectionWidth    = INT32(CalcPatchWidth(PAWidth, Columns,0));
01951             SectionHeight   = INT32(CalcPatchHeight(PAHeight,Rows,   0));
01952         }
01953         else
01954             NumPatches = 1;
01955 
01956         // PatchNumber is the number of the current patch being printed to.
01957         // MaxPatchNumber is the total number of patches printed on this piece of paper
01958         PatchNumber    = 0;         // incremented at the start of GetNextPatch()
01959         MaxPatchNumber = NumPatches;
01960 
01961         // Calc the object clip rect used to define which objects within the total printable area should
01962         // be printed on this piece of paper
01963         //
01964         // Default to the total printable area
01965         PatchClipRect = TotalPrintArea;
01966 
01967         if (NumPrintablePages > 1)
01968         {
01969             // The number of printable pages > 1 (i.e. we have a double page spread, we are printing
01970             // both left & right pages, and printing individual pages)
01971             
01972             INT32 m;
01973             
01974             if (Collated)
01975             {
01976                 // If collated output, then oscillate the clip rect
01977                 // between the left and right page, controlled by the current paper number
01978                 m = (PaperNumber-1) % NumPrintablePages;
01979             }
01980             else
01981             {
01982                 // Otherwise, print 'n' left pages followed by 'n' right pages
01983                 m = (PaperNumber-1) / (MaxPaperNumber / NumPrintablePages);
01984             }
01985 
01986             PatchClipRect.lo.x += (OrigPageWidth*m);
01987             PatchClipRect.hi.x  = PatchClipRect.lo.x + OrigPageWidth;
01988         }
01989         else
01990         {
01991             if (DPS && !WholeSpread && (DPSPrintRange != PRINTRANGEDPS_BOTH))
01992             {
01993                 // Here we have a DPS, we are printing individual pages, but we are either
01994                 // printing left-only or right-only pages
01995                 //
01996                 // So if right only, add the page width to the lo.x coord to move the area to the right hand side.
01997                 // In either case, the patch clip rect hi.x will be lo.x+OrigPageWidth.
01998 
01999                 if (DPSPrintRange == PRINTRANGEDPS_RIGHTPAGES)
02000                     PatchClipRect.lo.x += OrigPageWidth;
02001 
02002                 PatchClipRect.hi.x = PatchClipRect.lo.x + OrigPageWidth;
02003             }
02004         }                   
02005 
02006         // take into account the bleed margin
02007 /*
02008         PatchClipRect.Inflate(Bleed);
02009         if (Orient == PRINTORIENTATION_SIDEWAYS)
02010             PatchClipRect.Translate(-Bleed,Bleed);
02011         else
02012             PatchClipRect.Translate(Bleed,Bleed);
02013 */
02014         return TRUE;
02015     }
02016 
02017     return FALSE;
02018 }
02019 
02020 
02021 
02022 /********************************************************************************************
02023 
02024 >   BOOL PrintControl::MorePaper()
02025 
02026     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02027     Created:    11/6/96
02028     Inputs:     -
02029     Returns:    TRUE if there is more paper to come
02030                 FALSE if there's no more paper. 
02031     Purpose:    Call this for each piece of paper to be printed to.
02032 
02033 ********************************************************************************************/
02034 
02035 BOOL PrintControl::MorePaper()
02036 {
02037     if (Reprint && NumPaper < MaxPaperNumber)
02038         return TRUE;
02039 
02040     return (NumPaper > 0);
02041 }
02042 
02043 
02044 /********************************************************************************************
02045 
02046 >   BOOL PrintControl::ReprintPaper()
02047 
02048     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02049     Created:    26/4/95
02050     Inputs:     -
02051     Returns:    TRUE if all OK, FALSE otherwise
02052     Purpose:    This allows you to print on the same piece of paper again.
02053 
02054                 If you call this func after a call to GetNextPaper(), then the next time you
02055                 call GetNextPaper() you will actually be starting the print on the same piece of
02056                 paper.
02057 
02058     SeeAlso:    GetNextPaper()
02059 
02060 ********************************************************************************************/
02061 
02062 BOOL PrintControl::ReprintPaper()
02063 {
02064     Reprint = TRUE;
02065     return TRUE;
02066 }
02067 
02068 /********************************************************************************************
02069 
02070 >   BOOL PrintControl::GetNextPatch(PrintPatchInfo* pPatchInfo)
02071 
02072     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02073     Created:    26/4/95
02074     Inputs:     pPatchInfo = ptr to object to store patch info in
02075     Outputs:    -
02076     Returns:    TRUE if you should print another page on the paper
02077                 FALSE if the piece of paper printed to is finished.
02078     Purpose:    Each time this func returns TRUE, print the page using the data set up by this call.
02079 
02080                 If this call returns TRUE, the the given PrintPatchInfo has been set up with
02081                 all the data needed to print the given patch.
02082 
02083                 NB: You must call GetNextPaper() before calling this func as part of your print loop
02084 
02085     SeeAlso:    StartPrinting(), GetNextPaper(), EndPrinting()
02086 
02087 ********************************************************************************************/
02088 
02089 BOOL PrintControl::GetNextPatch(PrintPatchInfo* pPatchInfo)
02090 {
02091     ERROR2IF(!Printing,FALSE,"Not printing - have you called StartPrinting()?");
02092     ERROR2IF(pPatchInfo == NULL,FALSE,"Given NULL pPatchInfo param");
02093 
02094     if (NumPatches > 0)
02095     {
02096         NumPatches--;
02097         PatchNumber++;
02098 
02099         pPatchInfo->pSpread         = pSpread;
02100         pPatchInfo->Scale           = Scale;
02101         pPatchInfo->ClipRect        = PatchClipRect;
02102         pPatchInfo->Rotate          = (Orient == PRINTORIENTATION_SIDEWAYS);
02103         pPatchInfo->SelectedOnly    = ((ObjPrintRange == PRINTRANGEOBJ_SELECTED) && SelectionPresent);
02104         pPatchInfo->VisibleLayers   = (Layers == PRINTLAYERS_VISIBLEFOREGROUND);
02105         pPatchInfo->XTrans          = 0;
02106         pPatchInfo->YTrans          = 0;
02107         pPatchInfo->PaperWidth      = PaperWidth;
02108         pPatchInfo->PaperHeight     = PaperHeight;
02109         pPatchInfo->ScaledWidth     = ScaledWidth;
02110         pPatchInfo->ScaledHeight    = ScaledHeight;
02111         pPatchInfo->Bleed           = Bleed;
02112         pPatchInfo->CropArea        = CropArea;
02113         pPatchInfo->PaperNumber     = PaperNumber;
02114         pPatchInfo->MaxPaperNumber  = MaxPaperNumber;
02115         pPatchInfo->PatchNumber     = PatchNumber;
02116         pPatchInfo->MaxPatchNumber  = MaxPatchNumber;
02117         pPatchInfo->PALeftMargin    = PALeftMargin;
02118         pPatchInfo->PATopMargin     = PATopMargin;
02119 
02120         // set emulsion up/down for print rendering
02121         TypesetInfo* tpInfo = GetTypesetInfo();
02122         pPatchInfo->EmulsionDown = ( (tpInfo != NULL) && tpInfo->PrintEmulsionDown() );
02123 
02124         switch (FitType)
02125         {
02126             case PRINTFIT_BEST:
02127                 // Move it to the right by LeftMargin, and down by TopMargin
02128                 pPatchInfo->XTrans = LeftMargin;
02129                 pPatchInfo->YTrans = (PaperHeight-ScaledHeight)-TopMargin;
02130                 break;
02131 
02132             case PRINTFIT_BESTPAPER:
02133                 // Move it to the right by LeftMargin, and down by TopMargin
02134                 pPatchInfo->XTrans = LeftMargin;
02135                 pPatchInfo->YTrans = (PaperHeight-ScaledHeight)-TopMargin;
02136                 pPatchInfo->XTrans += CropLeftMargin;
02137                 pPatchInfo->YTrans -= CropTopMargin;
02138                 break;
02139 
02140             case PRINTFIT_CUSTOM:
02141             {
02142                 // Move it to the right by LeftMargin, and down by TopMargin
02143                 pPatchInfo->XTrans = LeftMargin;
02144                 pPatchInfo->YTrans = (PaperHeight-ScaledHeight)-TopMargin;
02145                 pPatchInfo->XTrans += CropLeftMargin;
02146                 pPatchInfo->YTrans -= CropTopMargin;
02147             }
02148             break;
02149 
02150             case PRINTFIT_MULTIPLE:
02151             {
02152                 // Translate to the bottom left of the current patch
02153                 INT32 CropAdjust = GetCropAdjust();
02154                 
02155                 pPatchInfo->XTrans = CropAdjust + (SectionWidth  * PatchColumn) + ((SectionWidth  - ScaledWidth)/2);
02156                 pPatchInfo->YTrans = CropAdjust + (SectionHeight * PatchRow)    + ((SectionHeight - ScaledHeight)/2);
02157 
02158                 PatchColumn += 1;
02159                 if (PatchColumn >= Columns)
02160                 {
02161                     PatchColumn = 0;
02162                     PatchRow += 1;
02163                 }
02164             }
02165             break;
02166 
02167             default:
02168                 ERROR3_PF(("Unknown fit type : %d",FitType));
02169                 break;
02170         }
02171 
02172         return TRUE;
02173     }
02174 
02175     return FALSE;
02176 }
02177 
02178 
02179 
02180 
02181 /********************************************************************************************
02182 
02183 >   BOOL PrintControl::StartPlatePrinting(PrintView *pPrintView, UINT32 *const pErrNo)
02184 
02185     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02186     Created:    11/6/96
02187     Inputs:     pPrintView - The View to which we are rendering
02188     Outputs:    errno - 
02189     Returns:    -
02190     Purpose:    This function makes sure the plate printing loop is initialised for the
02191                 next set of pages on a single sheet of paper to pass through the driver.
02192                 It sets up an appropriate ColourPlate and ColourCOntextCMYK for the
02193                 given PrintView.
02194 
02195 ********************************************************************************************/
02196 
02197 BOOL PrintControl::StartPlatePrinting(PrintView *pPrintView, UINT32 *const pErrNo)
02198 {
02199     // Clear the ouput error first
02200     (*pErrNo)=0;
02201 
02202     // If there's no view, drawing will be rather tricky
02203     if (pPrintView == NULL)
02204     {
02205         ERROR3("Sanity check, The view is NULL during StartPlatePrinting!");
02206         return FALSE;
02207     }
02208 
02209     // Get hold of the resident colour management system
02210     ColourContext *pContext;
02211 
02212 PORTNOTE("cms", "Disabled XaraCMS");
02213 #ifndef EXCLUDE_FROM_XARALX
02214     XaraCMS* ptheCMS=GetApplication()->GetCMSManager();
02215     if (ptheCMS!=NULL)
02216     {
02217         // First try to set the printer context specified in the ini file read
02218         // when we started up
02219         String_256 PrintProfile;
02220         ptheCMS->GetPrinterProfile(&PrintProfile);
02221         pContext = new ColourContextCMYK(pPrintView, &PrintProfile);
02222     
02223         if (pContext==NULL)
02224         {
02225             // We need to error here and inform the user we
02226             // are out of memory
02227             ERROR3("Failed to create a CMYK colour context during print initialisation in SetNextPlate()");
02228             (*pErrNo) = _R(IDS_OUT_OF_MEMORY);
02229             return FALSE;
02230         }
02231         
02232         if (!(pContext->IsDeviceContext()))
02233         {
02234             // Eeek, we failed to build the physical device context
02235             // which means something rather nasty went on. We must now
02236             // warn the user. They can either continue with a logical
02237             // context or abort the proceedings.
02238 
02239             // TO DO: Make this a nice resourced string!
02240             // Hang about, we should attempt to use a printer.xcms down
02241             // the root directory of Camelot, lets see if we can find that
02242 
02243             delete pContext;
02244             pContext=NULL;
02245 
02246             ptheCMS->GetDefaultPrinterProfile(&PrintProfile);
02247             pContext = new ColourContextCMYK(pPrintView, &PrintProfile);
02248 
02249             // if we've failed again
02250             if (pContext==NULL)
02251             {
02252                 ERROR3("Failed to create a CMYK colour context during print initialisation in SetNextPlate()");
02253                 (*pErrNo) = _R(IDS_OUT_OF_MEMORY);
02254                 return FALSE;
02255             }
02256 
02257             // ok if we've still failed to locate even this we really are stuck and will have to use the context
02258             // in logical mode, but lets ask the user about this first.
02259             if (!(pContext->IsDeviceContext()))
02260             {
02261                 ErrorInfo Info;
02262                 Info.ErrorMsg = _R(IDT_OPTS_LOGICALCONTEXT);
02263                 Info.Button[0] = _R(IDS_CONTINUE);
02264                 Info.Button[1] = _R(IDS_CANCEL);
02265                 if (AskQuestion(&Info) == _R(IDS_CANCEL))
02266                 {
02267                     (*pErrNo) = _R(IDS_PRINT_USERTERM);
02268                     return FALSE;
02269                 }
02270             }
02271         }
02272     }
02273     else
02274 #endif
02275     {
02276         // Create a logical colour context. This isn't strictly necessary, as the view will default to
02277         // using the global default (logical) context anyway, but we might as well be safe
02278         pContext = new ColourContextCMYK(pPrintView);
02279         if (pContext==NULL)
02280         {
02281             // we've failed to create a new colour context for this document
02282             // We must abort the printing loop
02283             ERROR3("Failed to create a CMYK colour context during print initialisation in SetNextPlate()");
02284             (*pErrNo) = _R(IDS_OUT_OF_MEMORY);
02285             return FALSE;
02286         }
02287     }
02288 
02289     // Set the new context in the view. The view will delete it when it's done with it
02290     // NOTE that the view will attach its own ColourPlate to this context, so there is no need
02291     // (indeed, no point whatsoever) for us to try to set that up for it.
02292     pPrintView->SetColourContext(COLOURMODEL_CMYK, pContext);
02293 
02294     // Set up the plate printing system, we do this for composite and separated output
02295     Typesetting.InitPlatesForPrinting();
02296 
02297     return TRUE;
02298 }
02299 
02300 
02301 
02302 /********************************************************************************************
02303 
02304 >   void PrintControl::EndPlatePrinting(PrintView *pPrintView)
02305 
02306     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02307     Created:    11/6/96
02308     Inputs:     -
02309     Returns:    -
02310     Purpose:    This function makes sure the plate printing loop is shut down correctly.
02311                 We need to make sure that the last plate is detached from the colour context
02312                 inside the print view, otherwise when the print view is destroyed the plate
02313                 in the colour context in the print view will be destroyed. As our printer
02314                 dialogue keeps this in its list, we need to make sure it only gets deleted
02315                 once during that lists destruction.
02316     
02317 ********************************************************************************************/
02318 
02319 void PrintControl::EndPlatePrinting(PrintView *pPrintView)
02320 {
02321     // If there's no view, drawing will be rather tricky
02322     if (pPrintView == NULL)
02323     {
02324         ERROR3("Sanity check, The view is NULL during StartPlatePrinting!");
02325         return;
02326     }
02327     
02328     pPrintView->SetColourContext(COLOURMODEL_CMYK, NULL);
02329 }
02330 
02331 
02332 
02333 /********************************************************************************************
02334 
02335 >   BOOL PrintControl::MorePlates()
02336 
02337     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02338     Created:    11/6/96
02339     Inputs:     -
02340     Returns:    TRUE if there is more plates to come
02341                 FALSE if there's no more plates. 
02342     Purpose:    Call this to determin whether there are more plates to print during this
02343                 separation.
02344 
02345 ********************************************************************************************/
02346 
02347 BOOL PrintControl::MorePlates()
02348 {
02349     return (Typesetting.NumPrintPlatesRemaining() > 0);
02350 }
02351 
02352 
02353 /********************************************************************************************
02354 
02355 >   void PrintControl::SetNextPlate(PrintView *pPrintView)
02356 
02357     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02358     Created:    11/6/96
02359     Inputs:     pPrintView = a pointer to the print view class.
02360     Returns:    -
02361     Purpose:    Call this to set up the view related data ready for the next plate rendering
02362     
02363 ********************************************************************************************/
02364 
02365 BOOL PrintControl::SetNextPlate(PrintView *pPrintView)
02366 {
02367     // If there's no view, drawing will be rather tricky
02368     if (pPrintView == NULL)
02369     {
02370         ERROR3("Sanity check, The view is NULL during SetNextPlate!");
02371         return FALSE;
02372     }
02373 
02374     // If we are not separating then do nothing but make sure
02375     // we force MorePlates() to terminate properly the next time
02376     // around.
02377     if (!Typesetting.AreSeparating())
02378     {
02379         Typesetting.SetNextCompositePlate();
02380         return TRUE;
02381     }
02382 
02383     // Find the next printing plate. We need to call this to decrement
02384     // the plate printing count and other such unsightlyness so that MorePlates
02385     // executes correctly. 
02386     ColourPlate *pPrintPlate = Typesetting.GetNextPrintPlate();
02387     if (pPrintPlate==NULL)
02388     {
02389         // There are no more plates left to print. MorePlates() has 
02390         // failed in its duty and should be shot.
02391         return FALSE;
02392     }
02393 
02394     // We now need to set this plate in the print view in order
02395     // to describe the separation correctly, this should be pretty easy
02396     // if we can get a hold of the print view of course.
02397     pPrintView->SetColourPlate(pPrintPlate);
02398 
02399     return TRUE;
02400 }
02401 
02402 
02403 
02404 
02405 /********************************************************************************************
02406 
02407 >   void PrintControl::RenderRect(RenderRegion* pRRegion,DocRect Rect,BOOL Fill)
02408 
02409     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02410     Created:    9/5/95
02411     Inputs:     pRRegion    = ptr to a render region
02412                 Rect        = rect to redraw
02413                 Fill        = TRUE if filled, FALSE if empty
02414     Outputs:    -
02415     Returns:    -
02416     Purpose:    Renders the rect given
02417     SeeAlso:    RenderPrintBorders()
02418 
02419 ********************************************************************************************/
02420 
02421 void PrintControl::RenderRect(RenderRegion* pRRegion,DocRect Rect,BOOL Fill)
02422 {
02423     if (Rect.IsValid() && !Rect.IsEmpty())
02424     {
02425         if (Fill)
02426             pRRegion->DrawRect(&Rect);
02427         else
02428             pRRegion->DrawPixelRect(&Rect);
02429     }
02430 }
02431 
02432 /********************************************************************************************
02433 
02434 >   void PrintControl::RenderPrintBorder(RenderRegion* pRRegion)
02435 
02436     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02437     Created:    26/4/95
02438     Inputs:     pRRegion = ptr to a render region
02439     Outputs:    -
02440     Returns:    -
02441     Purpose:    Renders the printable area on the spread according to the current print layout method.
02442     SeeAlso:    StartPrinting(), GetNextPaper(), EndPrinting()
02443     Note:       As we are being given a render region that may be in the background redraw list,
02444                 forcing a redraw of documents is very bad as this **MAY** delete the render region
02445                 we hae been given. This used to happen if setup hadn't been called before when
02446                 routine was entered for the first time.
02447 
02448 ********************************************************************************************/
02449 
02450 void PrintControl::RenderPrintBorder(RenderRegion* pRRegion)
02451 {
02452     if (SetUpFailed)
02453         return;
02454 
02455     BOOL DrawBorders = FALSE;
02456 
02457     switch (FitType)
02458     {
02459         // Always try and show print borders for these fit types
02460         case PRINTFIT_BEST:
02461         case PRINTFIT_BESTPAPER:
02462         case PRINTFIT_CUSTOM:
02463             DrawBorders = TRUE;
02464             break;
02465 
02466         // Only try and show print borders for multiple fit when doing 1 row by 1 column
02467         case PRINTFIT_MULTIPLE:
02468             DrawBorders = ((Rows == 1) && (Columns == 1));
02469             break;
02470 
02471         default: 
02472             ERROR3_PF(("Unknown fit type (%d)",FitType)); 
02473             break;
02474     }
02475 
02476     // If we can draw borders for this fit type, ensure that the relevent info is available to do so
02477     if (DrawBorders)
02478     {
02479         // Neville 29/8/97
02480         // As we are being passed a render region and so might be in the background redraw
02481         // loop, we must not force a redraw of the doc if we haven't called set up before.
02482         // If we do then this render region may be deleted and we wont get told about it.
02483         // This is bad! e.g. Load document with print borders set and have a font replacement
02484         // message go off.
02485         if (!PrintAreaSetUp)
02486             DrawBorders = SetUp(Document::GetSelectedSpread(), FALSE);
02487         else
02488             DrawBorders = SetUp(pSpread, FALSE);
02489     }
02490 
02491     // If the fit type is right, and we have all the info, draw the borders
02492     if (DrawBorders)
02493     {
02494         double ScaleFactor  = 100.0 / Scale.MakeDouble();
02495 
02496         INT32 ScaledPaperWidth  = INT32(double(PaperWidth) *ScaleFactor);
02497         INT32 ScaledPaperHeight = INT32(double(PaperHeight)*ScaleFactor);
02498         INT32 ScaledPAWidth     = INT32(double(PrintableArea.Width()) *ScaleFactor);
02499         INT32 ScaledPAHeight    = INT32(double(PrintableArea.Height())*ScaleFactor);
02500         INT32 ScaledPALeftMargin = INT32(double(PALeftMargin)*ScaleFactor);
02501         INT32 ScaledPATopMargin     = INT32(double(PATopMargin) *ScaleFactor);
02502         INT32 ScaledLeftMargin  = INT32(double(LeftMargin)  *ScaleFactor)+CropLeftMargin;
02503         INT32 ScaledTopMargin   = INT32(double(TopMargin)   *ScaleFactor)+CropTopMargin;
02504 
02505         INT32 StartPageNum = 0;                     // We're starting from page 0 (the left page) by default
02506         INT32 NumPages = GetNumPrintablePages();    // Find out how many we need to print
02507 
02508         // If we're only printing the right page, then start from page 1 (the right page)
02509         // and increment the number of pages by 1 (i.e. the loop terminating value)
02510         // This will make sure that the print borders get drawn over the right page
02511         if ((NumPages == 1) && (DPSPrintRange == PRINTRANGEDPS_RIGHTPAGES))
02512         {
02513             StartPageNum = 1;
02514             NumPages++;
02515         }
02516 
02517         for (INT32 PageNum = StartPageNum;PageNum < NumPages;PageNum++)
02518         {
02519             StockColour PaperCol  = COLOUR_YELLOW;
02520             StockColour PrAreaCol = COLOUR_RED;
02521 
02522             if (PageNum > 0)
02523             {
02524                 PaperCol  = COLOUR_GREEN;
02525                 PrAreaCol = COLOUR_BLUE;
02526             }
02527 
02528             // PagePrintArea defines the portion of the spread that is printable (this
02529             // is either the whole spread, or a single page when printing DPS & individual pages)
02530             DocRect PagePrintArea = TotalPrintArea;
02531             PagePrintArea.lo.x += OrigPageWidth*PageNum;
02532             PagePrintArea.hi.x = PagePrintArea.lo.x + OrigPageWidth;
02533             PagePrintArea.hi.y = PagePrintArea.lo.y + OrigPageHeight;
02534 
02535             // PrbleArea will define the printable area in relation to the current spread
02536             DocRect PrbleArea = PagePrintArea;
02537 
02538             // PaperArea represents the total area of the paper in the printer
02539             DocRect PaperArea;
02540 
02541             // If printing sideways, the width and height of the printable area should be swapped
02542             if (Orient == PRINTORIENTATION_SIDEWAYS)
02543             {
02544                 PrbleArea.hi.x = PrbleArea.lo.x+ScaledPAHeight;
02545                 PrbleArea.hi.y = PrbleArea.lo.y+ScaledPAWidth;
02546                 PrbleArea.Translate(ScaledPATopMargin,ScaledPALeftMargin);
02547                 PrbleArea.Translate(-ScaledTopMargin,-ScaledLeftMargin);
02548 
02549                 PaperArea = PrbleArea;
02550                 PaperArea.Translate(-ScaledPATopMargin,-ScaledPALeftMargin);
02551                 PaperArea.hi.x = PaperArea.lo.x + ScaledPaperHeight;
02552                 PaperArea.hi.y = PaperArea.lo.y + ScaledPaperWidth;
02553             }
02554             else
02555             {
02556                 PrbleArea.hi.x = PrbleArea.lo.x+ScaledPAWidth;
02557                 PrbleArea.lo.y = PrbleArea.hi.y-ScaledPAHeight;
02558                 PrbleArea.Translate(ScaledPALeftMargin,-ScaledPATopMargin);
02559                 PrbleArea.Translate(-ScaledLeftMargin,ScaledTopMargin);
02560 
02561                 PaperArea = PrbleArea;
02562                 PaperArea.Translate(-ScaledPALeftMargin,ScaledPATopMargin);
02563                 PaperArea.hi.x = PaperArea.lo.x + ScaledPaperWidth;
02564                 PaperArea.lo.y = PaperArea.hi.y - ScaledPaperHeight;
02565             }
02566 
02567             // We need to draw four grey slabs that show the areas on the page that will
02568             // not be printed
02569 
02570             pRRegion->SetLineColour(COLOUR_NONE);
02571             pRRegion->SetFillColour(COLOUR_MIDGREY);
02572 
02573             DocRect Slab = PagePrintArea;
02574             Slab.hi.x = PrbleArea.lo.x;
02575             RenderRect(pRRegion,Slab,TRUE);
02576 
02577             Slab = PagePrintArea;
02578             Slab.lo.x = PrbleArea.hi.x;
02579             RenderRect(pRRegion,Slab,TRUE);
02580 
02581             Slab = PagePrintArea;
02582             Slab.hi.y = PrbleArea.lo.y;
02583             RenderRect(pRRegion,Slab,TRUE);
02584 
02585             Slab = PagePrintArea;
02586             Slab.lo.y = PrbleArea.hi.y;
02587             RenderRect(pRRegion,Slab,TRUE);
02588 
02589             pRRegion->SetFillColour(COLOUR_BLACK);
02590             RenderRect(pRRegion,PagePrintArea,FALSE);
02591 
02592             pRRegion->SetFillColour(PrAreaCol);
02593             RenderRect(pRRegion,PrbleArea,FALSE);
02594 
02595             pRRegion->SetFillColour(PaperCol);
02596             RenderRect(pRRegion,PaperArea,FALSE);
02597         }
02598     }
02599 }
02600 
02601 /********************************************************************************************
02602 
02603 >   BOOL PrintControl::RedrawPrintableArea(DocView* pDocView)
02604 
02605     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02606     Created:    10/5/95
02607     Inputs:     pDocView - ptr to DocView to redraw
02608     Outputs:    -
02609     Returns:    -
02610     Purpose:    This func can be passed as a param to Document::ForceRedraw() and hence can control
02611                 which views get redraw.
02612                 This func ensures that only views that are showing print borders get redrawn.
02613     SeeAlso:    StartPrinting(), GetNextPaper(), EndPrinting()
02614 
02615 ********************************************************************************************/
02616 
02617 BOOL PrintControl::RedrawPrintableArea(DocView* pDocView)
02618 {
02619     if (pDocView->GetShowPrintBorders())
02620         return(TRUE);
02621     
02622     ColourPlateType PlateType = COLOURPLATE_NONE;
02623     if (pDocView->GetColourPlate() && !pDocView->GetColourPlate()->IsDisabled())
02624         PlateType = pDocView->GetColourPlate()->GetType();
02625         
02626     return(PlateType != COLOURPLATE_NONE && PlateType != COLOURPLATE_COMPOSITE);
02627 }
02628 
02629 
02630 //------------------------------------------------------------
02631 //------------------------------------------------------------
02632 //------------------------------------------------------------
02633 
02634 /******************************************************************************************
02635 
02636 >   PrintPatchInfo::PrintPatchInfo()
02637 
02638     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02639     Created:    26/4/95
02640     Inputs:     -
02641     Outputs:    -
02642     Returns:    -
02643     Purpose:    Default constructor
02644     Errors:     -
02645     SeeAlso:    -
02646 
02647 ******************************************************************************************/
02648 
02649 PrintPatchInfo::PrintPatchInfo()
02650 {
02651     Scale           = FIXED16(100);
02652     XTrans          = 0;
02653     YTrans          = 0;
02654     ClipRect        = DocRect(0,0,0,0);
02655     Rotate          = FALSE;
02656     SelectedOnly    = FALSE;
02657     EmulsionDown    = FALSE;
02658     VisibleLayers   = TRUE;
02659     pSpread         = NULL;
02660     PaperWidth      = 0;
02661     PaperHeight     = 0;
02662 
02663 
02664     PaperNumber     = 0;
02665     MaxPaperNumber  = 0;
02666     PatchNumber     = 0;
02667     MaxPatchNumber  = 0;
02668 };
02669 
02670 /******************************************************************************************
02671 
02672 >   PrintPatchInfo::~PrintPatchInfo()
02673 
02674     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02675     Created:    26/4/95
02676     Inputs:     -
02677     Outputs:    -
02678     Returns:    -
02679     Purpose:    Default deconstructor
02680     Errors:     -
02681     SeeAlso:    PrintPatchInfo()::PrintPatchInfo()
02682 
02683 ******************************************************************************************/
02684 
02685 PrintPatchInfo::~PrintPatchInfo()
02686 {
02687     // Does nowt as yet
02688 }
02689 
02690 
02691 /******************************************************************************************
02692 
02693 >   DocRect PrintPatchInfo::GetClipRect(BOOL AddBleed, BOOL AddCropArea)
02694 
02695     Author  :   Mike
02696     Created :   11/6/95 
02697     Inputs  :   AddBleed    = Inflate the output clip rectangle by the bleed value
02698                 AddCropArea = Inflate the output clip rectangle by the crop area
02699     Returns :   A clip rectangle.
02700     Purpose :   Return the value of the clip rectangle held in this structure. The clip
02701                 rectangle is defined to fit snuggly around a page. No other inflations
02702                 should or do occur around this clip rectangle. However the printing mechanism
02703                 needs to know about bleed sizes and cropmark areas in order to render
02704                 and clip objects correctly so it uses inflated rectangles on occasions.
02705                 It should not and cannot inflate rectangles itself however because this
02706                 would assume knowledge of patch positioning which only the printcontrol
02707                 class knows anything about.
02708 
02709 ******************************************************************************************/
02710 
02711 DocRect PrintPatchInfo::GetClipRect(BOOL AddBleed, BOOL AddCropArea) const
02712 {
02713     DocRect Temp = ClipRect;
02714     InflateRectBy(&Temp, AddBleed, AddCropArea);
02715     return Temp;
02716 }
02717 
02718 void PrintPatchInfo::InflateRectBy(DocRect *pRect, BOOL AddBleed, BOOL AddCropArea) const
02719 {
02720     if (AddBleed)
02721         pRect->Inflate(Bleed);
02722     if (AddCropArea)
02723         pRect->Inflate(CropArea);
02724 }
02725 
02726 void PrintPatchInfo::InflateRectBy(OilRect *pRect, BOOL AddBleed, BOOL AddCropArea) const
02727 {
02728     if (AddBleed)
02729         pRect->Inflate(Bleed);
02730     if (AddCropArea)
02731         pRect->Inflate(CropArea);
02732 }
02733 
02734 void PrintPatchInfo::DeflateRectBy(DocRect *pRect, BOOL AddBleed, BOOL AddCropArea) const
02735 {
02736     if (AddBleed)
02737         pRect->Inflate(-Bleed);
02738     if (AddCropArea)
02739         pRect->Inflate(-CropArea);
02740 }
02741 
02742 MILLIPOINT PrintPatchInfo::GetBleed() const
02743 {
02744     return Bleed;
02745 }
02746 
02747 MILLIPOINT PrintPatchInfo::GetCropArea() const
02748 {
02749     return CropArea;
02750 }
02751 
02752 
02753 
02754 /******************************************************************************************
02755 
02756 >   TypesetInfo::TypesetInfo()
02757 
02758     Author  : Mike
02759     Created : 11/6/95 
02760     Purpose : The default constructor for the typesetting class. We use this class to
02761               define the typesetting requirements of the next print run.
02762 
02763 ******************************************************************************************/
02764 
02765 TypesetInfo::TypesetInfo()
02766 {
02767     MakeSeparations     = FALSE;
02768 
02769     PrintResolution     = 300;
02770 
02771     ScreenFrequency     = 60.0;
02772     DefaultScreenType   = SCRTYPE_SPOT1;
02773 
02774     UseScreening        = FALSE;
02775     ShowPrintersMarks   = FALSE;
02776 
02777     EmulsionDown        = FALSE;
02778     PhotoNegative       = FALSE;
02779     OverprintBlack      = FALSE;
02780 
02781     NumPrintPlates      = 0;
02782     CurrPrintPlateNum   = 0;
02783     CurrentPlate        = NULL;
02784     CurrentPrintPlate   = NULL;
02785 }
02786 
02787 
02788 
02789 /******************************************************************************************
02790 
02791 >   TypesetInfo::~TypesetInfo()
02792 
02793     Author  : Mike
02794     Created : 11/6/95 
02795     Purpose : The destructor. We must remove all items from our PrintingPlates list
02796               and delete them, otherwise the base list class will complain profusely.
02797 
02798 ******************************************************************************************/
02799 
02800 TypesetInfo::~TypesetInfo()
02801 {
02802     DestroyPlateList();
02803 }
02804 
02805 
02806 /******************************************************************************************
02807 
02808 >   static TypesetInfo *TypesetInfo::FindTypesetInfoForDoc(Document *pDoc = NULL);
02809 
02810     Author  : Jason
02811     Created : 15/8/96
02812     Inputs  : pDoc = NULL (to look in selected doc) or the document to find the info for
02813     Returns : NULL, or the selected doc's TypesetInfo
02814     Purpose : Conveniently find the typeset info for the given document
02815 
02816 ******************************************************************************************/
02817 
02818 TypesetInfo *TypesetInfo::FindTypesetInfoForDoc(Document *pDoc)
02819 {
02820     if (pDoc == NULL)
02821         pDoc = Document::GetSelected();
02822 
02823     ERROR2IF(pDoc == NULL, NULL, "No document to find typeset info for!");
02824 
02825     // Find the doc's print component
02826     PrintComponent *pPrComp = (PrintComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(PrintComponent));
02827     ERROR2IF(pPrComp == NULL, NULL, "Can't find a document's print component");
02828 
02829     // Find a ptr to the print component's print control object
02830     PrintControl* pPrCtrl = pPrComp->GetPrintControl();
02831     ERROR2IF(pPrCtrl == NULL, NULL, "The doc's print component gave me a NULL print control object");
02832 
02833     TypesetInfo *pTInfo = pPrCtrl->GetTypesetInfo();
02834     ERROR2IF(pTInfo == NULL, NULL, "The doc's print control object gave me a NULL TypesetInfo object");
02835 
02836     return(pTInfo);
02837 }
02838 
02839 
02840 
02841 /******************************************************************************************
02842 
02843 >   TypesetInfo& TypesetInfo::operator=(TypesetInfo& other)
02844 
02845     Author  : Jason
02846     Created : 17/9/96
02847 
02848     Inputs  : other - the TypesetInfo object to copy
02849     Returns : the copy (this)
02850 
02851     Purpose : TypesetInfo assignment operator
02852 
02853 ******************************************************************************************/
02854 
02855 TypesetInfo& TypesetInfo::operator=(TypesetInfo& other)
02856 {
02857     MakeSeparations     = other.MakeSeparations;
02858     PrintResolution     = other.PrintResolution;
02859     ScreenFrequency     = other.ScreenFrequency;
02860     DefaultScreenType   = other.DefaultScreenType;
02861 
02862     UseScreening        = other.UseScreening;
02863 
02864     ShowPrintersMarks   = other.ShowPrintersMarks;
02865 
02866     EmulsionDown        = other.EmulsionDown;
02867     PhotoNegative       = other.PhotoNegative;
02868     OverprintBlack      = other.OverprintBlack;
02869     PrintSpotAsProcess  = other.PrintSpotAsProcess;
02870 
02871     // Now copy the plate list
02872     // First, vape all pointers to default values
02873     CurrPrintPlateNum   = 0;
02874     CurrentPlate        = NULL;
02875     CurrentPrintPlate   = NULL;
02876 
02877     // Now destroy any plates we may have already
02878     DestroyPlateList();
02879 
02880     ColourPlate *pPlate = other.GetFirstPlate();
02881     while (pPlate != NULL)
02882     {
02883         ColourPlate *pNewPlate = new ColourPlate(*pPlate);
02884 
02885         if (pNewPlate == NULL)
02886             break;
02887 
02888         AddPlate(pNewPlate);
02889         pPlate = other.GetNextPlate(pPlate);
02890     }
02891 
02892     return(*this);
02893 }
02894 
02895 
02896 
02897 /******************************************************************************************
02898 
02899 >   BOOL TypesetInfo::GetScreenName(ScreenType type, StringBase *pString)
02900 
02901     Author  : Mike
02902     Created : 31/08/96
02903     Inputs  : type = the type of screen to find the name for
02904     Returns : TRUE if the type is known
02905               FALSE if the type is unknown - pString will contain the default SPOT name
02906     Purpose : Conveniently convert from a screen type to a textual name
02907 
02908 ******************************************************************************************/
02909 
02910 BOOL TypesetInfo::GetScreenName(ScreenType type, StringBase *pString)
02911 {
02912     ERROR2IF(pString==NULL, FALSE, "NULL output string pointer passed to GetScreenName");
02913 
02914     String_256 Str;
02915     BOOL known=TRUE;    
02916 
02917     switch (type)
02918     {
02919         case SCRTYPE_SPOT2:
02920             Str.Load(_R(IDS_SCRTYPE_SPOT2));
02921             break;
02922         case SCRTYPE_TRIPLESPOT1:
02923             Str.Load(_R(IDS_SCRTYPE_TRIPLESPOT1));
02924             break;
02925         case SCRTYPE_TRIPLESPOT2:
02926             Str.Load(_R(IDS_SCRTYPE_TRIPLESPOT2));
02927             break;
02928         case SCRTYPE_ELLIPTICAL:
02929             Str.Load(_R(IDS_SCRTYPE_ELLIPTICAL));
02930             break;
02931         case SCRTYPE_LINE:
02932             Str.Load(_R(IDS_SCRTYPE_LINE));
02933             break;
02934         case SCRTYPE_CROSSHATCH:
02935             Str.Load(_R(IDS_SCRTYPE_CROSSHATCH));
02936             break;
02937         case SCRTYPE_MEZZOTINT:
02938             Str.Load(_R(IDS_SCRTYPE_MEZZOTINT));
02939             break;
02940         case SCRTYPE_SQUARE:
02941             Str.Load(_R(IDS_SCRTYPE_SQUARE));
02942             break;
02943         case SCRTYPE_DITHER:
02944             Str.Load(_R(IDS_SCRTYPE_DITHER));
02945             break;
02946         case SCRTYPE_SPOT1:
02947             Str.Load(_R(IDS_SCRTYPE_SPOT1));
02948             break;
02949         default:
02950             known=FALSE;
02951             Str.Load(_R(IDS_SCRTYPE_SPOT1));
02952             break;
02953     }   
02954 
02955     (*pString) = Str;
02956 
02957     return known;
02958 }
02959 
02960 
02961 /******************************************************************************************
02962 
02963     void TypesetInfo::SetSeparations(BOOL sep)
02964 
02965     Author  : Mike
02966     Created : 11/6/95 
02967     Inputs  : sep = a boolean which enables or disables separation output
02968     Purpose : To turn off and on printing of separated output.
02969 
02970                 if enabled, we colour-separate all output
02971 
02972                 if disabled, we print normal composite output
02973 
02974 ******************************************************************************************/
02975 
02976 void TypesetInfo::SetSeparations(BOOL sep)
02977 {
02978     MakeSeparations = sep;
02979 }
02980 
02981 
02982 
02983 /******************************************************************************************
02984 
02985     void TypesetInfo::SetScreening(BOOL state, BOOL SetAllPlates = TRUE)
02986 
02987     Author  : Mike
02988     Created : 11/6/95 
02989     Inputs  : sep = a boolean which enables or disables the output of setscreen commands
02990               SetAllPlates = FALSE to simply record the new state in this info class (not
02991                              recommended)
02992                              TRUE to set the state in all the plates held in this class
02993 
02994     Purpose : To turn off and on printing of screened output.
02995 
02996               If screening is enabled, the colour plate screen ang, freq, function
02997               will be output to the printer
02998 
02999               If disabled, no screening info willl be sent, and thus we use the
03000               printer default settings.
03001 
03002 ******************************************************************************************/
03003 
03004 void TypesetInfo::SetScreening(BOOL state, BOOL SetAllPlates)
03005 {
03006     UseScreening = state;
03007     if (SetAllPlates)
03008     {
03009         ColourPlate *pPlate = GetFirstPlate();
03010         while (pPlate != NULL)
03011         {
03012             pPlate->SetActiveScreening(state);  
03013             pPlate = GetNextPlate(pPlate);
03014         }
03015     }
03016 }
03017 
03018 
03019 
03020 /******************************************************************************************
03021 
03022     void TypesetInfo::SetPrintResolution(INT32 res, BOOL SetAllPlates = TRUE);
03023 
03024     Author  : Mike
03025     Created : 11/6/95 
03026     Inputs  : res = a dpi resolution
03027               SetAllPlates = FALSE to simply record the new printer resolution,
03028                              TRUE to reset all contained colour plates to recommended
03029                              default values for the new resolution. This will set 
03030                              angle, freq, and function for all plates.
03031 
03032     Purpose : Use this function to set the prefered postscript device resolution. The
03033               resolution determines the set of preferred screen frequencies.
03034 
03035 ******************************************************************************************/
03036 
03037 void TypesetInfo::SetPrintResolution(INT32 res, BOOL SetAllPlates)
03038 {
03039     PrintResolution = res;
03040 
03041     if (SetAllPlates)
03042         ResetAllPlatesToDefaultScreens();
03043 }
03044 
03045 
03046 
03047 /******************************************************************************************
03048 
03049     void TypesetInfo::SetDefaultScreenFrequency(double freq, BOOL SetAllPlates = TRUE)
03050 
03051     Author  :   Mike
03052     Created :   11/6/95 
03053     Inputs  :   freq = a double representing the screen frequency in lpi (possibly fractional)
03054                 SetAllPlates = FALSE to simply record the new printer resolution,
03055                              TRUE to reset all contained colour plates to this new
03056                              screening frequency.
03057 
03058     Purpose :   Use this function to set the preferred screening frequency used for plates
03059 
03060 ******************************************************************************************/
03061 
03062 void TypesetInfo::SetDefaultScreenFrequency(double freq, BOOL SetAllPlates)
03063 {
03064     if (freq < 2.0 || freq > 10000.0)
03065     {
03066         ERROR3("Silly screen frequency");
03067         return;
03068     }
03069 
03070     ScreenFrequency = freq;
03071 
03072     if (SetAllPlates)
03073         ResetAllPlatesToDefaultScreens();
03074 }
03075 
03076 
03077 
03078 /******************************************************************************************
03079 
03080 >   void TypesetInfo::SetScreenFunction(ScreenType func, BOOL SetAllPlates = TRUE);
03081 
03082     Author  : Mike
03083     Created : 11/6/95 
03084     Inputs  : func   = the screening function to set
03085               setall = TRUE, then set this screen type in all the plates in the plate list
03086                        FALSE - only remember this as the default (not recommended!)
03087 
03088     Purpose : Use this function to set the preferred screening function used for plates
03089     
03090 ******************************************************************************************/
03091 
03092 void TypesetInfo::SetScreenFunction(ScreenType func, BOOL SetAllPlates)
03093 {
03094     DefaultScreenType = func;
03095 
03096     if (SetAllPlates)
03097     {
03098         ColourPlate *pPlate = GetFirstPlate();
03099         while (pPlate != NULL)
03100         {
03101             pPlate->SetScreenFunction(func);    
03102             pPlate = GetNextPlate(pPlate);
03103         }
03104     }
03105 }
03106 
03107 
03108 
03109 /******************************************************************************************
03110 
03111 >   void TypesetInfo::ResetAllPlatesToDefaultScreens(void)
03112 
03113     Author  : Jason
03114     Created : 19/8/96
03115 
03116     Purpose : Resets all attached ColourPlates to the recommended defaults for:
03117                 Screen Angle
03118                 Screen Frequency
03119                 Screen Function (dot shape)
03120 
03121     SeeAlso:    SetPrintResolution; SetDefaultScreenFrequency; SetScreenFunction
03122 
03123 ******************************************************************************************/
03124 
03125 void TypesetInfo::ResetAllPlatesToDefaultScreens(void)
03126 {
03127     INT32 Res  = GetPrintResolution();
03128     INT32 Freq = (INT32) floor(GetDefaultScreenFrequency());
03129 
03130     ColourPlate *pPlate = GetFirstPlate();
03131     while (pPlate != NULL)
03132     {
03133         pPlate->ResetScreenToDefaults(Res, Freq);
03134         pPlate->SetScreenFunction(GetScreenFunction());
03135 
03136         pPlate = GetNextPlate(pPlate);
03137     }
03138 }
03139 
03140 
03141 
03142 /******************************************************************************************
03143 
03144 >   void TypesetInfo::EnsureAllPlatesHaveGlobalSettigns(void)
03145 
03146     Author  : Jason
03147     Created : 18/9/96
03148 
03149     Purpose :   For convenience and efficiency while rendering print jobs, ColourPlates
03150                 have their own copies of certain "global" flags (such as whether
03151                 screening is enabled).
03152 
03153                 As a consequence of this slightly untidy situation, it is possible for
03154                 the colour plates to get out of step with the overall option stored
03155                 in the TypesetInfo. To get around this, this function simply copies the
03156                 overall option from the TypesetInfo into all its colour plates.
03157 
03158                 It should be called prior to printing etc to ensure that these 'global'
03159                 settings are consistent across all plates and the parent TypesettingInfo
03160 
03161     Notes:      Currently copies the following states:
03162                     * Screen function
03163                     * Screening enabled flag
03164 
03165 ******************************************************************************************/
03166 
03167 void TypesetInfo::EnsureAllPlatesHaveGlobalSettings(void)
03168 {
03169     ColourPlate *pPlate = GetFirstPlate();
03170     while (pPlate != NULL)
03171     {
03172         pPlate->SetScreenFunction(GetScreenFunction());
03173         pPlate->SetActiveScreening(AreScreening());
03174 
03175         pPlate = GetNextPlate(pPlate);
03176     }   
03177 }
03178 
03179 
03180 
03181 /******************************************************************************************
03182 
03183 >   void TypesetInfo::SetPhotoNegative(BOOL state)
03184 
03185     Author  : Mike
03186     Created : 11/6/95 
03187     Inputs  : state  = the state of the photonegative flag
03188     Purpose : Use this function to set the photonegative local flag.
03189     
03190 ******************************************************************************************/
03191 
03192 void TypesetInfo::SetPhotoNegative(BOOL state)
03193 {
03194     PhotoNegative = state;
03195 }
03196 
03197 
03198 /******************************************************************************************
03199 
03200 >   void TypesetInfo::SetOverprintBlack(BOOL Always)
03201 
03202     Author  :   Jason
03203     Created :   7/8/96
03204 
03205     Inputs  :   Always - FALSE to disbale, or TRUE to enable "Always overprint black"
03206 
03207     Purpose :   Sets whether "black" will be always be overprinted automatically.
03208 
03209                 This works as follows:
03210                     Any colour which is defined as CMYK and which has more than 95% Key
03211                     component is considered "black". When AlwaysOverprintBlack is enabled,
03212                     such "black" colours will be overprinted automatically.
03213 
03214                     This option does not affect non-CMYK colours
03215 
03216     Notes:      The TypesetInfo constructor defaults to the FALSE (disabled) state
03217 
03218     SeeAlso:    RenderRegion::PrepareStrokeColour; RenderRegion::PrepareFillGeometry
03219 
03220 ******************************************************************************************/
03221 
03222 void TypesetInfo::SetOverprintBlack(BOOL Always)
03223 {
03224     OverprintBlack = Always;
03225 }
03226 
03227 
03228 
03229 /******************************************************************************************
03230 
03231 >   BOOL TypesetInfo::CheckForExistingPlate(ColourPlateType Type,
03232                                             IndexedColour *SpotColour = NULL)
03233 
03234     Author  : Jason
03235     Created : 25/6/96
03236     Inputs  : Type - The type of plate you are checking for
03237               SpotColour - If Type is COLOURPLATE_SPOT, then SpotColour should point
03238               to the IndexedColour defining the spot plate. It is ignored for all other
03239               types.
03240 
03241     Returns : TRUE if a matching plate is already in the list
03242               FALSE if you'll need to create and add a new plate of that type
03243 
03244     Purpose : Helper function for CreatePlateList. Determines if a plate of the given
03245               type is already available in the ColourPlate list. If Type is
03246               COLOURTYPE_SPOT, then SpotColour must also be specified.
03247 
03248     Notes:    This doesn't find an exact match for the ColourPlate, but simply another
03249               plate of the same type (e.g. Another CYAN plate, or another SPOT plate
03250               which is based on the same spot colour) - all other options (monochrome,
03251               screen settings etc) are ignored in the comparison.
03252 
03253 ******************************************************************************************/
03254 
03255 BOOL TypesetInfo::CheckForExistingPlate(ColourPlateType Type, IndexedColour *SpotColour)
03256 {
03257     ERROR3IF(Type == COLOURPLATE_SPOT && SpotColour == NULL, "Illegal NULL param");
03258 
03259     ColourPlate *Ptr = GetFirstPlate();
03260 
03261     while (Ptr != NULL)
03262     {
03263         if (Ptr->GetType() == Type)
03264         {
03265             // Just for safety we will make sure that the plate uses the same setting
03266             // for screen function as we do. (The plate holds a copy of this info for
03267             // convenience, and we don't really want plates using different screens)
03268             Ptr->SetScreenFunction(GetScreenFunction());
03269 
03270             // The basic types match, but if it's a spot plate, we have to check if
03271             // it is the same actual spot plate before we have an exact match
03272             if (Type == COLOURPLATE_SPOT)
03273             {
03274                 if (Ptr->GetSpotColour() == SpotColour)
03275                     return(TRUE);
03276                 //else 
03277                 //  Not an exact match, so drop through to continue searching
03278             }
03279             else
03280                 return(TRUE);               // The types match, so return TRUE
03281         }
03282 
03283         Ptr = GetNextPlate(Ptr);
03284     }
03285 
03286     // We didn't find it, so return FALSE
03287     return(FALSE);
03288 }
03289 
03290 
03291 
03292 /******************************************************************************************
03293 
03294 >   BOOL TypesetInfo::CreatePlateList()
03295 
03296     Author  : Jason (shell function by Mike)
03297     Created : 25/6/96 (11/6/95 - 95? Are you sure, Mike? ;-)
03298     Inputs  : -
03299     Returns : TRUE if the plate list has been constructed correctly
03300               FALSE if there's nothing in the plate list.
03301 
03302     Purpose : This function initialises or re-initialises the document plate list.
03303               This list contains a set of ColourPlates which will be used to control
03304               the printing of the document. Each plate will produce a distinct pass
03305               in the print loop.
03306 
03307               If the ColourPlate list has already been created, this function will
03308               update it by the following means:
03309               * Ensure that the process (C,M,Y,K) plates are in the list
03310               * Remove any Spot colours from the list which have since been deleted or
03311                 edited to no longer be spot colours
03312               * Add any new spot colours to the plate list
03313 
03314               Any existing plate settings for plates that are still valid will thus
03315               be retained.
03316 
03317 ******************************************************************************************/
03318 
03319 BOOL TypesetInfo::CreatePlateList()
03320 {
03321     ColourPlate *pPlate;
03322 
03323     INT32 Res  = GetPrintResolution();
03324     INT32 Freq = (INT32) floor(GetDefaultScreenFrequency());
03325 
03326     // --- First, make sure we've got a set of process (CMYK) plates...
03327     // Create a cyan plate to print.
03328     if (!CheckForExistingPlate(COLOURPLATE_CYAN))
03329     {
03330         pPlate = new ColourPlate(COLOURPLATE_CYAN, TRUE, FALSE);
03331         if (pPlate)
03332         {
03333             pPlate->ResetScreenToDefaults(Res, Freq);
03334             pPlate->SetScreenFunction(GetScreenFunction());
03335 
03336             AddPlate(pPlate);
03337         }
03338     }
03339 
03340     // Create a magenta plate to print.
03341     if (!CheckForExistingPlate(COLOURPLATE_MAGENTA))
03342     {
03343         pPlate = new ColourPlate(COLOURPLATE_MAGENTA, TRUE, FALSE);
03344         if (pPlate)
03345         {
03346             pPlate->ResetScreenToDefaults(Res, Freq);
03347             pPlate->SetScreenFunction(GetScreenFunction());
03348 
03349             AddPlate(pPlate);
03350         }
03351     }
03352 
03353     // Create a yellow plate to print.
03354     if (!CheckForExistingPlate(COLOURPLATE_YELLOW))
03355     {
03356         pPlate = new ColourPlate(COLOURPLATE_YELLOW, TRUE, FALSE);
03357         if (pPlate)
03358         {
03359             pPlate->ResetScreenToDefaults(Res, Freq);
03360             pPlate->SetScreenFunction(GetScreenFunction());
03361 
03362             AddPlate(pPlate);
03363         }
03364     }
03365 
03366     // Create a key plate to print.
03367     if (!CheckForExistingPlate(COLOURPLATE_KEY))
03368     {
03369         pPlate = new ColourPlate(COLOURPLATE_KEY, TRUE, FALSE);
03370         if (pPlate)
03371         {
03372             pPlate->ResetScreenToDefaults(Res, Freq);
03373             pPlate->SetScreenFunction(GetScreenFunction());
03374 
03375             AddPlate(pPlate);
03376         }
03377     }
03378 
03379 
03380     // --- Second, remove any "dead" plates (spot colours which are now deleted or
03381     //     have been edited so they are no longer spot colours)
03382     pPlate = (ColourPlate *) PrintingPlates.GetHead();
03383     ColourPlate *pNext;
03384     while (pPlate != NULL)
03385     {
03386         pNext = (ColourPlate *) PrintingPlates.GetNext(pPlate);
03387 
03388         if (pPlate->GetType() == COLOURPLATE_SPOT)
03389         {
03390             IndexedColour *pSpot = pPlate->GetSpotColour();
03391             if (pSpot != NULL)
03392             {
03393                 // If it's not a spot colour, or is deleted, then it no longer generates a plate
03394                 if (pSpot->GetType() != COLOURTYPE_SPOT || pSpot->IsDeleted())
03395                 {
03396                     PrintingPlates.RemoveItem(pPlate);
03397                     delete pPlate;
03398                 }
03399             }
03400         }
03401         pPlate = pNext;
03402     }
03403 
03404 
03405     // --- Finally, add plates for any spot colour which is not already accounted for
03406     //     in the existing plate list. We use the colours from the Selected document
03407     ColourList *ColList = ColourManager::GetColourList();
03408     ERROR3IF(ColList == NULL, "Can't find selected ColourList");
03409 
03410     if (ColList != NULL)
03411     {
03412         IndexedColour *IxCol =  (IndexedColour *) ColList->GetUndeletedHead();
03413         while (IxCol != NULL)
03414         {
03415             if (IxCol->GetType() == COLOURTYPE_SPOT)
03416             {
03417                 // We've found a spot colour. Is it already represented by a ColourPlate?
03418                 if (!CheckForExistingPlate(COLOURPLATE_SPOT, IxCol))
03419                 {
03420                     // No, it's not, so we'd better create a new plate for it
03421                     pPlate = new ColourPlate(IxCol, TRUE, FALSE);
03422                     if (pPlate)
03423                     {
03424                         pPlate->ResetScreenToDefaults(Res, Freq);
03425                         pPlate->SetScreenFunction(GetScreenFunction());
03426 
03427                         AddPlate(pPlate);
03428 
03429                         // If this colour is not used in the document, turn off printing of the plate
03430                         // by default. (This isn't brilliant - it'll leave it on if the colour is used
03431                         // in the UNDO, but it's better than leaving it on all the time)
03432                         // NOTE: We pass in TRUE so that it will ignore one use of the colour (the
03433                         // reference from the ColourPlate itself!)
03434                         if (!IxCol->IsInUse(TRUE))
03435                             pPlate->SetDisabled(TRUE);
03436                     }
03437                 }
03438             }
03439 
03440             IxCol = (IndexedColour *) ColList->GetUndeletedNext(IxCol);
03441         }
03442     }
03443 
03444     // And now, just make sure everything is tidy
03445     EnsureAllPlatesHaveGlobalSettings();
03446 
03447     return TRUE;
03448 }
03449 
03450 
03451 
03452 /******************************************************************************************
03453 
03454 >   void TypesetInfo::UpdatePlateList()
03455 
03456     Author  : Mike
03457     Created : 31/08/96
03458     Inputs  : -
03459     Returns : -
03460     Purpose : Makes sure all the plates in the plate list have all values up-to-date.
03461               This is called on StartPrinting(). The reason it is here is that on
03462               start up, the previous settings will be loaded in and set in TypsetInfo.
03463               However, the user could print immediately without bringing up any extra
03464               print option tabs. The list of plates is created needs to be updated with
03465               the loaded settings.
03466 
03467 ******************************************************************************************/
03468 
03469 void TypesetInfo::UpdatePlateList()
03470 {
03471     // Make sure all plate screening values are up-to-date
03472     SetScreening(UseScreening,TRUE);
03473     // Make sure screen plate / lpi / freq / angles are all correct
03474     ResetAllPlatesToDefaultScreens();
03475 }
03476 
03477 
03478 /******************************************************************************************
03479 
03480 >   ColourPlate *TypesetInfo::CreateColourPlate()
03481 
03482     Author  : Jason
03483     Created : 16/8/96
03484     Inputs  : -
03485     Returns : NULL (failed) or a new colour plate
03486 
03487     Purpose : Creates a new colour plate
03488                 The plate defaults to the same as for the ColourPlate() default constructor
03489                 (i.e. COLOURPLATE_NONE), but things like the screen function will be set
03490                 up by copying them from this TypesetInfo object.
03491 
03492                 This function is intended only for use by the native file import code,
03493                 which creates colour plates if any were saved in the file. However, each
03494                 plate takes many settings from its parent TypesetInfo (they're only stored
03495                 in the plate for easy access/efficiency when rendering)
03496 
03497     Notes:  See Also CheckForExistingPlate() which also sets the plate screen functions to
03498             make sure they tow the party line...
03499 
03500 ******************************************************************************************/
03501 
03502 ColourPlate *TypesetInfo::CreateColourPlate()
03503 {
03504     ColourPlate *pNewPlate = new ColourPlate(COLOURPLATE_NONE, TRUE, FALSE);
03505 
03506     // The only special info we currently need to set is the screen function...
03507     if (pNewPlate != NULL)
03508         pNewPlate->SetScreenFunction(GetScreenFunction());
03509 
03510     return(pNewPlate);
03511 }
03512 
03513 
03514 
03515 /******************************************************************************************
03516 
03517 >   void TypesetInfo::DestroyPlateList()
03518 
03519     Author  : Mike
03520     Created : 11/6/95 
03521     Inputs  : -
03522     Returns : -
03523     Purpose : This function simply empties the entire plate list of its contents, deleting
03524               each record as it goes. It is a seriously non-constant function.
03525 
03526 ******************************************************************************************/
03527 
03528 void TypesetInfo::DestroyPlateList()
03529 {
03530     ColourPlate *pPlate;
03531     while ((pPlate=(ColourPlate*)PrintingPlates.RemoveTail())) // Assignment
03532         delete pPlate;
03533 
03534     // We have no plates, so it's best to vape our current pointers
03535     CurrentPlate        = NULL;
03536     CurrentPrintPlate   = NULL;
03537 }
03538 
03539 /******************************************************************************************
03540 
03541 >   void TypesetInfo::AddPlate(ColourPlate* pPlate)
03542 
03543     Author  : Mike
03544     Created : 11/6/95 
03545     Inputs  : pPlate = a pointer to a colour plate
03546     Returns : -
03547     Purpose : Use this function to add a colour plate to the colour plate list.
03548               Note, the calling function no longer has ownership of this object. The object
03549               will be deleted automatically from the list whenever the plate list class is
03550               destroyed.
03551               
03552 ******************************************************************************************/
03553 
03554 void TypesetInfo::AddPlate(ColourPlate* pPlate)
03555 {
03556     ERROR3IF(pPlate==NULL, "AddPlate given a NULL plate pointer!");
03557     PrintingPlates.AddTail(pPlate);
03558 }
03559 
03560 /******************************************************************************************
03561 
03562 >   void TypesetInfo::SetCurrentPlate(ColourPlate* pPlate)
03563 
03564     Author  : Mike
03565     Created : 11/6/95 
03566     Inputs  : pPlate = a pointer to a colour plate
03567     Returns : -
03568     Purpose : Use this function to set the current colour plate. This current plate
03569               object is usually shown as the highlighted plate in the printing dialogue
03570               plate display list.
03571 
03572 ******************************************************************************************/
03573 
03574 void TypesetInfo::SetCurrentPlate(ColourPlate* pPlate)
03575 {
03576     ERROR3IF(pPlate==NULL, "SetCurrentPlate given a NULL plate pointer!");
03577     CurrentPlate = pPlate;
03578 }
03579 
03580 /******************************************************************************************
03581 
03582 >   ColourPlate* TypesetInfo::GetCurrentPlate() const
03583 
03584     Author  : Mike
03585     Created : 11/6/95 
03586     Inputs  : -
03587     Returns : a pointer to the current colour plate
03588     Purpose : Use this function to retrieve a pointer to the current plate.
03589               The current plate variable simply keeps track of the selected plate in the
03590               printing UI. This plate is the one which will receive all edits.
03591               
03592 ******************************************************************************************/
03593 
03594 ColourPlate* TypesetInfo::GetCurrentPlate() const
03595 {
03596     return CurrentPlate;
03597 }
03598 
03599 
03600 /******************************************************************************************
03601 
03602 >   DWORD TypesetInfo::GetNumPlates() const
03603 
03604     Author  : Mike
03605     Created : 11/6/95 
03606     Inputs  : -
03607     Returns : a dword, the number of plates in the list
03608     Purpose : Returns the number of plates in the print class plate list
03609               
03610 ******************************************************************************************/
03611 
03612 DWORD TypesetInfo::GetNumPlates() const
03613 {
03614     return PrintingPlates.GetCount();
03615 }
03616 
03617 
03618 
03619 
03620 /******************************************************************************************
03621 
03622 >   void TypesetInfo::InitPlatesForPrinting()
03623 
03624     Author  : Mike
03625     Created : 11/6/95 
03626     Inputs  : -
03627     Returns : -
03628     Purpose : Set up the plate printing service. This should be called before any attempt
03629               to access the functions GetNextPrintPlate(), NumPrintPlatesRemaining etc
03630               
03631 ******************************************************************************************/
03632 
03633 void TypesetInfo::InitPlatesForPrinting()
03634 {
03635     // We don't need to do anything if we're not separating, but as we
03636     // do nothing but set a plate, we don't need extra check code here
03637     // Set our internal current plate
03638     CurrPrintPlateNum=1;
03639     NumPrintPlates=1;
03640     CurrentPrintPlate=NULL;
03641     PrintPlatesToGo=1;
03642 
03643     if (AreSeparating())
03644     {
03645         NumPrintPlates = GetNumPrintPlates();
03646         PrintPlatesToGo = NumPrintPlates;
03647     }
03648 }
03649 
03650 
03651 
03652 /******************************************************************************************
03653 
03654 >   ColourPlate* TypesetInfo::GetFirstPrintPlate()
03655 
03656     Author  : Mike
03657     Created : 11/6/95 
03658     Inputs  : -
03659     Returns : A pointer to the first print plate (NULL if no more)
03660     Purpose : Return the first plate through which the document will be printed.
03661               The class variables CurrentPrintPlate and CurrPrintPlateNum will be
03662               set.
03663               
03664 ******************************************************************************************/
03665 
03666 ColourPlate* TypesetInfo::GetFirstPrintPlate()
03667 {
03668     // Retrieve the first plate from the list
03669     ColourPlate *pPlate = GetFirstPlate();
03670     return GetPrintPlate(0,pPlate);
03671 }
03672 
03673 /******************************************************************************************
03674 
03675 >   ColourPlate* TypesetInfo::GetNextPrintPlate()
03676 
03677     Author  : Mike
03678     Created : 11/6/95 
03679     Inputs  : -
03680     Returns : A pointer to the next print plate (NULL if no more)
03681     Purpose : Return the next plate through which the document will be printed.
03682               The class variables CurrentPrintPlate and CurrPrintPlateNum will be
03683               used to determin the next plate
03684               
03685 ******************************************************************************************/
03686 
03687 ColourPlate* TypesetInfo::GetNextPrintPlate()
03688 {
03689     ColourPlate *pPlate;
03690     if (CurrentPrintPlate==NULL)
03691     {
03692         // Retrieve the first plate from the list
03693         pPlate = GetFirstPlate();
03694         return GetPrintPlate(0,pPlate);
03695     }
03696     // otherwise retrieve the next plate
03697     pPlate = GetNextPlate(CurrentPrintPlate);
03698     return GetPrintPlate(CurrPrintPlateNum,pPlate);
03699 }
03700 
03701 
03702 /******************************************************************************************
03703 
03704     ColourPlate* TypesetInfo::GetPrintPlate(DWORD num, ColourPlate* pPlate)
03705 
03706     Author  : Mike
03707     Created : 11/6/95 
03708     Inputs  : num = the number of the plate
03709               pPlate = a pointer to the plate
03710     Returns : A pointer to a print plate (NULL if none)
03711     Purpose : This function is an internal helper function to GetFirstPrintPlate() and
03712               GetNextPrintPlate()
03713               
03714 ******************************************************************************************/
03715 
03716 ColourPlate* TypesetInfo::GetPrintPlate(DWORD pnum, ColourPlate* pPlate)
03717 {
03718     while (pPlate!=NULL)
03719     {
03720         pnum++;
03721         // if this plate is not disabled then return it
03722         if (!pPlate->IsDisabled())
03723         {
03724             CurrPrintPlateNum=pnum;
03725             PrintPlatesToGo--;
03726             return (CurrentPrintPlate=pPlate);
03727         }
03728         pPlate=GetNextPlate(pPlate);
03729     }
03730     return NULL;
03731 }
03732 
03733 
03734 /******************************************************************************************
03735 
03736 >   DWORD TypesetInfo::GetNumPrintPlates() const
03737 
03738     Author  : Mike
03739     Created : 11/6/95 
03740     Inputs  : -
03741     Returns : A DWORD, the number of plates this document can theoretically be separated
03742               to. This will usually be 4 (C,M,Y and K) plus any spot colour plates
03743     Purpose : Find out how many print plates are stored in the plate list.
03744               
03745 ******************************************************************************************/
03746 
03747 DWORD TypesetInfo::GetNumPrintPlates() const
03748 {
03749     ColourPlate* pPlate;
03750     DWORD        nPlates=0;
03751 
03752     pPlate = GetFirstPlate();
03753     while (pPlate!=NULL)
03754     {
03755         if (!pPlate->IsDisabled())
03756             nPlates++;
03757         pPlate=GetNextPlate(pPlate);
03758     }       
03759     return nPlates;
03760 }
03761 
03762 
03763 /******************************************************************************************
03764 
03765 >   ColourPlate* TypesetInfo::GetCurrentPlate() const
03766 
03767     Author  : Jason
03768     Created : 5/8/96
03769     Inputs  : -
03770     Returns : a pointer to the currently PRINTING colour plate
03771     Purpose : Use this function to retrieve a pointer to the currently printing plate.
03772               
03773 ******************************************************************************************/
03774 
03775 ColourPlate* TypesetInfo::GetCurrentPrintPlate() const
03776 {
03777     return CurrentPrintPlate;
03778 }
03779 
03780 
03781 /******************************************************************************************
03782 
03783 >   void TypesetInfo::NumPrintPlatesRemaining()
03784 
03785     Author  : Mike
03786     Created : 11/6/95 
03787     Inputs  : -
03788     Returns : The number of plate which remain to be printed
03789     Purpose : Calculate and return the number of plates remaining for this piece of paper
03790               
03791 ******************************************************************************************/
03792 
03793 INT32 TypesetInfo::NumPrintPlatesRemaining() const
03794 {
03795     // Calculate the number of plates remaining print
03796     return ( PrintPlatesToGo );
03797 }
03798 
03799 
03800 /******************************************************************************************
03801 
03802 >   void TypesetInfo::SetNextCompositePlate()
03803 
03804     Author  : Mike
03805     Created : 11/6/95 
03806     Inputs  : -
03807     Returns : -
03808     Purpose : Called from PrintControl::SetNextPlate(). This function simply allows
03809               composite printing to pass around the plate loop once without actually
03810               setting any plates. This function will set the internal typeset plate
03811               variables so that MorePlates() will return FALSE the next time it is
03812               called.
03813               
03814 ******************************************************************************************/
03815 
03816 void TypesetInfo::SetNextCompositePlate()
03817 {
03818     // Do absolutely nothing if we are in separation mode
03819     if (AreSeparating())
03820         return;
03821 
03822     // Set out internal variables so a call to MorePlates()
03823     // will terminate the print loop
03824     CurrentPrintPlate=NULL;
03825     PrintPlatesToGo=0;
03826 }

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