BOOL NodeRenderableInk::MakeAttributeComplete(Node* Root, BOOL CheckForDuplicates, /* = TRUE */ AttrTypeSet* pAffectedAttrTypes, /* = NULL */ BOOL IncludeDefaults, /* = FALSE */ BOOL bIncludeEffectAttrs /* = FALSE */) { Node* Current = NULL; // Pointer to the current node in the tree NodeAttribute* CurAttr; CCRuntimeClass* AttrType; BOOL Exists; Node* PreFirstChild = FindFirstChild(); // Remember the FirstChild of the node before we add // any new attributes, this will come in handy if we // need to abort. // Loop until all attributes are copied, we are not interested in the defaults cos these are the // same for all docs !. if (bIncludeEffectAttrs) Current = NodeAttribute::FindFirstAppliedAttr(this, Root); else Current = NodeAttribute::FindPrevAppliedAttr(this, Root); while (Current && (IncludeDefaults || (!(IS_A(Current->FindParent(), NodeDocument)))) ) { // Find the next node, snaking up the tree if (Current->IsAnAttribute()) { CurAttr = (NodeAttribute*)Current; if (CurAttr->CanBeAppliedToObject() && CurAttr->ShouldBeOptimized()) { AttrType = CurAttr->GetAttributeType(); BOOL Required = RequiresAttrib(AttrType) || this->IsCompound(); // Is the attribute required ? if (Required && (!pAffectedAttrTypes || pAffectedAttrTypes->InSet(AttrType))) { Exists = FALSE; if (CheckForDuplicates) { // triggers can have duplicates if(!CurAttr->CanBeMultiplyApplied()) { // Does the node already have this child attribute Exists = (GetChildAttrOfType(AttrType) != NULL); } } #ifdef _DEBUG if (!CheckForDuplicates) { // If we feel there is no need to check for duplicates then there shouldn't be any ! if (!CurAttr->CanBeMultiplyApplied()) { NodeAttribute* pChildAttr = GetChildAttrOfType(AttrType); if ((pChildAttr != NULL)) { #if DEBUG_TREE DebugTreeDlg::DumpSubTree(this, 4); #endif TRACE(_T("Duplicate Attr found at %x %s\n"), pChildAttr, pChildAttr->GetRuntimeClass()->m_lpszClassName); } // ERROR3IF((pChildAttr != NULL), "MakeAttributeComplete: Duplicate attr found !"); } } #endif if (!Exists) { // Make a copy of the attribute NodeAttribute* NewAttr = (NodeAttribute*)CurAttr->SimpleCopy(); if (NewAttr == NULL) { goto OutOfMemory; } // Now add the attribute to this node NewAttr->AttachNode(this, FIRSTCHILD, TRUE, FALSE); } } } } Current = NodeAttribute::FindPrevAppliedAttr(Current, Root); // in order to copy brush ink nodes we need to break if the parent is NULL, else is violates if (Current!=NULL && Current->FindParent() == NULL) break; } return TRUE; OutOfMemory: // Delete any new attributes added to the node Current = FindFirstChild(); Node* Next; while (Current != PreFirstChild) { ENSURE(Current != NULL, "PreFirstChild could not be found"); ENSURE(Current->IsAnAttribute(), "Should be a NodeAttribute"); Next = Current->FindNext(); // Delete the attribute Current->CascadeDelete(); delete Current; Current = Next; } return FALSE; }
BOOL NodeRenderableInk::FindCommonAttributesToFactorOut(CommonAttrSet* CommonAttributeSet) { CommonAttributeItem* CommonAttrItem; CommonAttributeItem* NextCommonAttrItem; // Place all attributes in the CommonAttributeSet if (!CommonAttributeSet->AddAllTypesToSet()) { return FALSE; // ERROR already called } // Scan all grouped objects for (Node* CurrentObject = FindFirstChild(); CurrentObject != NULL; CurrentObject = CurrentObject->FindNext()) { if (CurrentObject->IsAnObject()) { // Scan all attributes in the CommonAttributeSet in turn CommonAttrItem = (CommonAttributeItem*)CommonAttributeSet->GetHead(); while(CommonAttrItem != NULL) { // Hand over hand cos we may well delete the CommonAttrItem NextCommonAttrItem = (CommonAttributeItem*)(CommonAttributeSet->GetNext(CommonAttrItem)); // Does CurrentObject require the attribute to render if ( (((NodeRenderableInk*)CurrentObject)->RequiresAttrib(CommonAttrItem->AttrType)) || CurrentObject->IsCompound()) { BOOL DeleteCommonAttr = FALSE; // Until we know better // Ok the current object requires the attribute // Does the CurrentObject have a child attribute of this type ? NodeAttribute* pAttrNode = ((NodeRenderableInk*)CurrentObject)->GetChildAttrOfType(CommonAttrItem->AttrType); if (pAttrNode != NULL && pAttrNode->ShouldBeOptimized()) { // Ok it has an attribute of this type if (CommonAttrItem->pAttr == NULL) { // The attribute becomes a common attribute CommonAttrItem->pAttr = pAttrNode; CommonAttrItem->Status = Range::ATTR_COMMON; } else if(CommonAttrItem->pAttr->GetRuntimeClass() == pAttrNode->GetRuntimeClass()) { // Ok they are the same runtime class but are they equal if (!((*pAttrNode)==(*(CommonAttrItem->pAttr)))) { // They are not equal so remove CommonAttrItem from the // common attribute set. DeleteCommonAttr = TRUE; } // DY 12/5/2000 AttrBrushTypes cannot be factored because they // may contain caches of pressure or timestamp data which apply // to a specific node only. // They no longer contain this data so factor them like normal! //if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBrushType))) // DeleteCommonAttr = TRUE; } else { // They cannot be the same value cos they are different runtime types DeleteCommonAttr = TRUE; } } else { // The CurrentObject does not have an attribute of this type so it // cannot be common DeleteCommonAttr = TRUE; } if (DeleteCommonAttr) { delete(CommonAttributeSet->RemoveItem(CommonAttrItem)); } } CommonAttrItem = NextCommonAttrItem; } } // Removed because there are circumstances where certain attributes have // already been factored out eg. Corel filter //else //{ // ENSURE(CurrentObject->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeHidden), // "It's not an object, it's not a hidden node, so what is it ??"); //} } // Delete all NULL items in the CommonAttributeSet CommonAttrItem = (CommonAttributeItem*)CommonAttributeSet->GetHead(); while (CommonAttrItem != NULL) { CommonAttributeItem* Next = (CommonAttributeItem*)CommonAttributeSet->GetNext(CommonAttrItem); if (CommonAttrItem->pAttr == NULL) { // Item is a non required attribute so zap it delete (CommonAttributeSet->RemoveItem(CommonAttrItem)); } CommonAttrItem = Next; } return TRUE; // Job done }