CCAttrMap* CCAttrMap::Copy() { CCAttrMap *pNewAttrMap = new CCAttrMap( GetCount() ); if( pNewAttrMap != NULL ) { // iterating all (key, value) pairs for( iterator Pos = GetStartPosition(); Pos != GetEndPosition(); ) { CCRuntimeClass *pType; void *pVal; GetNextAssoc( Pos, pType, pVal ); // Get the attribute value of this attribute NodeAttribute* pAttr = (NodeAttribute*)pVal; // Copy the attribute NodeAttribute* pNewAttr = (NodeAttribute*) (pAttr->SimpleCopy()); // Stick the new attr into the new attr map if (pNewAttr != NULL) pNewAttrMap->SetAt(pNewAttr->GetAttributeType(),pNewAttr); } } pNewAttrMap->attrMapCreator = attrMapCreator; return pNewAttrMap; }
/******************************************************************************************** > static CCAttrMap * CCAttrMap::MakeAttrMapFromRenderRegion(RenderRegion * pRegion) Author: David_McClarnon (Xara Group Ltd) <*****@*****.**> Created: 24/2/2000 Inputs: The render region to get the attribute map from Outputs: An attribute map (copied) from the render region Returns: - Purpose: Makes an attribute out of the render region's current attribute state Notes: You MUST call DeleteAttributes afterwards to release memory - delete is not sufficient SeeAlso: - ********************************************************************************************/ CCAttrMap * CCAttrMap::MakeAttrMapFromRenderRegion(RenderRegion * pRegion) { CCAttrMap * pMap = new CCAttrMap; ENSURE(pMap,"No mem for attrmap"); if(!pMap) return NULL; // let's get every attribute in the render region AttributeValue * pAttrVal = NULL; NodeAttribute * pNewAttr = NULL; for (UINT32 i = 0; i < ATTR_FIRST_FREE_ID; i++) { pAttrVal = pRegion->GetCurrentAttribute(i); // make a new node out of this attribute value pNewAttr = pAttrVal->MakeNode(); // Karim 12/04/2000 // AttributeValues _do_not_have_to_have_ a corresponding NodeAttribute, // so can we please *check* that MakeNode didn't just return NULL! if (pNewAttr != NULL) { if(!pNewAttr->IsLinkedToNodeGeometry()) pMap->SetAt(pNewAttr->GetAttributeType(),pNewAttr); else { delete pNewAttr; pNewAttr = AttributeManager::GetDefaultAttribute((AttrIndex) i); if(pNewAttr) { ENSURE(pNewAttr->IsLinkedToNodeGeometry(),"Incorrect NodeAttribute returned by GetDefaultAttribute"); pMap->SetAt(pNewAttr->GetAttributeType(), pNewAttr); } else return NULL; } } } pMap->attrMapCreator = NULL; return pMap; }
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); } } }
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 BlendHelpers::BlendAttributes(BlendNodeParam * pParam, CCAttrMap* pBlendedAttrMap) Author: David_McClarnon (Xara Group Ltd) <*****@*****.**> based on blender code Created: 21/2/2000 Inputs: pParam - the blend node param Outputs: - Returns: TRUE if successful, FALSE otherwise Purpose: Blends the attributes of the two BlendPath objects by the amount specified in BlendRatio SeeAlso: - ********************************************************************************************/ BOOL BlendHelpers::BlendAttributes(BlendNodeParam * pParam, CCAttrMap* pBlendedAttrMap) { // Check entry params double BlendRatio = pParam->GetAttrBlendRatio(); BOOL ok = (pParam != NULL && pBlendedAttrMap != NULL); ERROR3IF(!ok,"One or more NULL entry params"); if (!ok) return FALSE; // Find the attributes that are applied to the blend paths BlendPath * pBlendPathStart = pParam->GetStartBlendPath(); BlendPath * pBlendPathEnd = pParam->GetEndBlendPath(); ok = (pBlendPathStart != NULL && pBlendPathEnd != NULL); ERROR3IF(!ok, "Blend paths are NULL"); if (!ok) return FALSE; ok = (pBlendPathStart->GetCreatedByNode() != NULL && pBlendPathEnd->GetCreatedByNode() != NULL); ERROR3IF(!ok, "Blend path created by nodes are NULL"); if (!ok) return FALSE; BOOL startExludeGLAs = TRUE, endExcludeGLAs = TRUE; NodeAttribute * pAttr = NULL; if(pBlendPathStart->GetCreatedByNode()->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFeather),&pAttr)) { startExludeGLAs = FALSE; } if(pBlendPathEnd->GetCreatedByNode()->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFeather),&pAttr)) { endExcludeGLAs = FALSE; } CCAttrMap* pAttrMapStart = CCAttrMap::MakeAppliedAttrMap(pBlendPathStart->GetCreatedByNode(), startExludeGLAs); CCAttrMap* pAttrMapEnd = CCAttrMap::MakeAppliedAttrMap(pBlendPathEnd->GetCreatedByNode(), endExcludeGLAs); if (!pAttrMapStart || !pAttrMapEnd) return FALSE; // find the attributes on the nodes if (pParam->GetNodeBlendPath() != NULL) { Trans2DMatrix* pRotateStart = GetRotateMatrix(pParam->GetNodeStart(), 360.0 - pParam->GetAngleStart()); Trans2DMatrix* pRotateEnd = GetRotateMatrix(pParam->GetNodeEnd(), 360.0 - pParam->GetAngleEnd()); if (pRotateStart) pAttrMapStart->Transform(*pRotateStart); if (pRotateEnd) pAttrMapEnd ->Transform(*pRotateEnd); if (pRotateStart) delete pRotateStart; if (pRotateEnd) delete pRotateEnd; } // These vars are used as params to the CCAttrMap funcs CCRuntimeClass *pTypeStart; void *pValStart; void *pValEnd; double OldBlendRatio = pParam->GetBlendRatio(); // Process each attribute in turn CCAttrMap::iterator PosStart = pAttrMapStart->GetStartPosition(); CCAttrMap::iterator EndStart = pAttrMapStart->GetEndPosition(); for (;PosStart != EndStart;) { // Get a ptr to the attr at position PosStart in the start node's attr map pAttrMapStart->GetNextAssoc(PosStart,pTypeStart,pValStart); NodeAttribute* pNodeAttrStart = (NodeAttribute *)pValStart; BlendRatio = OldBlendRatio; // Diccon 10/99 When using non-linear profiles for the objects those attributes // that make use of control points were not being profiled, making the objects look strange. // to avoid this those attributes now share the same profiles as the objects. if (pNodeAttrStart->IsAGradFill()) { if (!((AttrFillGeometry*)pNodeAttrStart)->IsAColourFill()) { BlendRatio = pParam->GetObjectRatio(); } else { BlendRatio = pParam->GetInvertedAttributeRatio(); } } if (pNodeAttrStart->IsAFlatFill() || (pNodeAttrStart->GetRuntimeClass() == CC_RUNTIME_CLASS(AttrLineWidth))) { BlendRatio = pParam->GetInvertedAttributeRatio(); } // Get a blended attribute NodeAttribute* pBlendedNodeAttr = NULL; // Find an attr of the same type in the end object's attr list, // and blend the two attrs together pValEnd = NULL; if (pAttrMapEnd->Lookup(pTypeStart,pValEnd)) { // We've found a matching end attr, so try to blend it with the start attr // Set up the param object to pass to the start attr's blend method BlendAttrParam BlendParam; NodeAttribute * pEndAttr = (NodeAttribute *)pValEnd; // Initialise the BlendParam with the end attr and blend ratio if (BlendParam.Init(pParam->GetRenderRegion(), pEndAttr,BlendRatio, pParam->GetColourBlendType(), pAttrMapStart, pAttrMapEnd)) { // Successfully initialised, so now try blending the attributes if (pNodeAttrStart->Blend(&BlendParam)) { // Attrs successfully blended, now get a ptr to the new attr. // Once we get the blended attr ptr, it belongs to us, so we have // to delete it when it is not needed pBlendedNodeAttr = BlendParam.GetBlendedAttr(); } } } // If we have a blended attr, pBlendedNodeAttr != NULL if (pBlendedNodeAttr != NULL) { // Get the type of the blended attr CCRuntimeClass *pTypeBlend = pBlendedNodeAttr->GetAttributeType(); void* pValBlend; // If we already have an attr in the blended attr map of the same type, // remove it and delete it, before inserting a new attr of this type if (pBlendedAttrMap->Lookup(pTypeBlend,pValBlend)) { if (pValBlend != NULL) { pBlendedAttrMap->RemoveKey(pTypeBlend); delete (NodeAttribute*)pValBlend; } } // add it to the blend map pBlendedAttrMap->SetAt(pTypeBlend,pBlendedNodeAttr); } } if (pParam->GetNodeBlendPath() != NULL) { Trans2DMatrix* pRotateStart = GetRotateMatrix(pParam->GetNodeStart(), pParam->GetAngleStart()); Trans2DMatrix* pRotateEnd = GetRotateMatrix(pParam->GetNodeEnd(), pParam->GetAngleEnd() ); if (pRotateStart) pAttrMapStart->Transform(*pRotateStart); if (pRotateEnd) pAttrMapEnd ->Transform(*pRotateEnd); if (pRotateStart) delete pRotateStart; if (pRotateEnd) delete pRotateEnd; } delete pAttrMapStart; delete pAttrMapEnd; return TRUE; }