void NodeRenderableInk::DeleteFactoredOutAttribs(BOOL Global, AttrTypeSet* pAffectedAttrTypes) { Node* pGroupNode = FindFirstChild(); while(pGroupNode!=NULL) { // Karim 30/08/2000 // Non-optimisable attributes, like feathers and names, // must not be automatically deleted - only automatically delete optimisable ones. if (pGroupNode->IsAnAttribute() && ((NodeAttribute*)pGroupNode)->ShouldBeOptimized()) { NodeAttribute* pGroupAttr = (NodeAttribute*)pGroupNode; CCRuntimeClass* GrouptAttrType = pGroupAttr->GetAttributeType(); if (pAffectedAttrTypes==NULL || pAffectedAttrTypes->InSet(GrouptAttrType)) { // delete this group attr type from all child objects of this group // BUT if obj discards child attrs only delete attr if it also has same value for (Node* pNode=FindFirstChild(); pNode!=NULL; pNode=pNode->FindNext()) { if (pNode->IsAnObject()) { NodeRenderableInk* pObject = (NodeRenderableInk*)pNode; NodeAttribute* pDeadAttr = pObject->GetChildAttrOfType(GrouptAttrType); if (pDeadAttr!=NULL) { // This code used to only test the attribute for equality if pObject // returned TRUE from DiscardsAttributeChildren, otherwise it would // just assume that they are identical and delete it. // The DiscardAttributeChildren checks are now done elsewhere so // this code now just assumes it can delete any attributes that have // got this far. // This optimisation relies on the tree being in a "legal" state // at the start (i.e. correctly optimised) and also helps to correct // problems where attributes may have been incorrectly left on children // (though such "corrections" may change the appearance of the document). pDeadAttr->CascadeDelete(); delete pDeadAttr; } } } } } pGroupNode = pGroupNode->FindNext(); } // Do we need to delete any parent compound's attributes if (Global) { Node* pParent = FindParent(); if (pParent && (pParent->IsCompound())) { // We need to delete the parent's attributes first (Recursive bit) ((NodeRenderableInk*)pParent)->DeleteFactoredOutAttribs(Global, pAffectedAttrTypes); } } }
void NodeRenderableInk::NormaliseAttributes() { NodeAttribute* ChildAttribute; NodeAttribute* GlobalAttribute; Node* LocalScan; Node* NextLocal; // Scan the child attribute block LocalScan = FindFirstChild(); // Stop if we hit an object or if there are no more children // NOTE: Stopping scanning when we find the first RendereblInk node prevents // Effect attributes being Normalised. THIS IS DELIBERATE! while((LocalScan != NULL) && (!LocalScan->IsAnObject())) { // Hand over hand (LocalScan may get deleted) NextLocal = LocalScan->FindNext(); if(LocalScan->IsAnAttribute() && ((NodeAttribute*)LocalScan)->ShouldBeOptimized()) // cos it could be a NodeHidden { ChildAttribute = (NodeAttribute*)LocalScan; // We now need to search up the tree to see if ChildAttribute is redundant // Node* GlobalScan = FindPreviousEffectiveNode(); Node* GlobalScan = NodeAttribute::FindPrevAppliedAttr(this); // Search until we can go no higher while (GlobalScan != NULL) { if (GlobalScan->IsAnAttribute()) { GlobalAttribute = (NodeAttribute*)GlobalScan; // An attribute has been found, is it the same class as ChildAttribute ? if(GlobalAttribute->GetRuntimeClass() == ChildAttribute->GetRuntimeClass()) { // Yes it is, so let's check if they are equal if ((*GlobalAttribute)==(*ChildAttribute)) { // They are equal so we can nuke the child object because it's // redundant ChildAttribute->CascadeDelete(); delete ChildAttribute; } break; // don't search any further } } // GlobalScan = GlobalScan->FindPreviousEffectiveNode(); // climb higher GlobalScan = NodeAttribute::FindPrevAppliedAttr(GlobalScan); } } LocalScan = NextLocal; // Get the next child } }