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 } }
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 }
BOOL OpChangeLineAttribOpDesc::SetCurrentSelectedAttrib() { // Nothing to do if no current document. if (Document::GetCurrent() == NULL) { /* TRACEUSER( "JustinF", _T("No current document in OpChangeLineAttribOpDesc") "::SetCurrentSelectedAttrib\n"); */ // There is no document so blank all gadgets. SetGadgetText(String(_T(""))); return TRUE; } // Determine if there is a common attribute. NodeAttribute* pAttr; SelRange::CommonAttribResult eResult; eResult = GetApplication()-> FindSelection()-> FindCommonAttribute(GetAttribRuntimeClass(), &pAttr); // Work out what to put in the combo-box according to the returned result. UINT32 nTxtID; switch (eResult) { case SelRange::ATTR_COMMON: case SelRange::ATTR_NONE: { // If there isn't an attribute we just return (this logic is copied from the // line-width combo OpDescriptor code). if (pAttr == NULL) { /* TRACEUSER( "JustinF", _T("No attribute in OpChangeLineAttribOpDesc") "::SetCurrentSelectedAttrib\n"); */ return TRUE; } // Check for something screwy. ERROR3IF(pAttr->GetRuntimeClass() != GetAttribRuntimeClass(), "Wrong kind of attribute in OpChangeLineAttribOpDesc" "::SetCurrentSelectedAttrib"); // There is, so call the derived class to provide some text. nTxtID = ConvertAttribToStringID(pAttr); if (nTxtID == 0) { ERROR3("Unexpected attribute type in OpChangeLineAttribOpDesc" "::SetCurrentSelectedAttrib!"); return FALSE; } break; } case SelRange::ATTR_MANY: nTxtID = _R(IDS_MANY); break; default: ERROR3("Unexpected case in OpChangeLineAttribOpDesc::SetCurrentSelectedAttrib!"); return FALSE; } // Set the gadget's text. SetGadgetText(String(nTxtID)); return TRUE; }
/******************************************************************************************** > 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; }