rndstack.cpp

Go to the documentation of this file.
00001 // $Id: rndstack.cpp 1282 2006-06-09 09:46:49Z 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 // A attribute stack to be used when rendering Camelot files.
00100 
00101 /*
00102 */
00103 
00104 #include "camtypes.h"
00105 
00106 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "attrval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 
00110 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "rndstack.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 
00113 /********************************************************************************************
00114 
00115 Technical notes:
00116 
00117 Important note:
00118 
00119 This class implements a rendering attribute context stack.  It is done using a simple
00120 array structure, which grows when required.  The stack is implemented using two classes;
00121 RenderStack and AttributeRec.  The stack array is held by the RenderStack object, and the
00122 array is an array of AttributeRec objects.
00123 
00124 The stack is optimised to avoid saving attributes when it is unnecessary. The way this
00125 works is that a 'context level' is maintained by the RenderStack object.  Whenever an
00126 attribute is changed, then the render region that owns this stack pushes the current
00127 attribute onto the stack, along with the current context level. Then when the render region
00128 wants to save the context, all the stack object does is increment the context level. Hence
00129 all future attributes pushed onto the context stack will have a different context level.
00130 When the context is to be restored, the stack pops off all the stack records whose context 
00131 level fields match the current context level, and then decrements the context level.
00132 
00133 For, example, given the following sequence of calls:
00134 
00135     pRegion->SetLineColour(COLOUR_BLACK);
00136     pRegion->SetLineWidth(250);
00137     pRegion->SaveContext();
00138     pRegion->SetLineColour(COLOUR_RED);
00139     pRegion->SaveContext();
00140     pRegion->SetLineColour(COLOUR_GREEN);
00141     pRegion->SetLineWidth(0);
00142     pRegion->SetFillColour(COLOUR_CYAN);
00143 
00144 then we would end up with a stack like this:
00145 
00146 
00147      AttributeValue     Context Level 
00148 
00149   +-------------------+---------------+
00150   |                   |               |    <--- Next free element ('Top')
00151   +-------------------+---------------+
00152   | FillColour: CYAN  |       2       |    <--- Last element
00153   +-------------------+---------------+
00154   | LineWidth:  0     |       2       |
00155   +-------------------+---------------+
00156   | LineColour: GREEN |       2       |
00157   +-------------------+---------------+
00158   | LineColour: RED   |       1       |
00159   +-------------------+---------------+
00160   | LineWidth:  250   |       0       |
00161   +-------------------+---------------+
00162   | LineColour: BLACK |       0       |    <--- First element
00163   +-------------------+---------------+
00164 
00165 
00166 and the current context level would be 2.  Therefore when RestoreContext() is next called, 
00167 the stack pops off all elements with the context level 2, i.e. the top three elements, and
00168 decrements the context value to 1.  Obviously the next time RestoreContext() is called, 
00169 then it just pops off one element (red line colour) and decrements the context level to 0.
00170 And this is basically how the stack works - this way, we don't have to save/restore every
00171 attribute whenever we save/restore the context, and so it is much more efficient.
00172 
00173 There is one more complication, because the attribute value itself is not pushed onto the
00174 stack, but a pointer to it.  The advantage of this is that less data has to be copied 
00175 when setting and restoring attributes, and we can encapsulate the setting and restoring
00176 of the attribute within the attribute class itself (see kernel\attr.{h,cpp}).  When an
00177 attribute is rendered, the render region asks it to render itself via its virtual
00178 function Render() - this will save the current attribute and install itself as the
00179 new current attribute via the RenderRegion::SvaeAttribute() function.  Similarly, when
00180 the attribute record is popped off the stack, the virtual function Restore() is called.
00181 This will set the current attribute to be itself, via the RenderRegion::RestoreAttribute()
00182 function.
00183 At the moment (4/2/94), all our attributes our contained within the RenderRegion, so this
00184 system is not strictly needed, but if we want tools to be able to add types of attributes,
00185 then we must have an extensible system like this.  At present, the current attribute array
00186 is of a fixed size, and when we start adding attributes via modules/tools, we will need
00187 to have a system of declaring/registering attributes when the modules/tools start up.
00188 They will then be given an 'ID' for their attribute.  This will in fact be an index into
00189 the CurrentAttrs array maintained by RenderRegion, which will be dynamically allocated
00190 when the render region is initialised, according to how many attributes have been
00191 declared/registered.
00192 
00193 
00194 ********************************************************************************************/
00195 
00196 // InitialStackSize - how many entries can fit in the default stack size.
00197 // Various tests show that the stack very rarely gets deeper than 40 levels, so 30
00198 // is more than enough.
00199 // (Jason here, several years later: We now have more than 30 default attributes
00200 // so the stack always has more than 30 items, and usually sits between 40 and 80
00201 // entries, so is now guaranteed to realloc for every render! As the records are
00202 // only 12 bytes each, I've changed this from 30+20 to 80+30 so that the
00203 // reallocing should happen infrequently (if ever) and we can double the number
00204 // of default attributes before we get into trouble again! However, I've
00205 // kept it relatively small to reduce the overhead of initialising unused entries)
00206 const INT32 InitialStackSize = 80;  // Was 30
00207 
00208 // StackGranularity - this dictates how many entries should be added to the stack
00209 // when we run out of space.
00210 const INT32 StackGranularity = 30;  // Was 20
00211 
00212 // ITEM_SIZE - this value is used when allocating memory for the stack.
00213 #define ITEM_SIZE (sizeof(AttributeRec))
00214 
00215 /********************************************************************************************
00216 
00217 >   class AttributeRec : public CC_CLASS_MEMDUMP
00218 
00219     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00220     Created:    28/01/94
00221     Purpose:    Encapsulates an item in the RenderStack class.
00222     SeeAlso:    RenderStack
00223 
00224 ********************************************************************************************/
00225 
00226 class AttributeRec : public CC_CLASS_MEMDUMP
00227 {
00228     CC_DECLARE_MEMDUMP(AttributeRec)
00229 
00230 public:
00231     AttributeRec();
00232     AttributeValue *pAttrValue;
00233     UINT32 ContextLevel;
00234     BOOL Temporary;
00235 };
00236 
00237 CC_IMPLEMENT_MEMDUMP(AttributeRec, CCObject)
00238 CC_IMPLEMENT_MEMDUMP(RenderStack, CCObject)
00239 
00240 /********************************************************************************************
00241 
00242 >   AttributeRec::AttributeRec()
00243 
00244     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00245     Created:    28/01/94
00246     Purpose:    Initialise a stack element in the RenderStack.
00247 
00248 ********************************************************************************************/
00249 
00250 AttributeRec::AttributeRec()
00251 {
00252     pAttrValue = NULL;
00253     ContextLevel = 0;
00254     Temporary = FALSE;
00255 }
00256 
00257 /********************************************************************************************
00258 
00259 >   RenderStack::RenderStack()
00260 
00261     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00262     Created:    28/01/94
00263     Purpose:    Sets up the empty rendering stack.
00264 
00265 ********************************************************************************************/
00266 
00267 RenderStack::RenderStack()
00268 {
00269     // Initialise stack variables
00270     ContextLevel = 0;
00271     StackLimit = 0;
00272     Top = 0;
00273     TheStack = NULL;
00274 }
00275 
00276 /********************************************************************************************
00277 
00278 >   RenderStack::~RenderStack()
00279 
00280     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00281     Created:    28/01/94
00282     Purpose:    Frees stack memory, including any temporary objects that belong to the
00283                 stack.
00284 
00285 ********************************************************************************************/
00286 
00287 RenderStack::~RenderStack()
00288 {
00289     // Delete all temporary items left in the stack
00290     for (UINT32 i = 0; i < Top; i++)
00291     {
00292         if (TheStack[i].Temporary)
00293         {
00294             // Make sure pointer is sane before we delete it.
00295             CC_ASSERT_VALID(TheStack[i].pAttrValue);
00296             delete TheStack[i].pAttrValue;
00297         }
00298     }
00299 
00300     // Clean up and free stack objects.
00301     ContextLevel = 0;
00302     StackLimit = 0;
00303     Top = 0;
00304     CCFree(TheStack);
00305     TheStack = NULL;
00306 }
00307 
00308 /********************************************************************************************
00309 
00310 >   BOOL RenderStack::Copy(const RenderStack *Other, RenderRegion *pRegion)
00311 
00312     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00313     Created:    31/01/94
00314 
00315     Inputs:     Other   - pointer to the RenderStack object to copy.
00316                 pRegion - The render-region in which this stack lives. Needed so that
00317                           all attrs currently on the stack can be properly de-initialised,
00318                           and all new attrs being copied over can be properly rendered into
00319                           the destination render region. Awful things are likely to happen
00320                           if "this" is not equal to "&pRegion->TheStack"!
00321 
00322     Returns:    TRUE if successful, FALSE otherwise.
00323 
00324     Purpose:    Copies a RenderStack object.  This cannot be done as a copy constructor as
00325                 it allocates memory and hence can fail.
00326                 This function handles RenderStacks which contain temporary objects, i.e.
00327                 objects created especially to put in the stack, as opposed to objects
00328                 from a document tree.  Such objects are duplicated in the new stack, as
00329                 otherwise the destructors of both stacks would try to delete the same
00330                 object twice.
00331 
00332     Errors:     Out of memory. Ensure failure if there is already data in the stack.
00333 
00334 ********************************************************************************************/
00335 
00336 BOOL RenderStack::Copy(const RenderStack *Other, RenderRegion *pRegion)
00337 {
00338     ERROR3IF(Other == NULL || pRegion == NULL, "Illegal NULL params");
00339 
00340 // WEBSTER - markn 15/8/97
00341 // This has bee taken out of Webster builds as it can cause fatal access violations with Paper render regions.
00342 // It is new path processor code that not's totally bug-free, and as path processors are not used in Webster,
00343 // it can be safely taken out.
00344 #ifndef WEBSTER
00345     // Make sure all attributes are properly popped && deinitialised, so that any used
00346     // PathProcessors are correctly removed, etc
00347     // (Note: This doesn't deinit the DEFAULT attributes, which we hope will never use
00348     // PathProcessors - this should be OK, because the places where this is called from
00349     // (at present) always make sure all PathProcessors are properly cleaned up too)
00350     CleanUpBeforeDestruct(pRegion);
00351 #endif // WEBSTER
00352 
00353     // Make sure we have an empty stack to work with
00354     if (TheStack!=NULL)
00355     {
00356         // Empty the current stack before copying the new one onto it
00357         // For every item in the stack, check to see if it is 'temporary'.  If it is,
00358         // we can't use it in our stack - we must take a copy.
00359         for (UINT32 i=0; i<Top; i++)
00360         {
00361             // Get rid of all the temp attrs in the stack
00362             if (TheStack[i].Temporary)
00363             {
00364                 // Delete this tempory attr.
00365                 CC_ASSERT_VALID(TheStack[i].pAttrValue);
00366                 delete TheStack[i].pAttrValue;
00367             }
00368         }
00369 
00370         // then get rid of the stack itself
00371         CCFree(TheStack);
00372         TheStack=NULL;
00373 
00374         ContextLevel = 0;
00375         StackLimit = 0;
00376         Top = 0;
00377     }
00378 
00379     // Sanity check
00380     ENSURE(TheStack == NULL,"RenderStack::Copy called on a non-empty stack");
00381 
00382 #if FALSE
00383     // Jason (7/3/97)
00384     // Copying the stack like this is rampant. We must render all the attributes across onto
00385     // the new stack, so that they are properly stacked and initialised
00386 /*
00387     // Copy stack variables
00388     ContextLevel = Other->ContextLevel;
00389     StackLimit = Other->StackLimit;
00390     Top = Other->Top;
00391 
00392     // The other stack may be empty, which will often be the case when merging as it may
00393     // not have started rendering yet.
00394     if (Other->TheStack == NULL)
00395     {
00396         // Just to be on the safe side
00397         TheStack = NULL;
00398 
00399         // We're done.
00400         return TRUE;
00401     }
00402 
00403     // Allocate the same amount of memory for the stack
00404     TheStack = (AttributeRec *) CCMalloc(StackLimit * ITEM_SIZE);
00405     if (TheStack == NULL)
00406         return FALSE;
00407 
00408     // Copy the other render region's stack data into this new stack
00409     memcpy(TheStack, Other->TheStack, StackLimit * ITEM_SIZE);
00410 
00411     // For every item in the stack, check to see if it is 'temporary'.  If it is,
00412     // we can't use it in our stack - we must take a copy.
00413     for (UINT32 i = 0; i < Top; i++)
00414     {
00415         if (TheStack[i].Temporary)
00416         {
00417             // Get the runtime class info on this object
00418             CCRuntimeClass *pCCRuntimeClass = TheStack[i].pAttrValue->GetRuntimeClass();
00419     
00420             // Create another object of the same type
00421             AttributeValue *pNewAttr = (AttributeValue *) pCCRuntimeClass->CreateObject();
00422 
00423             if (pNewAttr == NULL)
00424             {
00425                 // Failed to create object - quit with error, but first ensure that this
00426                 // stack is limited to the items copied so far. Otherwise the destructor
00427                 // will attempt to delete objects that belong to the other stack.
00428                 Top = i;
00429                 return FALSE;
00430             }
00431 
00432             // Object created ok - get the object to copy its contents across.
00433             pNewAttr->SimpleCopy(TheStack[i].pAttrValue);
00434 
00435             // Put it in the stack
00436             TheStack[i].pAttrValue = pNewAttr;
00437         }
00438     }
00439 */
00440 #else
00441     if (Other->TheStack == NULL)
00442         return(TRUE);
00443 
00444     UINT32 LastContextLevel = 0;
00445 
00446     // Copy all attributes across to the new stack by rendering them into the provided render region.
00447     // If we aren't "pRegion->TheStack" then we've just lost our paddle, and we're being sucked up the creek...
00448     for (UINT32 i = 0; i < Other->Top; i++)
00449     {
00450         // Make sure we copy context level information across too - if the context level changed, we must
00451         // save the context level now.
00452         if (LastContextLevel != Other->TheStack[i].ContextLevel)
00453             pRegion->SaveContext();
00454 
00455         // Get each attribute to render into our render region
00456         AttributeValue *pAttrVal = Other->TheStack[i].pAttrValue;
00457 
00458         // If it's temporary, then replace it with a unique copy for this render region
00459         if (Other->TheStack[i].Temporary)
00460         {
00461             // Get the runtime class info on this object
00462             CCRuntimeClass *pCCRuntimeClass = Other->TheStack[i].pAttrValue->GetRuntimeClass();
00463     
00464             // Create another object of the same type
00465             pAttrVal = (AttributeValue *) pCCRuntimeClass->CreateObject();
00466 
00467             if (pAttrVal == NULL)
00468                 return FALSE;
00469 
00470             // Object created ok - get the object to copy its contents across.
00471             pAttrVal->SimpleCopy(Other->TheStack[i].pAttrValue);
00472         }
00473 
00474         // and render the attribute into this render region
00475         pAttrVal->Render(pRegion, Other->TheStack[i].Temporary);
00476     }
00477     
00478 #endif
00479 
00480     // It worked
00481     return TRUE;
00482 }
00483 
00484 
00485 /********************************************************************************************
00486 
00487 >   BOOL RenderStack::GrowStack()
00488 
00489     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00490     Created:    28/01/94
00491     Returns:    TRUE if the stack size was increased, FALSE if not.
00492     Purpose:    Increase the size of the stack because a new element needs to be pushed onto
00493                 it, and there isn't enough room.
00494     Errors:     Out of memory.
00495 
00496 ********************************************************************************************/
00497 
00498 BOOL RenderStack::GrowStack()
00499 {
00500     INT32 FirstNewItem = 0;
00501 
00502     if (TheStack == NULL)
00503     {
00504         // Try to allocate initial memory block for the stack.
00505         TheStack = (AttributeRec *) CCMalloc(InitialStackSize * ITEM_SIZE);
00506 
00507         // Complain and return if it didn't work.
00508         if (TheStack == NULL)
00509             return FALSE;
00510 
00511         // Update stack limit to reflect new size
00512         StackLimit = InitialStackSize;
00513 
00514     }
00515     else
00516     {
00517 //      if (IsUserName("Tim"))
00518 //          TRACE( _T("Growing heap from %d to %d entries\n"), 
00519 //                StackLimit, StackLimit + StackGranularity);
00520 
00521         // Increase the stack allocation
00522         AttributeRec *NewStack = (AttributeRec *)
00523             CCRealloc(TheStack, (StackLimit + StackGranularity) * ITEM_SIZE);
00524 
00525         // Complain if no more memory
00526         if (NewStack == NULL)
00527             return FALSE;
00528 
00529         // Otherwise use this new block
00530         TheStack = NewStack;
00531 
00532         // Make sure only new items are initialised
00533         FirstNewItem = StackLimit;
00534 
00535         // Update stack limit to reflect new size
00536         StackLimit += StackGranularity;
00537     }
00538 
00539     // Initialise the stack elements
00540     for (UINT32 i = FirstNewItem; i < StackLimit; i++)
00541     {
00542         TheStack[i].pAttrValue = NULL;
00543         TheStack[i].ContextLevel = 0;
00544         TheStack[i].Temporary = FALSE;
00545     }
00546 
00547     // Return success
00548     return TRUE;
00549 }
00550 
00551 
00552 /********************************************************************************************
00553 
00554 >   BOOL RenderStack::Push(AttributeValue *pAttr, BOOL Temporary = FALSE)
00555 
00556     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00557     Created:    28/01/94
00558     Inputs:     pAttr - the attribute to push.
00559                 Temporary - TRUE if the AttributeValue should be deleted when the
00560                 attribute is popped from the stack, FALSE if not.
00561     Returns:    TRUE if the push succeeded, FALSE if not.
00562     Purpose:    Push an attribute value on to the stack.
00563                 The 'Temporary' parameter is used when the attribute has been constructed
00564                 especially for changing the attribute - i.e. it is not part of the Camelot
00565                 tree.  For example, when rendering something that is not a Camelot
00566                 document, we still need to change the line colour, so the function that
00567                 changes the line colour creates a temporary attribute that is pushed onto
00568                 the stack and then automatically deleted when it is removed.
00569                 If pAttr is NULL, then it is assumed that this is the first time this
00570                 attribute has been set, so we don't need to push the 'old' value.
00571     Errors:     Out of memory.
00572     SeeAlso:    RenderStack::RestoreContext; RenderStack::SaveContext
00573 
00574 ********************************************************************************************/
00575 
00576 BOOL RenderStack::Push(AttributeValue *pAttr, BOOL Temporary)
00577 {
00578     // If we're saving an attribute that hasn't been set up yet, don't bother.
00579     if (pAttr == NULL)
00580         return TRUE;
00581 
00582     // If we need more space, then get some.
00583     if (Top == StackLimit)
00584     {
00585         if (!GrowStack())
00586             return FALSE;
00587     }
00588 
00589     // Push the record onto the stack
00590     TheStack[Top].pAttrValue   = pAttr;
00591     TheStack[Top].ContextLevel = ContextLevel;
00592     TheStack[Top].Temporary    = Temporary;
00593 
00594     // Sanity checks
00595     CC_ASSERT_VALID(pAttr);
00596     ENSURE((Temporary == TRUE) || (Temporary == FALSE), 
00597            "Duff Temporary flag passed to Push()");
00598         
00599     // Move stack pointer to next record
00600     Top++;
00601 
00602     // Worked ok
00603     return TRUE;
00604 }
00605 
00606 
00607 /********************************************************************************************
00608 
00609 >   void RenderStack::RestoreContext(RenderRegion *pRegion)
00610 
00611     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00612     Created:    28/01/94
00613     Inputs:     pRegion - the render region that the context should be restored to.
00614     Purpose:    Restore all attributes saved by the last SaveContext() call.
00615 
00616 ********************************************************************************************/
00617 
00618 void RenderStack::RestoreContext(RenderRegion *pRegion)
00619 {
00620     ENSURE(ContextLevel > 0, "Too many calls to RestoreContext!");
00621 
00622     // Restore all attributes that have changed since SaveContext() was last called.
00623     while ((Top > 0) && (TheStack[Top-1].ContextLevel == ContextLevel))
00624     {
00625         // Move pointer to the item, because the stack is an 'empty' one.
00626         Top--;
00627 
00628         // Restore the attribute
00629         TheStack[Top].pAttrValue->Restore(pRegion, TheStack[Top].Temporary);
00630 
00631         // Make sure this is a valid pointer.
00632         CC_ASSERT_VALID((TheStack[Top].pAttrValue));
00633     }
00634 
00635     ContextLevel--;
00636 }
00637 
00638 
00639 
00640 /********************************************************************************************
00641 
00642 >   void RenderStack::CleanUpBeforeDestruct(RenderRegion *pRegion)
00643 
00644     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00645     Created:    14/01/97
00646     Inputs:     pRegion - the render region that the context should be restored to.
00647 
00648     Purpose:    Restore all attributes saved by all SaveContext() calls ever.
00649                 This just pops ALL entries from the stack, which gives all remaining
00650                 attributes in the stack a chance to clean up and avoid memory leaks.
00651                 (Used now to clean up stacked PathProcessors)
00652 
00653 ********************************************************************************************/
00654 
00655 void RenderStack::CleanUpBeforeDestruct(RenderRegion *pRegion)
00656 {
00657     ERROR3IF(pRegion == NULL, "Illegal NULL param");
00658 
00659     // Just repeatedly restore until we've popped everything.
00660     // That way if someone changes Restore, they won't break this function!
00661     while (ContextLevel > 0)
00662         RestoreContext(pRegion);
00663 }
00664 

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