prntview.cpp

Go to the documentation of this file.
00001 // $Id: prntview.cpp 1354 2006-06-23 20:23:25Z 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 // PrintView - subclass of DocView used for printing.
00100 
00101 /*
00102 */
00103 
00104 #include "camtypes.h"
00105 
00106 #include "prntview.h"
00107 
00108 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "camelot.h"
00110 #include "ccdc.h"
00111 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "princomp.h"
00116 #include "printctl.h"
00117 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 #include "prncamvw.h"
00119 #include "vstate.h"
00120 #include "osrndrgn.h"
00121 
00122 DECLARE_SOURCE("$Revision: 1354 $");
00123 
00124 
00125 CC_IMPLEMENT_DYNAMIC(PrintView, View)
00126 
00127 
00128 #define new CAM_DEBUG_NEW
00129 
00130 
00131 /********************************************************************************************
00132 
00133 >   PrintView::PrintView(Document *pOwnerDoc)
00134 
00135     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00136     Created:    02/08/95
00137     Inputs:     pDocument - the document to attach to (i.e. the one to print)
00138     Purpose:    None
00139     SeeAlso:    PrintView; View
00140 
00141 ********************************************************************************************/
00142 
00143 PrintView::PrintView(Document *pOwnerDoc)
00144 {
00145     // Set up document; no CamView yet.
00146     pDoc = pOwnerDoc;
00147     pViewWindow = NULL;
00148 
00149     // No DC yet
00150     PrintDC = NULL;
00151 
00152     // BODGE ALERT!!! Do this properly sometime.
00153     pVState = new ViewState;
00154 PORTNOTE("printing", "removed broken memory handling")
00155 #ifndef EXCLUDE_FROM_XARALX
00156     if (pVState == NULL) 
00157         AfxThrowMemoryException();
00158 #endif
00159 
00160     // Connect this view state to this view
00161     pVState->pView = this;
00162 
00163     // Get print information for this document.
00164     PrintComponent *pPrint = 
00165         (PrintComponent *) pOwnerDoc->GetDocComponent(CC_RUNTIME_CLASS(PrintComponent));
00166     if (pPrint == NULL)
00167     {
00168         ERROR2RAW("Unable to find PrintComponent in document.");
00169         return;
00170     }
00171 
00172     PrintControl *pPrintControl = pPrint->GetPrintControl();
00173     if (pPrintControl == NULL)
00174     {
00175         ERROR2RAW("Unable to find PrintControl object in document component.");
00176         return;
00177     }
00178 
00179     PrintMethodType PrintType = pPrintControl->GetPrintMethod();
00180 
00181     // Work out whether or not to Anti-alias printing
00182     if (PrintType == PRINTMETHOD_AABITMAP)
00183     {
00184         Quality AntiAlias(Quality::QualityMax);
00185         RenderQuality = AntiAlias;
00186     }
00187 }
00188 
00189 /********************************************************************************************
00190 
00191 >   ~PrintView::PrintView()
00192 
00193     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00194     Created:    02/08/95
00195     Purpose:    Destroys a printing view - this is because it has finished printing or
00196                 something went wrong during printing.
00197     SeeAlso:    PrintView; View
00198 
00199 ********************************************************************************************/
00200 
00201 PrintView::~PrintView()
00202 {
00203 }
00204 
00205 
00206 
00207 /********************************************************************************************
00208 
00209 >   CDC *PrintView::GetRenderDC()
00210 
00211     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00212     Created:    02/09/95
00213     Returns:    The printer DC.
00214     Purpose:    Access function for the device context of this printing view object.
00215     SeeAlso:    View; DocView
00216 
00217 ********************************************************************************************/
00218 
00219 CNativeDC *PrintView::GetRenderDC()
00220 {
00221     return PrintDC;
00222 }
00223 
00224 
00225 
00226 
00227 /********************************************************************************************
00228 
00229 >   void PrintView::ContinueRenderView(RenderRegion* pRRegion, Spread* pSpread,
00230                                        BOOL fRenderPaper = TRUE,
00231                                        BOOL fDeleteRegionAfter = TRUE,
00232                                      BOOL bForceImmediate = FALSE)
00233 
00234     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00235     Created:    02/09/95
00236     Inputs:     pRRegion - the region to use to render the view.
00237                 pSpread - the spread that is being rendered.
00238                 fRenderPaper --- by default TRUE, ignored anyway because we
00239                                  have *REAL* paper to scribble on.
00240                 fDeleteRegionAfter --- if TRUE then the View will deallocate the
00241                 render-region when it has finished rendering.  If FALSE then it
00242                 won't.  By default TRUE.
00243     Purpose:    Used by RenderRegion::DefaultRender() to carry on rendering a view.
00244                 In this case (i.e. printing) it only gets called once, as it calls
00245                 RenderView which prints the view in one go, i.e. we don't do
00246                 background rendering.
00247 
00248 ********************************************************************************************/
00249 
00250 void PrintView::ContinueRenderView(RenderRegion* pRRegion, Spread* pSpread,
00251                                    BOOL fRenderPaper, BOOL fDeleteRegionAfter,
00252                                      BOOL bForceImmediate)
00253 {
00254     // Disable bitmap caching but remember the old state so we can set it back
00255     ScopedFlagSetter fsBitmapCacheing(NodeRenderableBounded::bEnableCacheing, FALSE);
00256     
00257     // make sure the region is ok
00258     if (pRRegion==NULL)
00259         return;
00260 
00261     // We need to find out what sort of rendering we need to do, based on the options
00262     // in the print dialog. Start by finding the view and the doc we are printing
00263     Document* pDoc = GetDoc();
00264     if (pDoc!=NULL)
00265     {
00266         // Find print control object for this document, to see if we are
00267         // printing via bitmap or normally
00268         PrintComponent *pPrintComponent = (PrintComponent *)
00269             pDoc->GetDocComponent(CC_RUNTIME_CLASS(PrintComponent));
00270         
00271         // see if it exists or not.
00272         if (pPrintComponent==NULL)
00273         {
00274             if (fDeleteRegionAfter) delete pRRegion;
00275             return;
00276         }
00277 
00278         // Find the Print Control out of the component
00279         PrintControl *pPrintControl = pPrintComponent->GetPrintControl();
00280         if (pPrintControl == NULL)
00281         {
00282             if (fDeleteRegionAfter) delete pRRegion;
00283             return;
00284         }
00285 
00286         // and finally find out the printing method
00287         PrintMethodType PrintType = pPrintControl->GetPrintMethod();
00288         if ((PrintType == PRINTMETHOD_AABITMAP) || (PrintType == PRINTMETHOD_BITMAP))
00289         {
00290             // Get the region to clip all the rendering to
00291             DocRect ClipRect = pRRegion->GetClipRect();
00292             Matrix ViewTrans = pRRegion->GetMatrix();
00293 
00294             // Tell the RenderRegion that I am going to start rendering.
00295             if (!pRRegion->StartRender())
00296             {
00297                 if (fDeleteRegionAfter) delete pRRegion;
00298                 return;
00299             }
00300 
00301             // Render the spreads paper marks where necessary
00302             RenderPageMarks(pRRegion, ViewTrans, ClipRect, pSpread);
00303 
00304             // No - time to start rendering ink nodes - find the first one.
00305             pRRegion->SetSubRenderState(NULL);
00306 
00307             // Work out whether to print just selected objects, or all of them.
00308             if (pPrintControl->GetObjPrintRange() == PRINTRANGEOBJ_ALL)
00309             {
00310                 // Print *all* objects
00311                 pRRegion->RenderTree(pSpread, FALSE);
00312             }
00313             else
00314             {
00315                 // Print only *selected objects*
00316                 // (We do this by not rendering any bounded object that is not selected).
00317                 //
00318                 // This is in a different loop so that we don't impact performance of
00319                 // normal printing.
00320                 PrintRenderCallback MyCallback(this);
00321                 pRRegion->RenderTree(pSpread, FALSE, TRUE, &MyCallback);
00322             }
00323 
00324             // Finished rendering.
00325             pRRegion->StopRender();
00326 
00327             // The region has finished rendering - delete it.
00328             if (fDeleteRegionAfter) delete pRRegion;
00329         }
00330         else
00331         {
00332             // Build the view matrix to use
00333             Matrix ViewMatrix = pRRegion->GetMatrix();
00334             
00335             // Try and render the view using the 3 pass system
00336             if (PrintMonitor::PrintMaskType==PrintMonitor::MASK_OPTIMAL)
00337                 RenderOptimalView(pRRegion, ViewMatrix, pSpread, FALSE);
00338             else
00339                 RenderSimpleView(pRRegion, ViewMatrix, pSpread, FALSE);
00340         }
00341     }
00342 }
00343 
00344 
00345 /********************************************************************************************
00346 
00347 >   BOOL PrintRenderCallback::BeforeNode(Node* pNode, RenderRegion* pRender)
00348 
00349     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00350     Created:    30/11/2004
00351     Inputs:     pNode - pointer to node about to be rendered by RenderTree
00352                 pRender - pointer to RenderRegion running RenderTree loop
00353     Outputs:    -
00354     Returns:    TRUE if node can be rendered
00355                 FALSE if not
00356     Purpose:    Handle the callback from RenderTree that has been requested by PrintView
00357 
00358 ********************************************************************************************/
00359 
00360 BOOL PrintRenderCallback::BeforeNode(RenderRegion* pRender, Node* pNode)
00361 {
00362     return (m_pPrintView->IsPrintableNodeSelected(pNode));
00363 }
00364 
00365 
00366 /********************************************************************************************
00367 
00368 >   BOOL PrintView::ViewStateChanged()
00369 
00370     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00371     Created:    02/09/95
00372     Returns:    TRUE if all ok;
00373                 FALSE if not.
00374     Purpose:    Inform the PrintView that its OIL view object has changed the shared 
00375                 ViewState structure.
00376     SeeAlso:    View::ViewStateChanged
00377 
00378 ********************************************************************************************/
00379 
00380 BOOL PrintView::ViewStateChanged()
00381 {
00382     // Sanity checks.
00383     ERROR2IF(this==NULL,FALSE,"DocView member func called on NULL pointer");
00384     ERROR2IF(pDoc==NULL,FALSE,"ViewStateChanged: There MUST be an owner doc for this view!");
00385     
00386     DocCoord    ExtentLo;                       // coord of bottom-left of logical extent
00387     DocCoord    ExtentHi;                       // coord of top-right of logical extent
00388 
00389     // Read DocCoords extent of document & set extent in platform-indy ViewState struct.
00390     pDoc->GetExtents(&ExtentLo, &ExtentHi, &PhysExtent, this);
00391 
00392     // Set extent in platform-indy ViewState struct
00393     SetExtent(ExtentLo, ExtentHi);              
00394 
00395     return TRUE;
00396 }
00397 
00398 
00399 
00400 /********************************************************************************************
00401 
00402 >   void PrintView::SetPixelSize()
00403 
00404     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00405     Created:    02/10/95
00406     Purpose:    Sets up the normal and scaled pixel sizes according to this view.
00407 
00408 ********************************************************************************************/
00409 
00410 void PrintView::SetViewPixelSize()
00411 {
00412     // Set the scaled pixel size
00413     ScaledPixelWidth = PixelWidth / Scale;
00414     ScaledPixelHeight = PixelHeight / Scale;
00415 }
00416 
00417 
00418 
00419 /*********************************************************************************************
00420 
00421 >   void PrintView::SetForeBackMode(BOOL NewFlag)
00422 
00423     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00424     Created:    10/2/95
00425     Inputs:     NewFlag - New bg render flag.
00426     Purpose:    Set the background render flag for this view.
00427                                                                  
00428 *********************************************************************************************/
00429 
00430 void PrintView::SetForeBackMode(BOOL NewFlag)
00431 {
00432     // Nobody should try to set the printing to be background yet.
00433     ERROR3IF(NewFlag, "Trying to make a PrintView background render!");
00434 }
00435 
00436 
00437 
00438 /*********************************************************************************************
00439 
00440 >   BOOL PrintView::GetForeBackMode()
00441 
00442     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00443     Created:    10/2/95
00444     Returns:    TRUE if background rendering is on
00445     Purpose:    To find out if background rendering is on
00446                                                                  
00447 *********************************************************************************************/
00448 
00449 BOOL PrintView::GetForeBackMode()
00450 {
00451     // PrintViews don't background render yet.
00452     return FALSE;
00453 }
00454 
00455 
00456 /********************************************************************************************
00457 
00458 >   void PrintView::SetExtent(DocCoord lolog, DocCoord hilog)
00459 
00460     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00461     Created:    26/5/93
00462     Inputs:     Two DocCoords describing the low and high corners of a rectangle in logical
00463                 space describing the full extent of the document. I.E. the bottom-left corner
00464                 of the last chapter and the top-right corner of the first.
00465     Purpose:    Informs the PrintView that the extent of the document has changed in some way and 
00466                 that the view must be altered to take this into account (namely the 
00467                 scrollbars).
00468 
00469 ********************************************************************************************/
00470 
00471 void PrintView::SetExtent(DocCoord lolog, DocCoord hilog)
00472 {
00473     // "Pixelise" the extent DocCoords.
00474     // Effectively, this helps ensure that the spread will be aligned to a whole pixel boundary
00475     // and allows both GDraw and GDI to consistently plot the same pixels when rendering
00476     // the same primitive.
00477     // We need to do this even when printing because things like 
00478     // DocCoord::FindEnclosingChapter() default to pixelising extents so we get errors
00479     // because our coords do not lie within the pixelised extents.
00480     lolog.Pixelise(this);
00481     hilog.Pixelise(this);
00482 
00483     // Convert the extent given in DocCoord to WorkCoords...
00484     pVState->WorkAreaExtent.lo = lolog.ToWork(pDoc, this);
00485     pVState->WorkAreaExtent.hi = hilog.ToWork(pDoc, this);
00486 }
00487 
00488 
00489 
00490 
00491 
00492 
00493 /********************************************************************************************
00494 
00495 >   WorkRect PrintView::GetViewRect()
00496 
00497     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00498     Created:    5/7/93
00499     Returns:    A WorkCoords rectangle describing the viewport onto the document which this
00500                 view is displaying. I.E. The top left corner of this rectangle is the same as
00501                 the value returned by GetScrollOffsets().
00502     Purpose:    To find the rectangle describing the viewport onto the document.
00503 
00504 ********************************************************************************************/
00505 
00506 WorkRect PrintView::GetViewRect()
00507 {
00508     ERROR3("GetViewRect() called on unimplemented printing class!");
00509     return WorkRect(0,0,0,0);
00510 }
00511 
00512 
00513 
00514 
00515 /********************************************************************************************
00516 
00517 >   DocRect PrintView::GetDocViewRect(Spread* pSpread)
00518 
00519     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00520     Created:    21/7/93
00521     Inputs:     pSpread - the spread that we are interested in
00522     Returns:    A DocCoords rectangle describing the viewport onto the document which this
00523                 view is displaying. I.E. The top left corner of this rectangle is the same as
00524                 the value returned by GetScrollOffsets() except in DocCoords.
00525     Purpose:    To find the rectangle describing the viewport onto the document.
00526 
00527 ********************************************************************************************/
00528 
00529 DocRect PrintView::GetDocViewRect(Spread* pSpread)
00530 {
00531     ERROR3("GetDocViewRect() called on unimplemented printing class!");
00532     return DocRect(0,0,0,0);
00533 }
00534 
00535 
00536 
00537 
00538 /********************************************************************************************
00539 
00540 >   void PrintView::AttachToDC(CDC *pDC)
00541 
00542     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00543     Created:    02/10/95
00544     Inputs:     pDC - the printer DC to use (NULL if detaching).
00545     Purpose:    Attach a PrintView to a particular printer DC.  We need this because there
00546                 is no special 'PrintCamView' to ask for it, so ScreenCamView gives us this
00547                 DC when it receives an OnDraw() call, so we know which DC to print to.
00548     SeeAlso:    View::OnDraw; ScreenCamView::OnDraw; PrintView::SetPixelSize
00549 
00550 ********************************************************************************************/
00551 
00552 void PrintView::AttachToDC(CNativeDC *pDC)
00553 {
00554     // Use this DC.
00555     PrintDC = pDC;
00556 
00557     // If its a real DC (i.e. we are not being detached from a DC) then
00558     // get and remember the pixel size (used by PrintView::SetPixelSize()).
00559     if (PrintDC != NULL)
00560     {
00561         INT32 pixwidth  = OSRenderRegion::GetFixedDCPPI(*pDC).GetWidth();
00562         INT32 pixheight = OSRenderRegion::GetFixedDCPPI(*pDC).GetHeight();;
00563         
00564         // Set our own idea of pixel size.
00565         PixelWidth  = FIXED16(72000.0 / pixwidth);
00566         PixelHeight = FIXED16(72000.0 / pixheight);
00567     }
00568 }
00569 
00570 
00571 /********************************************************************************************
00572 
00573 >   void PrintView::MakeNewRenderRegion(Spread* pSpread, DocRect ClipRect, CDC* pDevContext,
00574                                         RenderType rType, BOOL PaintPaper, Node* pInvalidNode = NULL)
00575 
00576     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00577     Created:    5/4/95
00578     Inputs:     pSpread - The Spread to render
00579                 ClipRect - the Clipping rectangle of the bit to draw
00580                 pDevContext - the Device Context to render to
00581                 rType - the Type of the render region
00582                 PaintPaper - Should we draw the paper?
00583     Purpose:    Renders the document to the printer. This function will build all the render
00584                 regions needed to do a print.
00585     SeeAlso:    View::MakeNewRenderRegion
00586 
00587 ********************************************************************************************/
00588 
00589 void PrintView::MakeNewRenderRegion(Spread* pSpread, DocRect ClipRect, CNativeDC* pDevContext, RenderType rType, BOOL PaintPaper, Node* pInvalidNode)
00590 {
00591     // Construct the transformation matrix for the spread.
00592     Matrix RenderMatrix = ConstructRenderingMatrix(pSpread);
00593 
00594     // Go and create the new render region
00595     RenderRegion* pNewRegion = NULL;
00596     if (pViewWindow != NULL)
00597         pNewRegion = NewRenderRegion(ClipRect, RenderMatrix, GetRenderDC(), pSpread, rType);
00598 
00599     // See if it worked
00600     if (pNewRegion == NULL)
00601     {
00602         TRACEALL( _T("Not enough memory to create render region\n"));
00603         return;
00604     }
00605 
00606     pNewRegion->SetBackmostChangedNode(pInvalidNode);
00607 
00608     // Add the region to the list of regions to render and start the
00609     // rendering process off if it has some ink to render
00610     Camelot.AddRenderRegion(pNewRegion);
00611 
00612     // Here we will actually want to create all the strange types of render region
00613     // that we will need and render them on the spot instead of putting them in
00614     // the list of render regions. Don't forget to remove the #include app.h
00615     // when the use of the Camelot var goes away.
00616 }
00617 
00618 
00619 /********************************************************************************************
00620 
00621 >   Matrix PrintView::ConstructRenderingMatrix(Spread *pSpread)
00622 
00623     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00624     Created:    25/04/95
00625     Inputs:     pSpread - the spread that is to be rendered.
00626     Returns:    The required transformation matrix.
00627     Purpose:    From the given spread, construct a matrix that will convert spread
00628                 coordinates to OS coordinates.
00629     SeeAlso:    DocView::OnDraw
00630 
00631 ********************************************************************************************/
00632 
00633 Matrix PrintView::ConstructRenderingMatrix(Spread *pSpread)
00634 {
00635     // First, translate page to origin, taking account of rotation flag.
00636     DocCoord TranslateToOrigin;
00637     DocRect PatchClipRect = PatchInfo.GetClipRect(FALSE,FALSE);
00638 
00639     if (PatchInfo.Rotate)
00640         TranslateToOrigin = DocCoord(-PatchClipRect.lo.x, -PatchClipRect.lo.y);
00641     else
00642         TranslateToOrigin = DocCoord(-PatchClipRect.lo.x, -PatchClipRect.hi.y);
00643 
00644     // Construct the translation matrix
00645     Matrix TranslateToOriginMatrix = Matrix(TranslateToOrigin.x, TranslateToOrigin.y);
00646 
00647     // Do the optional rotation
00648     Matrix RotateMatrix(FIXED16(0));
00649     if (PatchInfo.Rotate)
00650         RotateMatrix = Matrix(FIXED16(270));
00651 
00652     // Do the scale operation (convert from percentage to ratio)
00653     FIXED16 fxScale = PatchInfo.Scale / FIXED16(100);
00654     Matrix PrintScaleMatrix(fxScale, fxScale);
00655 
00656     // Find the patch height so we can work out our final translation
00657     MILLIPOINT PatchHeight;
00658     PatchHeight = ((PatchInfo.Rotate) ? (PatchClipRect.Width()) : (PatchClipRect.Height()));
00659 
00660     // Calculate the translation to move our patch rectangle to the bottom of the paper
00661     MILLIPOINT YShift = -(PatchInfo.PaperHeight - ((MILLIPOINT) (PatchHeight * fxScale)));
00662     MILLIPOINT XShift = 0;
00663 
00664     // Conceptually speaking we now have a transform which scales the patch (area to print)
00665     // and positions it located at (0,-PaperHeight) bottom left on the paper with (x,y) increasing positive
00666     // to the left and up. This is the model used in the print control class to calculate a patch
00667     // position when working out best fit/multi/curstom fit. That class calculates +ive x,y translations
00668     // to fit pages onto paper considering (0,0) to be bottom left. ok so we now simply need to add
00669     // in those calculated translations and we're done.
00670 
00671     XShift += PatchInfo.XTrans;
00672     YShift += PatchInfo.YTrans;
00673 
00674     Matrix PatchTranslateMatrix(XShift, YShift);
00675 
00676     // Generate a flip matrix if necessary
00677     Matrix FlipX;
00678     if (PatchInfo.EmulsionDown)
00679     {
00680         if (PatchInfo.Rotate)
00681             FlipX = Matrix(FIXED16(1), FIXED16(0), FIXED16(0), FIXED16(-1), 0, -PatchInfo.PaperHeight);
00682         else
00683             FlipX = Matrix(FIXED16(-1), FIXED16(0), FIXED16(0), FIXED16(1), PatchInfo.PaperWidth, 0);
00684     }
00685 
00686     // MarkN wrote (way back when first descovered)
00687     // For some reason, NT takes the top-left corner of the printable area as the origin of the paper
00688     // so we compensate for that here by adjusting our X & Y translations accordingly
00689 
00690     // NB. this used to be for NT only, but it seems that MS have brought Win32s and Win95
00691     //     print borders into line with NT's setup so there is a consistent Win32 interface.
00692 
00693     // Mike wrote (more recently)
00694     // I've stollen the code out of PrintControl, which used to do this but now doesn't.
00695     // Finally fix the operating system origin. The operating system drivers
00696     // render everything as if (PALeftMargin, PATopMargin) was the origin, so
00697     // we need to shift everything slightly.
00698     Matrix FixOpTranslate(-PatchInfo.PALeftMargin,PatchInfo.PATopMargin);
00699 
00700     // The following matrix compositions MUST be performed in this order.
00701     // If you are tempted to optimise this code MAKE SURE THAT THEY ARE STILL
00702     // IN THIS ORDER WHEN YOU'VE FINISHED!
00703 
00704     // Start with identity
00705     Matrix RenderMatrix;
00706 
00707     // Translate to Origin
00708     RenderMatrix *= TranslateToOriginMatrix;
00709 
00710     // Optional rotate
00711     if (PatchInfo.Rotate)
00712         RenderMatrix *= RotateMatrix;
00713 
00714     // Scale (as in Print UI)
00715     RenderMatrix *= PrintScaleMatrix;
00716 
00717     // Patch translation
00718     RenderMatrix *= PatchTranslateMatrix;
00719 
00720     // Optional Flip around for emulsion down if nec.
00721     if (PatchInfo.EmulsionDown)
00722         RenderMatrix *= FlipX;
00723 
00724     // Opsys translation
00725     RenderMatrix *= FixOpTranslate;
00726 
00727     // All done.
00728     return RenderMatrix;
00729 }
00730 
00731 
00732 /********************************************************************************************
00733 
00734 >   void PrintView::OnDraw(CDC* pDevContext, OilRect OilClipRect)
00735 
00736     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00737     Created:    27/04/95
00738     Inputs:     pDevContext - the device context of the view to render.
00739                 OilClipRect - the clipping rectangle of the invalid region (in OilCoords).
00740     Purpose:    Do the printing, guv.
00741 
00742 ********************************************************************************************/
00743 
00744 void PrintView::OnDraw(CNativeDC* pDevContext, OilRect OilClipRect)
00745 {
00746     if (CCamApp::IsDisabled())
00747         return;                             // If the system is disabled, ignore
00748 
00749     // Find out what sort of (printing) device context we have.
00750     RenderType rType = CCDC::GetType(pDevContext, TRUE);
00751 
00752     // Find out which spread we are rendering
00753     Spread *pSpread = Document::GetSelectedSpread(); // PatchInfo.Spread
00754 
00755     // Get the rendering matrix for this view.
00756     Matrix RenderMatrix = ConstructRenderingMatrix(pSpread);
00757 
00758     // Get its inverse matrix
00759     Matrix InverseMatrix = RenderMatrix.Inverse();
00760 
00761     // Use this to convert OIL coords to spread coords
00762     DocRect ClipRect;
00763     ClipRect.lo.x = OilClipRect.lo.x;
00764     ClipRect.lo.y = OilClipRect.lo.y;
00765     ClipRect.hi.x = OilClipRect.hi.x;
00766     ClipRect.hi.y = OilClipRect.hi.y;
00767     InverseMatrix.transform(&ClipRect.lo);
00768     InverseMatrix.transform(&ClipRect.hi);
00769 
00770     // Rendering matrix may involve a rotation when printing so correct the rectangle
00771     // for this if necessary.
00772     CorrectRotatedRectangle((Rect *) &ClipRect);
00773     ERROR3IF(ClipRect.lo.x > ClipRect.hi.x, "PrintView::OnDraw clipping rect is invalid");
00774     ERROR3IF(ClipRect.lo.y > ClipRect.hi.y, "PrintView::OnDraw clipping rect is invalid");
00775 
00776     // Get the page clip rect
00777     DocRect SpreadClipRect = PatchInfo.GetClipRect(FALSE,FALSE);
00778     RenderMatrix.transform(&SpreadClipRect.lo);
00779     RenderMatrix.transform(&SpreadClipRect.hi);
00780     CorrectRotatedRectangle((Rect *) &SpreadClipRect);
00781     PatchInfo.InflateRectBy(&SpreadClipRect,TRUE,TRUE);
00782     InverseMatrix.transform(&SpreadClipRect.lo);
00783     InverseMatrix.transform(&SpreadClipRect.hi);
00784     CorrectRotatedRectangle((Rect *) &SpreadClipRect);
00785 
00786     // Clip to spread rectangle
00787     SpreadClipRect = SpreadClipRect.Intersection(ClipRect);
00788 
00789     // Make sure that the clip region is valid after the intersection
00790     if ((SpreadClipRect.IsValid()) && (!SpreadClipRect.IsEmpty()))
00791     {
00792         MakeNewRenderRegion(pSpread, SpreadClipRect, pDevContext, rType, TRUE);
00793 
00794     }
00795 }
00796 
00797 
00798 /********************************************************************************************
00799 
00800 >   void PrintView::CorrectRotatedRectangle(Rect *pRect)
00801 
00802     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00803     Created:    04/28/95
00804     Inputs:     pRect - the rectangle to correct.
00805     Outputs:    pRect - the corrected rectangle.
00806     Purpose:    Patches up rectangles after having been transformed by the rendering
00807                 matrix.  Because printing can involve a rotation through a multiple of
00808                 90 degress, the corners can become swapped, so we check for this and swap
00809                 them back around if necessary.
00810 
00811 ********************************************************************************************/
00812 
00813 void PrintView::CorrectRotatedRectangle(Rect *pRect)
00814 {
00815     MILLIPOINT Tmp;
00816 
00817     if (pRect->lo.x > pRect->hi.x)
00818     {
00819         Tmp = pRect->lo.x;
00820         pRect->lo.x = pRect->hi.x;
00821         pRect->hi.x = Tmp;
00822     }
00823 
00824     if (pRect->lo.y > pRect->hi.y)
00825     {
00826         Tmp = pRect->lo.y;
00827         pRect->lo.y = pRect->hi.y;
00828         pRect->hi.y = Tmp;
00829     }
00830 }

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