00001 // $Id: backgrnd.cpp 1664 2006-08-04 10:06:16Z gerry $ 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 // OpBackground implementation 00099 00100 /* 00101 */ 00102 00103 #include "camtypes.h" 00104 00105 #include "backgrnd.h" // OpBackground 00106 00107 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00109 #include "page.h" 00110 #include "layer.h" 00111 #include "sprdmsg.h" // SpreadMsg 00112 #include "nodershp.h" // NodeRegularShape 00113 #include "lineattr.h" // AttrStrokeColourChange 00114 //#include "attrmgr.h" // AttributeManager - in camtypes.h [AUTOMATICALLY REMOVED] 00115 #include "qualattr.h" // QualityAttribute 00116 00117 //#include "galstr.h" // _R(IDS_BACKGROUNDLAYERNAME) 00118 00119 CC_IMPLEMENT_DYNCREATE(OpBackground, UndoableOperation) 00120 CC_IMPLEMENT_MEMDUMP(OpBackgroundParam, OpParam) 00121 00122 #define new CAM_DEBUG_NEW 00123 00124 //-------------------------------------------------------------------------------------------- 00125 //-------------------------------------------------------------------------------------------- 00126 //-------------------------------------------------------------------------------------------- 00127 00128 #if !defined(EXCLUDE_FROM_RALPH) 00129 00130 /*********************************************************************************************** 00131 00132 > OpBackground::OpBackground() 00133 00134 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00135 Created: 26/3/97 00136 Inputs: - 00137 Outputs: - 00138 Returns: - 00139 Purpose: Default constructor 00140 SeeAlso: UndoableOperation 00141 00142 ***********************************************************************************************/ 00143 00144 OpBackground::OpBackground() 00145 { 00146 // m_pDoc = NULL; 00147 // m_pSpread = NULL; 00148 // m_pDocColour = NULL; 00149 // m_pBitmap = NULL; 00150 00151 // Versions of the parameters used in the drag and drop process 00152 // m_pDroppedBitmap = NULL; 00153 // m_pDroppedDocColour = NULL; 00154 } 00155 00156 00157 /*********************************************************************************************** 00158 00159 > OpBackground::~OpBackground() 00160 00161 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00162 Created: 26/3/97 00163 Inputs: - 00164 Outputs: - 00165 Returns: - 00166 Purpose: Default destructor 00167 SeeAlso: UndoableOperation 00168 00169 ***********************************************************************************************/ 00170 00171 OpBackground::~OpBackground() 00172 { 00173 } 00174 00175 /*********************************************************************************************** 00176 00177 > void OpBackground::DoWithParam(OpDescriptor* pOpDesc,OpParam* pParam) 00178 00179 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00180 Created: 26/3/97 00181 Inputs: pOpDesc = ptr op desc 00182 pOpParam = param block to use 00183 Outputs: - 00184 Returns: - 00185 Purpose: This function is used to create a guideline in the selected spread. 00186 It calls DoAddNewGuideline() with pParam->Param1 specifying the guideline type. 00187 SeeAlso: DoAddNewGuideline(), OilRuler::OnLButtonDown() 00188 00189 ***********************************************************************************************/ 00190 00191 void OpBackground::DoWithParam(OpDescriptor* pOpDesc,OpParam* pParam) 00192 { 00193 ERROR3IF(pParam == NULL,"pParam is NULL"); 00194 00195 TRACEUSER("Gerry", _T("OpBackground::DoWithParam")); 00196 00197 if (pParam != NULL) 00198 { 00199 BOOL ok = TRUE; 00200 00201 OpBackgroundParam* pOpBackgroundParam = (OpBackgroundParam*)pParam; 00202 // Document * pDoc = pOpBackgroundParam->pDoc; 00203 Spread * pSpread = pOpBackgroundParam->pSpread; 00204 DocColour * pDocColour = pOpBackgroundParam->pDocColour; 00205 KernelBitmap * pBitmap = pOpBackgroundParam->pBitmap; 00206 00207 // If no spread is given then use the selected one 00208 if (pSpread == NULL) 00209 { 00210 // We will work off the currently selected spread 00211 pSpread = Document::GetSelectedSpread(); 00212 } 00213 00214 // Go and do the job of making the page background 00215 ok = DoMakePageBackground(this, pSpread, pBitmap, pDocColour); 00216 } 00217 00218 End(); 00219 } 00220 00221 /*********************************************************************************************** 00222 00223 > static BOOL OpBackground::MakePageBackground(UndoableOperation * pOp, Spread * pSpread, DocColour * pDocColour) 00224 00225 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00226 Created: 7/4/97 00227 Inputs: pOp - the operation to use 00228 pSpread - the spread to apply the background to 00229 pDocColour - the doc colour to apply 00230 Outputs: - 00231 Returns: True if worked ok, False otherwise. 00232 Purpose: Tries to apply the DocColour or bitmap as a new page background. 00233 00234 It is up to the caller to call End() on the operation. This is so 00235 that an outside op should be able to call this and everything should 00236 work ok. 00237 SeeAlso: - 00238 00239 ***********************************************************************************************/ 00240 00241 BOOL OpBackground::MakePageBackground(UndoableOperation * pOp, Spread * pSpread, DocColour * pDocColour) 00242 { 00243 ERROR2IF(pOp == NULL || pSpread == NULL || pDocColour == NULL,FALSE,"MakePageBackground Bad params!"); 00244 00245 // Get the op to do its stuff 00246 BOOL ok = DoMakePageBackground(pOp, pSpread, NULL, pDocColour); 00247 00248 return ok; 00249 } 00250 00251 /*********************************************************************************************** 00252 00253 > static BOOL OpBackground::MakePageBackground(UndoableOperation * pOp, Spread * pSpread, KernelBitmap * pBitmap) 00254 00255 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00256 Created: 7/4/97 00257 Inputs: pOp - the operation to use 00258 pSpread - the spread to apply the background to 00259 pBitmap - the bitmap to apply 00260 Outputs: - 00261 Returns: True if worked ok, False otherwise. 00262 Purpose: Tries to apply the DocColour or bitmap as a new page background. 00263 00264 It is up to the caller to call End() on the operation. This is so 00265 that an outside op should be able to call this and everything should 00266 work ok. 00267 SeeAlso: - 00268 00269 ***********************************************************************************************/ 00270 00271 BOOL OpBackground::MakePageBackground(UndoableOperation * pOp, Spread * pSpread, KernelBitmap * pBitmap) 00272 { 00273 ERROR2IF(pOp == NULL || pSpread == NULL || pBitmap == NULL,FALSE,"MakePageBackground Bad params!"); 00274 00275 // Get the op to do its stuff 00276 BOOL ok = DoMakePageBackground(pOp, pSpread, pBitmap); 00277 00278 return ok; 00279 } 00280 00281 /*********************************************************************************************** 00282 00283 > static BOOL OpBackground::DoMakePageBackground(UndoableOperation * pOp, Spread * pSpread, KernelBitmap * pBitmap, 00284 DocColour * pDocColour = NULL) 00285 00286 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00287 Created: 7/4/97 00288 Inputs: pOp - the operation to use 00289 pSpread - the spread to apply the background to 00290 pBitmap - the bitmap to apply 00291 pDocColour - the doc colour to apply 00292 Outputs: - 00293 Returns: True if worked ok, False otherwise. 00294 Purpose: Tries to apply the DocColour or bitmap as a new page background. 00295 00296 It is up to the caller to call End() on the operation. This is so 00297 that an outside op should be able to call this and everything should 00298 work ok. 00299 SeeAlso: - 00300 00301 ***********************************************************************************************/ 00302 00303 BOOL OpBackground::DoMakePageBackground(UndoableOperation * pOp, Spread * pSpread, KernelBitmap * pBitmap, 00304 DocColour * pDocColour) 00305 { 00306 TRACEUSER("Gerry", _T("OpBackground::DoMakePageBackground")); 00307 00308 // Our inputs are actually set up in the class variables, so check them 00309 ERROR2IF(pSpread == NULL || pOp == NULL,FALSE,"DoMakePageBackground Bad params!"); 00310 ERROR2IF(pDocColour == NULL && pBitmap == NULL,FALSE,"DoMakePageBackground Bad params!"); 00311 00312 BOOL ok = TRUE; 00313 Page *pPage = pSpread->FindFirstPageInSpread (); 00314 DocRect Bounds = pPage->GetPageRect (); 00315 00316 // If there's a transparent background colour, just hide the existing node. 00317 if ( pDocColour != NULL && pDocColour->IsTransparent () ) 00318 { 00319 Layer* pOldLayer = pSpread->FindFirstPageBackgroundLayer (); 00320 00321 // Attempt to remove the old background layer. 00322 if ( pOldLayer != NULL ) 00323 { 00324 TRACEUSER("Gerry", _T("Removing old background")); 00325 if ( !pOp->DoHideNode(pOldLayer, TRUE ) ) 00326 { 00327 // Something went wrong, so handle the error. 00328 ERROR3( "OpBackground failed to hide the old page background" ); 00329 pOp->FailAndExecute (); 00330 ok = FALSE; 00331 } 00332 } 00333 } 00334 00335 // Otherwise create a new background layer. 00336 else 00337 { 00338 TRACEUSER("Gerry", _T("Creating new background")); 00339 Layer* pBackgroundLayer = DoCreateBackgroundLayer(pOp, pSpread); 00340 00341 if (pBackgroundLayer == NULL) 00342 { 00343 ERROR3("Something went wrong with the layer creation"); 00344 pOp->FailAndExecute(); 00345 ok = FALSE; 00346 } 00347 else 00348 { 00349 // Try and find an existing page filling rectangle on this layer 00350 NodeRegularShape * pShape = DoFindPageRectangle(pSpread, pBackgroundLayer); 00351 00352 // If not found then create a new one 00353 if (pShape != NULL) 00354 { 00355 // Hide the old version of the rectangle 00356 if (!pOp->DoHideNode(pShape, TRUE)) 00357 { 00358 ERROR3("OpBackground failed to hide the old node"); 00359 pOp->FailAndExecute(); 00360 ok = FALSE; 00361 } 00362 } 00363 00364 if (ok) 00365 { 00366 // Make a new rectangle of the correct size 00367 pShape = DoCreateRectangle(pSpread); 00368 00369 // Apply the bitmap or the colour to it before we insert it into the tree. 00370 if (pDocColour) 00371 { 00372 // Set the colour to be the background. 00373 ok = ApplyDocColour(pDocColour, pShape); 00374 } 00375 else if (pBitmap) 00376 { 00377 ok = ApplyBitmap(pBitmap, pShape); 00378 } 00379 else 00380 { 00381 ERROR3("OpBackground Haven't got anything to apply"); 00382 pOp->FailAndExecute(); 00383 ok = FALSE; 00384 } 00385 00386 // Apply a useful set of default attibutes on top of the fill colour 00387 // or bitmap fill. 00388 if ( pShape != NULL ) 00389 { 00390 ApplyDefaultAttributes(pShape); 00391 } 00392 } 00393 00394 // We must make the layer unlocked so that we don't get the stupid 00395 // inserting on locked layer message 00396 pBackgroundLayer->SetLocked(FALSE); 00397 00398 // And now insert it into the background layer 00399 if (ok && !pOp->DoInsertNewNode(pShape, pBackgroundLayer, FIRSTCHILD,FALSE, 00400 FALSE,FALSE,FALSE)) 00401 { 00402 delete pShape; 00403 pShape = NULL; 00404 pOp->FailAndExecute(); 00405 ok = FALSE; 00406 } 00407 00408 // Set the layer back to locked as we have finished inserting onto the layer 00409 pBackgroundLayer->SetLocked(TRUE); 00410 00411 // Since we prevented DoInsertnewNode from invalidating, it won't have cleared 00412 // the cache appropriately so we will have to do that ourselves... 00413 if (ok) 00414 pBackgroundLayer->ReleaseCached(); 00415 } 00416 } 00417 00418 // Force a redraw of the new background layer. 00419 if ( ok && !pOp->DoInvalidateRegion ( pSpread, Bounds ) ) 00420 { 00421 pOp->FailAndExecute(); 00422 ok = FALSE; 00423 } 00424 00425 return ok; 00426 } 00427 00428 /*********************************************************************************************** 00429 00430 > static NodeRegularShape * OpBackground::DoFindPageRectangle(Spread * pSpread, Layer* pBackgroundLayer) 00431 00432 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00433 Created: 27/3/97 00434 Inputs: pSpread - the spread to apply the background to 00435 pBackgroundLayer - the layer to search for the shape on 00436 Outputs: - 00437 Returns: The regular shape, if found 00438 Purpose: Tries to find the page filling rectangle on the specified layer. 00439 SeeAlso: - 00440 00441 ***********************************************************************************************/ 00442 00443 NodeRegularShape * OpBackground::DoFindPageRectangle(Spread * pSpread, Layer* pBackgroundLayer) 00444 { 00445 if (pSpread == NULL || pBackgroundLayer == NULL) 00446 return NULL; 00447 00448 // We want to find the rectangle which should be the same size as the current union of 00449 // all the pages on the current spread 00450 DocRect PagesRect; 00451 pSpread->GetPagesRect(&PagesRect); 00452 00453 return FindPageRectangle(pBackgroundLayer, PagesRect); 00454 } 00455 00456 /*********************************************************************************************** 00457 00458 > static NodeRegularShape * OpBackground::FindPageRectangle(Layer* pBackgroundLayer, const DocRect& PagesRect) 00459 00460 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00461 Created: 4/4/97 00462 Inputs: The layer to search for the shape on 00463 The encompassing rectangle of the current pages 00464 Outputs: - 00465 Returns: The regular shape, if found 00466 Purpose: Tries to find the page filling rectangle on the specified layer. 00467 SeeAlso: - 00468 00469 ***********************************************************************************************/ 00470 00471 NodeRegularShape * OpBackground::FindPageRectangle(Layer* pBackgroundLayer, const DocRect& PagesRect) 00472 { 00473 ERROR2IF(pBackgroundLayer == NULL,FALSE,"OpBackground::FindPageRectangle Bad params error!"); 00474 00475 NodeRegularShape *pShape = NULL; 00476 NodeRegularShape *pRegNode = NULL; 00477 Node * pNode = pBackgroundLayer->FindFirstChild(); 00478 DocRect rect; 00479 const MILLIPOINT delta = 1000; 00480 while (pNode != NULL) 00481 { 00482 // Only check regular shape nodes 00483 if (pNode->IS_KIND_OF(NodeRegularShape)) 00484 { 00485 // Only check rectangles 00486 pRegNode = (NodeRegularShape *)pNode; 00487 if (pRegNode->IsARectangle()) 00488 { 00489 //DocCoord MinorAxis NodeRegularShape::GetMinorAxes(); 00490 // The bounding rect should be roughly what we want 00491 rect = pRegNode->GetBoundingRect(TRUE, FALSE); 00492 if ( 00493 (PagesRect.lo.x > rect.lo.x - delta) && (PagesRect.lo.x < rect.lo.x + delta) && 00494 (PagesRect.hi.x > rect.hi.x - delta) && (PagesRect.hi.x < rect.hi.x + delta) && 00495 (PagesRect.lo.y > rect.lo.y - delta) && (PagesRect.lo.y < rect.lo.y + delta) && 00496 (PagesRect.hi.y > rect.hi.y - delta) && (PagesRect.hi.y < rect.hi.y + delta) 00497 ) 00498 { 00499 pShape = pRegNode; 00500 } 00501 } 00502 } 00503 00504 pNode = pNode->FindNext(); 00505 } 00506 00507 return pShape; 00508 } 00509 00510 /*********************************************************************************************** 00511 00512 > static NodeRegularShape * OpBackground::DoCreateRectangle(Spread * pSpread) 00513 00514 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00515 Created: 27/3/97 00516 Inputs: pSpread - the spread to apply the background to 00517 Outputs: - 00518 Returns: The regular shape 00519 Purpose: Returns a new rectangle the size of the current spread. 00520 SeeAlso: - 00521 00522 ***********************************************************************************************/ 00523 00524 NodeRegularShape * OpBackground::DoCreateRectangle(Spread * pSpread) 00525 { 00526 ERROR2IF(pSpread == NULL,FALSE,"OpBackground::DoCreateRectangle Bad params error!"); 00527 00528 if (pSpread == NULL) 00529 return NULL; 00530 00531 // This assumes that we have already checked to see if there is a page covering rectangle 00532 // already present on this layer. 00533 00534 // Create a new rectangle node on the layer 00535 NodeRegularShape *pShape = new NodeRegularShape; 00536 if (pShape != NULL) 00537 { 00538 BOOL ok = pShape->SetUpShape(); 00539 00540 if (!ok) 00541 { 00542 // Do something sensible in here 00543 delete pShape; 00544 return NULL; 00545 } 00546 00547 // We want to make the rectangle the same size as the current union of 00548 // all the pages on the current spread 00549 DocRect Rect; 00550 pSpread->GetPagesRect(&Rect); 00551 00552 /* // We must expand the rectangle by a single pixel as the page redraw 00553 // draws a single pixel line around the outside. 00554 const MILLIPOINT pixel = (MILLIPOINT)(72000.0/96.0); 00555 Rect.Inflate(pixel); */ 00556 00557 const INT32 CornerRadius = 0; // No curvature 00558 00559 if (pShape->MakeRectangle(Rect.Width(), Rect.Height(), CornerRadius)) 00560 { 00561 // Translate centre from 0,0 to required position relative to page 00562 INT32 XTrans = Rect.lo.x + (Rect.Width()/2); 00563 INT32 YTrans = Rect.lo.y + (Rect.Height()/2); 00564 Trans2DMatrix Trans(XTrans, YTrans); 00565 00566 pShape->Transform(Trans); 00567 00568 // finish off the shape 00569 pShape->InvalidateBoundingRect(); 00570 } 00571 } 00572 00573 return pShape; 00574 } 00575 00576 /*********************************************************************************************** 00577 00578 > static BOOL OpBackground::ApplyDocColour(DocColour * pColourToApply, NodeRegularShape * pShape) 00579 00580 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00581 Created: 27/3/97 00582 Inputs: The colour to apply 00583 The regular shape to apply the colour to 00584 Outputs: - 00585 Returns: 00586 Purpose: Applies the specified colour to the specified NodeRegularShape. 00587 SeeAlso: - 00588 00589 ***********************************************************************************************/ 00590 00591 BOOL OpBackground::ApplyDocColour(DocColour * pColourToApply, NodeRegularShape * pShape) 00592 { 00593 ERROR2IF(pColourToApply == NULL || pShape == NULL,FALSE,"OpBackground::ApplyDocColour Bar params!"); 00594 00595 // Set up a fill colour attribute 00596 AttrFlatColourFill *pFillColAttr = new AttrFlatColourFill(); 00597 if (pFillColAttr == NULL) 00598 { 00599 InformError(); 00600 return(FALSE); 00601 } 00602 00603 ((AttrFillGeometry*)pFillColAttr)->SetStartColour(pColourToApply); 00604 00605 // And now insert it as a child of the regular shape 00606 // Factoring should be ok as the Regular Shape is assumed to be the child of 00607 // layer 00608 pFillColAttr->AttachNode(pShape, FIRSTCHILD); 00609 00610 return TRUE; 00611 } 00612 00613 /*********************************************************************************************** 00614 00615 > static BOOL OpBackground::ApplyBitmap(KernelBitmap * pBitmapToApply, NodeRegularShape * pShape) 00616 00617 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00618 Created: 27/3/97 00619 Inputs: The bitmap to apply 00620 The regular shape to apply the bitmap to 00621 Outputs: - 00622 Returns: 00623 Purpose: Applies the specified bitmap to the specified NodeRegularShape. 00624 SeeAlso: - 00625 00626 ***********************************************************************************************/ 00627 00628 BOOL OpBackground::ApplyBitmap(KernelBitmap * pBitmapToApply, NodeRegularShape * pShape) 00629 { 00630 ERROR2IF(pBitmapToApply == NULL || pShape == NULL,FALSE,"OpBackground::ApplyBitmap Bar params!"); 00631 00632 // Set up a fill colour attribute 00633 AttrBitmapColourFill *pBitmapFillAttr = new AttrBitmapColourFill(); 00634 if (pBitmapFillAttr == NULL) 00635 { 00636 InformError(); 00637 return(FALSE); 00638 } 00639 00640 // Set the coordinates of the fill end points 00641 // We want to start the fill at the top left of the regular shape 00642 // The bounding rect should be roughly what we want 00643 DocRect Rect = pShape->GetBoundingRect(TRUE, FALSE); 00644 00645 // Get the size of the bitmap taking into account its DPI 00646 INT32 Width = pBitmapToApply->GetRecommendedWidth(); 00647 INT32 Height = pBitmapToApply->GetRecommendedHeight(); 00648 // You would think that the handles on the fill correspond to where you place them 00649 // but oh now the displayed handles are shown at different points. So instead of 00650 // positioning the start in the centre of the bitmap, you need to position it bottom left 00651 // The End should be centre and right but needs to be bottom right. 00652 // The End2 should be centre and top but needs to be top left. 00653 00654 // We want the start point to be half the height of the bitmap below this 00655 //DocCoord Start(Rect.lo.x + Width/2, Rect.hi.y - Height/2); 00656 DocCoord Start(Rect.lo.x, Rect.hi.y - Height); 00657 // We want the other end point to be same height as the centre point 00658 // but on the far right of the rectangle i.e the full width across 00659 //DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height/2); 00660 DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height); 00661 // We want the end point to be middle and top of the rectangle 00662 //DocCoord End2(Rect.lo.x + Width/2, Rect.hi.y); 00663 DocCoord End2(Rect.lo.x, Rect.hi.y); 00664 00665 ((AttrFillGeometry*)pBitmapFillAttr)->SetStartPoint(&Start); 00666 ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint(&End); 00667 ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint2(&End2); 00668 00669 // Now attach the correct bitmap to the fill 00670 ((AttrFillGeometry*)pBitmapFillAttr)->AttachBitmap(pBitmapToApply); 00671 00672 // And now insert it as a child of the regular shape 00673 // Factoring should be ok as the Regular Shape is assumed to be the child of 00674 // layer 00675 pBitmapFillAttr->AttachNode(pShape, FIRSTCHILD); 00676 00677 return TRUE; 00678 } 00679 00680 /*********************************************************************************************** 00681 00682 > static BOOL OpBackground::ApplyDefaultAttributes(NodeRegularShape * pShape) 00683 00684 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00685 Created: 1/4/97 00686 Inputs: The regular shape to apply the attributes to 00687 Outputs: - 00688 Returns: 00689 Purpose: Applies some useful default attributes to the specified NodeRegularShape. 00690 SeeAlso: - 00691 00692 ***********************************************************************************************/ 00693 00694 BOOL OpBackground::ApplyDefaultAttributes(NodeRegularShape * pShape) 00695 { 00696 ERROR2IF(pShape == NULL,FALSE,"OpBackground::ApplyDefaultAttributes Bar params!"); 00697 00698 // ***** 00699 // Set up a no colour line colour 00700 AttrStrokeColour * pLineColAttr = new AttrStrokeColour(); 00701 if (pLineColAttr == NULL) 00702 { 00703 InformError(); 00704 return(FALSE); 00705 } 00706 00707 DocColour ColNone(COLOUR_NONE); 00708 ((AttrFillGeometry*)pLineColAttr)->SetStartColour(&ColNone); 00709 // And now insert it as a child of the regular shape 00710 // Factoring should be ok as the Regular Shape is assumed to be the child of 00711 // layer 00712 pLineColAttr->AttachNode(pShape, LASTCHILD); 00713 00714 00715 00716 // ***** 00717 // Set up a line width attribute 00718 AttrLineWidth *pLineWidthAttr = new AttrLineWidth(); 00719 if (pLineWidthAttr == NULL) 00720 { 00721 InformError(); 00722 return(FALSE); 00723 } 00724 00725 ((AttrLineWidth*)pLineWidthAttr)->Value.LineWidth = 0; 00726 00727 // And now insert it as a child of the regular shape 00728 // Factoring should be ok as the Regular Shape is assumed to be the child of 00729 // layer 00730 pLineWidthAttr->AttachNode(pShape, LASTCHILD); 00731 00732 00733 // ***** 00734 // Set up a join type attribute 00735 AttrJoinType * pJoinTypeAttr = new AttrJoinType(); 00736 if (pLineWidthAttr == NULL) 00737 { 00738 InformError(); 00739 return(FALSE); 00740 } 00741 00742 // We will use a default constructed one as this should be vaguely correct 00743 // ((AttrLineWidth*)pJoinTypeAttr)->Value.LineWidth = 0; 00744 00745 // And now insert it as a child of the regular shape 00746 // Factoring should be ok as the Regular Shape is assumed to be the child of 00747 // layer 00748 pJoinTypeAttr->AttachNode(pShape, LASTCHILD); 00749 00750 return TRUE; 00751 } 00752 00753 00754 /*********************************************************************************************** 00755 00756 > static Layer* OpBackground::DoCreateBackgroundLayer(UndoableOperation * pOp, Spread * pSpread) 00757 00758 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00759 Created: 26/3/97 00760 Inputs: pOp - The operation to use 00761 pSpread - the spread to apply the background to 00762 Outputs: - 00763 Returns: Ptr to the background layer, or NULL one couldn't be created. 00764 Purpose: This returns a ptr to the background layer. 00765 00766 If the background layer already exists, a ptr to it is returned. 00767 00768 If there isn't a background layer, it is created and inserted into the doc tree. 00769 If this fails the func returns NULL 00770 00771 SeeAlso: OpBackground::DoNewGuideline() 00772 00773 ***********************************************************************************************/ 00774 00775 Layer* OpBackground::DoCreateBackgroundLayer(UndoableOperation * pOp, Spread * pSpread) 00776 { 00777 ERROR2IF(pOp == NULL || pSpread == NULL,FALSE,"OpBackground::DoCreateBackgroundLayer Bad params error!"); 00778 00779 // Search for our special page background layer 00780 Layer* pFoundLayer = pSpread->FindFirstPageBackgroundLayer(); 00781 // If we have found it then return this to the caller as we don't want 00782 // more than one present! 00783 if (pFoundLayer != NULL) 00784 return pFoundLayer; 00785 00786 // We didn't find a page background layer so go and create a new one 00787 Layer* pNewLayer = CreateBackgroundLayer(); 00788 if (pNewLayer != NULL) 00789 { 00790 // If we insert the new layer as the FIRSTCHILD then this will be like the guidelayer 00791 // and behind the page. If we insert as the last child then we will be at the front of 00792 // the stacking order. We need to insert ourselves as the node after the last page node 00793 Page *pLastPage = pSpread->FindLastPageInSpread(); 00794 00795 // Insert the new layer as the next node after the last page. 00796 if (pLastPage && pOp->DoInsertNewNode(pNewLayer, pLastPage, NEXT, FALSE,FALSE,FALSE,FALSE)) 00797 { 00798 pNewLayer->EnsureUniqueLayerID(); 00799 BROADCAST_TO_ALL(SpreadMsg(pSpread, SpreadMsg::LAYERCHANGES)); 00800 } 00801 else 00802 { 00803 delete pNewLayer; 00804 pNewLayer = NULL; 00805 } 00806 } 00807 00808 return pNewLayer; 00809 } 00810 00811 00812 00813 /*********************************************************************************************** 00814 00815 > static Layer* OpBackground::CreateBackgroundLayer() 00816 00817 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00818 Created: 26/3/97 00819 Inputs: - 00820 Outputs: - 00821 Returns: Ptr to a background layer that's ready to be inserted into the tree 00822 Purpose: This does everything required in creating a layer fit to be called the background layer 00823 SeeAlso: - 00824 00825 ***********************************************************************************************/ 00826 00827 Layer* OpBackground::CreateBackgroundLayer() 00828 { 00829 Layer* pNewLayer = new Layer; 00830 if (pNewLayer != NULL) 00831 { 00832 String_256 LayerName(_R(IDS_BACKGROUNDLAYERNAME)); 00833 00834 pNewLayer->SetVisible(TRUE); 00835 pNewLayer->SetLocked(TRUE); 00836 pNewLayer->SetPrintable(FALSE); 00837 pNewLayer->SetBackground(TRUE); 00838 pNewLayer->SetOutline(FALSE); 00839 pNewLayer->SetGuide(FALSE); 00840 pNewLayer->SetPageBackground(TRUE); // This is the special page background layer flag 00841 pNewLayer->SetLayerID(LayerName); 00842 00843 /* // Ensure we are always rendered at maximum quality so that turning WYSIWYG 00844 // down does not remove the page background! 00845 Quality Qual; 00846 Qual.SetQuality(QUALITY_MAX); 00847 QualityAttribute QualAttr(Qual); 00848 NodeAttribute* pNodeAttr = QualAttr.MakeNode(); 00849 pNodeAttr->AttachNode(pNewLayer, FIRSTCHILD); */ 00850 } 00851 00852 return pNewLayer; 00853 } 00854 00855 /*********************************************************************************************** 00856 00857 > static BOOL OpBackground::FixBackgroundLayer(Layer * pBackgroundLayer, const DocRect& NewPagesRect, 00858 const DocRect& OldPagesRect) 00859 00860 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00861 Created: 4/4/97 00862 Inputs: The background layer to fix 00863 The encompassing size of the new pages in the spread 00864 The encompassing size of the old pages in the spread 00865 Outputs: - 00866 Returns: Ptr to a background layer that's ready to be inserted into the tree 00867 Purpose: This tries to fix up the special page background layer so that the rectangle 00868 on it is resized to the cover the newly resized pages on the spread. 00869 SeeAlso: Spread::SetPageSize; 00870 00871 ***********************************************************************************************/ 00872 00873 BOOL OpBackground::FixBackgroundLayer(Layer * pBackgroundLayer, const DocRect& NewPagesRect, 00874 const DocRect& OldPagesRect) 00875 { 00876 ERROR2IF(pBackgroundLayer == NULL,FALSE,"OpBackground::FixBackgroundLayer Bad params!"); 00877 00878 //BOOL ok = TRUE; 00879 00880 // There should be a rectangle on the page encompassing the old position of the pages 00881 // so go and try and find it 00882 NodeRegularShape * pShape = FindPageRectangle(pBackgroundLayer, OldPagesRect); 00883 // If no rectangle is found then something might be slightly wrong. Should we error? 00884 if (pShape) 00885 { 00886 const INT32 CornerRadius = 0; // No curvature 00887 if (pShape->MakeRectangle(NewPagesRect.Width(), NewPagesRect.Height(), CornerRadius)) 00888 { 00889 // Translate centre from 0,0 to required position relative to page 00890 INT32 XTrans = NewPagesRect.lo.x + (NewPagesRect.Width()/2); 00891 INT32 YTrans = NewPagesRect.lo.y + (NewPagesRect.Height()/2); 00892 Trans2DMatrix Trans(XTrans, YTrans); 00893 00894 pShape->Transform(Trans); 00895 00896 // finish off the shape 00897 pShape->InvalidateBoundingRect(); 00898 } 00899 00900 // Find any bitmap fills and fix up the fill origin etc. 00901 Node * pNode = pShape->FindFirstChild(); 00902 while (pNode != NULL) 00903 { 00904 // Only check and fix bitmap colour fill attributes of the regular shape nodes 00905 if (pNode->IS_KIND_OF(AttrBitmapColourFill)) 00906 { 00907 // Convert the pointer to the correct type 00908 AttrBitmapColourFill * pBitmapFillAttr = (AttrBitmapColourFill*)pNode; 00909 00910 // Set the coordinates of the fill end points 00911 // We want to start the fill at the top left of the regular shape 00912 // The bounding rect should be roughly what we want 00913 DocRect Rect = pShape->GetBoundingRect(TRUE, FALSE); 00914 00915 KernelBitmap * pBitmap = ((AttrFillGeometry*)pBitmapFillAttr)->GetBitmap(); 00916 // Get the size of the bitmap taking into account its DPI 00917 INT32 Width = pBitmap->GetRecommendedWidth(); 00918 INT32 Height = pBitmap->GetRecommendedHeight(); 00919 // You would think that the handles on the fill correspond to where you place them 00920 // but oh now the displayed handles are shown at different points. So instead of 00921 // positioning the start in the centre of the bitmap, you need to position it bottom left 00922 // The End should be centre and right but needs to be bottom right. 00923 // The End2 should be centre and top but needs to be top left. 00924 00925 // We want the start point to be half the height of the bitmap below this 00926 //DocCoord Start(Rect.lo.x + Width/2, Rect.hi.y - Height/2); 00927 DocCoord Start(Rect.lo.x, Rect.hi.y - Height); 00928 // We want the other end point to be same height as the centre point 00929 // but on the far right of the rectangle i.e the full width across 00930 //DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height/2); 00931 DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height); 00932 // We want the end point to be middle and top of the rectangle 00933 //DocCoord End2(Rect.lo.x + Width/2, Rect.hi.y); 00934 DocCoord End2(Rect.lo.x, Rect.hi.y); 00935 00936 ((AttrFillGeometry*)pBitmapFillAttr)->SetStartPoint(&Start); 00937 ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint(&End); 00938 ((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint2(&End2); 00939 } 00940 00941 pNode = pNode->FindNext(); 00942 } 00943 } 00944 00945 return TRUE; 00946 } 00947 00948 00949 /*********************************************************************************************** 00950 00951 > static BOOL OpBackground::GetPageColour(Spread *pSpread, KernelBitmap **ppOutBitmap, 00952 DocColour **ppOutColour) 00953 00954 Author: Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com> 00955 Created: 23/6/97 00956 Inputs: pSpread - a spread 00957 Outputs: ppOutBitmap - receives the page bitmap, if a bitmap colour fill is applied to it 00958 ppOutColour - receives the page colour, if a flat colour fill is applied to it 00959 Returns: TRUE, if succesful, FALSE otherwise 00960 Purpose: Gets the page's fill attribute, which could only be either a colour, or a bitmap 00961 00962 ***********************************************************************************************/ 00963 00964 BOOL OpBackground::GetPageColour(Spread *pSpread, KernelBitmap **ppOutBitmap, 00965 DocColour **ppOutColour) 00966 { 00967 ERROR2IF(pSpread == NULL,FALSE,"OpBackground::GetPageColour Bad params error!"); 00968 ERROR2IF(ppOutBitmap == NULL || ppOutColour == NULL,FALSE,"OpBackground::GetPageColour Bad params error!"); 00969 00970 // Search for our special page background layer 00971 Layer* pFoundLayer = pSpread->FindFirstPageBackgroundLayer(); 00972 if (pFoundLayer == NULL) 00973 return FALSE; 00974 00975 // search for our page node 00976 NodeRegularShape *pNode = DoFindPageRectangle(pSpread, pFoundLayer); 00977 00978 if (!pNode) 00979 return FALSE; 00980 00981 // find the fill attribute applied to the page 00982 NodeAttribute *pAppliedAttr = NULL; 00983 pNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pAppliedAttr); 00984 00985 if (pAppliedAttr != NULL) 00986 { 00987 if (IS_A(pAppliedAttr, AttrFlatColourFill)) // flat colour fill? 00988 { 00989 // get the colour attribute 00990 ColourFillAttribute *pColAttr = (ColourFillAttribute *)(pAppliedAttr->GetAttributeValue()); 00991 00992 // set the colour pointer to the doc colour, and the bitmap pointer to NULL 00993 *ppOutBitmap = NULL; 00994 *ppOutColour = pColAttr->GetStartColour(); 00995 00996 } 00997 else if (IS_A(pAppliedAttr, AttrBitmapColourFill)) // bitmap fill 00998 { 00999 01000 // set the colour pointer to NULL, and the bitmap pointer to the kernel bitmap 01001 *ppOutBitmap = ((AttrFillGeometry *)pAppliedAttr)->GetBitmap(); 01002 *ppOutColour = NULL; 01003 } 01004 else 01005 return FALSE; 01006 } 01007 else 01008 return FALSE; 01009 01010 return TRUE; 01011 } 01012 01013 01014 01015 /*********************************************************************************************** 01016 01017 > virtual BOOL OpBackground::Undo() 01018 01019 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01020 Created: 26/3/97 01021 Inputs: - 01022 Outputs: - 01023 Returns: TRUE if successfull, FALSE otherwise 01024 Purpose: Called when the op is undone. 01025 This broadcasts a 'Guidelines changed' layer message 01026 SeeAlso: - 01027 01028 ***********************************************************************************************/ 01029 01030 /* BOOL OpBackground::Undo() 01031 { 01032 if (UndoableOperation::Undo()) 01033 { 01034 BroadcastGuidelineChanges(pBroadcastLayer); 01035 return TRUE; 01036 } 01037 01038 return FALSE; 01039 } */ 01040 01041 /*********************************************************************************************** 01042 01043 > virtual BOOL OpBackground::Redo() 01044 01045 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01046 Created: 26/3/97 01047 Inputs: - 01048 Outputs: - 01049 Returns: TRUE if successfull, FALSE otherwise 01050 Purpose: Called when the op is redone. 01051 This broadcasts a 'Guidelines changed' layer message 01052 SeeAlso: - 01053 01054 ***********************************************************************************************/ 01055 01056 /* BOOL OpBackground::Redo() 01057 { 01058 if (UndoableOperation::Redo()) 01059 { 01060 BroadcastGuidelineChanges(pBroadcastLayer); 01061 return TRUE; 01062 } 01063 01064 return FALSE; 01065 } */ 01066 01067 /*********************************************************************************************** 01068 01069 > static BOOL OpBackground::Init() 01070 01071 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01072 Created: 26/3/97 01073 Inputs: - 01074 Outputs: - 01075 Returns: TRUE if op successfully declared, FALSE otherwise 01076 Purpose: Registers an op desc for this op 01077 SeeAlso: - 01078 01079 ***********************************************************************************************/ 01080 01081 BOOL OpBackground::Init() 01082 { 01083 BOOL ok = RegisterOpDescriptor( 01084 0, 01085 0, 01086 CC_RUNTIME_CLASS(OpBackground), 01087 OPTOKEN_BACKGROUND, 01088 OpBackground::GetState, 01089 0, /* help ID */ 01090 0, /* bubble ID */ 01091 0 /* bitmap ID */ 01092 ); 01093 return ok; 01094 } 01095 01096 /*********************************************************************************************** 01097 01098 > static OpState OpBackground::GetState(String_256* Description, OpDescriptor*) 01099 01100 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01101 Created: 26/3/97 01102 Inputs: Description = ptr to place description of why this op can't happen 01103 pOpDesc = ptr to the Op Desc associated with this op 01104 Outputs: - 01105 Returns: An OpState object 01106 Purpose: Func for determining the usability of this op 01107 SeeAlso: - 01108 01109 ***********************************************************************************************/ 01110 01111 OpState OpBackground::GetState(String_256* Description, OpDescriptor*) 01112 { 01113 OpState State; 01114 return State; 01115 } 01116 01117 /*********************************************************************************************** 01118 01119 > static void OpBackground::GetOpName(String_256* OpName) 01120 01121 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01122 Created: 26/3/97 01123 Inputs: OpName = ptr to string 01124 Outputs: OpName contains a description of the op 01125 Returns: - 01126 Purpose: Returns a desc of the op. Mainly used to fill in the menu item for the undo/redo ops. 01127 SeeAlso: - 01128 01129 ***********************************************************************************************/ 01130 01131 void OpBackground::GetOpName(String_256* OpName) 01132 { 01133 *OpName = String_256(_R(IDS_UNDO_SETBACKGROUND)); 01134 } 01135 01136 01137 #endif // EXCLUDE_FROM_RALPH