00001 // $Id: rgnlist.cpp 1328 2006-06-15 19:23:45Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 00100 #include "camtypes.h" 00101 00102 //#include "rgnlist.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00103 #include "osrndrgn.h" 00104 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 #include "camview.h" 00108 #include "paper.h" 00109 //#include "menucmds.h" 00110 #include "camelot.h" 00111 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00113 //#include "ctrlhelp.h" 00114 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 #include "statline.h" 00116 #include "dragmgr.h" 00117 #include "prncamvw.h" 00118 #include "menuops.h" 00119 00120 DECLARE_SOURCE("$Revision: 1328 $"); 00121 00122 00123 /******************************************************************************************** 00124 00125 > class ViewItem : public ListItem 00126 00127 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00128 Created: 07/12/94 00129 Purpose: When optimising redraw for a particular View, we try to join all the 00130 render regions of a View into one if they cover more than 70% of the 00131 resulting union. This class is used to remember which DocViews we have 00132 already tried to optimise as we step through the render region list. 00133 SeeAlso: RenderRegionList; ViewList 00134 00135 ********************************************************************************************/ 00136 00137 class ViewItem : public ListItem 00138 { 00139 CC_DECLARE_MEMDUMP(ViewItem); 00140 00141 public: 00142 ViewItem(View *pNewView) : pView(pNewView) {} 00143 View *pView; 00144 }; 00145 00146 00147 /******************************************************************************************** 00148 00149 > class ViewList : public List 00150 00151 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00152 Created: 07/12/94 00153 Purpose: When optimising redraw for a particular View, we try to join all the 00154 render regions of a DocView into one if they cover more than 70% of the 00155 resulting union. This class is used to remember which Views we have 00156 already tried to optimise as we step through the render region list 00157 SeeAlso: ViewItem; RenderRegionList 00158 00159 ********************************************************************************************/ 00160 00161 class ViewList : public List 00162 { 00163 CC_DECLARE_MEMDUMP(ViewList) 00164 00165 public: 00166 ~ViewList() { DeleteAll(); } 00167 BOOL AddView(View *); 00168 BOOL IsViewOptimised(View*); 00169 }; 00170 00171 00172 00173 00174 00175 CC_IMPLEMENT_MEMDUMP(RenderRegionList, List) 00176 CC_IMPLEMENT_MEMDUMP(ViewItem, ListItem) 00177 CC_IMPLEMENT_MEMDUMP(ViewList, List) 00178 00179 #define new CAM_DEBUG_NEW 00180 00181 00182 /******************************************************************************************** 00183 00184 > BOOL ViewList::AddView(View *pView) 00185 00186 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00187 Created: 07/12/94 00188 Inputs: pView - pointer to the View to add to the list (only this pointer 00189 is stored in the list). 00190 Returns: TRUE if View was added ok; 00191 FALSE if not => ERROR1 00192 Purpose: Add a View to a list to indicate that it has been optimised. 00193 Errors: Out of memory => ERROR1 00194 SeeAlso: ViewList; ViewList::IsViewOptimised 00195 00196 ********************************************************************************************/ 00197 00198 BOOL ViewList::AddView(View *pView) 00199 { 00200 // Try to create the new item 00201 ViewItem *pItem = new ViewItem(pView); 00202 if (pItem == NULL) 00203 // Failed - flag error to caller 00204 return FALSE; 00205 00206 // Ok - add to list and return success 00207 AddTail(pItem); 00208 return TRUE; 00209 } 00210 00211 00212 /******************************************************************************************** 00213 00214 > BOOL ViewList::IsViewOptimised(View *pView) 00215 00216 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00217 Created: 07/12/94 00218 Inputs: pView - the View to test for. 00219 Returns: TRUE if the View has been optimised; 00220 FALSE if not 00221 Purpose: Determine whether the given View is recorded in this list as having 00222 been optimised or not. 00223 SeeAlso: ViewList; ViewList::AddView 00224 00225 ********************************************************************************************/ 00226 00227 BOOL ViewList::IsViewOptimised(View *pView) 00228 { 00229 ViewItem *pItem = (ViewItem *) GetHead(); 00230 while (pItem != NULL) 00231 { 00232 if (pItem->pView == pView) 00233 // It's in the list 00234 return TRUE; 00235 00236 // Try next item 00237 pItem = (ViewItem *) GetNext(pItem); 00238 } 00239 00240 // Not found - inform caller 00241 return FALSE; 00242 } 00243 00244 00245 /******************************************************************************************** 00246 00247 > RenderRegionList::RenderRegionList() 00248 00249 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00250 Created: 9/7/93 00251 Purpose: Initialises the RenderRegionList - in particular, the pointer to the 00252 last render region to be rendered. 00253 00254 ********************************************************************************************/ 00255 00256 RenderRegionList::RenderRegionList() 00257 { 00258 LastRendered = NULL; 00259 ListIsOptimal = FALSE; 00260 } 00261 00262 /******************************************************************************************** 00263 00264 > RenderRegionList::~RenderRegionList() 00265 00266 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00267 Created: 9/7/93 00268 Inputs: - 00269 Outputs: - 00270 Returns: - 00271 Purpose: Destroys all render regions in the list, and then destroys the list. 00272 Errors: - 00273 SeeAlso: - 00274 00275 ********************************************************************************************/ 00276 00277 RenderRegionList::~RenderRegionList() 00278 { 00279 // Call destructors on all objects in the list 00280 00281 RenderRegion *Item = (RenderRegion *) RemoveHead(); 00282 00283 while (Item != NULL) 00284 { 00285 // Delete the list item 00286 delete Item; 00287 00288 // Try the next item 00289 Item = (RenderRegion *) RemoveHead(); 00290 } 00291 } 00292 00293 00294 /******************************************************************************************** 00295 00296 > void RenderRegionList::Merge(RenderRegion *NewRegion) 00297 00298 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00299 Created: 9/7/93 00300 Inputs: NewRegion - the RenderRegion object to add to the list. 00301 Outputs: - 00302 Returns: - 00303 Purpose: Add a render region object to the application's global list of render 00304 regions. 00305 00306 Errors: - 00307 SeeAlso: - 00308 00309 ********************************************************************************************/ 00310 /* 00311 Technical notes: 00312 00313 Merging Algorithm 00314 ----------------- 00315 00316 The New Rect is assumed to be in a Null RenderState (ie. it hasn't rendered yet) 00317 00318 Clip any Rectangles in List to new Client Area (and Chapter) 00319 00320 For each Rectangle in the List, 00321 If the Rect is in the same View as the New Rect, 00322 And it is in the same Chapter as the New Rect, 00323 If the RenderState is at the start of the Tree, 00324 Does the New Rectangle contain the Rect in the List ? 00325 Or, is it Adjacent to the Rect in the List ? 00326 Yes, then Set Rect in List to Union of the two Rects. 00327 Ignoring the RenderState do they Intersect at all ? 00328 Yes, then Split the Rect in the list into sub rects excluding the new 00329 rect. 00330 00331 Add the New Rect to the List. 00332 Attempt to Compact the List. 00333 00334 ********************************************************************************************/ 00335 00336 void RenderRegionList::Merge(RenderRegion *NewRenderRegion) 00337 { 00338 // If it's a printer region, just render it to completion and return, because 00339 // we don't do background printing yet. 00340 if (NewRenderRegion->IsPrinting()) 00341 { 00342 NewRenderRegion->DefaultRender(); 00343 return; 00344 } 00345 00346 // Adjust any render regions that are being scrolled away 00347 ClipRectsToClient(); 00348 00349 // TRACE( _T("RenderRegionList::Merge GetCount == %d\n"), GetCount()); 00350 00351 if (GetCount() == 0) 00352 { 00353 // Couldn't merge with any others, so just add it to the list. 00354 AddTail((ListItem *) NewRenderRegion); 00355 // IMMEDIATE REDRAW 00356 //#if _DEBUG 00357 // ImmediateRender(true); // Added by GAT 00358 //#endif 00359 return; 00360 } 00361 00362 // Find out how big a pixel is 00363 PixelWidth = NewRenderRegion->GetScaledPixelWidth(); 00364 00365 // Attempt to compact the list 00366 MergeRenderRegions(NewRenderRegion); 00367 00368 // Make sure that there are no render regions that overlap - ever! 00369 RemoveRegionOverlap(NewRenderRegion); 00370 00371 // add the New RenderRegion on the end of the List 00372 AddTail((ListItem *) NewRenderRegion); 00373 00374 // Go though all the regions in the list and try to strictly 00375 // merge them with all the other in the list 00376 TidyUpAdjacentRegions(NewRenderRegion); 00377 00378 // Set flag to indicate that one or more new regions have been added, and so we 00379 // should check for the possibility of merging all regions the next time we try a 00380 // background render. 00381 ListIsOptimal = FALSE; 00382 // IMMEDIATE REDRAW 00383 // ImmediateRender(); 00384 } 00385 00386 00387 00388 /******************************************************************************************** 00389 00390 > void RenderRegionList::TidyUpAdjacentRegions(RenderRegion* pBrandNewRegion) 00391 00392 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00393 Created: 29/3/94 00394 Inputs: pBrandNewRegion - The region that has just been added to the list by OnDraw. 00395 We should not delete this region during the Tidy up or OnDraw gets upset 00396 Purpose: Goes through all the regions in the list and tests to see if any of them line 00397 up exactly. If they do, they are joined into a single region 00398 00399 ********************************************************************************************/ 00400 00401 void RenderRegionList::TidyUpAdjacentRegions(RenderRegion* pBrandNewRegion) 00402 { 00403 // Need to perform an Nsquared loop through the regions 00404 RenderRegion* pRegion = (RenderRegion*) GetHead(); 00405 00406 while(pRegion!=NULL) 00407 { 00408 // Get info about the region that we will need to test 00409 DocRect MergeClipRect = pRegion->GetRegionRect(); 00410 View* MergeView = pRegion->GetRenderView(); 00411 Node* NewContext = pRegion->GetRenderState(); 00412 00413 // Find the region after pRegion to start searching from 00414 RenderRegion* pCompare = (RenderRegion*) GetNext(pRegion); 00415 00416 // loop through all the regions that come after pRegion 00417 // see if any are suitbale for merging 00418 while(pCompare!=NULL) 00419 { 00420 // Find the next one now, as we may delete pCompare on the way through 00421 RenderRegion* pNextOne = (RenderRegion*) GetNext(pCompare); 00422 00423 // We do not want to delete the brand new region, we should delete the others first 00424 if (pCompare!=pBrandNewRegion) 00425 { 00426 // Find the equivalent information in this region ready for testing 00427 View* OldView = pCompare->GetRenderView(); 00428 Node* OldContext = pCompare->GetRenderState(); 00429 00430 // See if they can be merged 00431 if ( (MergeView == OldView) && 00432 (pRegion->GetRenderSpread()==pCompare->GetRenderSpread()) && 00433 ((OldContext==NewContext) || 00434 ((pRegion->CanBeMerged()) && (pCompare->CanBeMerged())))) 00435 { 00436 // So far so good. Just check that they are adjacent 00437 // Find this regions clip rect 00438 DocRect OldClipRect = pCompare->GetRegionRect(); 00439 00440 // see if one of the render regions is EXACTLY adjacent to this one 00441 if (OldClipRect.IsAdjacent(MergeClipRect, 0)) 00442 { 00443 DocRect ClipRect = OldClipRect.Union(MergeClipRect); 00444 00445 // Set the clip rect of one of the regions to be the union of both regions 00446 // pRegion->SetClipRect(ClipRect, TRUE); 00447 pRegion->SetBackmostChangedNode(pCompare->GetBackmostChangedNode()); 00448 pRegion->ResetRegion(ClipRect); 00449 00450 // Get rid of the other region 00451 Remove(pCompare); 00452 delete pCompare; 00453 } 00454 } 00455 } 00456 00457 // Get the next region 00458 pCompare = pNextOne; 00459 } 00460 00461 // Get the next region in the outer loop 00462 pRegion = (RenderRegion*) GetNext(pRegion); 00463 } 00464 } 00465 00466 00467 00468 00469 /******************************************************************************************** 00470 00471 > void RenderRegionList::StrictMerge(RenderRegion* pRegionToMerge) 00472 00473 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00474 Created: 12/01/94 00475 Inputs: pRegionToMerge - The region that we are planning to add to the list 00476 Purpose: Tries to merge the render region supplied with the rest of the list. 00477 They must be exactly adjacent ie. They don't intersect, and the union 00478 contains no area outside the two rectangles. 00479 00480 00481 ********************************************************************************************/ 00482 00483 void RenderRegionList::StrictMerge(RenderRegion* pRegionToMerge) 00484 { 00485 // set a flag to indicate if none of the render regions could be merged 00486 BOOL Merged; 00487 00488 // loop round until we can find no more render regions to merge together 00489 do 00490 { 00491 // We have not merged anything yet, so set the flag 00492 Merged = FALSE; 00493 00494 // Find the render region to merges clipping rectangle and context node and 00495 // find which view the render region is to be rendering to 00496 DocRect MergeClipRect = pRegionToMerge->GetRegionRect(); 00497 View* MergeView = pRegionToMerge->GetRenderView(); 00498 Node* NewContext = pRegionToMerge->GetRenderState(); 00499 00500 // Get the first render region in the list 00501 RenderRegion* pOldRegion = (RenderRegion*) GetHead(); 00502 RenderRegion* pNextRegion; 00503 00504 while (pOldRegion != NULL) 00505 { 00506 pNextRegion = (RenderRegion *) GetNext(pOldRegion); 00507 00508 // Find this old render regions view 00509 View* OldView = pOldRegion->GetRenderView(); 00510 Node* OldContext = pOldRegion->GetRenderState(); 00511 00512 // see if the two render regions can be merged 00513 if ( (MergeView == OldView) && 00514 (pOldRegion->GetRenderSpread()==pRegionToMerge->GetRenderSpread()) && 00515 ((OldContext==NewContext) || 00516 ((pOldRegion->CanBeMerged()) && (pRegionToMerge->CanBeMerged())))) 00517 { 00518 // Find this regions clip rect 00519 DocRect OldClipRect = pOldRegion->GetRegionRect(); 00520 00521 // see if one of the render regions is EXACTLY adjacent to this one 00522 if (OldClipRect.IsAdjacent(MergeClipRect, 0)) 00523 { 00524 DocRect ClipRect = OldClipRect.Union(MergeClipRect); 00525 00526 // Set the clip rect and get the render region to find its starting context node again 00527 // as things could have changed. 00528 // pRegionToMerge->SetClipRect(ClipRect, TRUE); 00529 pRegionToMerge->ResetRegion(ClipRect); 00530 Remove(pOldRegion); 00531 delete pOldRegion; 00532 Merged = TRUE; 00533 break; 00534 } 00535 } 00536 00537 // Get the next render region in the list 00538 // pOldRegion = (RenderRegion *) GetNext(pOldRegion); 00539 pOldRegion = pNextRegion; 00540 } 00541 } while( Merged ); 00542 00543 AddTail( (ListItem *) pRegionToMerge); 00544 } 00545 00546 00547 00548 /******************************************************************************************** 00549 00550 > void RenderRegionList::MergeRenderRegions() 00551 00552 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00553 Created: 12/7/93 00554 Inputs: - 00555 Outputs: - 00556 Returns: - 00557 Purpose: Attempts to find regions which can be merged together to make redrawing 00558 more efficient. At the moment, the two regions to be merged must satisfy 00559 the following conditions: 00560 00561 * They must be have got to the same node in the tree when they last stopped 00562 rendering. 00563 00564 * They must be rendering into the same View and Chapter. 00565 00566 * One of the regions must completely enclose or be adjacent to the other. 00567 00568 Errors: - 00569 SeeAlso: - 00570 00571 ********************************************************************************************/ 00572 00573 void RenderRegionList::MergeRenderRegions(RenderRegion* pRegionToMerge) 00574 { 00575 // set a flag to indicate if none of the render regions could be merged 00576 BOOL Merged; 00577 00578 // loop round until we can find no more render regions to merge together 00579 do 00580 { 00581 // We have not merged anything yet, so set the flag 00582 Merged = FALSE; 00583 00584 // Find the render region to merges clipping rectangle and context node 00585 DocRect MergeClipRect = pRegionToMerge->GetRegionRect(); 00586 00587 // Find which view the render region is to be rendering to 00588 View* MergeView = pRegionToMerge->GetRenderView(); 00589 00590 // Get the first render region in the list 00591 RenderRegion* pOldRegion = (RenderRegion*) GetHead(); 00592 RenderRegion* pNextRegion; 00593 00594 while (pOldRegion != NULL) 00595 { 00596 pNextRegion = (RenderRegion *) GetNext(pOldRegion); 00597 00598 if (pOldRegion != pRegionToMerge) 00599 { 00600 // Find this old render regions view 00601 View* OldView = pOldRegion->GetRenderView(); 00602 00603 // see if the two render regions can be merged 00604 if ( (MergeView == OldView) && 00605 (pOldRegion->GetRenderSpread()==pRegionToMerge->GetRenderSpread()) && 00606 (pOldRegion->CanBeMerged()) && (pRegionToMerge->CanBeMerged())) 00607 { 00608 // Find this regions clip rect 00609 DocRect OldClipRect = pOldRegion->GetRegionRect(); 00610 00611 // see if one of the render regions contains the other 00612 if (MergeClipRect.ContainsRect(OldClipRect)) 00613 { 00614 // Get rid of the region that is inside the other 00615 pRegionToMerge->SetBackmostChangedNode(pOldRegion->GetBackmostChangedNode()); 00616 pRegionToMerge->NeedsOSPaper = pRegionToMerge->NeedsOSPaper && pOldRegion->NeedsOSPaper; 00617 Remove(pOldRegion); 00618 delete pOldRegion; 00619 Merged = TRUE; 00620 break; 00621 } 00622 else if (OldClipRect.ContainsRect(MergeClipRect)) 00623 { 00624 // Get rid of the region that is inside the other 00625 // pRegionToMerge->SetClipRect(OldClipRect, TRUE); 00626 pRegionToMerge->SetBackmostChangedNode(pOldRegion->GetBackmostChangedNode()); 00627 pRegionToMerge->ResetRegion(OldClipRect); 00628 pRegionToMerge->NeedsOSPaper = pRegionToMerge->NeedsOSPaper && pOldRegion->NeedsOSPaper; 00629 Remove(pOldRegion); 00630 delete pOldRegion; 00631 Merged = TRUE; 00632 break; 00633 } 00634 else 00635 { 00636 // Find the smallest dimension of the new region 00637 INT32 ShortSide = MergeClipRect.Height(); 00638 if (MergeClipRect.Width() < ShortSide) 00639 ShortSide = MergeClipRect.Width(); 00640 00641 // Make sure that this figure is smaller than the sides 00642 ShortSide /= 3; 00643 00644 // Want a fuzzyness of at least 64 pixels 00645 INT32 MinFuzzy = PixelWidth * 64; 00646 if (ShortSide<MinFuzzy) 00647 ShortSide = MinFuzzy; 00648 00649 // If there is an overlap, then do some merging 00650 if (OldClipRect.IsAdjacent(MergeClipRect, ShortSide)) 00651 { 00652 DocRect ClipRect = OldClipRect.Union(MergeClipRect); 00653 // pRegionToMerge->SetClipRect(ClipRect, TRUE); 00654 pRegionToMerge->SetBackmostChangedNode(pOldRegion->GetBackmostChangedNode()); 00655 pRegionToMerge->ResetRegion(ClipRect); 00656 pRegionToMerge->NeedsOSPaper = pRegionToMerge->NeedsOSPaper && pOldRegion->NeedsOSPaper; 00657 Remove(pOldRegion); 00658 delete pOldRegion; 00659 Merged = TRUE; 00660 break; 00661 } 00662 } 00663 } 00664 } 00665 00666 // Get the next render region in the list 00667 // pOldRegion = (RenderRegion *) GetNext(pOldRegion); 00668 pOldRegion = pNextRegion; 00669 } 00670 } while( Merged ); 00671 } 00672 00673 00674 00675 00676 /******************************************************************************************** 00677 00678 > void RenderRegionList::RemoveRegionOverlap(RenderRegion* NewRenderRegion) 00679 00680 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00681 Created: 10/01/94 00682 Inputs: NewRenderRegion - pointer to the render region being added 00683 Purpose: Called when adding a new render region to the list. It checks the new 00684 render region for overlap with all the old render regions and if it 00685 overlapps any of them, the old region is slit up. This function should 00686 guarantee that you never get render regions that overlap, so that the 00687 EORed stuff does not get screwed up by getting rendered more than once. 00688 00689 ********************************************************************************************/ 00690 00691 void RenderRegionList::RemoveRegionOverlap(RenderRegion* NewRenderRegion) 00692 { 00693 // Find the clipping rect of the new render region 00694 DocRect NewClipRect = NewRenderRegion->GetRegionRect(); 00695 DocRect OldClipRect; 00696 00697 // Find which view and spread the render region is to be rendering to 00698 View* NewView = NewRenderRegion->GetRenderView(); 00699 Spread* NewSpread = NewRenderRegion->GetRenderSpread(); 00700 00701 // Get the first render region in the list 00702 RenderRegion* pOldRegion = (RenderRegion*) GetHead(); 00703 00704 while (pOldRegion != NULL) 00705 { 00706 // Get the old render regions clipping rectangle 00707 OldClipRect = pOldRegion->GetRegionRect(); 00708 00709 // Find which view and spread the render region is to be rendering to 00710 View* OldView = pOldRegion->GetRenderView(); 00711 Spread* OldSpread = pOldRegion->GetRenderSpread(); 00712 00713 // If they intersect, split the old rectangle up into bits 00714 if ((OldView==NewView) && (OldSpread==NewSpread) && 00715 (OldClipRect.IsIntersectedWith(NewClipRect))) 00716 { 00717 if (NewClipRect.ContainsRect(OldClipRect)) 00718 { 00719 // The 2 regions were the same, so get rid of it, and go back around 00720 // the loop with the next region in the list. 00721 NewRenderRegion->SetBackmostChangedNode(pOldRegion->GetBackmostChangedNode()); 00722 NewRenderRegion->NeedsOSPaper = NewRenderRegion->NeedsOSPaper && pOldRegion->NeedsOSPaper; 00723 RenderRegion *Tmp = pOldRegion; 00724 pOldRegion = (RenderRegion *) GetNext(pOldRegion); 00725 Remove(Tmp); 00726 delete Tmp; 00727 continue; 00728 } 00729 else 00730 { 00731 // Split the old rect into sub-rects and add the new one 00732 DocRect SubRects[4]; 00733 INT32 RectCount = OldClipRect.SplitRect(NewClipRect, SubRects); 00734 ENSURE( RectCount!=0, "No rectangles found in SplitRect" ); 00735 00736 // Change the clip rect of the region already in the list 00737 // pOldRegion->ResizeRegion(SubRects[0]); 00738 // pOldRegion->SetClipRect(SubRects[0]); 00739 pOldRegion->ResetRegion(SubRects[0]); 00740 00741 // and create some new render regions if needed 00742 for (INT32 i=1; i<RectCount; i++) 00743 { 00744 // Create a new render region. 00745 // NB. important to pass in View pointer so that we get correct bitmap depth. 00746 RenderRegion* SubRenderRegion = OSRenderRegion::Create(SubRects[i], 00747 pOldRegion->GetMatrix(), 00748 OldView->GetViewScale(), 00749 RENDERTYPE_SCREEN, 00750 NewView); 00751 00752 //OSRenderRegion* SubRenderRegion = new OSRenderRegion(*(OSRenderRegion*)pOldRegion); 00753 00754 ENSURE( SubRenderRegion != NULL, "RenderRegionList::Merge: SubRenderRegion == 0"); 00755 if (SubRenderRegion == NULL) 00756 return; 00757 00758 // Set the new clip region and see if it joins exactly 00759 if (!SubRenderRegion->CopyRenderInfo(*pOldRegion)) 00760 { 00761 // copying failed, so tidy up 00762 delete SubRenderRegion; 00763 TRACE( _T("CopyRenderInfo %d failed\n"), i); 00764 continue; // carry on round loop 00765 } 00766 00767 // make sure the region is re-rendered 00768 // SubRenderRegion->IsPaperRendered = FALSE; 00769 // SubRenderRegion->IsInkRenderStarted = FALSE; 00770 00771 // SubRenderRegion->SetClipRect(SubRects[i]); 00772 SubRenderRegion->ResetRegion(SubRects[i]); 00773 // SubRenderRegion->ResizeRegion(SubRects[i]); 00774 StrictMerge(SubRenderRegion); 00775 } 00776 } 00777 } 00778 00779 // Get the next region in the list 00780 pOldRegion = (RenderRegion*) GetNext(pOldRegion); 00781 } 00782 } 00783 00784 00785 00786 00787 /******************************************************************************************** 00788 00789 > void RenderRegionList::ClipRectsToClient() 00790 00791 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00792 Created: 21/7/93 00793 Inputs: - 00794 Outputs: - 00795 Returns: - 00796 Purpose: Clips the RenderRegions in the list to the client area, incase it has been 00797 scrolled. 00798 Errors: - 00799 Scope: Private. 00800 SeeAlso: - 00801 00802 ********************************************************************************************/ 00803 00804 void RenderRegionList::ClipRectsToClient() 00805 { 00806 RenderRegion *pRegion = (RenderRegion*) GetHead(); 00807 while (pRegion != NULL) 00808 { 00809 // Find the view associated with the window and skip if null. 00810 View* pView = pRegion->GetRenderView(); 00811 if (pView != NULL && DocView::GetCurrent() == pView) 00812 { 00813 // Get the views rectangle, and convert it into spread coords 00814 DocRect ClientRect = pView->GetDocViewRect(pRegion->GetRenderSpread()); 00815 pRegion->GetRenderSpread()->DocCoordToSpreadCoord(&ClientRect); 00816 00817 // Get the clipping rectangle of this render region 00818 DocRect ClipRect = pRegion->GetRegionRect(); 00819 00820 // see if we need to lose any parts of the render region 00821 if (!ClientRect.ContainsRect(ClipRect)) 00822 { 00823 if (ClipRect.IsIntersectedWith(ClientRect)) 00824 { 00825 ClipRect = ClipRect.Intersection(ClientRect); 00826 pRegion->ResizeRegion(ClipRect); 00827 // pRegion->SetClipRect(ClipRect); 00828 // pRegion->ResetRegion(ClipRect); 00829 } 00830 else 00831 { 00832 // This render region is now off screen, so we can throw it away 00833 RenderRegion* pPrev = (RenderRegion *) GetPrev(pRegion); 00834 Remove(pRegion); 00835 delete pRegion; 00836 pRegion = pPrev; 00837 } 00838 } 00839 } 00840 00841 // Try the next item. 00842 pRegion = (RenderRegion*) ((pRegion != NULL) ? GetNext(pRegion) : GetHead()); 00843 } 00844 } 00845 00846 /******************************************************************************************** 00847 00848 > void RenderRegionList::Remove(RenderRegion *RegionToRemove) 00849 00850 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00851 Created: 9/7/93 00852 Inputs: RegionToRemove - the render region object to remove from the list. 00853 Outputs: - 00854 Returns: - 00855 Purpose: Removes a render region from the application's list of render regions, 00856 It DOES NOT delete the RenderRegion object itself. 00857 This is used when the region has been completely rendered and is 00858 no longer needed. 00859 Errors: - 00860 SeeAlso: - 00861 00862 ********************************************************************************************/ 00863 00864 void RenderRegionList::Remove(RenderRegion *RegionToRemove) 00865 { 00866 ENSURE( FindPosition(RegionToRemove) != NOT_IN_LIST, 00867 "Could not find RenderRegion to Remove" ); 00868 00869 // Is it the LastRendered one? 00870 if (RegionToRemove == LastRendered) 00871 { 00872 // Yes - so make LastRendered point to the previous render region 00873 // which means if Item is first in the list, LastRendered is set to 00874 // NULL, which is what we want - see BackgroundRender(). 00875 LastRendered = (RenderRegion *) GetPrev(RegionToRemove); 00876 } 00877 00878 // Remove the item from the list 00879 RemoveItem((ListItem *) RegionToRemove); 00880 00881 } 00882 00883 /******************************************************************************************** 00884 00885 > void RenderRegionList::Remove(Document *pParentDoc) 00886 00887 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00888 Created: 9/7/93 00889 Inputs: pParentDoc - the parent document that is being removed. 00890 Purpose: Removes all render regions from the application's list of render regions 00891 that are associated with a particular document. 00892 Usually called because the document is being closed (deleted). 00893 It deletes all RenderRegion objects it removes. 00894 00895 HOWEVER: 00896 When a Document is being closed, all of its DocViews should already have 00897 been closed, so there should be NO render regions still in the list that 00898 are associated with this document, so this function will ENSURE whenever 00899 it finds a render region belonging to this document. 00900 NB. This is a debugging aid, and hence it only exists in debug builds. 00901 00902 00903 ********************************************************************************************/ 00904 00905 #if _DEBUG 00906 00907 void RenderRegionList::Remove(Document *pParentDoc) 00908 { 00909 #if 0 00910 // Find the NodeDocument object of the tree associated with this document 00911 Node *pRoot = pParentDoc->GetFirstNode(); 00912 ENSURE(pRoot != NULL, "Document has no root node"); 00913 pRoot = pRoot->FindNext(); 00914 ENSURE(pRoot != NULL, "Document has no NodeDocument node"); 00915 00916 // Start at the beginning 00917 RenderRegion *Item = (RenderRegion *) GetHead(); 00918 00919 // Look for this render region 00920 while (Item != NULL) 00921 { 00922 // Find its parent NodeDocument object 00923 Node *pNode = Item->GetRenderChapter(); 00924 ENSURE(pNode != NULL, "RenderRegion has no Chapter!"); 00925 Node *pParent = pNode->FindParent(); 00926 ENSURE(pParent != NULL, "Chapter has no parent!"); 00927 00928 // Find ultimate parent 00929 while (pParent != NULL) 00930 { 00931 pNode = pParent; 00932 pParent = pNode->FindParent(); 00933 } 00934 00935 // Is it the same as the document passed by the caller? 00936 if (pNode == pRoot) 00937 { 00938 // Is it the LastRendered one? 00939 if (Item == LastRendered) 00940 { 00941 // Yes - so make LastRendered point to the previous render region 00942 // which means if Item is first in the list, LastRendered is set to 00943 // NULL, which is what we want - see BackgroundRender(). 00944 LastRendered = (RenderRegion *) GetPrev(Item); 00945 } 00946 00947 // Move to next region and remove this one from the list and delete it. 00948 RenderRegion *Tmp = Item; 00949 Item = (RenderRegion *) GetNext(Item); 00950 RemoveItem((ListItem *) Tmp); 00951 delete Tmp; 00952 00953 // Bitch about the fact that this should not have happened 00954 ENSURE(FALSE, "Found a render region that should have been deleted"); 00955 } 00956 else 00957 // Try the next region 00958 Item = (RenderRegion *) GetNext(Item); 00959 } 00960 #endif 00961 } 00962 00963 #endif 00964 00965 /******************************************************************************************** 00966 00967 > void RenderRegionList::Remove(View *pView) 00968 00969 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00970 Created: 9/7/93 00971 Inputs: pView - the parent view that is being removed. 00972 Purpose: Removes all render regions from the application's list of render regions 00973 that are associated with a particular view. 00974 Usually called because the docview is being closed (deleted). 00975 It deletes all RenderRegion objects it removes. 00976 00977 ********************************************************************************************/ 00978 00979 void RenderRegionList::Remove(View *pView) 00980 { 00981 // Start at the beginning and try to find render regions attached to this CWnd object. 00982 RenderRegion *Item = (RenderRegion *) GetHead(); 00983 00984 while (Item != NULL) 00985 { 00986 // Is it the same as the View passed by the caller? 00987 if (Item->GetRenderView() == pView) 00988 { 00989 // Is it the LastRendered one? 00990 if (Item == LastRendered) 00991 { 00992 // Yes - so make LastRendered point to the previous render region 00993 // which means if Item is first in the list, LastRendered is set to 00994 // NULL, which is what we want - see BackgroundRender(). 00995 LastRendered = (RenderRegion *) GetPrev(Item); 00996 } 00997 00998 // Move to next region and remove this one from the list and delete it. 00999 RenderRegion *Tmp = Item; 01000 Item = (RenderRegion *) GetNext(Item); 01001 RemoveItem((ListItem *) Tmp); 01002 delete Tmp; 01003 } 01004 else 01005 // Try the next region 01006 Item = (RenderRegion *) GetNext(Item); 01007 } 01008 } 01009 01010 /******************************************************************************************** 01011 01012 > BOOL RenderRegionList::BackgroundRender() 01013 01014 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01015 Created: 9/7/93 01016 Inputs: - 01017 Outputs: - 01018 Returns: TRUE if rendering was done, FALSE if no render regions to render. 01019 Purpose: Cycles through the members of the render region list, rendering each 01020 one in turn. Only one render region is rendered on each call to 01021 BackgroundRender(). 01022 Errors: - 01023 SeeAlso: - 01024 01025 ********************************************************************************************/ 01026 01027 BOOL RenderRegionList::BackgroundRender() 01028 { 01029 if ( CCamApp::IsDisabled() ) 01030 { 01031 // TRACE( wxT("BGR - IsDisabled\n") ); 01032 return FALSE; // If he has got the system disabled, ignore 01033 } 01034 01035 // print monitor not present on viewer 01036 01037 // Make sure printing is ok. 01038 if (!PrintMonitor::IsPrintStatusOK()) 01039 { 01040 // No - a print job has gone wrong, so we delete all printing render regions 01041 // before continuing. 01042 RenderRegion *pRender = (RenderRegion *) GetHead(); 01043 while (pRender != NULL) 01044 { 01045 if (pRender->IsPrinting()) 01046 { 01047 // Render region is printing (well it's not really as an exception 01048 // has occured) so delete it. 01049 Remove(pRender); 01050 delete pRender; 01051 } 01052 01053 // Try next region 01054 pRender = (RenderRegion *) GetNext(pRender); 01055 } 01056 01057 // Reset the last rendered render region 01058 LastRendered = NULL; 01059 } 01060 01061 if (GetCount() == 0) 01062 { 01063 // TRACE( wxT("BGR - No regions\n") ); 01064 return FALSE; 01065 } 01066 01067 //GAT 01068 // if (ControlHelper::IsUserInterfaceCaptured()) 01069 // return FALSE; // No bg rendering if UI is captured (e.g. menu is up) 01070 // 01071 // if (DragManagerOp::IsDragActive()) 01072 // return FALSE; // No bg rendering if a DragManager op is active (NB this is for 01073 // colour/bitmap/bar drags only - not doc operation drags). 01074 if (ViewOps::IsFullScreenPending()) // no bg rendering if we are about to enter full screen mode 01075 { 01076 // TRACE( wxT("BGR - About to full screen\n") ); 01077 return FALSE; 01078 } 01079 01080 // Optimise list based on render region percentage coverage 01081 TryTotalUnion(); 01082 01083 // Work out which render region to render 01084 if (LastRendered != NULL) 01085 LastRendered = (RenderRegion*) GetNext(LastRendered); 01086 01087 if (LastRendered == NULL) 01088 LastRendered = (RenderRegion*) GetHead(); 01089 01090 if (LastRendered == NULL) 01091 { 01092 // TRACE( wxT("BGR - No last region\n") ); 01093 return FALSE; // No regions to render 01094 } 01095 01096 // Ignore the RenderRegion if we are Printing, because 01097 // we have probably been called from the Print AbortProc 01098 // and are already rendering. 01099 if (LastRendered->IsPrinting()) 01100 { 01101 // TRACE( wxT("BGR - Is printing\n") ); 01102 return FALSE; 01103 } 01104 01105 // TRACEUSER("Gerry", _T("BackgroundRender\n")); 01106 // Show the user we are rendering. 01107 if (GetApplication()->GetpStatusLine()) 01108 GetApplication()->GetpStatusLine()->SetRenderIndicator(Animate); 01109 GetApplication()->BgRendering = TRUE; 01110 01111 // Do the render. 01112 Error::RenderThreadIn(); // Make errors close window 01113 LastRendered->DefaultRender(); 01114 Error::RenderThreadOut(); // Normal errors 01115 01116 // Turn off render indicator if needed. 01117 if (GetCount() ==0) 01118 { 01119 if (GetApplication()->GetpStatusLine()) 01120 GetApplication()->GetpStatusLine()->SetRenderIndicator(NotRendering); 01121 GetApplication()->BgRendering = FALSE; 01122 } 01123 01124 // We did some rendering so return TRUE 01125 return TRUE; 01126 } 01127 01128 01129 /******************************************************************************************** 01130 01131 > void RenderRegionList::ImmediateRender(BOOL bForceImmediate = FALSE) 01132 01133 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 01134 Created: 05/01/94 01135 Purpose: Finds all render regions associated with DocViews that have background 01136 rendering disabled, and renders them all immediately (i.e. to completion). 01137 01138 ********************************************************************************************/ 01139 01140 void RenderRegionList::ImmediateRender(BOOL bForceImmediate) 01141 { 01142 TRACE( wxT("Warning - RenderRegionList::ImmediateRender - removed code\n") ); 01143 // TRACE( _T("Look, I'm in RenderRegionList::ImmediateRender()\n")); 01144 01145 if ( CCamApp::IsDisabled() ) 01146 return; // If he has got the system disabled, ignore 01147 01148 #ifndef STANDALONE 01149 // Make sure printing is ok. 01150 if (!PrintMonitor::IsPrintStatusOK()) 01151 { 01152 // No - a print job has gone wrong, so we delete all printing render regions 01153 // before continuing. 01154 RenderRegion *pRender = (RenderRegion *) GetHead(); 01155 while (pRender != NULL) 01156 { 01157 if (pRender->IsPrinting()) 01158 { 01159 // Render region is printing (well it's not really as an exception 01160 // has occured) so delete it. 01161 Remove(pRender); 01162 delete pRender; 01163 } 01164 01165 // Try next region 01166 pRender = (RenderRegion *) GetNext(pRender); 01167 } 01168 01169 // Reset the last rendered render region 01170 LastRendered = NULL; 01171 } 01172 #endif 01173 if (GetCount() == 0) 01174 return; 01175 01176 PORTNOTE("other", "Disabled ControlHelper") 01177 #ifndef EXCLUDE_FROM_XARALX 01178 if (ControlHelper::IsUserInterfaceCaptured()) 01179 return; // No bg rendering if UI is captured (e.g. menu is up) 01180 #endif 01181 if (DragManagerOp::IsDragActive()) 01182 return; // No bg rendering if a DragManager op is active (NB this is for 01183 // colour/bitmap/bar drags only - not doc operation drags) 01184 01185 if(ViewOps::IsFullScreenPending()) // no bg rendering if we are about to enter full screen mode 01186 return; 01187 01188 // Optimise list based on render region percentage coverage 01189 TryTotalUnion(); 01190 RenderRegion *pRegion = (RenderRegion *) GetHead(); 01191 01192 // Start the rendering indicator going. 01193 if (GetApplication()->GetpStatusLine()) 01194 GetApplication()->GetpStatusLine()->SetRenderIndicator(Rendering); 01195 01196 while (pRegion != NULL) 01197 { 01198 // Find the next region before this one is deleted 01199 RenderRegion* pNext = (RenderRegion *) GetNext(pRegion); 01200 01201 if (pRegion->IsPrinting() == FALSE) 01202 { 01203 // If this render region's DocView does not have background rendering enabled, 01204 // then it must be an immediate render region, so render it. 01205 View *pView = pRegion->GetRenderView(); 01206 ENSURE(pView != NULL, "No DocView in ImmediateRender!"); 01207 01208 if ( !pView->GetForeBackMode() || bForceImmediate ) 01209 { 01210 // Keep user up to date 01211 if (GetApplication()->GetpStatusLine()) 01212 GetApplication()->GetpStatusLine()->SetRenderIndicator(Animate); 01213 //TRACE( _T("Immediate Render now\n")); 01214 01215 // Render it. 01216 Error::RenderThreadIn(); // Make errors close window 01217 pRegion->DefaultRender(bForceImmediate); 01218 Error::RenderThreadOut(); // Normal errors 01219 } 01220 } 01221 01222 // Find the next render region 01223 pRegion = pNext; 01224 } 01225 01226 // Disable rendering indicator. 01227 01228 if (GetApplication()->GetpStatusLine()) 01229 GetApplication()->GetpStatusLine()->SetRenderIndicator(NotRendering); 01230 } 01231 01232 01233 01234 /******************************************************************************************** 01235 01236 > void RenderRegionList::HandleNodeDeletion(Node* pNode) 01237 01238 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01239 Created: 10/08/2004 01240 Purpose: Tells RenderRegions that they should be afraid, very afraid, if they are 01241 holding a pointer to this node... 01242 01243 ********************************************************************************************/ 01244 01245 void RenderRegionList::HandleNodeDeletion(Node* pNode) 01246 { 01247 if (GetCount() == 0) 01248 return; 01249 01250 RenderRegion *pRegion = (RenderRegion *) GetHead(); 01251 01252 while (pRegion != NULL) 01253 { 01254 // Find the next region before this one is deleted 01255 RenderRegion* pNext = (RenderRegion *) GetNext(pRegion); 01256 01257 // TODO: Could attack the context pointer here as well! 01258 01259 // Make sure we're not holding onto a pointer to this node as the "backmost" 01260 pRegion->ClearBackmostChangedNode(pNode); 01261 // And hope that this region is about to get merged out of existence!!! 01262 01263 // Find the next render region 01264 pRegion = pNext; 01265 } 01266 01267 } 01268 01269 01270 01271 /******************************************************************************************** 01272 01273 > void RenderRegionList::TryTotalUnion() 01274 01275 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01276 Created: 07/12/94 01277 Purpose: For each DocView, try to union all the render regions, and see if the 01278 individual areas add up to more than 70% of the union area. If they do 01279 then we union all the regions together and just render one big one. 01280 SeeAlso: RenderRegionList::DoTotalUnion 01281 01282 ********************************************************************************************/ 01283 01284 void RenderRegionList::TryTotalUnion() 01285 { 01286 if (ListIsOptimal) 01287 // No need to do our checks 01288 return; 01289 01290 DocRect TotalUnion; 01291 01292 // List of DocViews we have optimised so far 01293 ViewList Views; 01294 01295 // Go through each render region, and for each View, work out if it's worth 01296 // merging all the rectangles into one. 01297 RenderRegion *pRegion = (RenderRegion *) GetHead(); 01298 01299 while (pRegion != NULL) 01300 { 01301 View *pView = pRegion->GetRenderView(); 01302 Spread* pSpread = pRegion->GetRenderSpread(); 01303 01304 // Have we optimised this region's View already? 01305 if (!Views.IsViewOptimised(pView)) 01306 { 01307 // Haven't done this one yet - add it to the list for future reference 01308 if (!Views.AddView(pView)) 01309 { 01310 // Error - abort merging 01311 Views.DeleteAll(); 01312 return; 01313 } 01314 01315 // We only do this merging for regions that have not started ink rendering yet. 01316 if (pRegion->CanBeMerged()) 01317 { 01318 // Get the union of all regions in this View, and the total area of them 01319 RenderRegion *pRegion2 = pRegion; 01320 01321 // Indicates whether to test the percentage coverage - we don't if either: 01322 // (a) This View has only one region, or 01323 // (b) This View has regions which have started drawing ink already. 01324 BOOL TryUnion = FALSE; 01325 01326 DocRect TotalUnion; 01327 double CombinedArea = 0.0; 01328 01329 while (pRegion2 != NULL) 01330 { 01331 // Is this the correct View and render context? 01332 if (pRegion2->GetRenderView() == pView && 01333 pRegion2->GetRenderSpread() == pSpread 01334 ) 01335 { 01336 // More than one region - we can try to union them 01337 TryUnion = TRUE; 01338 01339 // Have we started rendering the ink into this region yet? 01340 if (!pRegion2->CanBeMerged()) 01341 { 01342 // Yes, and we can't union if any have started rendering ink 01343 TryUnion = FALSE; 01344 01345 // Quit the while loop 01346 break; 01347 } 01348 else 01349 { 01350 // No - so accumulate this region. 01351 DocRect ClipRect = pRegion2->GetRegionRect(); 01352 TotalUnion = TotalUnion.Union(ClipRect); 01353 CombinedArea += ((double) ClipRect.Width()) * ((double) ClipRect.Height()); 01354 } 01355 } 01356 01357 // Find the next render region 01358 pRegion2 = (RenderRegion *) GetNext(pRegion2); 01359 } 01360 01361 if (TryUnion) 01362 { 01363 // Ok - if the combined area is 70% or more of the area of the union, then 01364 // we might as well union all these regions. 01365 double UnionArea = (double) TotalUnion.Width() * (double) TotalUnion.Height(); 01366 double Coverage = CombinedArea / UnionArea; 01367 01368 if (Coverage > 0.60) 01369 { 01370 // Yes - let's union all these regions 01371 DoTotalUnion(pRegion, pView, TotalUnion); 01372 } 01373 } 01374 } 01375 } 01376 01377 // Find the next render region 01378 pRegion = (RenderRegion *) GetNext(pRegion); 01379 } 01380 01381 // Don't bother with this again unless a new render region is added. 01382 ListIsOptimal = TRUE; 01383 } 01384 01385 01386 /******************************************************************************************** 01387 01388 > void RenderRegionList::DoTotalUnion(RenderRegion *pRegion, View *pView, 01389 DocRect TotalUnion) 01390 01391 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01392 Created: 07/12/94 01393 Inputs: pRegion - the region to put the merged area into. 01394 pView - the View that should have all its regions merged. 01395 TotalUnion - the union of all the regions for this DocView. 01396 Purpose: For the specified DocView, find all the regions that are attached to 01397 it, and union them all together and use the region 'pRegion' to hold 01398 this new region. All the other regions of this DocView are removed from 01399 the list and deleted. 01400 SeeAlso: RenderRegionList::TryTotalUnion 01401 01402 ********************************************************************************************/ 01403 01404 void RenderRegionList::DoTotalUnion(RenderRegion *pRegion, View *pView, 01405 DocRect TotalUnion) 01406 { 01407 pRegion->ResetRegion(TotalUnion); 01408 Spread* pSpread = pRegion->GetRenderSpread(); 01409 01410 // Delete all the others 01411 RenderRegion *pRegion2 =(RenderRegion *) GetNext(pRegion); 01412 01413 while (pRegion2 != NULL) 01414 { 01415 // Remember the 'next' region because we might delete this one. 01416 RenderRegion *pNextRegion = (RenderRegion *) GetNext(pRegion2); 01417 01418 // Is this the correct DocView and render context? 01419 if ((pRegion2->GetRenderView() == pView) && 01420 (pRegion2->GetRenderSpread() == pSpread) && 01421 (pRegion2->CanBeMerged())) 01422 { 01423 // Yes - delete this region 01424 pRegion->NeedsOSPaper = pRegion->NeedsOSPaper && pRegion2->NeedsOSPaper; 01425 Remove(pRegion2); 01426 delete pRegion2; 01427 01428 // Make sure we don't have a dangling pointer to this region. 01429 if (pRegion2 == LastRendered) 01430 // Start from the beginning of the list again. 01431 LastRendered = NULL; 01432 } 01433 01434 // Find the next render region 01435 pRegion2 = pNextRegion; 01436 } 01437 }