spread.cpp

Go to the documentation of this file.
00001 // $Id: spread.cpp 1737 2006-09-04 15:17:04Z luke $
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 // Spread class implementation
00100 
00101 
00102 #include "camtypes.h"
00103 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "simon.h"
00105 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "rndrgn.h"
00107 #include "page.h"
00108 #include "exceptio.h"       // For BlowUpOnCrashMe() method      
00109 #include "chapter.h"
00110 //#include "mario.h"            // amounst other things _R(IDE_NOMORE_MEMORY)
00111 #include "layer.h"
00112 //#include "convert.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 #include "sglayer.h"
00115 #include "usercord.h"
00116 //#include "tim.h"
00117 
00118 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 #include "cxftags.h"
00120 //#include "cxfdefs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00121 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 #include "viewcomp.h"
00123 #include "unitcomp.h"
00124 
00125 #include "nodedoc.h"
00126 #include "backgrnd.h"   // OpBackground
00127 //#include "animparams.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00128 #include "progress.h"
00129 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00130 #include "optsmsgs.h"
00131 #include "oilbitmap.h"  // CWxBitmap
00132 #include "grid.h"
00133 
00134 //#include "prevwres.h" // _R(IDS_TAG_LAYER_FRAMEPROPS)
00135 //#include "frameops.h" // for OpGrabAllFrames
00136   
00137 CC_IMPLEMENT_DYNAMIC(Spread, NodeRenderablePaper)          
00138 
00139 // Declare smart memory handling in Debug builds
00140 #define new CAM_DEBUG_NEW
00141 
00142 
00143 
00144 #if NEW_PASTEBOARD
00145 // See the spread.h header for the definition of NEW_PASTEBOARD
00146 // Note that I've set it to fail to compile until you've been made aware of the problem!
00147 #error ("New pasteboard code is enabled. Import/Export is probably broken")
00148 #endif
00149 
00150 
00151 // Maximum pasteboard size - beyond this size we start to get problems at high zoom or something
00152 // SeeAlso: kernel\optspage.cpp
00153 const MILLIPOINT MaxPasteboardSize = 9 * 72000 * 12;    // maximum = 108in = 9 ft = 275cm
00154 
00155 
00156 #ifdef RALPH
00157 #define NO_SPREAD 1
00158 #endif
00159  
00160 /*********************************************************************************************
00161 
00162 >    Spread::Spread() 
00163 
00164      Author:    Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00165      Created:   13/5/93
00166      Inputs:    -
00167      Outputs:   
00168      Returns:   -
00169               
00170      Purpose: This constructor creates a Spread linked to no other nodes, with all status
00171               flags false, and NULL bounding and pasteboard rectangles.            
00172             
00173      Errors:    
00174 
00175 **********************************************************************************************/
00176  
00177 
00178 Spread::Spread(): NodeRenderablePaper()
00179 {   
00180     UserOrigin              = DocCoord(0, 0);
00181     SpreadOrigin            = DocCoord(0, 0);
00182     BleedOffset             = 36000;
00183     ShowDropShadow          = TRUE;
00184     RalphDontShowPaper      = FALSE;
00185     //AnimPropertiesParam   = constructed
00186     //SpreadDimScale        = constructed
00187 }                    
00188  
00189 
00190 /***********************************************************************************************
00191 
00192 >   Spread::Spread
00193     (
00194         Node* ContextNode,  
00195         AttachNodeDirection Direction, 
00196         MILLIPOINT BleedOffset = 0,  
00197         BOOL Locked = FALSE, 
00198         BOOL Mangled = FALSE,  
00199         BOOL Marked = FALSE, 
00200         BOOL Selected = FALSE, 
00201     )
00202 
00203     Author:  Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00204     Created: 26/4/93             
00205     
00206     Inputs: ContextNode: Pointer to a node which this node is to be attached to.     
00207     
00208             Direction: 
00209             
00210                 Specifies the direction in which this node is to be attached to the 
00211                 ContextNode. The values this variable can take are as follows: 
00212                                   
00213                 PREV      : Attach node as a previous sibling of the context node
00214                 NEXT      : Attach node as a next sibling of the context node
00215                 FIRSTCHILD: Attach node as the first child of the context node
00216                 LASTCHILD : Attach node as a last child of the context node                               
00217                           
00218             BoundingRect: Bounding rectangle  
00219                                   
00220             The remaining inputs specify the status of the node: 
00221             
00222             Locked:     Is node locked ?
00223             Mangled:    Is node mangled ?
00224             Marked:     Is node marked ?
00225             Selected:   Is node selected ?
00226             
00227     Outputs:   -
00228     Returns:   - 
00229     Purpose: This method initialises the node and links it to ContextNode in the
00230              direction specified by Direction. All neccesary tree links are
00231              updated.     
00232              
00233     Errors:  An assertion error will occur if ContextNode is NULL
00234 
00235 
00236 ***********************************************************************************************/
00237 
00238 Spread::Spread(Node* ContextNode,  
00239                     AttachNodeDirection Direction,   
00240                     const DocRect& PasteRect, 
00241                     MILLIPOINT Bleed, 
00242                     BOOL Locked, 
00243                     BOOL Mangled,  
00244                     BOOL Marked, 
00245                     BOOL Selected 
00246                    ): NodeRenderablePaper(ContextNode, Direction, Locked, Mangled, 
00247                                         Marked, Selected)
00248 {   
00249     BleedOffset = Bleed;
00250 
00251     // Set the default spread coord origin
00252     SpreadOrigin    = PasteRect.lo;
00253 
00254     // Pasteboard is used to indicate the width of the document (for scroll bars etc)
00255     SetInitialPasteboardRect(PasteRect);
00256 
00257     // Default to showing the drop shadow on the page
00258     ShowDropShadow = TRUE;
00259     
00260     // we only render paper in some ralph document modes
00261     RalphDontShowPaper = FALSE;
00262 
00263     UserOrigin      = DocCoord(0,0);
00264 }  
00265 
00266 
00267 
00268 /********************************************************************************************
00269 
00270 >   virtual String Spread::Describe(BOOL Plural, BOOL Verbose = TRUE)
00271 
00272     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00273     Created:    21/6/93
00274     Inputs:     Plural: Flag indicating if the string description should be plural or
00275                         singular. 
00276     Outputs:    -
00277     Retuns:     Description of the object 
00278     Purpose:    To return a description of the Node object in either the singular or the 
00279                 plural. This method is called by the DescribeRange method.
00280                 
00281                 The description will always begin with a lower case letter.   
00282                 
00283     Errors:     A resource exception will be thrown if a problem occurs when loading the 
00284                 string resource. 
00285     SeeAlso:    -
00286 
00287 ********************************************************************************************/
00288 /*
00289     Technical Notes:
00290     
00291     The String resource identifiers should be of the form: ID_<Class>_DescriptionS for the 
00292     singular description and ID_<Class>_DescriptionP for the plural. 
00293 */              
00294               
00295 String Spread::Describe(BOOL Plural, BOOL Verbose) 
00296 {     
00297     if (Plural)
00298         return(String(_R(IDS_SPREAD_DESCRP)));  
00299     else
00300         return(String(_R(IDS_SPREAD_DESCRS))); 
00301 }; 
00302 
00303 
00304 
00305 
00306 /********************************************************************************************
00307 
00308 >   DocRect Spread::GetBoundingRect(BOOL DontUseAttrs=FALSE, BOOL HitTest=FALSE)
00309 
00310     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00311     Created:    11/9/94
00312     Inputs:     DontUseAttrs - If this is TRUE the node should not try to use the
00313                 attributes associated with the node. It will also leave the flag
00314                 IsBoundingRectValid FALSE. This var defaults to FALSE
00315                 HitTest - TRUE if being called during HitTest
00316     Returns:    The nodes bounding rectangle
00317     Purpose:    returns the nodes bounding rectangle. If the rectangle is valid the
00318                 rectangle is simply returned, but is IsBoundingRectValid is FALSE (cos
00319                 someone called InvaldateBoundingRect() on this node, or one of its
00320                 children) then the bounding rect is first calculated and the flag reset,
00321                 before it is returned. The Spreads bounds rect is measured in Document
00322                 Coords and this conversion is made in here. ie. All objects below the spread
00323                 measure their coords etc relative to the spread, but the spread itself is
00324                 measured relative to the document.
00325 
00326 ********************************************************************************************/
00327 
00328 DocRect Spread::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
00329 {
00330     // if the bounding rect of this node is not valid then fill in something
00331     if (!IsBoundingRectValid || DontUseAttrs)
00332     {
00333         // just set it to be an empty rectangle
00334         DocRect BoundRect(0,0,0,0);
00335         
00336         Node* pNode = FindFirstChild();
00337         while (pNode!=NULL)
00338         {
00339             // Add in the bounding rect of this node with all the others
00340             if (pNode->IsBounded())
00341                 BoundRect = BoundRect.Union(((NodeRenderableBounded*)pNode)->GetBoundingRect(DontUseAttrs));
00342 
00343             // And find the next node
00344             pNode = pNode->FindNext();
00345         }
00346 
00347         // Convert the bounding rect obtained from spread coords to document coords
00348         SpreadCoordToDocCoord(&BoundRect);
00349 
00350         if (DontUseAttrs)
00351             return BoundRect;
00352 
00353         // Copy the unions into the nodes bounding rect param
00354         BoundingRectangle = BoundRect;
00355 
00356         // mark the bounding rect as valid
00357         IsBoundingRectValid = TRUE;
00358     }
00359 
00360     // and return the bounding rect
00361     return BoundingRectangle;
00362 }
00363 
00364 
00365 
00366 
00367 /********************************************************************************************
00368 
00369 >   DocRect Spread::GetDrawingSize () const
00370 
00371     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00372     Created:    25/09/96
00373     Returns:    Size of the rectangle encompassing the drawing.
00374     Purpose:    Works out the size of the rectangle encompassing the drawing.
00375                 Code also used to work out the pixel size in the bitmap export options
00376                 dialog box.
00377                 Graeme (13/7/00) - Changed the code so that the background layer is ignored.
00378 
00379 ********************************************************************************************/
00380 
00381 DocRect Spread::GetDrawingSize () const
00382 {
00383     // Start out with an empty clip rectangle.
00384     DocRect SpreadRect;
00385     SpreadRect.MakeEmpty ();
00386 
00387     // Find the first layer in the spread.
00388     Layer* pLayer = FindFirstLayer ();
00389 
00390     // Loop through the layers, and union the bounding boxes of all visible, non-background
00391     // layers.
00392     while ( pLayer != NULL )
00393     {
00394         // Let's see if it is visible, and not a background layer.
00395         if ( pLayer->IsVisible() && !pLayer->IsBackground () )
00396         {
00397             // This one is visible, so union its bounding box in.
00398             SpreadRect = SpreadRect.Union(pLayer->GetBoundingRect () );
00399         }
00400 
00401         // Find the next layer.
00402         pLayer = pLayer->FindNextLayer ();
00403     }
00404 
00405     // Return the found rectangle to the caller.    
00406     return SpreadRect;
00407 }
00408 
00409 
00410 /********************************************************************************************
00411 
00412 >   BOOL Spread::IsSpread() const
00413 
00414     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00415     Created:    15/02/95
00416     Returns:    TRUE  - this IS a spread node.
00417     Purpose:    Tell the caller that this is a spread node.
00418 
00419 ********************************************************************************************/
00420 
00421 BOOL Spread::IsSpread() const
00422 {
00423     // Yes, this is a spread!
00424     return TRUE;
00425 }
00426 
00427 
00428 
00429 /***********************************************************************************************
00430 
00431 >   void Spread::RenderPasteboard(void) const
00432 
00433     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00434     Created:    14/5/93
00435     Inputs:     -
00436     Outputs:    -
00437     Returns:    -  
00438     Purpose:    To render the pasteboard and off-paste area
00439     Errors:     -     
00440     Scope:      Private
00441     SeeAlso:    -
00442 
00443 ***********************************************************************************************/
00444 
00445 void Spread::RenderPasteboard( RenderRegion* pRender )
00446 {                     
00447     // Ensure we don't dither the filled areas
00448     pRender->SetSolidColours(TRUE);
00449 
00450     // Ensure that the top coord of this pasteboard is exactly the same as the bottom of 
00451     // the upper pasteboard.    
00452                   
00453 #ifdef _DEBUG
00454     Spread* PrevSpread = FindPreviousSpread(); 
00455     if (PrevSpread != NULL)
00456         ENSURE((PasteboardRect.HighCorner().y == 
00457                PrevSpread->GetPasteboardRect(FALSE,pRender->GetRenderView()).LowCorner().y),
00458                "Spreads are not properly vertically aligned");  
00459 #endif
00460 
00461     // Find out the Clip rect of the render region to help decide which rectangles to try to draw
00462     DocRect SpreadPasteboard = GetWidePasteboard(pRender->GetRenderView());
00463 
00464     DocCoordToSpreadCoord(&SpreadPasteboard);
00465 
00466     Page* CurrentPage = FindFirstPageInSpread();
00467     
00468     // --- Divide the pasteboard up into filled rectangles and render them ---
00469     
00470     DocRect CurrentPageRect = CurrentPage->GetPageRect();
00471                                                        
00472     // Ensure that we have a transparent line colour throughout
00473     pRender->SetLineColour(COLOUR_TRANS); 
00474 
00475     // Set up a pasteboard colour
00476     DocColour COLOUR_PASTEBOARD(192L, 192L, 192L);
00477 #ifdef NO_SPREAD
00478     COLOUR_PASTEBOARD = DocColour(Page::PageColour);
00479 #endif
00480     // colour the pasteboard white to hide it if we're in ralph DRAWING_VIEW mode
00481     // ( this flag is set in Render() )
00482     if (RalphDontShowPaper) 
00483         COLOUR_PASTEBOARD = DocColour(255L, 255L, 255L);
00484     
00485     COLOUR_PASTEBOARD.SetSeparable(FALSE);      // Don't colour-separate the pasteboard
00486 
00487     // We can now have a zero sized top pasteboard and due to pixelization of the
00488     // SpreadPasteboard DocRect this may give rise to errors if Top is just
00489     // constructed. So we must check it before hand.
00490     // Effectively doing the same as the ENSURE((Low.x <= High.x) && (Low.y <= High.y)
00491     // in the DocRect constructor.
00492     if (SpreadPasteboard.HighCorner().y > CurrentPageRect.HighCorner().y)
00493     {
00494         // Render the top pasteboard rectangle                                                    
00495         DocRect Top(DocCoord(SpreadPasteboard.LowCorner().x, 
00496                             CurrentPageRect.HighCorner().y),
00497                     DocCoord(SpreadPasteboard.HighCorner().x,
00498                             SpreadPasteboard.HighCorner().y));  
00499                 
00500         pRender->SetFillColour(COLOUR_PASTEBOARD);
00501         pRender->DrawRect(&Top);
00502     }
00503 
00504     // For each row of pages in a spread, render a rectangle to the left of the left-most 
00505     // page reaching the left of the pasteboard, and a rectangle to the right of the right-most 
00506     // page reaching the right of the pasteboard. Also if any off-paste area needs to be rendered
00507     // then render a rectangle to the right of the right pasteboard rectangle.  
00508         
00509     do 
00510     {
00511         // Render rectangle to the left of the left-most page but first check 
00512         // that there is enough of a left section to worry about
00513         if (CurrentPageRect.LowCorner().x > SpreadPasteboard.LowCorner().x)
00514         {
00515             // Render rectangle to the left of the left-most page
00516             DocRect Left(DocCoord(SpreadPasteboard.LowCorner().x,
00517                                   CurrentPageRect.LowCorner().y),
00518                          DocCoord(CurrentPageRect.LowCorner().x,
00519                                   CurrentPageRect.HighCorner().y));
00520 
00521             pRender->SetFillColour(COLOUR_PASTEBOARD);
00522             pRender->DrawRect(&Left);
00523         }
00524 
00525         // Find the right-most page in the current row
00526         while (CurrentPage->FindRightPage())
00527             CurrentPage = CurrentPage->FindNextPage();
00528                                      
00529         CurrentPageRect = CurrentPage->GetPageRect();
00530          
00531         // Render rectangle to the right of the right-most page but first check 
00532         // that there is enough of a right section to worry about
00533         if (SpreadPasteboard.HighCorner().x > CurrentPageRect.HighCorner().x)
00534         {
00535             // Render a rectangle to the right of the right-most page
00536             DocRect Right(DocCoord(CurrentPageRect.HighCorner().x, 
00537                                    CurrentPageRect.LowCorner().y), 
00538                           DocCoord(SpreadPasteboard.HighCorner().x, 
00539                                    CurrentPageRect.HighCorner().y)); 
00540                                    
00541             pRender->SetFillColour(COLOUR_PASTEBOARD); // added 24/3/97
00542             pRender->DrawRect(&Right);
00543         }
00544 
00545         CurrentPage = CurrentPage->FindNextPage(); // Move to the first page in the next row
00546         if (CurrentPage != NULL)
00547         {
00548             CurrentPageRect = CurrentPage->GetPageRect();
00549         }
00550     } while (CurrentPage != NULL); // While there are more rows 
00551     
00552     // Check that there is enough of a bottom section to worry about
00553     if (CurrentPageRect.LowCorner().y > SpreadPasteboard.LowCorner().y)
00554     {
00555         // Render a rectangle below the lowest page
00556         DocRect Bottom(DocCoord(SpreadPasteboard.LowCorner().x, 
00557                                 SpreadPasteboard.LowCorner().y), 
00558                        DocCoord(SpreadPasteboard.HighCorner().x,
00559                                 CurrentPageRect.LowCorner().y));
00560                                 
00561         pRender->SetFillColour(COLOUR_PASTEBOARD);
00562         pRender->DrawRect(&Bottom);      
00563     }
00564 
00565     // And revert to normal dithered plotting
00566     pRender->SetSolidColours(FALSE);
00567 }
00568 
00569 
00570 
00571 /***********************************************************************************************
00572 
00573 >   void Spread::RenderDropShadows(void) const
00574 
00575     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00576     Created:    11/5/93
00577     Purpose:    To render right-hand and bottom drop shadows
00578     Scope:      private
00579 
00580 ***********************************************************************************************/
00581 
00582 void Spread::RenderDropShadows(RenderRegion* pRender) 
00583 {             
00584     // If we have the new page background layer present then we needn't bother redrawing the
00585     // page as we might get a flash of white as we redraw
00586     // Therefore, we don't need to add a pixel on the right hand side page border
00587     BOOL PageBackgroundPresent = FALSE;
00588     // Is there a page background layer on the spread?
00589     Layer* pLayer = FindFirstPageBackgroundLayer();
00590     // Yes, the layer is present but is it visible?
00591     if (pLayer && pLayer->IsVisible())
00592         PageBackgroundPresent = TRUE;
00593 
00594     // Ensure filled areas are not dithered
00595     pRender->SetSolidColours(TRUE);
00596 
00597     // Setup attributes                                                         
00598     pRender->SetLineWidth(0); // means single pixel lines   
00599     pRender->SetLineColour(COLOUR_TRANS); 
00600 
00601     DocColour COLOUR_SHADOW(COLOUR_MIDGREY);
00602     pRender->SetFillColour(COLOUR_SHADOW);
00603 
00604     // Get the scaled pixel size for the view
00605     FIXED16 ScaledPixelWidth;
00606     FIXED16 ScaledPixelHeight;
00607     pRender->GetRenderView()->GetScaledPixelSize(&ScaledPixelWidth, &ScaledPixelHeight);
00608 
00609     // Find out how many millipoints 4 pixels is
00610     MILLIPOINT DropWidth = 4 * (min(ScaledPixelWidth.MakeLong(), ScaledPixelHeight.MakeLong() ));
00611     
00612     MILLIPOINT ExtraPixel = ScaledPixelWidth.MakeLong();
00613     if (PageBackgroundPresent)
00614         ExtraPixel = 0;
00615     
00616     // The page we are currently drawing drop shadows for
00617     Page* CurrentPage = FindFirstPageInSpread(); 
00618       
00619     //Render drop shadows for each page in turn  
00620     while (CurrentPage != NULL)   
00621     {                                  
00622         // Will indicate if page has a left or right drop shadow
00623         BOOL PageHasADropShadow = FALSE; 
00624         DocRect PageRect = CurrentPage->GetPageRect();
00625         
00626         // If the current page has no page to its right then we should render a right-hand
00627         // drop shadow 
00628         if (!(CurrentPage->FindRightPage())) 
00629         {                                         
00630             // Take width of page outline into account by rendering drop shadow one pixel beyond
00631             // edge of page! This makes drop shadow same width as its height below the page.
00632             DocRect RightHandDropShadow(PageRect.HighCorner().x + ExtraPixel, 
00633                                       PageRect.LowCorner().y - DropWidth,
00634                                       PageRect.HighCorner().x + DropWidth + ExtraPixel, 
00635                                       PageRect.HighCorner().y - DropWidth 
00636                                      );   
00637                                      
00638             pRender->DrawRect(&RightHandDropShadow);
00639 
00640 /*          // Attempt to render fuzzy shadow edge using bitmap...
00641             {
00642                 DocRect r = RightHandDropShadow;
00643                 CWxBitmap*          pBitmap = new CWxBitmap();
00644                 pBitmap->LoadBitmap(_R(IDB_SPREAD_RIGHTEDGE));
00645                 KernelBitmap*       pkBitmap = new KernelBitmap(pBitmap, TRUE);
00646 
00647                 pRender->RenderBits(pkBitmap, (DocCoord*)&r, 2, TRUE, NULL);    // Unclean!
00648     
00649                 if (pBitmap)
00650                 {
00651                     pBitmap->BMBytes = ((CWxBitmap*)OILBitmap::Default)->BMBytes;
00652                 }
00653                 if (pkBitmap)
00654                 {
00655                     delete pkBitmap;
00656                     pkBitmap = NULL;
00657                 }
00658             }
00659 */
00660             PageHasADropShadow = TRUE;
00661                                      
00662         }                                
00663         
00664         // If the current page has no page vertically joined beneath it then render a 
00665         // bottom drop shadow. 
00666         if (!(CurrentPage->FindBottomPage()))
00667         {
00668             //Render bottom drop shadow    
00669             DocRect BottomDropShadow(PageRect.LowCorner().x + DropWidth, 
00670                                    PageRect.LowCorner().y - DropWidth, 
00671                                    PageRect.HighCorner().x + DropWidth, 
00672                                    PageRect.LowCorner().y  
00673                                   );         
00674             
00675             pRender->DrawRect(&BottomDropShadow);
00676 
00677 /*          // Attempt to render fuzzy shadow edge using bitmap...
00678             {
00679                 DocRect r = BottomDropShadow;
00680                 CWxBitmap*          pBitmap = new CWxBitmap();
00681                 pBitmap->LoadBitmap(_R(IDB_SPREAD_BOTTOMEDGE));
00682                 KernelBitmap*       pkBitmap = new KernelBitmap(pBitmap, TRUE);
00683 
00684                 pRender->RenderBits(pkBitmap, (DocCoord*)&r, 2, TRUE, NULL);    // Unclean!
00685     
00686                 if (pBitmap)
00687                 {
00688                     pBitmap->BMBytes = ((CWxBitmap*)OILBitmap::Default)->BMBytes;
00689                 }
00690                 if (pkBitmap)
00691                 {
00692                     delete pkBitmap;
00693                     pkBitmap = NULL;
00694                 }
00695             }
00696 */
00697             PageHasADropShadow = TRUE; 
00698         }       
00699         
00700         // This bit is not very beautiful. If a page has a page to its right and a page beneath
00701         // it, and the page to its right does not have have a page beneath it, then there will
00702         // be a little cube of drop shadow left to draw at the bottom right hand corner of the 
00703         // page. 
00704         
00705         if (!PageHasADropShadow)
00706         {
00707             // The page has a page to its right and a page beneath it   
00708             ENSURE( CurrentPage->FindRightPage(), 
00709                     "Spread::RenderDropShadows: Cannot find right page");               
00710             if (CurrentPage->FindRightPage()->FindBottomPage() == NULL) 
00711             {
00712                 DocRect MissingCube(PageRect.HighCorner().x, 
00713                                     PageRect.LowCorner().y - DropWidth,
00714                                     PageRect.HighCorner().x + DropWidth, 
00715                                     PageRect.LowCorner().y); 
00716                 
00717                 pRender->DrawRect(&MissingCube);  
00718             }
00719         }
00720                          
00721         // Move to next page
00722         CurrentPage = CurrentPage->FindNextPage();  
00723     }
00724 
00725     // And return to normal dithered rendering
00726     pRender->SetSolidColours(FALSE);
00727 }  
00728 
00729 
00730 /***********************************************************************************************
00731 
00732 >   void Spread::RenderBleedArea( RenderRegion* pRender )
00733 
00734     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00735     Created:    15/5/93
00736     Purpose:    Renders the Bleed Area rectangle if the BleedOffset is not 0
00737     Scope:      private
00738 
00739 ***********************************************************************************************/
00740 
00741 void Spread::RenderBleedArea( RenderRegion* pRender) 
00742 {                                
00743     if  (BleedOffset != 0)
00744     {                                 
00745         // Draw a rectangle BleedOffset outside the common bounding rectangle of all pages
00746         // in the spread. 
00747     
00748         // Calculate the common bounding rectangle of all the spread's pages
00749         DocRect BleedRectangle; 
00750         
00751         Page* CurrentPage = FindFirstPageInSpread(); 
00752         while(CurrentPage != NULL)
00753         {
00754             DocRect PageRect = CurrentPage->GetPageRect();
00755             BleedRectangle = BleedRectangle.Union(PageRect); 
00756             CurrentPage = CurrentPage->FindNextPage(); 
00757         }                 
00758         BleedRectangle.Inflate(BleedOffset);                     
00759 
00760         // Ensure plotting does not use dithered colours
00761         pRender->SetSolidColours(TRUE);
00762 
00763         // Draw a rectangle covering the page 
00764         // Set up attributes for drawing page rectangle
00765         pRender->SetLineWidth(0);                   // Means single-pixel lines
00766         pRender->SetLineColour(COLOUR_TRANS); 
00767 
00768         DocColour COLOUR_BLEEDAREA(COLOUR_RED);
00769         pRender->SetFillColour(COLOUR_BLEEDAREA);
00770         pRender->DrawPixelRect(&BleedRectangle);
00771 
00772         // And return to normal dithered rendering
00773         pRender->SetSolidColours(FALSE);
00774     }
00775 }    
00776 
00777 
00778 
00779 /***********************************************************************************************
00780 
00781 >   void Spread::Render( RenderRegion* pRender )
00782 
00783     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00784     Created:    10/5/93
00785     Inputs:     pRender - The render region to draw into
00786     Purpose:    Renders spread items:
00787                     Pasteboard and off-paste area
00788                     Main fold line
00789                     Spread dividers
00790                     Bleed Area
00791                     Drop-shadows
00792                     Spread outline
00793                     Print margin
00794 
00795 ***********************************************************************************************/
00796 
00797 void Spread::Render( RenderRegion* pRender )
00798 {
00799     // If we should blow up, then blow up - don't worry, this is a very quick inline check
00800     OpException::BlowUpOnCrashMe();
00801 
00802 // ralph only renders paper/pasteboard in some view modes   
00803 #ifdef RALPH
00804     //find the parent NodeDocument 
00805     Node* pCurrentNode = FindParent(); 
00806     while(pCurrentNode != NULL)   
00807     {
00808         if (pCurrentNode->IsNodeDocument())
00809             break;   
00810         pCurrentNode = pCurrentNode->FindParent(); 
00811     }
00812     BaseDocument * pDoc =NULL;
00813     // get a Document *
00814     if(pCurrentNode)
00815         pDoc = ((NodeDocument*)(pCurrentNode))->GetParentDoc(); 
00816     // set RalphDontShowPaper - it will be tested in RenderPasteboard   
00817     if(pDoc)
00818         RalphDontShowPaper =((Document*)pDoc)->RalphDontShowPaper();
00819 #endif
00820 
00821     // --- Render pasteboard ---
00822     RenderPasteboard(pRender);
00823 
00824     if(!RalphDontShowPaper)
00825     {
00826 
00827         // --- Render main fold line ---
00828         Chapter* pChapter = FindParentChapter();
00829         ERROR3IF(pChapter == NULL,"Spread::Render: Could not find parent chapter");
00830 
00831         if (pChapter != NULL && pChapter->ShouldShowFoldLine())
00832         {
00833             MILLIPOINT MainFoldLineXCoord = pChapter->GetFoldLineXCoord();
00834 
00835             DocRect PBRect = GetPasteboardRect(TRUE, pRender->GetRenderView());
00836 
00837             pRender->SetLineWidth(0);                   // Means single-pixel lines
00838             pRender->SetLineColour(COLOUR_TRANS);
00839 
00840             DocColour COLOUR_FOLDLINE   = DocColour(150L, 150L, 150L);
00841             COLOUR_FOLDLINE.SetSeparable(FALSE);        // Don't colour-separate the fold line
00842 
00843             pRender->SetFillColour(COLOUR_FOLDLINE);
00844             pRender->DrawPixelLine(DocCoord(MainFoldLineXCoord, PBRect.lo.y),
00845                                    DocCoord(MainFoldLineXCoord, PBRect.hi.y));
00846         }
00847 
00848         // --- Render spread dividers ---
00849 
00850         // Set the colour for the spread divide (mid grey)
00851 /*      DocColour COLOUR_SPREADDIVIDE = DocColour(64L, 32L, 32L); //DocColour(127L, 127L, 127L);
00852         COLOUR_SPREADDIVIDE.SetSeparable(FALSE);        // Don't colour-separate the spread divider
00853 
00854         pRender->SetLineColour(COLOUR_SPREADDIVIDE);
00855 
00856         // Set the line width (Wider for the first spread in the chapter)
00857         if (FindPrevious()==NULL)
00858         {
00859             MILLIPOINT LineWidth = 4*PixelHeight; 
00860             pRender->SetLineWidth(LineWidth);
00861         }
00862         else
00863             pRender->SetLineWidth(0);
00864 
00865         // Draw line along the top of the pasteboard 
00866         View *pView = pRender->GetRenderView();
00867         MILLIPOINT Width = GetWidePasteboard(pView).Width();
00868         MILLIPOINT Height = GetWidePasteboard(pView).Height();
00869         pRender->DrawLine(DocCoord(-Width, Height), DocCoord(Width, Height));
00870 */
00871 
00872         if (FindPreviousSpread()!=NULL)
00873         {
00874             DocColour COLOUR_SPREADDIVIDE = DocColour(64L, 32L, 32L); //DocColour(127L, 127L, 127L);
00875             COLOUR_SPREADDIVIDE.SetSeparable(FALSE);        // Don't colour-separate the spread divider
00876             pRender->SetFillColour(COLOUR_SPREADDIVIDE);
00877 
00878             View *pView = pRender->GetRenderView();
00879             DocRect sd = GetWidePasteboard(pView);
00880             DocCoordToSpreadCoord(&sd);
00881 
00882             FIXED16 ScaledPixelWidth;
00883             FIXED16 ScaledPixelHeight;
00884             pRender->GetRenderView()->GetScaledPixelSize(&ScaledPixelWidth, &ScaledPixelHeight);
00885             sd.lo.y = sd.hi.y - ScaledPixelWidth.MakeLong();
00886             pRender->DrawRect(&sd);
00887         }
00888         
00889         // --- Render drop shadows ---
00890         if (ShowDropShadow)
00891             RenderDropShadows( pRender );      
00892         
00893         // --- Render bleed area, if not 0 size ---
00894         // Render after page shadow as otherwise page shadow may overdraw the bleed margin
00895         // and the bleed margin will disappear.
00896         RenderBleedArea(pRender);
00897     }
00898 }  
00899 
00900 
00901     
00902 /***********************************************************************************************
00903 
00904 > Node* Spread::SimpleCopy()   
00905 
00906     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00907     Created:    28/4/93
00908     
00909     Inputs:         - 
00910     Outputs:    
00911     Returns:    A copy of the node, or NULL if memory runs out 
00912          
00913     Purpose:    This method returns a shallow copy of the node with all Node pointers NULL. 
00914                 The function is virtual, and must be defined for all derived classes.  
00915            
00916     Errors:     If memory runs out when trying to copy, then ERROR is called with an out of memory
00917                 error and the function returns NULL. 
00918 
00919     Scope:      protected       
00920 
00921 **********************************************************************************************/
00922 
00923 Node* Spread::SimpleCopy()
00924 {
00925     Spread* NodeCopy; 
00926     NodeCopy = new Spread();
00927     ERRORIF(NodeCopy == NULL, _R(IDE_NOMORE_MEMORY), NULL); 
00928     CopyNodeContents(NodeCopy);   
00929     return (NodeCopy);
00930 }  
00931 
00932 
00933 
00934 /***********************************************************************************************
00935 
00936 >   void Spread::CopyNodeContents(Spread* NodeCopy)
00937 
00938     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00939     Created:    28/4/93
00940     
00941     Inputs:           
00942     Outputs:    A copy of this node
00943     Returns:    -
00944          
00945     Purpose:    This method copies the node's contents to the node pointed to by NodeCopy.
00946               
00947     Errors:     An assertion failure will occur if NodeCopy is NULL
00948     
00949     Scope:      protected
00950                                      
00951 ***********************************************************************************************/
00952 
00953 void Spread::CopyNodeContents(Spread* NodeCopy)
00954 {                         
00955     ERROR3IF(NodeCopy == NULL,"Trying to copy node contents to\n"
00956                             "a node pointed to by a NULL pointer"); 
00957     NodeRenderablePaper::CopyNodeContents(NodeCopy); 
00958     
00959     NodeCopy->BleedOffset = BleedOffset;
00960     NodeCopy->ShowDropShadow = ShowDropShadow;
00961     NodeCopy->SpreadOrigin = SpreadOrigin;
00962     NodeCopy->UserOrigin = UserOrigin;
00963     NodeCopy->m_AnimPropertiesParam = m_AnimPropertiesParam;
00964     NodeCopy->SpreadDimScale = SpreadDimScale;
00965     NodeCopy->RalphDontShowPaper = RalphDontShowPaper;
00966 }
00967 
00968           
00969 /***********************************************************************************************
00970 >   void Spread::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00971 
00972     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00973     Created:    18/12/2003
00974     Outputs:    -
00975     Purpose:    Polymorphically copies the contents of this node to another
00976     Errors:     An assertion failure will occur if NodeCopy is NULL
00977     Scope:      protected
00978                                      
00979 ***********************************************************************************************/
00980 
00981 void Spread::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00982 {
00983     ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
00984     ENSURE(IS_A(pNodeCopy, Spread), "PolyCopyNodeContents given wrong dest node type");
00985 
00986     if (IS_A(pNodeCopy, Spread))
00987         CopyNodeContents((Spread*)pNodeCopy);
00988 }
00989 
00990 
00991 
00992 /***********************************************************************************************
00993 
00994 >   Page* Spread::FindFirstPageInSpread() const
00995 
00996     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00997     Created:    11/5/93
00998     Inputs:     -
00999     Outputs:    -
01000     Returns:    The first page in the spread, or NULL if the spread has no pages
01001     Purpose:    To find the first page in a spread
01002     Errors:     -
01003     SeeAlso:    -
01004 
01005 ***********************************************************************************************/
01006 
01007 Page* Spread::FindFirstPageInSpread() const
01008 {                     
01009     Node* CurrentNode = FindFirstChild(); 
01010     while(CurrentNode != NULL)   
01011     {
01012         if (CurrentNode->IsKindOf(CC_RUNTIME_CLASS(Page)))
01013             return ((Page*)CurrentNode);     
01014         CurrentNode = CurrentNode->FindNext(); 
01015     }
01016     return (NULL); // No pages were found
01017 }
01018 
01019 
01020   
01021 /***********************************************************************************************
01022 
01023 >   Spread* Spread::FindNextSpread(void)
01024 
01025     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01026     Created:    11/5/93
01027     Inputs:     -
01028     Outputs:    -
01029     Returns:    The next sibling spread of this node, or NULL if there are no more spreads. 
01030     Purpose:    To find the next sibling spread
01031     Errors:     -
01032     SeeAlso:    -
01033 
01034 ***********************************************************************************************/
01035 
01036 Spread* Spread::FindNextSpread(void)
01037 {
01038     Node* CurrentNode = FindNext(); 
01039     while (CurrentNode != 0)
01040     {
01041         if (CurrentNode->IsSpread()) return (Spread*) CurrentNode;    
01042         CurrentNode = CurrentNode->FindNext(); 
01043     }
01044     return 0;                           // No spread found
01045 }                                                               
01046 
01047 
01048 
01049 /***********************************************************************************************
01050 
01051 >   Spread* Spread::FindPreviousSpread(void)
01052 
01053     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01054     Created:    11/5/93
01055     Inputs:     -
01056     Outputs:    -
01057     Returns:    The previous sibling spread of this node, or NULL if there are none.    
01058     Purpose:    To find the current spreads previous sibling spread
01059     Errors:     -
01060     SeeAlso:    -
01061 
01062 ***********************************************************************************************/
01063 
01064 Spread* Spread::FindPreviousSpread(void)
01065 {
01066     Node* CurrentNode = FindPrevious(); 
01067     while (CurrentNode != 0)
01068     {
01069         if (CurrentNode->IsSpread()) return (Spread*) CurrentNode;
01070         CurrentNode = CurrentNode->FindPrevious(); 
01071     }
01072     return 0;                           // No spread found
01073 }       
01074 
01075 
01076 
01077 /********************************************************************************************
01078 
01079 >   Layer* Spread::FindActiveLayer(void)
01080 
01081     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01082     Created:    6/1/94
01083     Inputs:     -
01084     Outputs:    -
01085     Returns:    The active layer for the spread, or NULL if there is no active layer 
01086                 Note: a spread should always have one active layer, so in a DEBUG build an 
01087                 ENSURE failure will occur if no active layer exists. 
01088 
01089     Purpose:    For finding the spreads active layer. 
01090     Errors:     An ENSURE failure will occur if the spread has no active layer, or if the spread
01091                 has more than one active layer. 
01092     SeeAlso:    -
01093 
01094 ********************************************************************************************/
01095 
01096 Layer* Spread::FindActiveLayer(void)
01097 {
01098     // Changed by MarkN 11/8/94 to use Spread::FindFirstLayer()and Layer::FindNextLayer()
01099 
01100     Layer* pActiveLayer = NULL; 
01101     Layer* pLayer = FindFirstLayer();    // Get first child 
01102     BOOL MultipleActiveLayers = FALSE;
01103     while (pLayer != NULL)
01104     {
01105         if (pLayer->IsActive())         // we have found an active layer 
01106         {
01107             // There should only ever be one active layer 
01108             ERROR3IF(pActiveLayer != NULL, "Spread has more than one active layer");
01109             if (pActiveLayer != NULL)
01110                 MultipleActiveLayers = TRUE;
01111             pActiveLayer = pLayer; 
01112         }
01113 
01114         pLayer = pLayer->FindNextLayer(); // Find next layer
01115     } 
01116 
01117     // This line added by MarkN 22/3/95, to ensure that this function cannot fail
01118     // as long as there is at least one layer in this spread.
01119     // The MultipleActiveLayers added by Neville 12/6/96 so that multiple active layers
01120     // are fixed, if found.
01121     if (pActiveLayer == NULL || MultipleActiveLayers)
01122         LayerSGallery::EnsureActiveLayerIntegrity(this,&pActiveLayer);
01123     // Fail if the spread has no active layer 
01124     return (pActiveLayer);
01125 } 
01126 
01127 
01128 
01129 /********************************************************************************************
01130 
01131 >   Layer* Spread::FindFirstLayer() const
01132 
01133     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01134     Created:    18/1/94
01135     Inputs:     -
01136     Outputs:    -
01137     Returns:    The first layer on the spread, or NULL if the spread has no layers.  
01138                 
01139     Purpose:    To find the spread's first layer. 
01140 
01141     Errors:     -
01142     SeeAlso:    -
01143 
01144 ********************************************************************************************/
01145 
01146 Layer* Spread::FindFirstLayer() const
01147 {
01148     Node* Current = FindFirstChild(); 
01149     while (Current != NULL)
01150     {
01151         if (Current->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer))
01152         {
01153             return (Layer*)Current; 
01154         }   
01155         Current = Current->FindNext();  
01156     }
01157 
01158     return (NULL); 
01159 }
01160  
01161                     
01162 /********************************************************************************************
01163 
01164 >   Layer* Spread::FindLastLayer() const 
01165 
01166     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01167     Created:    9/8/94
01168     Inputs:     -
01169     Outputs:    -
01170     Returns:    The last layer on the spread, or NULL if the spread has no layers.  
01171                 
01172     Purpose:    To find the spread's last layer. 
01173 
01174     Errors:     -
01175     SeeAlso:    -
01176 
01177 ********************************************************************************************/
01178 
01179 Layer* Spread::FindLastLayer() const
01180 {
01181     Node* pNode = FindFirstChild(); 
01182     Layer* pLastLayer = NULL;
01183 
01184     while (pNode != NULL)
01185     {
01186         if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer))
01187             pLastLayer = (Layer*)pNode; 
01188 
01189         pNode = pNode->FindNext();  
01190     }
01191 
01192     return (pLastLayer); 
01193 }
01194  
01195 
01196 
01197 /********************************************************************************************
01198 
01199 >   Layer* Spread::FindFirstGuideLayer() const
01200 
01201     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01202     Created:    4/10/95
01203     Inputs:     -
01204     Outputs:    -
01205     Returns:    The first guide layer on the spread, or NULL if the spread has no layers.  
01206                 
01207     Purpose:    To find the spread's first guide layer. 
01208 
01209     Errors:     -
01210     SeeAlso:    -
01211 
01212 ********************************************************************************************/
01213 
01214 Layer* Spread::FindFirstGuideLayer() const
01215 {
01216     Layer* pLayer = FindFirstLayer();
01217     while (pLayer != NULL)
01218     {
01219         if (pLayer->IsGuide())
01220             return pLayer;
01221 
01222         pLayer = pLayer->FindNextLayer();
01223     }
01224 
01225     return NULL;
01226 }
01227 
01228 /********************************************************************************************
01229 
01230 >   Layer* Spread::FindFirstPageBackgroundLayer() const
01231 
01232     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01233     Created:    4/4/97
01234     Inputs:     -
01235     Outputs:    -
01236     Returns:    The first page background layer on the spread, or NULL if the spread has no layers.  
01237     Purpose:    To find the spread's first page background layer. 
01238     Errors:     -
01239     SeeAlso:    -
01240 
01241 ********************************************************************************************/
01242 
01243 Layer* Spread::FindFirstPageBackgroundLayer() const
01244 {
01245     // Search through the children of this Spread, looking for Layer nodes.
01246     // Use the special flag of the page background layer as its identifier.
01247     Layer* pLayer = FindFirstLayer(); 
01248     while (pLayer != NULL)
01249     {
01250         // See if this is a page background layer
01251         if (pLayer->IsPageBackground())
01252         {
01253             // Cor blimey, we've found one, so return this layer to the caller
01254             return pLayer;
01255         }
01256         
01257         pLayer = pLayer->FindNextLayer();   
01258     }
01259 
01260     // Nothing found
01261     return NULL;
01262 }
01263 
01264 /********************************************************************************************
01265 
01266 >   Layer* Spread::FindFirstFrameLayer() const
01267 
01268     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01269     Created:    23/4/97
01270     Inputs:     -
01271     Outputs:    -
01272     Returns:    The first frame layer on the spread, or NULL if the spread has no layers.  
01273     Purpose:    To find the spread's first frame layer. 
01274     Errors:     -
01275     SeeAlso:    -
01276 
01277 ********************************************************************************************/
01278 
01279 Layer* Spread::FindFirstFrameLayer() const
01280 {
01281     // Search through the children of this Spread, looking for Layer nodes.
01282     // Use the special flag for frame layers as its identifier.
01283     Layer* pLayer = FindFirstLayer(); 
01284     while (pLayer != NULL)
01285     {
01286         // See if this is a frame layer
01287         if (pLayer->IsFrame())
01288         {
01289             // Cor blimey, we've found one, so return this layer to the caller
01290             return pLayer;
01291         }
01292         
01293         pLayer = pLayer->FindNextLayer();   
01294     }
01295 
01296     // Nothing found
01297     return NULL;
01298 }
01299 
01300 /********************************************************************************************
01301 
01302 >   Layer* Spread::FindLastFrameLayer() const 
01303 
01304     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01305     Created:    21/5/97
01306     Inputs:     -
01307     Outputs:    -
01308     Returns:    The last frame layer on the spread, or NULL if the spread has no frame layers.  
01309     Purpose:    To find the spread's last framelayer. 
01310     Errors:     -
01311     SeeAlso:    -
01312 
01313 ********************************************************************************************/
01314 
01315 Layer* Spread::FindLastFrameLayer() const
01316 {
01317     // Search through the children of this Spread, looking for Layer nodes.
01318     // Use the special flag for frame layers as its identifier.
01319     Layer* pLayer = FindFirstLayer(); 
01320     Layer* pLastLayer = NULL;
01321     while (pLayer != NULL)
01322     {
01323         // See if this is a frame layer
01324         if (pLayer->IsFrame())
01325         {
01326             // Cor blimey, we've found one, so remember this as a potential last frame layer
01327             pLastLayer = pLayer;
01328         }
01329         
01330         pLayer = pLayer->FindNextLayer();   
01331     }
01332 
01333     // Return what we found as the last layer
01334     return pLastLayer;
01335 }
01336 
01337 /********************************************************************************************
01338 
01339 >   Page* Spread::FindLastPageInSpread() const
01340 
01341     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01342     Created:    4/4/97
01343     Inputs:     -
01344     Outputs:    -
01345     Returns:    The last page on the spread, or NULL if the spread has no pages.  
01346     Purpose:    To find the spread's last page.
01347                 Layers and other renderable nodes should always be inserted after the last page.
01348                 Otherwise, there is likely to be redraw problems.
01349     Errors:     -
01350     SeeAlso:    FindFirstPageInSpread;
01351 
01352 ********************************************************************************************/
01353 
01354 Page* Spread::FindLastPageInSpread() const
01355 {
01356     // Get the first page and then continually get the next page until one is not found
01357     // Each time we get a real page we note this as a potential last page.
01358     Page *pLastPage = NULL;
01359     Page *pPage = FindFirstPageInSpread();
01360     while (pPage != NULL)
01361     {
01362         pLastPage = pPage; // note this page as a potential last page
01363         pPage = pPage->FindNextPage();
01364     }
01365 
01366     // return what we think is the last page
01367     return pLastPage;
01368 }
01369 
01370 /********************************************************************************************
01371 
01372 >   DocRect Spread::GetWidePasteboard(View *pView)
01373 
01374     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01375     Created:    22/11/94
01376     Inputs:     pView - the view to pixelise to.
01377     Purpose:    Return the pixelised boundary of the "wide pasteboard"
01378 
01379 ********************************************************************************************/
01380 
01381 DocRect Spread::GetWidePasteboard(View *pView)
01382 {
01383     ERROR2IF(this==NULL,DocRect(0,0,0,0),"GetWidePasteboard called on NULL pointer");
01384 
01385     // A large size - roughly the width/height of 30 A4 pages. We use this to extend
01386     // the WPB to an effective "infinity" in certain directions.
01387     const MILLIPOINT LargeNumber = 30 * (10 * 72000);
01388 
01389     DocRect WPB(PasteboardRect);
01390 
01391     // Inflate the left/right sides out to effective "infinity"
01392     WPB.Inflate(LargeNumber, 0);
01393 
01394     // If this is the very last spread in the chapter, expand its WPB down by "infinity"
01395     if (FindNextSpread() == NULL)
01396         WPB.lo.y -= LargeNumber;
01397 
01398     // Pixelise and return the result
01399     WPB.lo.Pixelise(pView);
01400     WPB.hi.Pixelise(pView);
01401 
01402     return(WPB);
01403 }
01404 
01405 
01406 
01407 
01408 #ifdef _DEBUG    
01409     
01410 void Spread::ShowDebugTreeDetails() const
01411 {                                 
01412     TRACE( _T("Spread ")); 
01413     Node::ShowDebugTreeDetails(); 
01414 }
01415 
01416 #endif  
01417 
01418 /********************************************************************************************
01419 
01420 >   void* Spread::GetDebugDetails(StringBase* Str) 
01421 
01422     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01423     Created:    21/9/93
01424     Inputs:     -
01425     Outputs:    Str: String giving debug info about the node
01426     Returns:    -
01427     Purpose:    For obtaining debug information about the Node
01428     Errors:     -
01429     SeeAlso:    -
01430 
01431 ********************************************************************************************/
01432 
01433 void Spread::GetDebugDetails(StringBase* Str)
01434 {
01435     NodeRenderablePaper::GetDebugDetails(Str);
01436     String_256 TempStr;
01437 
01438     TempStr._MakeMsg(TEXT("\r\nBleed Offset = #1%ld"), BleedOffset);
01439     *Str += TempStr;
01440 
01441     TempStr._MakeMsg(TEXT("\r\nSpreadCoord Origin = #1%ld, #2%ld"),
01442                      SpreadOrigin.x, SpreadOrigin.y); 
01443     *Str += TempStr;
01444 }
01445 
01446 
01447 
01448 /********************************************************************************************
01449 
01450 >   virtual UINT32 Spread::GetNodeSize() const
01451 
01452     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01453     Created:    6/10/93
01454     Inputs:     -
01455     Outputs:    -
01456     Returns:    The size of the node in bytes
01457     Purpose:    For finding the size of the node 
01458                 
01459     SeeAlso:    Node::GetSubtreeSize
01460 
01461 ********************************************************************************************/
01462 
01463 UINT32 Spread::GetNodeSize() const 
01464 {     
01465     return (sizeof(Spread)); 
01466 }  
01467 
01468 
01469 
01470 /********************************************************************************************
01471 
01472 >   DocRect Spread::GetPageBounds() const
01473 
01474     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01475     Created:    18/5/94
01476     Inputs:     -
01477     Outputs:    -
01478     Returns:    A document rectangle which is the rectangle bounding all Pages in
01479                 this Spread.  This really is a document rectangle, not a spread
01480                 rectangle hiding as a DocRect, ie. it is relative to the bottom-left
01481                 of the document, not the spread.
01482     Purpose:    Finds the bounding rectangle of this Spread, defined as the smallest
01483                 rectangle enclosing all the Pages the Spread contains.
01484     Errors:     -
01485     SeeAlso:    Page::GetPageRect
01486 
01487 ********************************************************************************************/
01488 
01489 DocRect Spread::GetPageBounds() const
01490 {
01491     // Start with an empty bounding rectangle.
01492     DocRect drBound;
01493     drBound.MakeEmpty();
01494 
01495     // Search through the children of this Spread, looking for Page nodes.
01496     Node* Current = FindFirstChild(); 
01497     while (Current != NULL)
01498     {
01499         if (Current->GetRuntimeClass() == CC_RUNTIME_CLASS(Page))
01500         {
01501             // Found a page node.  Take the union of its bounding rectangle and
01502             // the accumulated bounds.
01503             drBound = drBound.Union(((Page*) Current)->GetPageRect());
01504         }   
01505         Current = Current->FindNext();  
01506     }
01507 
01508     // Convert the value from spread coordinates to document coords
01509     SpreadCoordToDocCoord(&drBound);
01510 
01511     // Return the accumulated bounds.
01512     return drBound;
01513 }
01514 
01515 
01516 
01517 /********************************************************************************************
01518 
01519 >   DocRect Spread::GetPageVisibleBounds() const
01520 
01521     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01522     Created:    18/5/94
01523     Inputs:     -
01524     Outputs:    -
01525     Returns:    A document rectangle which is the rectangle bounding all Pages in
01526                 this Spread.  This really is a document rectangle, not a spread
01527                 rectangle hiding as a DocRect, ie. it is relative to the bottom-left
01528                 of the document, not the spread.
01529     
01530     Purpose:    Finds the bounding rectangle of this Spread, defined as the smallest
01531                 rectangle enclosing all the Pages the Spread contains.
01532 
01533                 The visible bounds exclude all non-visible layers
01534 
01535     Errors:     -
01536     SeeAlso:    Page::GetPageRect
01537 
01538 ********************************************************************************************/
01539 
01540 DocRect Spread::GetPageVisibleBounds() const
01541 {
01542     // Start with an empty bounding rectangle.
01543     DocRect drBound;
01544     drBound.MakeEmpty();
01545 
01546     // Search through the children of this Spread, looking for Layer nodes.
01547     Layer* pCurrent = ((Spread*)this)->FindFirstLayer(); 
01548     while (pCurrent != NULL)
01549     {
01550         // Only add the bounding box of the layer in if it is visible and if it is not
01551         // either a guide layer or the page background layer.
01552         if (pCurrent->IncludeLayerInBoundingCalcs())
01553         {
01554             // Found a visible layer node.  Take the union of its bounding rectangle and
01555             // the accumulated bounds.
01556             drBound = drBound.Union(pCurrent->GetBoundingRect());
01557         }   
01558         
01559         pCurrent = pCurrent->FindNextLayer();   
01560     }
01561 
01562     // Convert the value from spread coordinates to document coords
01563     SpreadCoordToDocCoord(&drBound);
01564 
01565     // Return the accumulated bounds.
01566     return drBound;
01567 }
01568 
01569 
01570 
01571 /********************************************************************************************
01572 
01573 >   DimScale* Spread::GetPtrDimScale()
01574 
01575     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01576     Created:    14/6/94
01577     Inputs:     -
01578     Outputs:    -
01579     Returns:    A ptr to the dimension scale object for all objects in this Spread
01580     Purpose:    For getting a ptr to the Spread's dimension scale object
01581     Errors:     -
01582     SeeAlso:    -
01583 
01584 ********************************************************************************************/
01585 
01586 DimScale* Spread::GetPtrDimScale()
01587 {
01588     return (&SpreadDimScale);
01589 } 
01590 
01591 
01592 
01593 /********************************************************************************************
01594 
01595 >   MILLIPOINT Spread::GetBleedOffset() const
01596 
01597     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01598     Created:    14/12/94
01599     Inputs:     -
01600     Outputs:    -
01601     Returns:    The current size in millipoints of this spreads bleed are.
01602     Purpose:    For getting the Spread's bleed area size. 
01603     Errors:     -
01604     SeeAlso:    SetBleedOffset();
01605 
01606 ********************************************************************************************/
01607 
01608 MILLIPOINT Spread::GetBleedOffset() const
01609 {
01610     return BleedOffset;
01611 } 
01612 
01613 
01614 
01615 /********************************************************************************************
01616 
01617 >   BOOL Spread::SetBleedOffset(MILLIPOINT Bleed)
01618 
01619     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01620     Created:    14/12/94
01621     Inputs:     -
01622     Outputs:    -
01623     Returns:    The current size in millipoints of this spreads bleed are.
01624     Purpose:    For setting a new value for the Spread's bleed area size. 
01625     Errors:     -
01626     SeeAlso:    GetBleedOffset();
01627 
01628 ********************************************************************************************/
01629 
01630 BOOL Spread::SetBleedOffset(MILLIPOINT Bleed)
01631 {
01632     BleedOffset = Bleed;    // set up new bleed value
01633     
01634     return TRUE;
01635 } 
01636 
01637 
01638 
01639 /********************************************************************************************
01640 
01641 >   BOOL Spread::GetShowDropShadow() const
01642 
01643     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01644     Created:    14/12/94
01645     Inputs:     -
01646     Outputs:    -
01647     Returns:    The current drop shadow display state as either True or False.
01648     Purpose:    Finds out the current drop shadow display state.
01649     Errors:     -
01650     SeeAlso:    SetShowDropShadow();
01651 
01652 ********************************************************************************************/
01653 
01654 BOOL Spread::GetShowDropShadow() const
01655 {
01656     return ShowDropShadow;
01657 } 
01658 
01659 
01660 
01661 /********************************************************************************************
01662 
01663 >   BOOL Spread::SetShowDropShadow(BOOL NewState)
01664 
01665     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01666     Created:    14/12/94
01667     Inputs:     New drop shadow display state.
01668     Outputs:    -
01669     Returns:    The old drop shadow display state as either True or False.
01670     Purpose:    Allows the setting of a new drop shadow display state.
01671     Errors:     -
01672     SeeAlso:    GetShowDropShadow();
01673 
01674 ********************************************************************************************/
01675 
01676 BOOL Spread::SetShowDropShadow(BOOL NewState)
01677 {
01678 //  WEBSTER-ranbirr-13/11/96
01679 #ifndef WEBSTER
01680     BOOL OldState = ShowDropShadow; // note current old state
01681     ShowDropShadow = NewState;      // Set up the required new state
01682     return OldState;                // return old state to the caller
01683 
01684 #else //webster
01685 
01686     BOOL OldState = FALSE;  
01687     ShowDropShadow = FALSE ;
01688     return OldState;                // return old state to the caller
01689 #endif //Webster
01690 
01691 }
01692 
01693 #if NEW_PASTEBOARD
01694 // New pasteboard code by Jason. This keeps the bottom left corner of the page where
01695 // it was, and rejigs the page size, other pages, bleed, and pasteboard to fit tidily
01696 // around the outside. This results in a much tidier spread than the old code, but
01697 // due to flaws in our V1 save file format, completely scrags save/load!
01698 // Hopefully for V2, we can fix the save/load code to allow us to use more sensible layouts
01699 
01700 /********************************************************************************************
01701 
01702 >   BOOL Spread::GetPageSize(MILLIPOINT *Width, MILLIPOINT *Height, MILLIPOINT *Margin,
01703                              MILLIPOINT *Bleed, BOOL *Dps, BOOL *ShowDropShadow)
01704 
01705     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01706     Created:    4/1/95
01707     Inputs:     -
01708     Outputs:    Width           returned width of the page in millipoints
01709                 Height          returned height of the page in millipoints
01710                 Margin          returned size of the margin area in millipoints (0 = none)
01711                 Bleed           returned size of the bleed area in millipoints (0 = none)
01712                 Dps             returned whether another page (or pages) is present or not.
01713                 ShowDropShadow  returned new drop shadow display state.
01714     Returns:    Whether we completed the scanning operation ok or not as True or False.
01715     Purpose:    Allows the current page size specified for a spread to be determined.
01716                 Assumes that all pages in one spread are the same size and hence returns
01717                 this size.
01718 
01719                 Note: Any of the input params can be NULL (Markn 4/4/95)
01720 
01721     Errors:     Will error if pages are not consistent.
01722     SeeAlso:    Spread::SetPageSize
01723 
01724 ********************************************************************************************/
01725 
01726 BOOL Spread::GetPageSize(MILLIPOINT *Width, MILLIPOINT *Height, MILLIPOINT *Margin,
01727                          MILLIPOINT *Bleed, BOOL *Dps, BOOL *ShowDropShadow)
01728 {
01729     ERROR2IF(this==NULL,FALSE,"Spread::GetPageSize called on NULL pointer");
01730 
01731     // Set up defaults in case of dodgy exit
01732     if (Width   != NULL) *Width  = 0;
01733     if (Height  != NULL) *Height = 0;
01734     if (Margin  != NULL) *Margin = 0;
01735     if (Bleed   != NULL) *Bleed  = 0;
01736     if (Dps     != NULL) *Dps = FALSE;
01737     if (ShowDropShadow != NULL) *ShowDropShadow = TRUE;
01738 
01739     Page *pPage = FindFirstPageInSpread();
01740     ERROR2IF(pPage == NULL,FALSE,"Spread::GetPageSize(): Could not find first Page");
01741     
01742     // Measured in millipoints
01743     DocRect PageRect = pPage->GetPageRect();
01744 
01745     MILLIPOINT PageWidth = PageRect.Width();
01746     MILLIPOINT PageHeight = PageRect.Height();  
01747 
01748     // Set up the return height and width according to this first page
01749     if (Width  != NULL) *Width  = PageWidth;
01750     if (Height != NULL) *Height = PageHeight;
01751 
01752     // Calculate the margin value
01753     if (Margin != NULL)
01754     {
01755         // The margin is the border between the edge of the page and the pasteboard
01756         // We assume that this is the same on all sides, which is the default whenever
01757         // the page size changes - If the user makes it lopsided, we'll use the maximum
01758         // value so that the page options dialogue shows a sensible new value.
01759         DocRect PasteRect = GetPasteboardRect();
01760         DocCoordToSpreadCoord(&PasteRect);
01761 
01762         INT32 MaxMargin = ABS(PageRect.lo.x - PasteRect.lo.x);
01763 
01764         INT32 temp = ABS(PageRect.lo.y - PasteRect.lo.y);
01765         if (temp > MaxMargin) MaxMargin = temp;
01766 
01767         temp = ABS(PageRect.hi.x - PasteRect.hi.x);
01768         if (temp > MaxMargin) MaxMargin = temp;
01769 
01770         temp = ABS(PageRect.hi.y - PasteRect.hi.y);
01771         if (temp > MaxMargin) MaxMargin = temp;
01772 
01773         *Margin = MaxMargin;
01774     }
01775 
01776     // Find out if dps by finding the next page in the spread and see if measurements are
01777     // the same as at present. Will only work in the simple case.
01778     pPage = pPage->FindNextPage();
01779 
01780     if (pPage != NULL)
01781     {
01782         // Measured in millipoints
01783         DocRect Page2Rect = pPage->GetPageRect();
01784 
01785         MILLIPOINT Page2Width = PageRect.Width();
01786         MILLIPOINT Page2Height = PageRect.Height(); 
01787 
01788         // lox,loy,hix,hiy
01789         if (Page2Rect.lo.x == PageRect.hi.x && Page2Rect.lo.y == PageRect.lo.y &&
01790             Page2Width == PageWidth && Page2Height == PageHeight)
01791         {
01792             if (Dps != NULL)
01793                 *Dps = TRUE;
01794         }
01795         else
01796         {
01797             // unrecognised page structure found
01798             ERROR2(FALSE,"bad page structure found in Spread::GetPageSize");
01799         }
01800     }
01801     else
01802     {
01803         if (Dps != NULL)
01804             *Dps = FALSE;
01805     }
01806 
01807     // Now get the current bleed size for the spread 
01808     if (Bleed != NULL)
01809         *Bleed = GetBleedOffset();
01810 
01811     if (ShowDropShadow != NULL)
01812         *ShowDropShadow = GetShowDropShadow();
01813 
01814     return TRUE;
01815 }
01816 
01817 
01818 
01819 /********************************************************************************************
01820 
01821 >   BOOL Spread::SetPageSize(const MILLIPOINT Width, const MILLIPOINT Height, const MILLIPOINT Margin,
01822                              const MILLIPOINT Bleed, const BOOL Dps, const BOOL ShowDropShadow)
01823 
01824     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> (Hacked about a lot by Jason, 13/3/96)
01825     Created:    14/12/94
01826     Inputs:     Width           New width of pages in millipoints
01827                 Height          New height of pages in millipoints
01828                 Margin          New size of the margin area in millipoints (0 = none)
01829                 Bleed           New size of the bleed area in millipoints (0 = none)
01830                 Dps             (Double page spread) FALSE = 1 page; TRUE = 2 pages
01831                 ShowDropShadow  New drop shadow display state.
01832     Outputs:    -
01833 
01834     Returns:    TRUE if we were successful
01835 
01836     Purpose:    Allows the setting of a new page size by height and width for all pages
01837                 in this spread. Also allows changing of other spread attributes such as:-
01838                     margin around pages in spread (gap between pasteboard edge and pages),
01839                     bleed size
01840                     single/double page spread
01841                     whether a drop shadow is displayed for pages on this spread.
01842 
01843     Notes:      The pages will be resized such that the bottom left of the bottom-left-most
01844                 page stays in the same spot.
01845 
01846                 Assumes there is only one default grid per spread
01847 
01848     Errors:     -
01849     SeeAlso:    -
01850 
01851 ********************************************************************************************/
01852 
01853 BOOL Spread::SetPageSize(const MILLIPOINT Width, const MILLIPOINT Height, const MILLIPOINT Margin,
01854                          const MILLIPOINT Bleed, const BOOL Dps, const BOOL ShowDropShadow)
01855 {
01856     ERROR2IF(this == NULL,FALSE,"Spread::SetPageSize called on NULL pointer");
01857 
01858     // Include the bleed area into the margin we were given
01859     MILLIPOINT PageMargin = Margin + Bleed;
01860 
01861     // --- Sort out the default grid (* Assumes there is only one default grid *)
01862     // Find the position of the grid relative to the pages so this can be maintained
01863     // (see the end of this function)
01864     NodeGrid* pGrid = FindFirstDefaultGridInSpread();
01865     DocCoord PageRelGridOrigin;
01866 
01867     if (pGrid != NULL)
01868     {
01869         DocCoord GridOrigin;
01870 
01871         pGrid->GetOrigin(&GridOrigin.x, &GridOrigin.y);
01872         SpreadCoordToPagesCoord(&PageRelGridOrigin, GridOrigin);
01873     }
01874 
01875     // --- Reposition/resize/add/remove pages as necessary
01876     if (!AdjustAllPages(Width, Height, Margin, Dps))
01877         return FALSE;
01878 
01879 
01880     // --- Create and set a tidy new pasteboard rectangle
01881     {
01882         // Determine the new combined width of all the pages
01883         MILLIPOINT WidthOfPages = Width;            // 1 page (single page spread)
01884         if (Dps)
01885             WidthOfPages = 2 * Width;               // 2 pages (double page spread)
01886 
01887         // First, make it the right size, centered about (0,0)
01888         MILLIPOINT x = (WidthOfPages + 2*PageMargin) / 2;
01889         MILLIPOINT y = (Height + 2*PageMargin) / 2;
01890 
01891         DocRect NewPasteRect = DocRect(-x, -y, x, y);
01892 
01893         // Translate it to the center of the new page spread, so it is centered on the pages
01894         // Note that the Rect is now in the correct place in _Document_ coords.
01895         DocRect PagesRect = GetPageBounds();
01896         x = (PagesRect.lo.x / 2) + (PagesRect.hi.x / 2);    // NOTE: Maths done carefully
01897         y = (PagesRect.lo.y / 2) + (PagesRect.hi.y / 2);    // to avoid integer overflows!
01898         NewPasteRect.Translate(x, y);
01899 
01900         // And expand it as necessary to include all the objects in the spread
01901 
01902 /*  Strangely, the BoundingRect seems to include the entire pasteboard area if the document is blank-
01903     This means we always make the pasteboard 1 inch bigger than requested!
01904 
01905 
01906         DocRect ObjectBounds = GetBoundingRect();
01907         if (ObjectBounds.IsValid())
01908         {
01909             // Inflate to get a 1inch margin around the objects, to ensure you can
01910             // see all their blobs and have a bit of a margin near the edge of the 
01911             // scroll extent.
01912             ObjectBounds.Inflate(72000);
01913             NewPasteRect = NewPasteRect.Union(ObjectBounds);
01914         }
01915 */
01916         // Convert it from spread coordinates into document coords, and set it
01917         ChangePasteboardRect(NewPasteRect);
01918 
01919         // Finally, ensure all pasteboards butt up to each other tidily
01920         AdjustPasteboards();
01921     }
01922 
01923     // --- Set fold line position
01924     // Find the chapter in which we belong
01925     Chapter* pChapter = FindParentChapter();
01926     ERROR3IF(pChapter == NULL,"Spread::SetPageSize: Could not find parent chapter");
01927     if (pChapter != NULL)
01928     {
01929         // Set the main fold line x coordinate. Initialise to non-showing value
01930         MILLIPOINT FoldLineX = 0;
01931         BOOL ShowFoldLine = FALSE;
01932 
01933         // Check if there is another spread present or not
01934         // If not and only a single page then do not show the fold line
01935         Spread* pNextSpread = FindNextSpread();
01936         if (pNextSpread != NULL || Dps)
01937         {
01938             // We have more than one spread and/or a double page spread so
01939             // set the fold line to the join between the two pages or the right hand
01940             // side of the left page 
01941             FoldLineX = PageMargin + Width;
01942             ShowFoldLine = TRUE;
01943         }
01944 
01945         // Set the fold line position, and enable/disable display of it as appropriate
01946         pChapter->SetFoldLineXCoord(FoldLineX, ShowFoldLine);
01947         pChapter->InvalidateBoundingRect();
01948     }
01949 
01950     // --- Set the new bleed size for this spread
01951     if (!SetBleedOffset(Bleed))
01952         return FALSE;
01953 
01954     // --- Set the new dropshadow state
01955     SetShowDropShadow(ShowDropShadow);
01956 
01957     // --- Adjust the default grid origin to a sensible place relative to the page
01958     if (pGrid != NULL)
01959     {
01960         DocCoord GridOrigin;
01961         PagesCoordToSpreadCoord(&GridOrigin, PageRelGridOrigin);
01962         pGrid->SetOrigin(GridOrigin.x, GridOrigin.y);
01963     }
01964 
01965     return TRUE;
01966 }
01967 
01968 
01969 
01970 /********************************************************************************************
01971 
01972 >   BOOL Spread::AdjustAllPages(const MILLIPOINT Width, const MILLIPOINT Height,
01973                                    const MILLIPOINT Margin, const BOOL Dps)
01974 
01975     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> (Hacked about a lot by Jason, 13/3/96)
01976     Created:    16/1/95
01977 
01978     Inputs:     Width           New width of the page in millipoints
01979                 Height          New height of the page in millipoints
01980                 Margin          New size of the margin area in millipoints (0 = none)
01981                 Dps             Whether another page is required or not.
01982 
01983     Outputs:    -
01984     Returns:    TRUE if we were successful
01985 
01986     Purpose:    Configures the pages in a spread.
01987                 This simple function only allows:
01988                     * All pages must be the same size
01989                     * Spreads can only be Single or Double page spreads
01990 
01991                 This will:
01992                     * Make all pages the given size
01993                     * Move all pages so they butt up against each other
01994                     * Ensure that the pasteboard includes the margin around the outside
01995                       of the pages
01996                     * Create/delete page(s) as necessary to make a single/double page spread
01997 
01998 ********************************************************************************************/
01999 
02000 BOOL Spread::AdjustAllPages(const MILLIPOINT Width, const MILLIPOINT Height,
02001                                const MILLIPOINT Margin, const BOOL Dps)
02002 {
02003     // Find the first page in the spread
02004     Page *pFirstPage = FindFirstPageInSpread();
02005     ERROR2IF(pFirstPage == NULL, FALSE, "This spread has no pages?!");
02006 
02007     // Get the size and position of the first page
02008     DocRect OldPageRect = pFirstPage->GetPageRect();
02009 
02010     // And place the new page with its bottom left corner in the same spot
02011     DocRect PageRect(0, 0, Width, Height);
02012     PageRect.Translate(OldPageRect.lo.x, OldPageRect.lo.y);
02013 
02014     if (!pFirstPage->SetPageRect(PageRect))
02015         return FALSE;
02016 
02017     // Find out if there is a 2nd page in the spread. This will be created/deleted/adjusted
02018     // as necessary to achieve the desired set of pages
02019     Page *pPage = pFirstPage->FindNextPage();
02020     if (pPage != NULL)
02021     {
02022         // --- We have 2 (or more) pages...
02023         if (Dps)
02024         {
02025             // ... and we want 2 pages, so just translate the current page to butt up
02026             // to the first page, and also set it to the new size
02027             PageRect.Translate(Width, 0);
02028             if (!pPage->SetPageRect(PageRect))
02029                 return FALSE;
02030 
02031             // And advance to the next page. This should be NULL, but if it's not,
02032             // we'll drop out and delete all surplus pages anyway
02033             pPage = pPage->FindNextPage();
02034             ERROR3IF(pPage != NULL, "Surplus page(s) found in double page spread - I've deleted them");
02035         }
02036 
02037         // Finally, delete any surplus pages
02038         Page *pNext;
02039         while (pPage != NULL)
02040         {
02041             pNext = pPage->FindNextPage();
02042             pPage->CascadeDelete();
02043             // Of course, Cascade delete does not actually delete the page, so now do that
02044             delete pPage;
02045             pPage = pNext;
02046         }
02047     }
02048     else
02049     {
02050         // --- There is only one page
02051         // If we need 2 pages, then we'll have to create a new one
02052         if (Dps)
02053         {
02054             // Position the new one just to the right of the first page
02055             PageRect.Translate(Width, 0);
02056 
02057             Page *Page2 = new Page(this, LASTCHILD, PageRect);
02058             if (Page2 == NULL)
02059             {
02060                 // We ran out of memory
02061                 InformError(_R(IDE_NOMORE_MEMORY));
02062                 return FALSE;
02063             }
02064         }
02065     }
02066 
02067     return TRUE;
02068 }
02069 
02070 #else
02071 
02072 /********************************************************************************************
02073 
02074 >   BOOL Spread::GetPageSize(MILLIPOINT *Width, MILLIPOINT *Height, MILLIPOINT *Margin,
02075                              MILLIPOINT *Bleed, BOOL *Dps, BOOL *ShowDropShadow)
02076 
02077     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02078     Created:    4/1/95
02079     Inputs:     -
02080     Outputs:    Width           returned width of the page in millipoints
02081                 Height          returned height of the page in millipoints
02082                 Margin          returned size of the margin area in millipoints (0 = none)
02083                 Bleed           returned size of the bleed area in millipoints (0 = none)
02084                 Dps             returned whether another page (or pages) is present or not.
02085                 ShowDropShadow  returned new drop shadow display state.
02086     Returns:    Whether we completed the scanning operation ok or not as True or False.
02087     Purpose:    Allows the current page size specified for a spread to be determined.
02088                 Assumes that all pages in one spread are the same size and hence returns
02089                 this size.
02090 
02091                 Note: Any of the input params can be NULL (Markn 4/4/95)
02092 
02093     Errors:     Will error if pages are not consistent.
02094     SeeAlso:    SetPageSize;
02095 
02096 ********************************************************************************************/
02097 BOOL Spread::GetPageSize(MILLIPOINT *Width, MILLIPOINT *Height, MILLIPOINT *Margin,
02098                          MILLIPOINT *Bleed, BOOL *Dps, BOOL *ShowDropShadow)
02099 {
02100     ERROR2IF(this==NULL,FALSE,"Spread::GetPageSize called on NULL pointer");
02101 
02102     // Set up defaults in case of dodgy exit
02103     if (Width   != NULL) *Width  = 0;
02104     if (Height  != NULL) *Height = 0;
02105     if (Margin  != NULL) *Margin = 0;
02106     if (Bleed   != NULL) *Bleed  = 0;
02107     if (Dps     != NULL) *Dps = FALSE;
02108 //  WEBSTER-ranbirr-13/11/96
02109 #ifndef WEBSTER
02110     if (ShowDropShadow != NULL) *ShowDropShadow = TRUE;
02111 #endif //webster
02112     Page *pPage = FindFirstPageInSpread();
02113     ERROR2IF(pPage == NULL,FALSE,"Spread::GetPageSize(): Could not find first Page");
02114     
02115     // Measured in millipoints
02116     DocRect PageRect = pPage->GetPageRect();
02117 
02118     MILLIPOINT PageWidth = PageRect.Width();
02119     MILLIPOINT PageHeight = PageRect.Height();  
02120 
02121     // Set up the return height and width according to this first page
02122     if (Width  != NULL) *Width  = PageWidth;
02123     if (Height != NULL) *Height = PageHeight;
02124 
02125     // Get present low corner position, we will use this to calculate the gap around the pages
02126     DocCoord Low = PageRect.LowCorner();
02127     // Assume: Margin = the position of the bottom left hand corner of the old page.
02128     // Use y as the initial defualt page is shifted across giving large x and correct y.
02129     if (Margin != NULL) *Margin = Low.y;
02130 
02131     // Find out if dps by finding the next page in the spread and see if measurements are
02132     // the same as at present. Will only work in the simple case.
02133     pPage = pPage->FindNextPage();
02134 
02135     if (pPage != NULL)
02136     {
02137         // Measured in millipoints
02138         DocRect Page2Rect = pPage->GetPageRect();
02139 
02140         MILLIPOINT Page2Width = PageRect.Width();
02141         MILLIPOINT Page2Height = PageRect.Height(); 
02142 
02143         // lox,loy,hix,hiy
02144         if( Page2Rect.lo.x == PageRect.hi.x && 
02145             Page2Rect.lo.y == PageRect.lo.y &&
02146             Page2Width == PageWidth && 
02147             Page2Height == PageHeight)
02148         {
02149             if (Dps != NULL) *Dps = TRUE;   
02150         }
02151         else
02152         {
02153             // unrecognised page structure found
02154             ERROR2(FALSE,"bad page structure found in Spread::GetPageSize");
02155         }
02156     }
02157     else
02158     {
02159         if (Dps != NULL) *Dps = FALSE;
02160     }
02161 
02162     // Now get the current bleed size for the spread 
02163     if (Bleed != NULL) *Bleed = GetBleedOffset();
02164 
02165     if (ShowDropShadow != NULL) *ShowDropShadow = GetShowDropShadow();
02166 
02167     return TRUE;
02168 }
02169 
02170 /********************************************************************************************
02171 
02172 >   BOOL Spread::SetPageSize(const MILLIPOINT Width, const MILLIPOINT Height, const MILLIPOINT Margin,
02173                              const MILLIPOINT Bleed, const BOOL Dps, const BOOL ShowDropShadow)
02174 
02175     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02176     Created:    14/12/94
02177     Inputs:     Width           New width of the page in millipoints
02178                 Height          New height of the page in millipoints
02179                 Margin          New size of the margin area in millipoints (0 = none)
02180                 Bleed           New size of the bleed area in millipoints (0 = none)
02181                 Dps             Whether another page is required or not.
02182                 ShowDropShadow  New drop shadow display state.
02183     Outputs:    -
02184     Returns:    Whether we completed the operation ok or not as True or False.
02185     Purpose:    Allows the setting of a new page size by height and width for all pages
02186                 in this spread. Also allows changing of other spread attributes such as:-
02187                     margin around pages in spread,
02188                     bleed size
02189                     single/double page spread
02190                     whether a drop shadow is displayed for this spread.
02191     Errors:     -
02192     SeeAlso:    -
02193 
02194 ********************************************************************************************/
02195 
02196 BOOL Spread::SetPageSize(const MILLIPOINT Width, const MILLIPOINT Height, const MILLIPOINT Margin,
02197                          const MILLIPOINT Bleed, const BOOL Dps, const BOOL ShowDropShadow)
02198 {
02199     ERROR2IF(this==NULL,FALSE,"Spread::SetPageSize called on NULL pointer");
02200 
02201     // Resize all the pages in the spread to be of the new size specified.
02202     
02203     // To set page size for all pages in this spread we will...
02204     // Find the layout of the pages in the spread (could be X or T shaped!) and calculate
02205     // the overall bounds plus the bounds of the objects on the page.
02206     // Expand pasteboard rect to give same offsets around new pages
02207     // (We won't allow pasteboard to shrink smaller than outermost objects)
02208     // Translate any spread after this one so there's no gap or overlap with this one
02209     // Set each page to the new page size
02210     // Translate pages so they butt up exactly to each other
02211     // (in their original layout of course)
02212     // (We won't try to translate any objects on this spread.)
02213 
02214     BOOL ok = TRUE;
02215     
02216     // Note the present pages rect
02217     DocRect OldPagesRect;
02218     GetPagesRect(&OldPagesRect);
02219 
02220     // find the position of the grid relative to the pages so this can be maintained
02221     NodeGrid* pGrid=FindFirstDefaultGridInSpread();
02222     ERROR2IF(pGrid==NULL,FALSE,"Spread::SetPageSize() no current default grid");
02223     DocCoord GridOrigin;
02224     pGrid->GetOrigin(&GridOrigin.x,&GridOrigin.y);
02225     DocCoord PageRelGridOrigin;
02226     SpreadCoordToPagesCoord(&PageRelGridOrigin,GridOrigin);
02227     // Check if Margin < Bleed, if so then add the margin to the bleed
02228     MILLIPOINT PageMargin = 0;
02229     if (Margin < Bleed)
02230         PageMargin = Margin + Bleed;
02231     else
02232         PageMargin = Margin;
02233 
02234     // Set up a new pasteboard rectangle to be of the correct size according to the new spec
02235     // for the page or pages for this spread.
02236     // First set up the width of the pages according to whether we require one or two pages. 
02237     MILLIPOINT WidthOfPages = 0;
02238     if (Dps)
02239         WidthOfPages = PageMargin + 2 * Width;
02240     else
02241         WidthOfPages = Width;
02242 
02243     // Set up the class variables for page height/width to echo the new values so any
02244     // pasteboard calculations use them.
02245 // REMOVED - No other code actually references these variables, so I've removed 'em!
02246 //  PageWidth = Width;
02247 //  PageHeight = Height;
02248 
02249     // Get current pasteboard rectangle 
02250     //DocRect OldPasteRect = GetPasteboardRect(FALSE);
02251     
02252     // Resize this by the required amount i.e. difference between old and new
02253     DocRect PasteRect(MinDocCoord + 0x10000,
02254                           (MaxDocCoord - 0x10000) - (PageMargin + Height + PageMargin),
02255                           (MinDocCoord + 0x10000) + (PageMargin + WidthOfPages + PageMargin),
02256                           MaxDocCoord - 0x10000);
02257 
02258     // Align all the pasteboards for all spreads in this chapter
02259     ok = AlignPasteboards(PasteRect, PageMargin);   
02260     if (!ok)
02261         return FALSE;
02262 
02263     // Find the chapter which we belong to
02264     Chapter* pChapter = FindParentChapter();
02265     ERROR3IF(pChapter == NULL,"Spread::SetPageSize: Could not find parent chapter");
02266     if (pChapter != NULL)
02267     {
02268         // Set the main fold line x coordinate. Initialise to non-showing value
02269         MILLIPOINT FoldLineX = -1000;
02270         // Check if there is another spread present or not
02271         // If not and only a single page then do not show the fold line
02272         Spread* pNextSpread = FindNextSpread(); 
02273         if (pNextSpread != NULL || Dps == TRUE)
02274         {
02275             // We have more than one spread and/or a double page spread so
02276             // set the fold line to the join between the two pages or the right hand
02277             // side of the left page 
02278             FoldLineX = PageMargin + Width;
02279         }
02280         pChapter->SetFoldLineXCoord(FoldLineX);
02281         pChapter->InvalidateBoundingRect();
02282     }
02283 
02284     // Now change the position of all pages in the spread.      
02285     // Calling routine has checked if the page size has changed or not and not called us
02286     // if nothing has changed.
02287     // Should have checked everything including going from dps to sps or sps to dps and
02288     // deleting/adding pages accordingly and setting the new bleed and shadow state.
02289     ok = SetSizeOfAllPages(Width, Height, PageMargin, Dps);
02290     if (!ok)
02291         return FALSE;
02292 
02293     // Now set the current bleed size for this spread 
02294     ok = ok && SetBleedOffset(Bleed);
02295     if (!ok)
02296         return FALSE;
02297 
02298     SetShowDropShadow(ShowDropShadow);
02299 
02300     // Adjust the default grid size to fit the new page layout
02301     DocRect  Rect = GetPasteboardRect(FALSE);
02302     Rect.Translate(-Rect.lo.x, -Rect.lo.y);
02303  
02304     pGrid->SetBoundingRect(Rect);
02305     pGrid->InvalidateBoundingRect();
02306     PagesCoordToSpreadCoord(&GridOrigin,PageRelGridOrigin);
02307     pGrid->SetOrigin(GridOrigin.x,GridOrigin.y);
02308 
02309     // Now, we must ensure that the special page background layer, if present
02310     // gets resized to fit around the new page structure
02311     Layer * pLayer = FindFirstPageBackgroundLayer();
02312     if (pLayer)
02313     {
02314         // Call the static function in the background op to go and fix up
02315         // the covering rectangle
02316         // First, get that size of the rectangle required to fill the present
02317         // pages.
02318         DocRect NewPagesRect;
02319         GetPagesRect(&NewPagesRect);
02320         // Translate the old pages from the old origin to the new
02321         OldPagesRect.Translate(-OldPagesRect.lo.x, -OldPagesRect.lo.y);
02322         OldPagesRect.Translate(NewPagesRect.lo.x, NewPagesRect.lo.y);
02323         
02324 PORTNOTE("other","Removed OpBackground usage")
02325 #ifndef EXCLUDE_FROM_XARALX
02326         OpBackground::FixBackgroundLayer(pLayer, NewPagesRect, OldPagesRect);
02327 #endif
02328     }
02329     
02330     return TRUE;
02331 }
02332 
02333 /********************************************************************************************
02334 
02335 >   BOOL Spread::AlignPasteboards(const DocRect PasteRect, const INT32 Margin)
02336 
02337     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02338     Created:    16/1/95
02339     Inputs:     New size of the paste board rectangle for this spread.
02340     Outputs:    -
02341     Returns:    Whether we completed the operation ok or not as True or False.
02342     Purpose:    Tries to align all the pasteboards of the spreads in this chapter to the new
02343                 size of this spread.
02344                 Checks to see if the objects on the spread are bigger than the newly specified 
02345                 pasteboard rectangle and if so will put a margin around the object rectangle
02346                 and then combine this with the specified pasteboard height. This means we will
02347                 not loose any objects off the spread.
02348                 As it is changing the size and position of the spread, it will invalidate the
02349                 spreads bounding rectangle so that hopefully all bounding boxes will be 
02350                 recalculated rather than using the old and more than likely wrong cached one. 
02351                 Assumes at present that it is only called on the first spread in the chapter.
02352     Errors:     -
02353     SeeAlso:    -
02354 
02355 ********************************************************************************************/
02356 
02357 BOOL Spread::AlignPasteboards(const DocRect NewPasteRect, const MILLIPOINT Margin)
02358 {
02359     ERROR2IF(this==NULL,FALSE,"Spread::AlignPasteboards called on NULL pointer");
02360 
02361     // Work out the overall bounds of the pages and objects on the page in the spread
02362     // This will be in document coordinates
02363     DocRect ObjectsBounds = GetBoundingRect(FALSE);
02364 
02365     // Take copy of entry pasteboard rectangle size
02366     DocRect PasteRect = NewPasteRect;
02367 
02368     // Note:: The tops of the old paste board rectangle and the new are aligned rather
02369     // than the bottoms. Hence the 0,0s are different. This means that direct comparisons
02370     // between new size, old size and bounding rectangles are not possible.
02371     // First, get the current paste board rectangle for this spread.
02372     DocRect SpreadRect = GetPasteboardRect();
02373 
02374     // Work out the maximum height and width of pasteboard required to encompass all the
02375     // current objects on the page. Include a margin around the outside. 
02376     MILLIPOINT HeightReqd = ObjectsBounds.hi.y - SpreadRect.lo.y + Margin;
02377     MILLIPOINT WidthReqd = ObjectsBounds.hi.x - SpreadRect.lo.x + Margin;
02378     // Above calculations will not include objects off the bottom and/or left hand side of
02379     // the page. We would need to shift the bottom left hand corner of the page plus all
02380     // objects if we were going to move these objects back onto the page.
02381     
02382     // If bounding rectangle of objects on page is bigger than the size of this new pasteboard
02383     // rectangle then resize the pasteboard to include the objects bounding box.
02384     if (PasteRect.Width() < WidthReqd ||
02385         PasteRect.Height() < HeightReqd )
02386     {
02387         // Work out what the new required width and height of the pasteboard rectangle is
02388         // including a margin size border around the outside of the objects bounding rectangle
02389         // so that all the handles are accessable. 
02390         MILLIPOINT SpreadHeight = 0;
02391         MILLIPOINT SpreadWidth = 0;
02392         if (HeightReqd < PasteRect.Height() )
02393             SpreadHeight = PasteRect.Height();
02394         else
02395             SpreadHeight = HeightReqd;
02396 
02397         if (WidthReqd < PasteRect.Width() )
02398             SpreadWidth = PasteRect.Width();
02399         else
02400             SpreadWidth = WidthReqd;
02401               
02402         // Contruct a new PasteRect to take this object bounding rectangle into account.
02403         PasteRect = DocRect(MinDocCoord + 0x10000,
02404                            (MaxDocCoord - 0x10000) - (SpreadHeight),
02405                            (MinDocCoord + 0x10000) + (SpreadWidth),
02406                            MaxDocCoord - 0x10000);
02407     }
02408 
02409     // Now we have the required size and position, go and set it
02410     ChangePasteboardRect(PasteRect); 
02411 
02412     // Make the wide pasteboard align to the new one
02413     // REMOVED - WPB now calculated on the fly rather than cached
02414 //  WidePasteboard.lo.y = PasteRect.lo.y;
02415 //  WidePasteboard.hi.y = PasteRect.hi.y;
02416 
02417     // Make sure bounding rectangles are invalidated so that they are recalculated
02418     InvalidateBoundingRect();
02419 
02420     // Now ensure all following spreads are properly attached to this one 
02421     // Assumes that we are altering the first spread in the document
02422     // Note this spread as a possible last spread in the document
02423     Spread* pLastSpread = this;
02424     Spread* pThisSpread = this;
02425     Spread* pNextSpread = FindNextSpread(); 
02426     while (pNextSpread != NULL)
02427     {
02428         // Next spread present, so adjust the pasteboard on the first/previous spread to
02429         // be correct assuming that it is not the last one present.
02430 // REMOVED- AdjustPasteboardHeight used to set the wide pasteboard - this is no longer necessary
02431 // as the Wide Pasteboard is calculated on the fly rather than cached now.
02432 //      pThisSpread->AdjustPasteboardHeight(FALSE);
02433 
02434         DocRect FirstPasteRect = pThisSpread->GetPasteboardRect(FALSE);
02435         DocRect SecondPasteRect = pNextSpread->GetPasteboardRect(FALSE);
02436         // Construct a new Pasteboard rectangle of the correct size and initial position
02437         // and then move it down by the height of the first spread (Down = -ve). 
02438         DocRect TempPasteRect(MinDocCoord + 0x10000,
02439                       (MaxDocCoord - 0x10000) - SecondPasteRect.Height(),
02440                       (MinDocCoord + 0x10000) + SecondPasteRect.Width(),
02441                       MaxDocCoord - 0x10000);
02442 
02443         TempPasteRect.Translate(0, -( FirstPasteRect.Height() )); 
02444         // Now we have the required size and position, go and set it
02445         pNextSpread->ChangePasteboardRect(TempPasteRect); 
02446 
02447         // Make the wide pasteboard align to the new one
02448 //      REMOVED - WPB now calculated on the fly rather than cached
02449 //      pNextSpread->WidePasteboard.lo.y = TempPasteRect.lo.y;
02450 //      pNextSpread->WidePasteboard.hi.y = TempPasteRect.hi.y;
02451 
02452 #ifdef _DEBUG
02453         // On Debug versions check that the spreads are aligned correctly
02454         FirstPasteRect = pThisSpread->GetPasteboardRect(FALSE);
02455         SecondPasteRect = pNextSpread->GetPasteboardRect(FALSE);
02456 TRACEUSER( "Neville", _T("First spread low corner y = %d\n"),FirstPasteRect.LowCorner().y);
02457 TRACEUSER( "Neville", _T("Second spread high corner y = %d\n"),SecondPasteRect.HighCorner().y);
02458         ENSURE((SecondPasteRect.HighCorner().y == FirstPasteRect.LowCorner().y),
02459            "Spread::SetPageSize() Spreads are not properly vertically aligned");
02460 #endif  
02461         
02462         // Make sure bounding rectangles are invalidated so that they are recalculated
02463         pNextSpread->InvalidateBoundingRect();
02464 
02465         // Note this next spread as a possible last spread and this spread
02466         pLastSpread = pNextSpread;
02467         pThisSpread = pNextSpread;
02468 
02469         // Now, see whether there is a next spread or not.
02470         pNextSpread = pNextSpread->FindNextSpread(); 
02471     }
02472 
02473     // Last spread in document/chapter so adjust the bottom pasteboard to be correct
02474 // REMOVED - this method just adjusts the Wide pasteboard - no longer necessary as the WPB
02475 // is calculated on the fly rather than cached
02476 //  if (pLastSpread != NULL)
02477 //      pLastSpread->AdjustPasteboardHeight(TRUE);
02478 
02479     return TRUE;
02480 }
02481 
02482 /********************************************************************************************
02483 
02484 >   BOOL Spread::SetSizeOfAllPages(const MILLIPOINT Width, const MILLIPOINT Height,
02485                                    const MILLIPOINT Margin, const BOOL Dps)
02486 
02487     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02488     Created:    16/1/95
02489     Inputs:     Width           New width of the page in millipoints
02490                 Height          New height of the page in millipoints
02491                 Margin          New size of the margin area in millipoints (0 = none)
02492                 Dps             Whether another page is required or not.
02493 
02494     Outputs:    -
02495     Returns:    Whether we completed the operation ok or not as True or False.
02496     Purpose:    Sets the sizes of all pages in this spread to conform to the newly specified
02497                 width and height. It will try and align all the pages. It will also try and
02498                 create and or delete any pages which are necessary to conform to the specified
02499                 single/double page spread flag. 
02500                 Assumes all the pages in a spread are the same size.
02501     Errors:     -
02502     SeeAlso:    -
02503 
02504 ********************************************************************************************/
02505 
02506 BOOL Spread::SetSizeOfAllPages(const MILLIPOINT Width, const MILLIPOINT Height,
02507                                const MILLIPOINT Margin, const BOOL Dps)
02508 {
02509     ERROR2IF(this==NULL,FALSE,"Spread::SetSizeOfAllPages called on NULL pointer");
02510 
02511     BOOL ok = TRUE;
02512 
02513     // Find the first page in the spread
02514     Page *pPage = FindFirstPageInSpread();
02515     ERROR2IF(pPage == NULL,FALSE,"Spread::SetSizeOfAllPages(): Could not find first Page");
02516         
02517     // Take note of where this first page is
02518 //  Page* pFirstPage = pPage;
02519     
02520     // Get the size and position of the first page
02521     DocRect OldPageRect = pPage->GetPageRect();
02522     
02523     // Get present low corner position, we will use this to calculate the gap around the pages
02524     DocCoord Low = OldPageRect.LowCorner();
02525 
02526     // Set up the new starting position of the page
02527         Low.x = Margin;
02528     Low.y = Margin;
02529 
02530     // Construct a new position and size with the required params
02531     DocRect PageRect(Low, Width, Height);
02532     ok = pPage->SetPageRect(PageRect);  
02533     if (!ok)
02534         return FALSE;
02535 
02536     // Find out if there is a next page in the spread. If there is, then we need to
02537     // change that as well, if we are in dps mode, or delete it if dps is off 
02538     Page* pCurrentPage = pPage;
02539     pPage = pPage->FindNextPage();
02540     if (pPage != NULL)
02541     {
02542         if (Dps)
02543         {
02544             // Move the current page across by one page worths and set this as the new
02545             // size/position for the next page 
02546             PageRect.Translate(Width, 0);   
02547             ok = pPage->SetPageRect(PageRect);
02548             if (!ok)
02549                 return FALSE;
02550             
02551             // Now check to see if any more pages exist. If so then delete them.
02552             pPage = pPage->FindNextPage();
02553             while (pPage != NULL)
02554             {
02555                 ERROR3("Spread::SetSizeOfAllPages extra page found in double page spread");
02556             }
02557         }
02558         else
02559         {
02560             // Delete any pages over the initial one.
02561             do
02562             {
02563                 pPage->CascadeDelete();
02564                 // Of course, Cascade delete does not actually delete the page, so now do that
02565                 delete pPage;
02566                 // Check to see if any pages remain after the first required one 
02567                 pPage = pCurrentPage;
02568                 pPage = pPage->FindNextPage();
02569             }
02570             while (pPage != NULL);
02571         }
02572     }
02573     else
02574     {
02575         // If not double page spread then everything is correct
02576         // otherwise we will need to create a page of the correct size and position
02577         if (Dps)
02578         {
02579             // move first page across by one page worths
02580             PageRect.Translate(Width, 0);
02581             // Create a new last page based on this size/position 
02582             Page* Page2 = new Page(this, LASTCHILD, PageRect);
02583             if (Page2 == NULL)
02584             {
02585                 // We ran out of memory or something
02586                 InformError(_R(IDE_NOMORE_MEMORY));
02587                 return FALSE;
02588             }
02589         }
02590     }
02591 
02592     return TRUE;
02593 }
02594 #endif
02595 
02596 /********************************************************************************************
02597 
02598 >   Document* Spread::FindParentDocument()
02599 
02600     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02601     Created:    12/6/97
02602     Returns:    A pointer to the parent document of this spread.
02603     Purpose:    Finds the parent document for this spread. Should always be one present.
02604                 Defined as an explicit function so that caller just has to check for NULL
02605                 returns, rather than also checking that the parent is a chapter. Also, makes
02606                 it more encapsulated and friendly.  
02607 
02608 ********************************************************************************************/
02609 
02610 Document* Spread::FindParentDocument()
02611 {
02612     BaseDocument *pBaseDoc = FindOwnerDoc();
02613 
02614     // Make sure we have a real document
02615     if (!pBaseDoc || !pBaseDoc->IS_KIND_OF(Document))
02616     {
02617         if (pBaseDoc == NULL)
02618         {
02619             ERROR3("Eh up, the spread has no parent document");
02620         }
02621         else
02622         {
02623             ERROR3("Document is not a real Document - it's a BaseDocument!");
02624         }
02625 
02626         return NULL;
02627     }
02628 
02629     Document *pDoc = (Document *) pBaseDoc;
02630     return pDoc;
02631 }
02632 
02633 /********************************************************************************************
02634 
02635 >   Chapter* Spread::FindParentChapter()
02636 
02637     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02638     Created:    17/1/95
02639     Inputs:     -
02640     Outputs:    -
02641     Returns:    A pointer to the parent chapter of this spread. Will be NULL if no parent
02642                 chapter is found. This of course should never happen.
02643     Purpose:    Finds the parent chapter for this spread. Should always be one present.
02644                 Defined as an explicit function so that caller just has to check for NULL
02645                 returns, rather than also checking that the parent is a chapter. Also, makes
02646                 it more encapsulated and friendly.  
02647     Errors:     -
02648     SeeAlso:    -
02649 
02650 ********************************************************************************************/
02651 
02652 Chapter* Spread::FindParentChapter()
02653 {
02654     ERROR2IF(this==NULL,NULL,"Spread::FindParentChapter called on NULL pointer");
02655 
02656     Node* pCurrentNode = FindParent(); 
02657     while(pCurrentNode != NULL)   
02658     {
02659         if (pCurrentNode->IsKindOf(CC_RUNTIME_CLASS(Chapter)))
02660             return ((Chapter*)pCurrentNode);     
02661         pCurrentNode = pCurrentNode->FindParent(); 
02662     }
02663     return NULL;
02664 }
02665 
02666 /********************************************************************************************
02667 
02668 >   NodeGrid* Spread::FindFirstDefaultGridInSpread()
02669 
02670     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02671     Created:    9/1/95
02672     Inputs:     -
02673     Outputs:    -
02674     Returns:    A pointer to the grid node. Will be NULL if no default grid is found.
02675     Purpose:    Finds the first default grid that has been defined in this spread. Should be
02676                 the only one present.
02677     Errors:     -
02678     SeeAlso:    -
02679 
02680 ********************************************************************************************/
02681 
02682 NodeGrid* Spread::FindFirstDefaultGridInSpread()
02683 {
02684     ERROR2IF(this==NULL,NULL,"Spread::FindFirstDefaultGridInSpread called on NULL pointer");
02685 
02686     Node* pCurrentNode = FindFirstChild(); 
02687     while(pCurrentNode != NULL)   
02688     {
02689         if (pCurrentNode->IsKindOf(CC_RUNTIME_CLASS(NodeGrid)))
02690         {
02691             // Found a grid type node. Check if its a default type.
02692             NodeGrid* pCurrentGrid = (NodeGrid*)pCurrentNode;
02693             if (pCurrentGrid->IsDefault())
02694                 return (pCurrentGrid);   
02695         }
02696 
02697         pCurrentNode = pCurrentNode->FindNext(); 
02698     }
02699     return (NULL); // No default grids were found
02700 }
02701 
02702 
02703 /********************************************************************************************
02704 
02705 >   BOOL Spread::CreateDefaultPageAndGrid(BOOL CreateGrid = TRUE)
02706 
02707     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02708     Created:    5/8/96
02709     Inputs:     CreateGrid = TRUE if you want a grid & page
02710                              FALSE if you only want a grid
02711     Outputs:    -
02712     Returns:    TRUE if ok, FALSE if it fails
02713     Purpose:    This creates a default page and a default grid and places them as children of the spread.
02714 
02715                 It doesn't check to see the spread has already got a page(s) or grid(s), so only call
02716                 this when creating a spread for the first time.
02717 
02718                 (I appoligise for the disgusting default parameter - it is due to circumstances beyond my control)
02719     Errors:     -
02720     SeeAlso:    -
02721 
02722 ********************************************************************************************/
02723 
02724 MILLIPOINT              PageWidth  = ( 8 * 72000);
02725 MILLIPOINT              PageHeight = (11 * 72000);
02726 
02727 // Default page size/position.
02728 MILLIPOINT              Gap = 72000L;
02729 
02730 BOOL Spread::CreateDefaultPageAndGrid(BOOL CreateGrid)
02731 {
02732     // Work out where to put the page and create it
02733     DocRect PageRect(Gap, Gap, Gap+PageWidth, Gap+(1*PageHeight));
02734     Page *pPage = new Page(this, FIRSTCHILD, PageRect);
02735     if (pPage == NULL)
02736         return(FALSE);
02737 
02738     // Create a default blanket grid in the given spread
02739     if (CreateGrid)
02740         NodeGrid::MakeDefaultGrid(this);
02741 
02742     return TRUE;
02743 }
02744 
02745 /********************************************************************************************
02746 >   DocCoord Spread::GetUserOrigin()
02747 
02748     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
02749     Created:    6/9/95
02750     Returns:    Offset from SpreadCoords to UserCoords
02751 ********************************************************************************************/
02752 
02753 DocCoord Spread::GetUserOrigin()
02754 {
02755     return UserOrigin;
02756 }
02757 
02758 
02759 /********************************************************************************************
02760 >   BOOL Spread::GetPagesRect(DocRect* pPagesRect)
02761 
02762     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
02763     Created:    17/1/95
02764     Outputs:    pPagesRect
02765     Returns:    FALSE if fails (PagesRect unchanged)
02766     Purpose:    Get the union rect of all pages on the spread (in SpreadCoords)
02767     Errors:     pPagesRect==NULL
02768                 no pages in spread
02769 ********************************************************************************************/
02770 
02771 BOOL Spread::GetPagesRect(DocRect* pPagesRect)
02772 {
02773     ERROR2IF(pPagesRect==NULL,FALSE,"Spread::GetPagesRect() - pPagesRect==NULL");
02774 
02775     Page* pPage=FindFirstPageInSpread();
02776     ERROR2IF(pPage==NULL,FALSE,"Spread::GetPagesRect() - no pages in spread!");
02777 
02778     *pPagesRect=pPage->GetPageRect();
02779     pPage=pPage->FindNextPage();
02780     while (pPage)
02781     {
02782         DocRect PageRect=pPage->GetPageRect();
02783         *pPagesRect=pPagesRect->Union(PageRect);
02784         pPage=pPage->FindNextPage();
02785     }
02786 
02787     return TRUE;
02788 }
02789 
02790 
02791 /********************************************************************************************
02792 >   BOOL Spread::SpreadCoordToPagesCoord(DocCoord* pPagesCoord, DocCoord SpreadCoord)
02793 
02794     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
02795     Created:    17/1/95
02796     Inputs:     SpreadCoord
02797     Outputs:    pPagesCoord
02798     Returns:    FALSE if fails (PagesCoord unchanged)
02799     Purpose:    Convert SpreadCoord to PagesCoord (relative to union of pages in spread)
02800 ********************************************************************************************/
02801 
02802 BOOL Spread::SpreadCoordToPagesCoord(DocCoord* pPagesCoord, DocCoord SpreadCoord)
02803 {
02804     ERROR2IF(pPagesCoord==NULL,FALSE,"Spread::SpreadCoordToPagesCoord() - pPagesCoord==NULL");
02805     
02806     DocRect PagesRect;
02807     if (GetPagesRect(&PagesRect)==FALSE)
02808         return FALSE;
02809 
02810     *pPagesCoord=SpreadCoord-PagesRect.lo;
02811     return TRUE;
02812 }
02813 
02814 
02815 /********************************************************************************************
02816 >   BOOL Spread::PagesCoordToSpreadCoord(DocCoord* pSpreadCoord, DocCoord PagesCoord)
02817 
02818     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
02819     Created:    17/1/95
02820     Inputs:     PagesCoord
02821     Outputs:    pSpreadCoord
02822     Returns:    FALSE if fails (SpreadCoord unchanged)
02823     Purpose:    Convert PagesCoord (relative to union of pages in spread) to SpreadCoord 
02824 ********************************************************************************************/
02825 
02826 BOOL Spread::PagesCoordToSpreadCoord(DocCoord* pSpreadCoord, DocCoord PagesCoord)
02827 {
02828     ERROR2IF(pSpreadCoord==NULL,FALSE,"Spread::PagesCoordToSpreadCoord() - pSpreadCoord==NULL");
02829     
02830     DocRect PagesRect;
02831     if (GetPagesRect(&PagesRect)==FALSE)
02832         return FALSE;
02833 
02834     *pSpreadCoord=PagesCoord+PagesRect.lo;
02835     return TRUE;
02836 }
02837 
02838 
02839 /********************************************************************************************
02840 >   BOOL Spread::TextToSpreadCoord(DocCoord* pSpreadCoord, StringBase* pxText, StringBase* pyText)
02841 
02842     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
02843     Created:    17/1/95
02844     Inputs:     pxText - x UserCoord in text form
02845                 pyText - y UserCoord in text form
02846     Outputs:    pSpreadCoord
02847     Returns:    FALSE if fails (SpreadCoord unchanged)
02848     Purpose:    Convert Coord in text form (relative to union of pages in spread) into SpreadCoord
02849 ********************************************************************************************/
02850 
02851 BOOL Spread::TextToSpreadCoord(DocCoord* pSpreadCoord, StringBase* pxText, StringBase* pyText)
02852 {
02853     ERROR2IF(pSpreadCoord==NULL,FALSE,"Spread::TextToSpreadCoord() - pSpreadCoord==NULL");
02854     ERROR2IF(      pxText==NULL,FALSE,"Spread::TextToSpreadCoord() - pxText==NULL");
02855     ERROR2IF(      pyText==NULL,FALSE,"Spread::TextToSpreadCoord() - pyText==NULL");
02856     
02857     DimScale* pDimScale=DimScale::GetPtrDimScale(this);
02858     ERROR2IF(pDimScale==NULL,FALSE,"Spread::TextToSpreadCoord() - pDimScale==NULL");
02859 
02860     UserCoord UserPos(0,0);
02861     if (pDimScale->ConvertToMillipoints(*pxText, &(UserPos.x))==FALSE)
02862         return FALSE;
02863     if (pDimScale->ConvertToMillipoints(*pyText, &(UserPos.y))==FALSE)
02864         return FALSE;
02865 
02866     *pSpreadCoord = UserPos.ToSpread(this);
02867     return TRUE;
02868 }
02869 
02870 
02871 /********************************************************************************************
02872 >   BOOL Spread::SpreadCoordToText(StringBase* pxText, StringBase* pyText, DocCoord SpreadCoord,
02873                     BOOL xUnitSpecifier=TRUE, BOOL yUnitSpecifier=TRUE, INT32 dp=-1)
02874 
02875     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
02876     Created:    17/1/95
02877     Inputs:     SpreadCoord
02878                 xUnitSpecifier (default TRUE)  - append unit specifier to x text
02879                 yUnitSpecifier (default TRUE)  - append unit specifier to y text
02880                 dp             (default 2)     - decimal places (-1 = use system default)
02881     Outputs:    pxText - x UserCoord in text form
02882                 pyText - y UserCoord in text form
02883     Returns:    FALSE if fails (xText,yText unchanged)
02884     Purpose:    Convert SpreadCoord into Coord in text form (relative to union of pages in spread) 
02885     Note:       If only Y specifier required and units are prefix
02886                 then the unit specifier is actually placed before the x value
02887 ********************************************************************************************/
02888 
02889 BOOL Spread::SpreadCoordToText(String_256* pxText, String_256* pyText, DocCoord SpreadCoord,
02890                                 BOOL xUnitSpecifier, BOOL yUnitSpecifier, INT32 dp)
02891 {
02892     ERROR2IF(pxText==NULL,FALSE,"Spread::SpreadCoordToText() - pxText==NULL");
02893     ERROR2IF(pyText==NULL,FALSE,"Spread::SpreadCoordToText() - pyText==NULL");
02894     ERROR2IF(    dp<-1   ,FALSE,"Spread::SpreadCoordToText() - dp<-1");
02895     
02896     DimScale* pDimScale=DimScale::GetPtrDimScale(this);
02897     ERROR2IF(pDimScale==NULL,FALSE,"Spread::SpreadCoordToText() - pDimScale==NULL");
02898 
02899     // if only Y unit specified, and units are prefix, force X unit specifier only
02900     if (xUnitSpecifier==FALSE && yUnitSpecifier==TRUE)
02901     {
02902         // Get the current unit list from the document and the the current scale units
02903         DocUnitList* pDocUnitList=DocUnitList::GetCurrentDocUnitList();
02904         ERROR2IF(pDocUnitList==NULL,FALSE,"Spread::SpreadCoordToText() - DocUnitList::GetCurrentDocUnitList() returned NULL");
02905         Unit* pUnit=pDocUnitList->FindUnit(pDimScale->GetUnits());
02906         ERROR2IF(pUnit==NULL,FALSE,"Spread::SpreadCoordToText() - pDocUnitList->FindUnit() returned NULL");
02907         if (pUnit->IsPrefix())
02908         {
02909             xUnitSpecifier=TRUE;
02910             yUnitSpecifier=FALSE;
02911         }
02912     }
02913  
02914     UserCoord UserPos=SpreadCoord.ToUser(this);
02915     pDimScale->ConvertToUnits(UserPos.x, pxText, xUnitSpecifier, dp);
02916     pDimScale->ConvertToUnits(UserPos.y, pyText, yUnitSpecifier, dp);
02917 
02918     return TRUE;
02919 }
02920 
02921 
02922 /********************************************************************************************
02923 >   BOOL Spread::GetDecimalPlacesForPixelResolution(View *pView, INT32* dp)
02924 
02925     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
02926     Created:    18/1/95
02927     Returns:    FALSE if fails
02928     Outputs:    dp - number of dp (-ve values limited to 0)
02929     Purpose:    Find the number of dp to resolve a pixel in units and scale associated with spread
02930                 (calulates the both x and y and returns max)
02931 ********************************************************************************************/
02932 
02933 BOOL Spread::GetDecimalPlacesForPixelResolution(View *pView, INT32* dp)
02934 {
02935     DimScale* pDimScale=DimScale::GetPtrDimScale(this);
02936     ERROR2IF(pDimScale==NULL,FALSE,"Spread::GetDecimalPlacesForPixelResolution() - pDimScale==NULL");
02937 
02938     INT32 xdp=2;
02939     INT32 ydp=2;
02940     double MPPerUnit=0.0;
02941     if( pDimScale->ConvertToDouble( String_8( _T("1") ), &MPPerUnit ) == FALSE )
02942         return FALSE;
02943 
02944     FIXED16 PixelWidth,
02945             PixelHeight;
02946             
02947     pView->GetScaledPixelSize(&PixelWidth, &PixelHeight);
02948 
02949     if (PixelWidth==0 || PixelHeight==0)
02950         return FALSE;
02951 
02952     ERROR2IF(MPPerUnit<1,FALSE,"Spread::GetDecimalPlacesForPixelResolution() - Millipoints per Unit < 1!");
02953     xdp=(INT32)log10(MPPerUnit/PixelWidth.MakeDouble() )+1;
02954     ydp=(INT32)log10(MPPerUnit/PixelHeight.MakeDouble())+1;
02955 
02956     if (xdp<0) xdp=0;
02957     if (ydp<0) ydp=0;
02958     *dp = xdp>ydp ? xdp : ydp;
02959     return TRUE;
02960 }
02961 
02962 
02963 
02964 /********************************************************************************************
02965 
02966 >   DocCoord Spread::GetSpreadCoordOrigin(BOOL Pixelise, View *pView) const
02967 
02968     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02969     Created:    7/3/96
02970 
02971     Inputs:     Pixelise - TRUE if you want the coordinate pixelised
02972                 pView - NULL, or the View to use for pixelisation purposes.
02973                 (These inputs are exactly the same as those in GetPasteboardRect)
02974 
02975     Returns:    The spread coordinate origin, in document coordinates
02976 
02977     Purpose:    To determine the spread coordinate origin
02978                 This is used to convert between document and spread coordinates:
02979                     DocCoord    = SpreadCoord + Origin
02980                     SpreadCoord = DocCoord - Origin
02981 
02982     Notes:      In the past, spread coords shared their origin with the bottom left corner
02983                 of a spread's pasteboard. Obviously, if we tried to move this corner, we got
02984                 into deep strife, so I've separated out the 2 points. By default the origin
02985                 will happen to sit on the bottom left corner of the pasteboard, but this
02986                 will change if the pasteboard is ever resized. Generally the SCO does not
02987                 move (unless you have multiple spreads and a whole spread has to shift
02988                 down to make room).
02989 
02990                 WARNING: Because the SCO is not associated with the pasteboard corner any
02991                 more, it is easy to resize the pasteboard so that the SCO lies *outside*
02992                 the pasteboard. This can cause ERROR3's to go off if you try to call
02993                 FindEnclosingChapter on the SCO (because no chapter encloses it!).
02994                 Note that FindEnclosingChapter is called by the (document form) of
02995                 DocCoord::ToWork. I have changed the ERROR3 message to point at this warning.
02996 
02997     SeeAlso:    NodePaper::GetPasteBoardRect; Spread::SetSpreadCoordOrigin
02998 
02999 ********************************************************************************************/
03000 
03001 DocCoord Spread::GetSpreadCoordOrigin(BOOL Pixelise, View *pView) const
03002 {
03003 #if NEW_PASTEBOARD
03004 // New functionality: Spread Origin is separate from pasteboard bottom left corner
03005     if (Pixelise)
03006     {
03007         DocCoord temp(SpreadOrigin);
03008 
03009         if (pView != NULL)
03010             temp.Pixelise(pView);
03011         else
03012             temp.Pixelise();
03013     
03014         return(temp);
03015     }
03016 
03017     return(SpreadOrigin);
03018 #else
03019     // To keep the old functionality, the spread origin currently always sits on the
03020     // pasteboard bottom left corner.
03021     if (Pixelise)
03022     {
03023         DocCoord temp(PasteboardRect.lo);
03024 
03025         if (pView != NULL)
03026             temp.Pixelise(pView);
03027         else
03028             temp.Pixelise();
03029     
03030         return(temp);
03031     }
03032 
03033     return(PasteboardRect.lo);
03034 #endif
03035 }
03036 
03037 
03038 
03039 /********************************************************************************************
03040 
03041 >   void Spread::SetSpreadCoordOrigin(DocCoord NewOrigin)
03042 
03043     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03044     Created:    7/3/96
03045 
03046     Inputs:     NewOrigin - the new origin point for the spread coordinates within
03047                 this spread
03048 
03049     Purpose:    To set the spread coordinate origin
03050                 This is used to convert between document and spread coordinates:
03051                     DocCoord    = SpreadCoord + Origin
03052                     SpreadCoord = DocCoord - Origin
03053 
03054     Notes:      Moving the spread coord origin effectively moves all nodes on the
03055                 spread (pages, layers, objects, etc) in the opposite direction. It 
03056                 may therefore result in objects and even pages moving off the pasteboard.
03057 
03058                 Note also that you'll probably have to redraw some stuff!
03059 
03060                 Use carefully - Talk to Jason about it first!
03061 
03062     SeeAlso:    Spread::GetSpreadCoordOrigin
03063 
03064 ********************************************************************************************/
03065 
03066 void Spread::SetSpreadCoordOrigin(DocCoord NewOrigin)
03067 {
03068 #if !NEW_PASTEBOARD
03069     ERROR3("You can't set the spread coord origin (unimplemented) - Talk to Jason/Phil");
03070 #endif
03071 
03072     SpreadOrigin = NewOrigin;
03073 }
03074 
03075 
03076 
03077 /********************************************************************************************
03078 
03079 >   void Spread::SpreadCoordToDocCoord(DocCoord *pSpreadCoord) const
03080 >   void Spread::SpreadCoordToDocCoord(DocRect *pSpreadRect) const
03081 
03082     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03083     Created:    11/3/96
03084 
03085     Inputs:     } pSpreadCoord/pSpreadRect - The coordinate/rectangle to be converted
03086     Outputs:    }
03087 
03088     Purpose:    To convert between Document and Spread coordinate spaces
03089 
03090     SeeAlso:    Spread::GetSpreadCoordOrigin
03091 
03092 ********************************************************************************************/
03093 
03094 void Spread::SpreadCoordToDocCoord(DocCoord *pSpreadCoord) const
03095 {
03096     ERROR3IF(pSpreadCoord == NULL, "Illegal NULL params");
03097 
03098     DocCoord Origin = GetSpreadCoordOrigin();
03099 
03100     pSpreadCoord->x += Origin.x;
03101     pSpreadCoord->y += Origin.y;
03102 }
03103 
03104 
03105 
03106 void Spread::SpreadCoordToDocCoord(DocRect *pSpreadRect) const
03107 {
03108     ERROR3IF(pSpreadRect == NULL, "Illegal NULL params");
03109 
03110     SpreadCoordToDocCoord(&pSpreadRect->lo);
03111     SpreadCoordToDocCoord(&pSpreadRect->hi);
03112 }
03113 
03114 
03115 
03116 /********************************************************************************************
03117 
03118 >   void Spread::DocCoordToSpreadCoord(DocCoord *pDocCoord) const
03119 >   void Spread::DocCoordToSpreadCoord(DocCoord *pDocRect) const
03120 
03121     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03122     Created:    11/3/96
03123 
03124     Inputs:     } pDocCoord/pDocRect - The coordinate/rectangle to be converted
03125     Outputs:    }
03126 
03127     Purpose:    To convert between Document and Spread coordinate spaces
03128 
03129     SeeAlso:    Spread::GetSpreadCoordOrigin
03130 
03131 ********************************************************************************************/
03132 
03133 void Spread::DocCoordToSpreadCoord(DocCoord *pDocCoord) const
03134 {
03135     ERROR3IF(pDocCoord == NULL, "Illegal NULL params");
03136 
03137     DocCoord Origin = GetSpreadCoordOrigin();
03138 
03139     pDocCoord->x -= Origin.x;
03140     pDocCoord->y -= Origin.y;
03141 }
03142 
03143 
03144 
03145 void Spread::DocCoordToSpreadCoord(DocRect *pDocRect) const
03146 {
03147     ERROR3IF(pDocRect == NULL, "Illegal NULL params");
03148 
03149     DocCoordToSpreadCoord(&pDocRect->lo);
03150     DocCoordToSpreadCoord(&pDocRect->hi);
03151 }
03152 
03153 
03154 
03155 /********************************************************************************************
03156 
03157 >   DocCoord Spread::GetMaxPasteboardSize(void)
03158 
03159     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03160     Created:    19/2/96
03161 
03162     Returns:    The maximum pasteboard size (x,y)
03163 
03164     Purpose:    To determine the maximum size that the pasteboard will allow itself
03165                 to be expanded to.
03166 
03167     Notes:      In document coordinates, the bottom left of the pasteboard is fixed.
03168                 However, by moving all objects inside the pasteboard (all spread coords)
03169                 we can effectively expand the pasteboard in any direction. Thus, if the
03170                 pasteboard width/height is smaller than the returned maximum, you can
03171                 still expand the pasteboard in any direction. Thus, the return value from
03172                 this method gives the maximum size rather than the max position rectangle.
03173 
03174     SeeAlso:    Spread::ExpandPasteboardToInclude
03175 
03176 ********************************************************************************************/
03177 
03178 DocCoord Spread::GetMaxPasteboardSize(void)
03179 {
03180 #if !NEW_PASTEBOARD
03181     ERROR3("Warning: GetMaxPasteboardSize is unsupported at present! See Jason/Phil");
03182 #endif
03183 
03184     DocCoord MPB(MaxPasteboardSize, MaxPasteboardSize);
03185     return(MPB);
03186 }
03187 
03188 
03189 
03190 /********************************************************************************************
03191 
03192 >   BOOL Spread::ExpandPasteboardToInclude(DocRect IncludeRect)
03193 
03194     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03195     Created:    19/2/96
03196 
03197     Inputs:     IncludeRect - The rectangle (in SPREAD coordinates, i.e. standard renderable
03198                 object bounds) which you wish to include into the spread's pasteboard range.
03199 
03200     Returns:    TRUE if the pasteboard was successfully expanded.
03201                 FALSE if the pasteboard has reached its maximum size and cannot be expanded
03202                 further (note: the pasteboard may still expand during this call, but the
03203                 return code indicates that it has now reached maximum extent). The given
03204                 rectangle lies outside the available maximum bounds.
03205 
03206     Purpose:    To expand the pasteboard area to include the given rectangle. Used when
03207                 objects are moved outside the current pasteboard area to keep them in an
03208                 area which the user can see. The pasteboard will never expand beyond
03209                 a maximum size (see Spread::GetMaxPasteboardSize)
03210 
03211     Notes:      **** This has only been tested for single-spread documents ****
03212 
03213                 The pasteboard expands equally in all directions in order to keep all
03214                 page "margins" equal. This is necessary so that window scroll positions
03215                 are not messed when we re-load a file
03216 
03217     SeeAlso:    Spread::GetMaxPasteboardSize; NodeRenderablePaper::ChangePasteboardRect
03218 
03219 ********************************************************************************************/
03220 
03221 BOOL Spread::ExpandPasteboardToInclude(DocRect IncludeRect)
03222 {
03223 #if NEW_PASTEBOARD
03224 #error ("This code has been commented out for safety. Please uncomment and try again");
03225 
03226     Progress Hourglass;     // Ensure an hourglass is running while we're busy
03227 
03228     // Convert the Spread coordinates "IncludeRect" into Document coordinates "IncludeDocRect"
03229     DocRect IncludeDocRect(IncludeRect);
03230     SpreadCoordToDocCoord(&IncludeDocRect);
03231 
03232     // If the pasteboard is already big enough, return immediately (success)
03233     if (PasteboardRect.ContainsRect(IncludeDocRect))
03234         return(TRUE);
03235 
03236     // Remember where the view was looking before we moved things about
03237     DocView *pView = DocView::GetSelected();
03238     DocRect ViewRect;
03239     if (pView != NULL)
03240     {
03241         ViewRect = pView->GetDocViewRect(this);
03242         DocCoordToSpreadCoord(&ViewRect);
03243     }
03244 
03245     // Inflate the IncludeRect in order to add a margin outside it. 72000mpt => 1 inch
03246     IncludeDocRect.Inflate(72000);
03247 
03248     // And include the rectangle into the new pasteboard rectangle
03249     DocRect NewBounds(PasteboardRect);
03250     NewBounds = NewBounds.Union(IncludeDocRect);
03251 
03252     // And now find the amount by which the "margin" should change, and inflate the pasteboard
03253     // rect in all directions, to keep the margin equal around the pages.
03254     INT32 InflateBy = 0;
03255     {
03256         InflateBy = ABS(NewBounds.lo.x - PasteboardRect.lo.x);
03257 
03258         INT32 temp = ABS(NewBounds.lo.y - PasteboardRect.lo.y);
03259         if (temp > InflateBy) InflateBy = temp;
03260 
03261         temp = ABS(NewBounds.hi.x - PasteboardRect.hi.x);
03262         if (temp > InflateBy) InflateBy = temp;
03263 
03264         temp = ABS(NewBounds.hi.y - PasteboardRect.hi.y);
03265         if (temp > InflateBy) InflateBy = temp;
03266 
03267 
03268         // Make sure we don't expand beyond the maximum size
03269         DocCoord MaxSize = GetMaxPasteboardSize();
03270         if (PasteboardRect.Width() + 2*InflateBy > MaxSize.x)
03271             InflateBy = (MaxSize.x - PasteboardRect.Width()) / 2;
03272 
03273         if (PasteboardRect.Height() + 2*InflateBy > MaxSize.y)
03274             InflateBy = (MaxSize.y - PasteboardRect.Height()) / 2;
03275 
03276         // And inflate the original pasteboard
03277         NewBounds = PasteboardRect;
03278         NewBounds.Inflate(InflateBy, InflateBy);
03279     }
03280 
03281     // Now we have the required size and position, go and set it
03282     ChangePasteboardRect(NewBounds);
03283 
03284     // Make sure bounding rectangles are invalidated so that they are recalculated
03285     InvalidateBoundingRect();
03286 
03287     // Now run through all spreads, lining up their pasteboards so they don't overlap,
03288     // and making sure that their default grids fully cover the pasteboards.
03289     // Note that this also ensures that the document is redrawn
03290     AdjustPasteboards();
03291 
03292     Document *pParentDoc = (Document *) FindOwnerDoc();
03293     if (pParentDoc != NULL)
03294     {
03295         // Pretend that page size has changed to cause related UI to change (rulers mainly)
03296         BROADCAST_TO_ALL(OptionsChangingMsg(pParentDoc,
03297                             OptionsChangingMsg::NEWPAGESIZE));
03298     }
03299 
03300     // Try to keep the scroll offsets sensible
03301     if (pView != NULL && pView->GetDoc() == pParentDoc)
03302     {
03303         // First, scroll to the previously visible view rectangle - this will adjust for the
03304         // new size of the pasteboard (i.e. new size of the view window extent) to make the
03305         // view look like it has not moved at all.
03306         pView->ScrollToShow(&ViewRect);
03307 
03308         // Now, make sure that the IncludeRect is visible on screen
03309         pView->ScrollToShow(&IncludeRect);
03310     }
03311 
03312     return(TRUE);           // return - successful
03313 
03314 #else
03315     // Pasteboard can never expand. Sniffle, Sob!
03316     // We return TRUE if the pasteboard already includes the specified rectangle, and
03317     // FALSE if we would have to expand to include it.
03318 
03319     // Convert the Spread coordinates "IncludeRect" into Document coordinates "IncludeDocRect"
03320     DocRect IncludeDocRect(IncludeRect);
03321     SpreadCoordToDocCoord(&IncludeDocRect);
03322 
03323     // If the pasteboard is already big enough, return immediately (success)
03324     if (PasteboardRect.ContainsRect(IncludeDocRect))
03325         return(TRUE);
03326 
03327     return(FALSE);
03328 #endif
03329 }
03330 
03331 
03332 
03333 /********************************************************************************************
03334 
03335 >   void Spread::AdjustPasteboards(void)
03336 
03337     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03338     Created:    13/3/96
03339 
03340     Purpose:    This runs through all spreads in this spread's parent chapter, doing
03341                 the following:
03342 
03343                 1) Find the minimum and maximum x values of all spread pasteboards in
03344                    the chapter, and set all pasteboards to have this same x extent
03345                    so that they all line up tidily in a nice clean column.
03346 
03347                 2) Move the pasteboards (and contents) as necessary so that recently
03348                    expanded pasteboards do not overlap neighbouring spreads, and
03349                    they all butt up against each other nicely.
03350                    (Note: The whole pasteboard is moved, including shifting the
03351                    spread coord origin to keep it in the same relative position)
03352 
03353                 3) Ensure that all default grids fully cover their pasteboard.
03354 
03355                 Finally, it will cause a redraw of all views onto this document to
03356                 ensure that they are correctly updated.
03357 
03358     Notes:      **** This has only been tested for single-spread Chapters ****
03359                 (Although it has been written to hopefully handle multiple spreads)
03360 
03361     SeeAlso:    Spread::GetMaxPasteboardSize; NodeRenderablePaper::ChangePasteboardRect
03362 
03363 ********************************************************************************************/
03364 
03365 void Spread::AdjustPasteboards(void)
03366 {
03367 //#if NEW_PASTEBOARD
03368     Chapter* ParentChapter = FindParentChapter();
03369     ERROR3IF(ParentChapter == NULL, "No parent Chapter?!");
03370 
03371     // First, find the minimum and maximum pasteboard x extents for the entire document.
03372     // Helpfully, our parent Chapter's pasteboard rect is a union of all of ours!
03373     DocRect ChapterBounds = ParentChapter->GetPasteboardRect();
03374 
03375     // Now we loop through all spreads from this one onwards, doing 2 things
03376     // 1) Make sure that each following spread is shifted to the correct document coordinates
03377     //    by ensuring its pasteboard is placed after this spread's one.
03378     // 2) Make sure that all default grids in all spreads fully cover the pasteboards.
03379     Spread* pThisSpread = ParentChapter->FindFirstSpread();
03380 
03381     // Force the x extent of the first pasteboard to match all others in this chapter
03382     DocRect TempPasteRect = pThisSpread->GetPasteboardRect();
03383     TempPasteRect.lo.x = ChapterBounds.lo.x;
03384     TempPasteRect.hi.x = ChapterBounds.hi.x;
03385 
03386 /*if (pThisSpread->FindNextSpread())
03387 {
03388     DocCoord OriginOffset(pThisSpread->SpreadOrigin.x - pThisSpread->PasteboardRect.lo.x,
03389                             pThisSpread->SpreadOrigin.y - pThisSpread->PasteboardRect.lo.y);
03390 
03391     DocRect r;
03392     pThisSpread->GetPagesRect(&r);
03393     pThisSpread->SpreadCoordToDocCoord(&r);
03394     r.Inflate(18000);
03395     INT32 ydiff = r.lo.y - TempPasteRect.lo.y;
03396     TempPasteRect.lo.y = r.lo.y;
03397 
03398     pThisSpread->SpreadOrigin.x = TempPasteRect.lo.x + OriginOffset.x;
03399     pThisSpread->SpreadOrigin.y = TempPasteRect.lo.y + OriginOffset.y - ydiff;
03400 }
03401 */
03402 
03403     pThisSpread->ChangePasteboardRect(TempPasteRect);
03404     pThisSpread->InvalidateBoundingRect();
03405 
03406     // For each spread...
03407     while (pThisSpread != NULL)
03408     {
03409         Progress::Update();     // Update any active hourglass
03410 
03411         Spread* pNextSpread = pThisSpread->FindNextSpread();
03412 
03413         // --- If there is a spread following this one, fix its pasteboard rect position
03414         if (pNextSpread != NULL)
03415         {
03416             DocRect FirstPasteRect  = pThisSpread->GetPasteboardRect(FALSE);
03417 /*if (pThisSpread->FindNextSpread())
03418 {
03419     DocRect r;
03420     pThisSpread->GetPagesRect(&r);
03421     pThisSpread->SpreadCoordToDocCoord(&r);
03422     r.Inflate(18000);
03423     FirstPasteRect.lo.y = r.lo.y;
03424 }
03425 if (pThisSpread->FindPreviousSpread())
03426 {
03427     DocRect r;
03428     pThisSpread->GetPagesRect(&r);
03429     pThisSpread->SpreadCoordToDocCoord(&r);
03430     r.Inflate(18000);
03431     FirstPasteRect.hi.y = r.hi.y;
03432 }
03433 */
03434             DocRect SecondPasteRect = pNextSpread->GetPasteboardRect(FALSE);
03435             DocCoord OriginOffset(pNextSpread->SpreadOrigin.x - pNextSpread->PasteboardRect.lo.x,
03436                                     pNextSpread->SpreadOrigin.y - pNextSpread->PasteboardRect.lo.y);
03437 
03438 /*if (pNextSpread->FindNextSpread())
03439 {
03440     DocRect r;
03441     pNextSpread->GetPagesRect(&r);
03442     pNextSpread->SpreadCoordToDocCoord(&r);
03443     r.Inflate(18000);
03444     INT32 ydiff = r.lo.y - SecondPasteRect.lo.y;
03445     SecondPasteRect.lo.y = r.lo.y;
03446     OriginOffset.y -= ydiff;
03447 }
03448 if (pNextSpread->FindPreviousSpread())
03449 {
03450     DocRect r;
03451     pNextSpread->GetPagesRect(&r);
03452     pNextSpread->SpreadCoordToDocCoord(&r);
03453     r.Inflate(18000);
03454     SecondPasteRect.hi.y = r.hi.y;
03455 }
03456 */
03457 
03458             // Construct a new Pasteboard rectangle of the correct size, and move it
03459             // to lie just below the previous spread's pasteboard area
03460             TempPasteRect = SecondPasteRect;
03461 
03462             TempPasteRect.Translate(-TempPasteRect.lo.x, -TempPasteRect.lo.y);
03463             TempPasteRect.Translate(FirstPasteRect.lo.x, FirstPasteRect.lo.y - TempPasteRect.Height()); 
03464 
03465             // And force the x extent of this pasteboard to match all others in this chapter
03466             TempPasteRect.lo.x = ChapterBounds.lo.x;
03467             TempPasteRect.hi.x = ChapterBounds.hi.x;
03468 
03469             // Move the spread coordinate origin so that it stays at the same relative offset
03470             // from the pasteboard bottom left corner, or else all objects inside the spread
03471             // will suddenly shift to a new place on (or off) the pasteboard!
03472             pNextSpread->SpreadOrigin.x = TempPasteRect.lo.x + OriginOffset.x;
03473             pNextSpread->SpreadOrigin.y = TempPasteRect.lo.y + OriginOffset.y;
03474 
03475             // Set the new paste rect
03476             pNextSpread->ChangePasteboardRect(TempPasteRect);
03477         
03478             // Make sure bounding rectangles are invalidated so that they are recalculated
03479             pNextSpread->InvalidateBoundingRect();
03480         }
03481 
03482         // --- Fix all the default grids to exactly cover their pasteboards
03483         Node *ptr = pThisSpread->FindFirstChild();
03484         while (ptr != NULL)
03485         {
03486             if (ptr->IsKindOf(CC_RUNTIME_CLASS(NodeGrid)))
03487             {
03488                 // Found a grid type node. Check if its a default type.
03489                 NodeGrid* pCurrentGrid = (NodeGrid*)ptr;
03490 
03491                 if (pCurrentGrid->IsDefault())
03492                 {
03493                     // Default grids need to fill the spread's pasteboard rect
03494                     DocRect Bounds = pThisSpread->GetPasteboardRect();
03495                     DocCoordToSpreadCoord(&Bounds);                 
03496 
03497                     // And set the new bounding rect
03498                     pCurrentGrid->SetBoundingRect(Bounds);
03499                 }
03500             }
03501 
03502             ptr = ptr->FindNext(); 
03503         }
03504 
03505         // --- And move on to the next spread to fix
03506         pThisSpread = pNextSpread;
03507     }
03508 
03509     // And invalidate all displayed views on this document, in order to make sure they
03510     // correctly update on screen.
03511     Document *pDoc = (Document *)FindOwnerDoc();
03512     if (pDoc != NULL)
03513         pDoc->ForceRedraw();
03514 
03515 //#else
03516 //ERROR3("Spread::AdjustPasteboards is unimplemented - see Jason/Phil");
03517 //#endif
03518 }
03519 
03520 
03521 
03522 /***********************************************************************************************
03523 
03524 >   virtual void Spread::SetInitialPasteboardRect(const DocRect& PasteRect)
03525 
03526     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03527     Created:    12/3/96
03528 
03529     Inputs:     PasteRect: Rectangle representing the outer limits of the pasteboard 
03530 
03531     Purpose:    To set the initial pasteboard rectangle of this node, and then change the 
03532                 pasteboard rectangles of all its parents.
03533 
03534                 The method also changes the document extents in the NodeDocument node at 
03535                 the root of the tree.
03536 
03537     Notes:      Spread overrides this base class method in order to set its Spread Coordinate
03538                 Origin suitably. It then calls the base class to do the normal things.
03539 
03540     SeeAlso:    NodeRenderablePaper::SetInitialPasteboardRect
03541 
03542 ***********************************************************************************************/
03543 
03544 void Spread::SetInitialPasteboardRect(const DocRect& PasteRect)
03545 {
03546     // Call the base class to do its stuff
03547     NodeRenderablePaper::SetInitialPasteboardRect(PasteRect);
03548 
03549     // Set the spread coordinate origin to be at the bottom left of the pasteboard by default
03550     SpreadOrigin = PasteboardRect.lo;
03551 }
03552 
03553 
03554 
03555 /********************************************************************************************
03556 
03557 >   virtual BOOL Spread::PostImport()
03558 
03559     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03560     Created:    18/3/96
03561 
03562     Inputs:     -
03563     Outputs:    -
03564     Returns:    TRUE/FALSE for success/failure
03565 
03566     Purpose:    This function is called after a document is imported.  Nodes should override
03567                 this function to do any post-import processing.
03568 
03569                 The spread overrides this function in order to automatically resize its
03570                 pasteboard to include all the newly imported nodes if possible.
03571 
03572     Notes:      Calls the base class PostImport after doing its own processing
03573 
03574     SeeAlso:    Node::PostImport
03575 
03576 ********************************************************************************************/
03577 
03578 BOOL Spread::PostImport()
03579 {
03580     // Get the bounding rect. This comes back in document coords, so we convert to spread
03581     // coords and then call ExpandPasteboardToInclude to include our bounds in the PB area.
03582     if (NodeRenderablePaper::PostImport())
03583     {
03584         DocRect Bounds = GetBoundingRect();
03585         DocCoordToSpreadCoord(&Bounds);
03586         ExpandPasteboardToInclude(Bounds);
03587 
03588         AdjustPasteboards();
03589 
03590         return(TRUE);
03591     }
03592 
03593     return(FALSE);
03594 }
03595 
03596 
03597 //---------------------------------------------------------------
03598 //---------------------------------------------------------------
03599 //---------------------------------------------------------------
03600 
03601 /********************************************************************************************
03602 
03603 >   virtual BOOL Spread::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
03604 
03605     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
03606     Created:    24/6/96
03607     Inputs:     pFilter = ptr to the filter
03608     Returns:    TRUE if record is written, FALSE if not
03609     Purpose:    Web files do not write out spreads.
03610                 
03611                 This code assumes that the document only has one spread
03612 
03613     SeeAlso:    Node::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
03614 
03615 ********************************************************************************************/
03616 
03617 BOOL Spread::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
03618 {
03619     return FALSE;
03620 }
03621 
03622 /********************************************************************************************
03623 
03624 >   virtual BOOL Spread::WritePreChildrenNative(BaseCamelotFilter* pFilter)
03625 
03626     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
03627     Created:    24/6/96
03628     Inputs:     pFilter = ptr to the filter
03629     Returns:    TRUE if record is written, FALSE if not
03630     Purpose:    Writes the spread record to the filter
03631 
03632                 Native files write out all spreads.
03633 
03634     SeeAlso:    Node::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
03635 
03636 ********************************************************************************************/
03637 
03638 BOOL Spread::WritePreChildrenNative(BaseCamelotFilter* pFilter)
03639 {
03640 #ifdef DO_EXPORT
03641     ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
03642     
03643     BOOL RecordWritten = FALSE;
03644 
03645     // Always write out the spread record in native files
03646     CXaraFileRecord Rec(TAG_SPREAD,TAG_SPREAD_SIZE);
03647     if (pFilter->Write(&Rec) != 0)
03648         RecordWritten = TRUE;
03649     else
03650         pFilter->GotError(_R(IDE_FILE_WRITE_ERROR));
03651 
03652     return RecordWritten;
03653 #else
03654     return FALSE;
03655 #endif
03656 }
03657 
03658 /********************************************************************************************
03659 
03660 >   BOOL Spread::WriteBeginChildRecordsNative(BaseCamelotFilter* pFilter)
03661 
03662     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
03663     Created:    1/8/96
03664     Inputs:     pFilter = ptr to the filter to write to
03665     Outputs:    -
03666     Returns:    TRUE ok, FALSE otherwise
03667     Purpose:    Begins the child record sequence for spread in the native format
03668 
03669                 The native format writes out all spreads and includes the spread details record 
03670                 as the spread's first child record
03671 
03672     SeeAlso:    WritePreChildrenNative()
03673 
03674 ********************************************************************************************/
03675 
03676 BOOL Spread::WriteBeginChildRecordsNative(BaseCamelotFilter* pFilter)
03677 {
03678 #ifdef DO_EXPORT
03679     ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
03680 
03681     BOOL RecordWritten = FALSE;
03682 
03683     // First thing to do is write out the Down record
03684     RecordWritten = (pFilter->WriteZeroSizedRecord(TAG_DOWN));
03685     
03686     // Write out the page sizes etc for this spread
03687     if (RecordWritten) RecordWritten = WriteSpreadInformation(pFilter);
03688     if (RecordWritten) RecordWritten = WriteSpreadScaling(pFilter);
03689     
03690     // write out the  Animtion Record.
03691     if (RecordWritten) RecordWritten = WriteSpreadAnimProperties(pFilter);
03692     
03693     return RecordWritten;
03694 #else
03695     return TRUE;
03696 #endif //DO_EXPORT
03697 }
03698 
03699 /********************************************************************************************
03700 
03701 >   BOOL Spread::WriteEndChildRecordsNative(BaseCamelotFilter* pFilter)
03702 
03703     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
03704     Created:    1/8/96
03705     Inputs:     pFilter = ptr to the filter to write to
03706     Outputs:    -
03707     Returns:    TRUE ok, FALSE otherwise
03708     Purpose:    Ends the child record sequence for spreads in the native format
03709 
03710                 The native format writes out all spreads.  This func just writes out the Up record
03711 
03712     SeeAlso:    WritePreChildrenNative()
03713 
03714 ********************************************************************************************/
03715 
03716 BOOL Spread::WriteEndChildRecordsNative(BaseCamelotFilter* pFilter)
03717 {
03718 #ifdef DO_EXPORT
03719     ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
03720     return pFilter->WriteZeroSizedRecord(TAG_UP);
03721 #else
03722     return FALSE;
03723 #endif
03724 }
03725 
03726 /********************************************************************************************
03727 
03728 >   BOOL Spread::WriteBeginChildRecordsWeb(BaseCamelotFilter* pFilter)
03729 
03730     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
03731     Created:    1/8/96
03732     Inputs:     pFilter = ptr to the filter to write to
03733     Outputs:    -
03734     Returns:    TRUE ok, FALSE otherwise
03735     Purpose:    Begins the child record sequence for spread in the web format
03736 
03737                 Web export doesn't write out spread records, so this overrides the default
03738                 behaviour in Node by ensuring the Down record does not get written
03739 
03740     SeeAlso:    WritePreChildrenNative()
03741 
03742 ********************************************************************************************/
03743 
03744 BOOL Spread::WriteBeginChildRecordsWeb(BaseCamelotFilter* pFilter)
03745 {
03746     return TRUE;
03747 }
03748 
03749 /********************************************************************************************
03750 
03751 >   BOOL Spread::WriteEndChildRecordsWeb(BaseCamelotFilter* pFilter)
03752 
03753     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
03754     Created:    1/8/96
03755     Inputs:     pFilter = ptr to the filter to write to
03756     Outputs:    -
03757     Returns:    TRUE ok, FALSE otherwise
03758     Purpose:    Ends the child record sequence for spread in the web format
03759 
03760                 Web export doesn't write out spread records, so this overrides the default
03761                 behaviour in Node by ensuring the Up record does not get written
03762 
03763     SeeAlso:    WritePreChildrenNative()
03764 
03765 ********************************************************************************************/
03766 
03767 BOOL Spread::WriteEndChildRecordsWeb(BaseCamelotFilter* pFilter)
03768 {
03769     return TRUE;
03770 }
03771 
03772 /********************************************************************************************
03773 
03774 >   BOOL Spread::WriteSpreadAnimationProperties(BaseCamelotFilter* pFilter)
03775     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
03776     Created:    8/5/97
03777     Input:      pFilter = ptr to the filter to export to.
03778     Outputs:    -
03779     Returns:    TRUE if ok, FALSE otherwise.
03780     Purpose:    Exports the Animation Properties details for this Spread to the filter.
03781     Notes:      Karim 07/12/2000 - modified to save out transparent GIF information.
03782 
03783 *********************************************************************************************/
03784 
03785 BOOL Spread::WriteSpreadAnimProperties(BaseCamelotFilter* pFilter)
03786 {
03787 #ifdef DO_EXPORT
03788     ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
03789 
03790     BOOL RecordWritten = FALSE;
03791 
03792     BOOL ok = TRUE;
03793         
03794     // Add a description of the TAG_SPREAD_ANIMPROPS record, for older importers that don't understand this record
03795     pFilter->AddTagDescription(TAG_SPREAD_ANIMPROPS, _R(IDS_TAG_SPREAD_ANIMPROPS));
03796 
03797     // Start a record to save our data in
03798     CXaraFileRecord Rec(TAG_SPREAD_ANIMPROPS, TAG_SPREAD_ANIMPROPS_SIZE);
03799 
03800     // Get our information...
03801     DWORD   Loop                =   m_AnimPropertiesParam.GetAnimLoop();
03802     DWORD   GlobalDelay         =   m_AnimPropertiesParam.GetGlobalAnimDelay();
03803     DWORD   Dither              =   m_AnimPropertiesParam.GetDither();
03804     DWORD   WebPalette          =   m_AnimPropertiesParam.GetPalette();
03805     DWORD   ColoursPalette      =   m_AnimPropertiesParam.GetPaletteCols();
03806     DWORD   NumColsInPalette    =   m_AnimPropertiesParam.GetNumColsInPalette();
03807 
03808     // We have a flags word so get the bits that affect it
03809     BOOL    SystemCols          =   m_AnimPropertiesParam.GetUseSystemCols();
03810     BOOL    BgTransparent       =   m_AnimPropertiesParam.GetIsBackGroundTransp();
03811 
03812     // And now fill in the bits in the flags word.
03813     // To be compatible with CX2, we set the flag if BgTransparent is FALSE,
03814     // as CX2 automatically did bg transparent GIFs all the time.
03815     BYTE    FlagsWord           =   (SystemCols     ? 1 : 0);
03816             FlagsWord           |=  (BgTransparent  ? 0 : 2);
03817 
03818     ok = Rec.Init();
03819     
03820     if (ok)
03821         ok = Rec.WriteUINT32(Loop); 
03822     if (ok)
03823         ok = Rec.WriteUINT32(GlobalDelay);
03824     if (ok)
03825         ok = Rec.WriteUINT32(Dither);
03826     if (ok)
03827         ok = Rec.WriteUINT32(WebPalette);
03828     if (ok)
03829         ok = Rec.WriteUINT32(ColoursPalette);
03830     if (ok)
03831         ok = Rec.WriteUINT32(NumColsInPalette);
03832     if (ok)
03833         ok = Rec.WriteUINT32(FlagsWord);
03834 
03835     // Write out the record.
03836     if (pFilter->Write(&Rec) != 0)
03837         RecordWritten = TRUE;
03838     else
03839         pFilter->GotError(_R(IDE_FILE_WRITE_ERROR));
03840 
03841     return RecordWritten;
03842 #else
03843     return FALSE;   
03844 #endif 
03845     }
03846 
03847 /******************************************************************************************************
03848 
03849 >   void Spread::SetAnimationLoop(const DWORD &Loop)
03850 
03851     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
03852     Created:    8/5/97
03853     Input:      Loop :- Global loop value.
03854     Outputs:    -
03855     Returns:    -
03856     Purpose:    Sets the loop value within the class data member m_AnimPropertiesParam.
03857                 This value has been recieved from the Animation properties tab.
03858                 
03859 *******************************************************************************************************/
03860 void Spread::SetAnimationLoop(const DWORD &Loop)
03861 {
03862     m_AnimPropertiesParam.SetAnimLoop(Loop);
03863 }
03864 
03865 
03866 /******************************************************************************************************
03867 
03868 >   void Spread::SetAnimationDelay(const DWORD GlobalDelay)
03869 
03870     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
03871     Created:    8/5/97
03872     Input:      Global Delay :- Global Delay value.
03873     Outputs:    -
03874     Returns:    -
03875     Purpose:    Sets the the delay value within the class data member m_AnimPropertiesParam.
03876                 This value has been recieved from the Animation properties tab.
03877                 
03878 *******************************************************************************************************/
03879 void Spread::SetAnimationDelay(const DWORD GlobalDelay)
03880 {
03881     m_AnimPropertiesParam.SetGlobalanimDelay(GlobalDelay);
03882 }
03883 
03884 /******************************************************************************************************
03885 
03886 >   void SetAnimationColours(const DITHER& Dither, const WEB_PALETTE& WebPalette, 
03887                              const PALETTE_COLOURS& ColoursPalette, const DWORD& NumColsInPalette,
03888                              const BOOL& IsBackgroundTransparent);                  
03889     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
03890     Created:    8/5/97
03891     Input:      Dither, WebPalette, ColoursPalette, NumColsInPalette,
03892                 IsBackgroundTransparent:- Animation colour preferences.
03893     Outputs:    -
03894     Returns:    -
03895     Purpose:    Sets the values for the animation colours within the class data member m_AnimPropertiesParam.
03896                 These values have been recieved from the Animation properties tab.
03897     Notes:      Karim 07/12/2000 - added IsBackgroundTransparent parameter.
03898                 
03899 *******************************************************************************************************/
03900 void Spread::SetAnimationColours(const DITHER& Dither, const WEB_PALETTE& WebPalette, 
03901                                  const PALETTE_COLOURS& ColoursPalette, const DWORD& NumColsInPalette,
03902                                  const BOOL& IsBackgroundTransparent)
03903 {
03904     // test if we need to junk any cached bitmaps
03905     if (Dither != m_AnimPropertiesParam.GetDither() ||
03906         WebPalette != m_AnimPropertiesParam.GetPalette() ||
03907         ColoursPalette != m_AnimPropertiesParam.GetPaletteCols() ||
03908         NumColsInPalette != m_AnimPropertiesParam.GetNumColsInPalette() ||
03909         IsBackgroundTransparent != m_AnimPropertiesParam.GetIsBackGroundTransp())
03910     {
03911         // force a refresh (regrab) of all frames as
03912         // the palette has changed etc..
03913 PORTNOTETRACE("OpGrabAllFrames","Spread::SetAnimationColours - Not setting OpGrabAllFrames force refresh flag");
03914 #ifndef EXCLUDE_FROM_XARALX
03915         OpGrabAllFrames::ms_ForceRefreshOfAllFrames = TRUE;
03916 #endif
03917     }
03918 
03919     m_AnimPropertiesParam.SetDither(Dither);
03920     m_AnimPropertiesParam.SetPalette(WebPalette);
03921     m_AnimPropertiesParam.SetPaletteCols(ColoursPalette);
03922     m_AnimPropertiesParam.SetNumColsInPalette(NumColsInPalette);
03923     m_AnimPropertiesParam.SetIsBackGroundTransp(IsBackgroundTransparent);
03924 }
03925 
03926 /******************************************************************************************************
03927 
03928 >   void GetAnimationColours(DITHER * pDither, WEB_PALETTE * pWebPalette, 
03929                              PALETTE_COLOURS * pColoursPalette, DWORD * pNumColsInPalette,
03930                              BOOL * pIsBackgroundTransparent);
03931     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03932     Created:    31/7/97
03933     Outputs:    Dither, WebPalette, ColoursPalette, NumColsInPalette,
03934                 IsBackgroundTransparent:- Animation colour preferences.
03935     Returns:    -
03936     Purpose:    Gets the values for the animation colours within the class data member m_AnimPropertiesParam.
03937     Notes:      Karim 07/12/2000 - added IsBackgroundTransparent parameter.
03938                 
03939 *******************************************************************************************************/
03940 
03941 void Spread::GetAnimationColours(DITHER * pDither, WEB_PALETTE * pWebPalette, 
03942                                  PALETTE_COLOURS * pColoursPalette, DWORD * pNumColsInPalette,
03943                                  BOOL * pIsBackgroundTransparent)
03944 {
03945     if (pDither != NULL)
03946         *pDither = m_AnimPropertiesParam.GetDither();
03947     if (pWebPalette != NULL)
03948         *pWebPalette = m_AnimPropertiesParam.GetPalette();
03949     if (pColoursPalette != NULL)
03950         *pColoursPalette = m_AnimPropertiesParam.GetPaletteCols();
03951     if (pNumColsInPalette != NULL)
03952         *pNumColsInPalette = m_AnimPropertiesParam.GetNumColsInPalette();
03953     if (pIsBackgroundTransparent != NULL)
03954         *pIsBackgroundTransparent = m_AnimPropertiesParam.GetIsBackGroundTransp(); 
03955 }
03956 
03957 /********************************************************************************************
03958 
03959 >   BOOL Spread::WriteSpreadInformation(BaseCamelotFilter* pFilter)
03960 
03961     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03962     Created:    6/8/96
03963     Input:      pFilter = ptr to the filter to export to
03964     Outputs:    -
03965     Returns:    TRUE if ok, FALSE otherwise
03966     Purpose:    Exports the page details, margins, bleed size and other spread related
03967                 information for this spread to the filter.
03968                 We output an information record rather than the individual pages as:-
03969                     - all the pages in the spread are defined to be the same size
03970                     - this is the same way that the old format used (not a good argument I know!)
03971                     - all the code to do it this way is present and proved
03972                     - it is a logical packing of all spread related information into one record 
03973     SeeAlso:    Spread::WritePreChildrenNative; Spread::WritePreChildrenWeb;
03974 
03975 ********************************************************************************************/
03976 
03977 BOOL Spread::WriteSpreadInformation(BaseCamelotFilter* pFilter)
03978 {
03979 #ifdef DO_EXPORT
03980     ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
03981 
03982 //  BOOL RecordWritten = FALSE;
03983 
03984     // Now save out the information record
03985     MILLIPOINT Width = 0;
03986     MILLIPOINT Height = 0;
03987     MILLIPOINT Margin = 0;
03988     MILLIPOINT Bleed = 0;
03989     BOOL Dps = TRUE;
03990     BOOL ShowDropShadow = TRUE;
03991 
03992     BOOL ok = TRUE;
03993 
03994     // and go and get all the page info
03995     if (ok) ok = GetPageSize(&Width, &Height, &Margin, &Bleed, &Dps, &ShowDropShadow);
03996 
03997     // If it worked, we had better try and output some info
03998     if (ok)
03999     {
04000         CXaraFileRecord Rec(TAG_SPREADINFORMATION, TAG_SPREADINFORMATION_SIZE);
04001 
04002         ok = Rec.Init();
04003 
04004         // Width, Height of page
04005         if (ok) ok = Rec.WriteINT32(Width); 
04006         if (ok) ok = Rec.WriteINT32(Height);
04007         // <Margin : MILLIPOINT>    The margin to add around all four sides of the pages in the spread to make up the pasteboard. 
04008         if (ok) ok = Rec.WriteINT32(Margin);    
04009         // <Bleed : MILLIPOINT> Bleed margin to add around all pages in this spread. (0 means none)
04010         if (ok) ok = Rec.WriteINT32(Bleed); 
04011         // <SpreadFlags : BYTE> Flags for the current spread.
04012         // SpreadFlags ::= DoublePageSpread | ShowDropShadow
04013         // ShowDropShadow flag to say whether we apply a page shadow behind the page
04014         // DoublePageSpread flag to say whether one or two pages are present 
04015         BYTE FlagsWord = (ShowDropShadow ? 2 : 0) | (Dps ? 1 : 0);
04016         if (ok) ok = Rec.WriteBYTE(FlagsWord);  
04017 
04018         // Finally, write the record out to file
04019         if (ok) ok = (pFilter->Write(&Rec) != 0);
04020     }
04021         
04022     return ok;
04023 #else
04024     return FALSE;
04025 #endif
04026 }
04027 
04028 
04029 /********************************************************************************************
04030 
04031 >   BOOL Spread::WriteSpreadScaling(BaseCamelotFilter* pFilter)
04032 
04033     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04034     Created:    6/8/96
04035     Input:      pFilter = ptr to the filter to export to
04036     Outputs:    -
04037     Returns:    TRUE if ok, FALSE otherwise
04038     Purpose:    Exports the scaling information for this spread to the filter
04039     SeeAlso:    Spread::WritePreChildrenNative; Spread::WritePreChildrenWeb;
04040 
04041 ********************************************************************************************/
04042 
04043 BOOL Spread::WriteSpreadScaling(BaseCamelotFilter* pFilter)
04044 {
04045 #ifdef DO_EXPORT
04046     ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
04047 
04048     BOOL ok = FALSE;
04049     
04050     DimScale* pDimScale = GetPtrDimScale();
04051     if (pDimScale != NULL)
04052     {
04053         // Find out if it is active
04054         BOOL Active = pDimScale->IsActive();
04055 
04056         // Find out about the scale factor strings
04057         String_32 DrawingScale = pDimScale->GetDrawingScaleStr();
04058         String_32 RealScale = pDimScale->GetRealScaleStr();
04059 
04060         // If we just save the strings directly, we will named references to the units being used.
04061         // This is bad as if somebody saves out '10cm' and then loads this onto a Japanese version,
04062         // they will not get what they expected. If we strip the scaling factor and units from the strings
04063         // and save this instead, the units as a units reference, then everything will be happy. The units
04064         // will get loaded in and converted into the correct locale format. (Apart from user units of course).
04065         UnitType Default = pDimScale->GetUnits();
04066 
04067         double      DrawingScaleValue   = 1.0;
04068         UnitType    DrawingUnits        = NOTYPE;
04069         ok = Convert::StringToComponents(DrawingScale, &DrawingScaleValue, &DrawingUnits);
04070 
04071         if (DrawingUnits == NOTYPE)
04072             DrawingUnits = Default;
04073 
04074         double      RealScaleValue      = 1.0;
04075         UnitType    RealUnits           = NOTYPE;
04076         ok = Convert::StringToComponents(RealScale, &RealScaleValue, &RealUnits);
04077 
04078         if (RealUnits == NOTYPE)
04079             RealUnits = Default;
04080         
04081         // Convert the unittype into a reference
04082         UnitListComponent * pUnitsComponent = pFilter->GetUnitDocComponent();
04083         ERROR2IF(pUnitsComponent == NULL,FALSE,"WriteGridAndRulerSettings No units doc component present");
04084 
04085         INT32 DrawingUnitsRef = pUnitsComponent->GetWriteUnitReference(DrawingUnits, pFilter);
04086         INT32 RealUnitsRef = pUnitsComponent->GetWriteUnitReference(RealUnits, pFilter);
04087 
04088         INT32 Tag = TAG_SPREADSCALING_INACTIVE;
04089         INT32 Size = TAG_SPREADSCALING_INACTIVE_SIZE;
04090         if (Active)
04091         {
04092             Tag = TAG_SPREADSCALING_ACTIVE;
04093             Size = TAG_SPREADSCALING_ACTIVE_SIZE;
04094         }
04095 
04096         CXaraFileRecord Rec(Tag, Size);
04097 
04098         ok = Rec.Init();
04099 
04100         if (ok) ok = Rec.WriteDOUBLE(DrawingScaleValue);    
04101         if (ok) ok = Rec.WriteINT32(DrawingUnitsRef);   
04102         if (ok) ok = Rec.WriteDOUBLE(RealScaleValue);   
04103         if (ok) ok = Rec.WriteINT32(RealUnitsRef);  
04104 
04105         // Finally, write the record out to file
04106         // In the process get the record number that this was written out as
04107         INT32 RecordNumber = 0L;
04108         if (ok) RecordNumber = pFilter->Write(&Rec);
04109 
04110         // If we have had a problem at any of the stages then return that to the caller
04111         if (!ok || RecordNumber <= 0)
04112             ok = FALSE;
04113     }
04114 
04115     return ok;
04116 #else
04117     return TRUE;
04118 #endif //DO_EXPORT
04119 }
04120 
04121 /********************************************************************************************
04122 
04123 >   BOOL Sperad::SetAnimPropertiesParam(AnimPropertiesParam* pParam)
04124 
04125     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
04126     Created:    07/05/97
04127     Inputs:     pParam - Sets the Animation Properties details for this spread.
04128     Returns:    TRUE if ok, FALSE otherwise.
04129     
04130 ********************************************************************************************/
04131 void Spread::SetSpreadAnimPropertiesParam(const AnimPropertiesParam& Param)
04132 {
04133     m_AnimPropertiesParam = Param;
04134 }
04135 
04136 /********************************************************************************************
04137 
04138 >   void Sperad::GetAnimPropertiesParam()
04139 
04140     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
04141     Created:    07/05/97
04142     Purpose:    Returns the the Animation Properties details for this spread.
04143         
04144 ********************************************************************************************/
04145 AnimPropertiesParam& Spread::GetSpreadAnimPropertiesParam()
04146 {
04147     return m_AnimPropertiesParam;
04148 }
04149 
04150 /********************************************************************************************************************
04151 >   BOOL Spread::SetSpreadAnimPropertiesParam(const DWORD &Loop, const DWORD &GlobalDelay, const DITHER &Dither, 
04152                                                 const WEB_PALETTE &WebPalette, const PALETTE_COLOURS &ColoursPalette,
04153                                                 const DWORD &NumColsInPalette, const BOOL& UseSystemColours,
04154                                                 const BOOL& IsBackgroundTransparent)
04155     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
04156     Created:    07/05/97
04157     Purpose:    Sets the Animation Properties details for this spread.
04158     Notes:      Karim 07/12/00 - added IsBackgroundTransparent parameter.
04159         
04160 *********************************************************************************************************************/
04161 
04162 BOOL Spread::SetSpreadAnimPropertiesParam(const DWORD &Loop, const DWORD &GlobalDelay, const DITHER &Dither, 
04163                                             const WEB_PALETTE &WebPalette, const PALETTE_COLOURS &ColoursPalette,
04164                                             const DWORD &NumColsInPalette, const BOOL& UseSystemColours,
04165                                             const BOOL& IsBackgroundTransparent)
04166 {
04167     ERROR2IF(this==NULL,FALSE,"Spread::SetSpreadAnimProperties cslled on NULL pointer");
04168 
04169     m_AnimPropertiesParam.SetAnimLoop(Loop);
04170     m_AnimPropertiesParam.SetGlobalanimDelay(GlobalDelay);  
04171     m_AnimPropertiesParam.SetDither(Dither);
04172     m_AnimPropertiesParam.SetPalette(WebPalette);
04173     m_AnimPropertiesParam.SetPaletteCols(ColoursPalette);
04174     m_AnimPropertiesParam.SetNumColsInPalette(NumColsInPalette);
04175     m_AnimPropertiesParam.SetUseSystemCols(UseSystemColours);
04176     m_AnimPropertiesParam.SetIsBackGroundTransp(IsBackgroundTransparent);
04177 
04178     return TRUE;
04179 }
04180 
04181 /********************************************************************************************************************
04182 BOOL Spread::GetSpreadAnimPropertiesParam(DWORD *Loop, DWORD *GlobalDelay, DITHER *Dither, 
04183                                             WEB_PALETTE *WebPalette, PALETTE_COLOURS* ColoursPalette,
04184                                             DWORD* NumColsInPalette, BOOL* UseSystemColours,
04185                                             BOOL* IsBgTransparent) 
04186 
04187     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
04188     Created:    01/04/97
04189     Purpose:    Allows access to the Animation Properties details for this spread.
04190     Notes:      Karim 07/12/00 - added IsBgTransparent parameter.
04191         
04192 *********************************************************************************************************************/
04193 BOOL Spread::GetSpreadAnimPropertiesParam(DWORD *Loop, DWORD *GlobalDelay, DITHER *Dither, 
04194                                             WEB_PALETTE *WebPalette, PALETTE_COLOURS* ColoursPalette,
04195                                             DWORD* NumColsInPalette, BOOL* UseSystemColours,
04196                                             BOOL* IsBgTransparent)
04197 {
04198     ERROR2IF(this==NULL,FALSE,"Spread::GetSpreadAnimProperties cslled on NULL pointer");
04199 
04200     *Loop               =        m_AnimPropertiesParam.GetAnimLoop();
04201     *GlobalDelay        =        m_AnimPropertiesParam.GetGlobalAnimDelay();    
04202     *Dither             =        m_AnimPropertiesParam.GetDither();
04203     *WebPalette         =        m_AnimPropertiesParam.GetPalette();
04204     *ColoursPalette     =        m_AnimPropertiesParam.GetPaletteCols();
04205     *NumColsInPalette   =        m_AnimPropertiesParam.GetNumColsInPalette();
04206     *UseSystemColours   =        m_AnimPropertiesParam.GetUseSystemCols();
04207     if (IsBgTransparent != NULL)
04208         *IsBgTransparent=        m_AnimPropertiesParam.GetIsBackGroundTransp();
04209 
04210     return TRUE;
04211 }
04212 
04213 /********************************************************************************************
04214 
04215 >   void Spread::SetAnimationBoundingRect(const DocRect& BoundingRect)
04216 
04217     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04218     Created:    10/06/97
04219     Inputs:     BoundingRect - the new bounding rect for this spread.
04220     Purpose:    Sets the new stored bounding rect for this spread.
04221 
04222 ********************************************************************************************/
04223 
04224 void Spread::SetAnimationBoundingRect(const DocRect& BoundingRect)
04225 {
04226     m_AnimPropertiesParam.SetBoundingRect(BoundingRect);
04227 }
04228 
04229 /********************************************************************************************
04230 
04231 >   DocRect Spread::GetAnimationBoundingRect()
04232 
04233     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04234     Created:    10/06/97
04235     Returns:    the stored bounding rect for the animation
04236     Purpose:    Returns the stored animation bounding rect for this spread.
04237         
04238 ********************************************************************************************/
04239 
04240 DocRect Spread::GetAnimationBoundingRect()
04241 {
04242     return m_AnimPropertiesParam.GetBoundingRect();
04243 }
04244 
04245 
04246 /********************************************************************************************
04247 
04248 >   void Spread::SetAnimationQuality(const Quality& NewQuality)
04249 
04250     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04251     Created:    21/7/97
04252     Inputs:     NewQuality - the new capture quality for this spread.
04253     Purpose:    Sets the new stored quality that the animation for this spread was captured at.
04254   
04255 ********************************************************************************************/
04256 
04257 void Spread::SetAnimationQuality(const Quality& NewQuality)
04258 {
04259     m_AnimPropertiesParam.SetAnimationQuality(NewQuality);
04260 }
04261 
04262 
04263 /********************************************************************************************
04264 
04265 >   Quality Spread::GetAnimationQuality()
04266 
04267     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04268     Created:    21/7/97
04269     Returns:    the stored quality for the animation
04270     Purpose:    Returns the stored quality that the animation for this spread was captured at.
04271         
04272 ********************************************************************************************/
04273 
04274 Quality Spread::GetAnimationQuality()
04275 {
04276     return m_AnimPropertiesParam.GetAnimationQuality();
04277 }
04278 
04279 
04280 /********************************************************************************************
04281 
04282 >   SubtreeRenderState Spread::RenderSubtree(RenderRegion* pRender, Node** ppNextNode, BOOL bClip)
04283 
04284     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
04285     Created:    12/07/2004
04286     Returns:    indicator as to whether rendering can proceed in this subtree
04287     Purpose:    -
04288         
04289 ********************************************************************************************/
04290 
04291 SubtreeRenderState Spread::RenderSubtree(RenderRegion* pRender, Node** ppNextNode, BOOL bClip)
04292 {
04293     return SUBTREE_ROOTANDCHILDREN;
04294 }
04295 
04296 
04297 /********************************************************************************************
04298 
04299 >   BOOL Spread::NeedsToExport(RenderRegion *pRender, BOOL VisibleLayersOnly = FALSE,
04300                                             BOOL CheckSelected = FALSE)
04301 
04302     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
04303     Created:    01/12/2004
04304     Inputs:     pRender - A pointer to the current export region (null if none)
04305                 VisibleLayersOnly - TRUE => remove nodes which are on invisible layers
04306                                        - FALSE => export everything
04307                 CheckSelected - TRUE => we check if object selected and only export selected bjects
04308                               - FALSE => we don't bother checking for selection or not
04309     Returns:    FALSE => we never want to export NodeRenderablePaper objects.
04310     Purpose:    Indicate that we don't want to export this class of nodes.
04311     SeeAlso:    NodeRenderablePaper::NeedsToRender
04312 
04313 ********************************************************************************************/
04314 
04315 BOOL Spread::NeedsToExport(RenderRegion *pRender, BOOL VisibleLayersOnly, BOOL CheckSelected)
04316 {
04317     return TRUE;
04318 }
04319 
04320      

Generated on Sat Nov 10 03:47:04 2007 for Camelot by  doxygen 1.4.4