RenderStack Class Reference

To provide a stack on which to save attribute values while rendering the Camelot tree. The stack is optimised to minimise the amount of pushing and popping actually done. More...

#include <rndstack.h>

List of all members.

Public Member Functions

 RenderStack ()
 Sets up the empty rendering stack.
 ~RenderStack ()
 Frees stack memory, including any temporary objects that belong to the stack.
BOOL Push (AttributeValue *pAttrValue, BOOL Temporary=FALSE)
 Push an attribute value on to the stack. The 'Temporary' parameter is used when the attribute has been constructed especially for changing the attribute - i.e. it is not part of the Camelot tree. For example, when rendering something that is not a Camelot document, we still need to change the line colour, so the function that changes the line colour creates a temporary attribute that is pushed onto the stack and then automatically deleted when it is removed. If pAttr is NULL, then it is assumed that this is the first time this attribute has been set, so we don't need to push the 'old' value.
void SaveContext ()
void RestoreContext (RenderRegion *pRegion)
 Restore all attributes saved by the last SaveContext() call.
void CleanUpBeforeDestruct (RenderRegion *pRegion)
 Restore all attributes saved by all SaveContext() calls ever. This just pops ALL entries from the stack, which gives all remaining attributes in the stack a chance to clean up and avoid memory leaks. (Used now to clean up stacked PathProcessors).
BOOL Copy (const RenderStack *Other, RenderRegion *pRegion)
 Copies a RenderStack object. This cannot be done as a copy constructor as it allocates memory and hence can fail. This function handles RenderStacks which contain temporary objects, i.e. objects created especially to put in the stack, as opposed to objects from a document tree. Such objects are duplicated in the new stack, as otherwise the destructors of both stacks would try to delete the same object twice.

Private Member Functions

BOOL GrowStack ()
 Increase the size of the stack because a new element needs to be pushed onto it, and there isn't enough room.

Private Attributes

AttributeRecTheStack
UINT32 Top
UINT32 StackLimit
UINT32 ContextLevel


Detailed Description

To provide a stack on which to save attribute values while rendering the Camelot tree. The stack is optimised to minimise the amount of pushing and popping actually done.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94
See also:
AttributeRec; RenderRegion; AttributeValue; NodeAttribute

Definition at line 121 of file rndstack.h.


Constructor & Destructor Documentation

RenderStack::RenderStack  ) 
 

Sets up the empty rendering stack.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94

Definition at line 267 of file rndstack.cpp.

00268 {
00269     // Initialise stack variables
00270     ContextLevel = 0;
00271     StackLimit = 0;
00272     Top = 0;
00273     TheStack = NULL;
00274 }

RenderStack::~RenderStack  ) 
 

Frees stack memory, including any temporary objects that belong to the stack.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94

Definition at line 287 of file rndstack.cpp.

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 }


Member Function Documentation

void RenderStack::CleanUpBeforeDestruct RenderRegion pRegion  ) 
 

Restore all attributes saved by all SaveContext() calls ever. This just pops ALL entries from the stack, which gives all remaining attributes in the stack a chance to clean up and avoid memory leaks. (Used now to clean up stacked PathProcessors).

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/01/97
Parameters:
pRegion - the render region that the context should be restored to. [INPUTS]

Definition at line 655 of file rndstack.cpp.

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 }

BOOL RenderStack::Copy const RenderStack Other,
RenderRegion pRegion
 

Copies a RenderStack object. This cannot be done as a copy constructor as it allocates memory and hence can fail. This function handles RenderStacks which contain temporary objects, i.e. objects created especially to put in the stack, as opposed to objects from a document tree. Such objects are duplicated in the new stack, as otherwise the destructors of both stacks would try to delete the same object twice.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/01/94
Parameters:
Other - pointer to the RenderStack object to copy. [INPUTS] pRegion - The render-region in which this stack lives. Needed so that all attrs currently on the stack can be properly de-initialised, and all new attrs being copied over can be properly rendered into the destination render region. Awful things are likely to happen if "this" is not equal to "&pRegion->TheStack"!
Returns:
TRUE if successful, FALSE otherwise.

Errors: Out of memory. Ensure failure if there is already data in the stack.

Definition at line 336 of file rndstack.cpp.

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 }

BOOL RenderStack::GrowStack  )  [private]
 

Increase the size of the stack because a new element needs to be pushed onto it, and there isn't enough room.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94
Returns:
TRUE if the stack size was increased, FALSE if not.

Errors: Out of memory.

Definition at line 498 of file rndstack.cpp.

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 }

BOOL RenderStack::Push AttributeValue pAttr,
BOOL  Temporary = FALSE
 

Push an attribute value on to the stack. The 'Temporary' parameter is used when the attribute has been constructed especially for changing the attribute - i.e. it is not part of the Camelot tree. For example, when rendering something that is not a Camelot document, we still need to change the line colour, so the function that changes the line colour creates a temporary attribute that is pushed onto the stack and then automatically deleted when it is removed. If pAttr is NULL, then it is assumed that this is the first time this attribute has been set, so we don't need to push the 'old' value.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94
Parameters:
pAttr - the attribute to push. [INPUTS] Temporary - TRUE if the AttributeValue should be deleted when the attribute is popped from the stack, FALSE if not.
Returns:
TRUE if the push succeeded, FALSE if not.

Errors: Out of memory.

See also:
RenderStack::RestoreContext; RenderStack::SaveContext

Definition at line 576 of file rndstack.cpp.

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 }

void RenderStack::RestoreContext RenderRegion pRegion  ) 
 

Restore all attributes saved by the last SaveContext() call.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/01/94
Parameters:
pRegion - the render region that the context should be restored to. [INPUTS]

Definition at line 618 of file rndstack.cpp.

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 }

void RenderStack::SaveContext  )  [inline]
 

Definition at line 131 of file rndstack.h.

00131 { ContextLevel++; }


Member Data Documentation

UINT32 RenderStack::ContextLevel [private]
 

Definition at line 155 of file rndstack.h.

UINT32 RenderStack::StackLimit [private]
 

Definition at line 152 of file rndstack.h.

AttributeRec* RenderStack::TheStack [private]
 

Definition at line 145 of file rndstack.h.

UINT32 RenderStack::Top [private]
 

Definition at line 149 of file rndstack.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 04:00:34 2007 for Camelot by  doxygen 1.4.4