#include <rndstack.h>
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 | |
AttributeRec * | TheStack |
UINT32 | Top |
UINT32 | StackLimit |
UINT32 | ContextLevel |
Definition at line 121 of file rndstack.h.
|
Sets up the empty rendering stack.
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 }
|
|
Frees stack memory, including any temporary objects that belong to the stack.
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 }
|
|
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).
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 }
|
|
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.
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 }
|
|
Increase the size of the stack because a new element needs to be pushed onto it, and there isn't enough room.
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 }
|
|
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.
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 }
|
|
Restore all attributes saved by the last SaveContext() call.
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 }
|
|
Definition at line 131 of file rndstack.h. 00131 { ContextLevel++; }
|
|
Definition at line 155 of file rndstack.h. |
|
Definition at line 152 of file rndstack.h. |
|
Definition at line 145 of file rndstack.h. |
|
Definition at line 149 of file rndstack.h. |