// $Id: xpfcaps.cpp 1366 2006-06-26 11:18:18Z gerry $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ /// /* */ #include "camtypes.h" #include "xpfcaps.h" #include "xpfrgn.h" #include "cxfrgshp.h" #include "strkattr.h" #include "brshattr.h" #include "fillramp.h" #include "fthrattr.h" #include "fillattr2.h" // The implements to match the declares in the .h file. CC_IMPLEMENT_MEMDUMP(XPFCapability, CC_CLASS_MEMDUMP); CC_IMPLEMENT_MEMDUMP(XPFCComplexClass, XPFCapability); CC_IMPLEMENT_MEMDUMP(XPFCLayer, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCContour, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCShadow, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCBevel, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCBlend, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCMould, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCRectangle, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCEllipse, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCPolygon, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCBitmap, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCText, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCClipView, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCBitmapEffect, XPFCComplexClass); CC_IMPLEMENT_MEMDUMP(XPFCFill, XPFCapability); CC_IMPLEMENT_MEMDUMP(XPFCFillTrans, XPFCapability); CC_IMPLEMENT_MEMDUMP(XPFCLine, XPFCapability); CC_IMPLEMENT_MEMDUMP(XPFCLineTrans, XPFCapability); CC_IMPLEMENT_MEMDUMP(XPFCFeather, XPFCapability); CC_IMPLEMENT_MEMDUMP(XPFCColour, XPFCapability); CC_IMPLEMENT_MEMDUMP(CapabilityTree, CC_CLASS_MEMDUMP); // This will get Camelot to display the filename and linenumber of any memory allocations // that are not released at program exit #define new CAM_DEBUG_NEW XPFConvertType XPFCapability::GetConvertTypeForNode(Node* pNode) { if (!DoesNodeMatch(pNode)) return(XPFCONVTYPE_UNKNOWN); XPFConvertType Type = m_ConvertType; // Scan through the children asking any that match this node // to return the convert type XPFCapability* pCap = m_pChild; while (pCap) { XPFConvertType ThisType = pCap->GetConvertTypeForNode(pNode); if (ThisType != XPFCONVTYPE_UNKNOWN) Type = ThisType; pCap = pCap->GetNext(); } return(Type); } XPFConvertType XPFCapability::GetConvertTypeForAttrs(RenderRegion* pRegion) { if (!DoAttributesMatch(pRegion)) return(XPFCONVTYPE_UNKNOWN); XPFConvertType Type = m_ConvertType; // Scan through the children asking any that match this node // to return the convert type XPFCapability* pCap = m_pChild; while (pCap) { XPFConvertType ThisType = pCap->GetConvertTypeForAttrs(pRegion); if (ThisType != XPFCONVTYPE_UNKNOWN) Type = ThisType; pCap = pCap->GetNext(); } return(Type); } BOOL XPFCapability::AreAllChildrenText(Node* pRootNode, BOOL bPlain) { Node* pNode = pRootNode->FindFirstChild(); while (pNode) { // Check this node if (pNode->IsAnObject()) { // If it is a group then check its children if (pNode->IsAGroup() && !AreAllChildrenText(pNode, bPlain)) return(FALSE); // If it is not a text story then return false if (!IS_A(pNode, TextStory)) return(FALSE); if (bPlain && !IsTextStoryPlain(pNode)) return(FALSE); } // Move on to the next node pNode = pNode->FindNext(); } return(TRUE); } /**************************************************************************** > BOOL XPFCapability::IsTextStoryPlain(Node* pNode) Author: Gerry_Iles (Xara Group Ltd) Created: 17/08/2005 Returns: TRUE if the node only contains "plain" text, FALSE if it doesn't Purpose: This determines if a text story only contains simple text. This is currently defined as flat fill, flat fill trans, constant line width, no dash patterns etc... ****************************************************************************/ BOOL XPFCapability::IsTextStoryPlain(Node* pNode) { // TRACEUSER( "Gerry", _T("IsTextStoryPlain(%s)\n"), pNode->GetRuntimeClass()->m_lpszClassName); // If the node has children then we must loop through them testing each Node* pChild = pNode->FindFirstChild(); while (pChild) { if (!IsTextStoryPlain(pChild)) return(FALSE); pChild = pChild->FindNext(); } if (pNode->IsAnAttribute()) { NodeAttribute* pAttr = (NodeAttribute*)pNode; // These don't return a sensible value from GetAttributeIndex so // we have to check the runtime class if (pAttr->GetAttributeType() == CC_RUNTIME_CLASS(AttrFillGeometry)) { if (!pAttr->IsAFlatFill()) return(FALSE); } else if (pAttr->GetAttributeType() == CC_RUNTIME_CLASS(AttrTranspFillGeometry)) { if (!pAttr->IsAFlatFill()) return(FALSE); TranspFillAttribute* pTrans = (TranspFillAttribute*)(pAttr->GetAttributeValue()); // Get the type UINT32 Type = pTrans->GetTranspType(); // If we are flat, mix and 0% trans if (Type != TT_Mix || *(pTrans->GetStartTransp()) != 0) { return(FALSE); } } else { switch (pAttr->GetAttributeIndex()) { case ATTR_FILLGEOMETRY: case ATTR_TRANSPFILLGEOMETRY: { TRACEUSER( "Gerry", _T("FillGeometry attribute not trapped\n")); } break; case ATTR_DASHPATTERN: { DashPatternAttribute* pDash = (DashPatternAttribute*)(pAttr->GetAttributeValue()); DashPatternAttribute NoDash; // If the attribute is different to the "no dash" then return FALSE // then we do not match if (NoDash.IsDifferent(pDash)) return(FALSE); } break; case ATTR_STROKETYPE: { StrokeTypeAttrValue* pStroke = (StrokeTypeAttrValue*)(pAttr->GetAttributeValue()); StrokeTypeAttrValue DefStroke; if (!((*pStroke) == DefStroke)) return(FALSE); } break; case ATTR_VARWIDTH: { VariableWidthAttrValue* pVarWidth = (VariableWidthAttrValue*)(pAttr->GetAttributeValue()); VariableWidthAttrValue DefVarWidth; if (!((*pVarWidth) == DefVarWidth)) return(FALSE); } break; case ATTR_BRUSHTYPE: { BrushAttrValue* pBrush = (BrushAttrValue*)(pAttr->GetAttributeValue()); BrushAttrValue DefBrush; if (DefBrush.IsDifferent(pBrush)) return(FALSE); } break; case ATTR_FEATHER: { FeatherAttrValue* pFeather = (FeatherAttrValue*)(pAttr->GetAttributeValue()); if (pFeather->GetFeatherSize() != 0) return(FALSE); } break; default: break; } } } // We've got this far so there are no non-plain attributes and we can return TRUE return(TRUE); } BOOL XPFCComplexClass::DoesNodeMatch(Node* pNode) { return(pNode->IsKindOf(m_pClass)); } BOOL XPFCLayer::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); Layer* pLayer = (Layer*)pNode; // Now test the property attributes if (m_bVisible != XPFB_UNKNOWN && pLayer->IsVisible() != m_bVisible) return(FALSE); if (m_bLocked != XPFB_UNKNOWN && pLayer->IsLocked() != m_bLocked) return(FALSE); if (m_bPrintable != XPFB_UNKNOWN && pLayer->IsPrintable() != m_bPrintable) return(FALSE); if (m_bActive != XPFB_UNKNOWN && pLayer->IsActive() != m_bActive) return(FALSE); if (m_bBackground != XPFB_UNKNOWN && pLayer->IsBackground() != m_bBackground) return(FALSE); if (m_bGuide != XPFB_UNKNOWN && pLayer->IsGuide() != m_bGuide) return(FALSE); if (m_ContentOnly != XPFP_UNKNOWN) { // Currently we only support text and plaintext // Loop through subtree checking all objects // If not a text story then return false // If doing plaintext then if not plain return false if (!AreAllChildrenText(pNode, (m_ContentOnly == XPFP_CONTENTONLY_PLAINTEXT))) return(FALSE); } return(TRUE); } BOOL XPFCShadow::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); NodeShadowController* pCont = (NodeShadowController*)pNode; // Now test the property attributes if (m_Type != XPFP_UNKNOWN && pCont->GetShadowType() != m_Type) return(FALSE); return(TRUE); } BOOL XPFCBevel::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); NodeBevelController* pCont = (NodeBevelController*)pNode; // Now test the property attributes if (m_Type != XPFP_UNKNOWN && pCont->m_BevelType != m_Type) return(FALSE); if (m_Side != XPFP_UNKNOWN) { XPFProp Side = (pCont->m_bOuter) ? XPFP_BEVELSIDE_OUTER : XPFP_BEVELSIDE_INNER; if (m_Side != Side) return(FALSE); } return(TRUE); } BOOL XPFCBlend::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); NodeBlend* pBlend = (NodeBlend*)pNode; // Now test the property attributes if (m_Effect != XPFP_UNKNOWN && pBlend->GetColourBlendType() != m_Effect) return(FALSE); if (m_bOnCurve != XPFB_UNKNOWN && pBlend->IsOnACurve() != m_bOnCurve) return(FALSE); CProfileBiasGain DefaultProfile; if (m_bObjProfile != XPFB_UNKNOWN) { BOOL bBlend = (*(pBlend->GetObjectProfile()) == DefaultProfile); if (bBlend == m_bObjProfile) return(FALSE); } if (m_bAttrProfile != XPFB_UNKNOWN) { BOOL bBlend = (*(pBlend->GetAttrProfile()) == DefaultProfile); if (bBlend == m_bAttrProfile) return(FALSE); } return(TRUE); } BOOL XPFCMould::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); NodeMould* pMould = (NodeMould*)pNode; // Now test the property attributes if (m_Type != XPFP_UNKNOWN && pMould->DescribeGeometry() != m_Type) return(FALSE); if (m_bGradFill != XPFB_UNKNOWN) { // Scan story for non-plain attributes BOOL bGradFill = HasGraduatedFill(pNode); TRACEUSER( "Gerry", _T("HasGraduatedFill returned %s\n"), bGradFill ? _T("true") : _T("false")); if (bGradFill != m_bGradFill) return(FALSE); } return(TRUE); } /**************************************************************************** > BOOL XPFCMould::HasGraduatedFill(Node* pNode) Author: Gerry_Iles (Xara Group Ltd) Created: 17/08/2005 Returns: TRUE if the node contains any fills or transparencies that require perspectivised rendering. Purpose: This determines if a mould uses any attributes that will not render correctly if converted to simple shapes ****************************************************************************/ BOOL XPFCMould::HasGraduatedFill(Node* pNode) { // TRACEUSER( "Gerry", _T("HasGraduatedFill(%s)\n"), pNode->GetRuntimeClass()->m_lpszClassName); // If the node has children then we must loop through them testing each Node* pChild = pNode->FindFirstChild(); while (pChild) { if (HasGraduatedFill(pChild)) return(TRUE); pChild = pChild->FindNext(); } if (pNode->IsAnAttribute()) { NodeAttribute* pAttr = (NodeAttribute*)pNode; // These don't return a sensible value from GetAttributeIndex so // we have to check the runtime class if (pAttr->GetAttributeType() == CC_RUNTIME_CLASS(AttrFillGeometry) || pAttr->GetAttributeType() == CC_RUNTIME_CLASS(AttrTranspFillGeometry)) { if (!pAttr->IsAFlatFill()) return(TRUE); } } // We've got this far so there are no perspectivisable fills and we can return FALSE return(FALSE); } BOOL XPFCRectangle::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); NodeRegularShape* pShape = (NodeRegularShape*)pNode; if (!CXaraFileRegularShape::IsRectangle(pShape)) return(FALSE); // Now test the property attributes if (m_bComplex != XPFB_UNKNOWN && CXaraFileRegularShape::IsSimple(pShape) == m_bComplex) return(FALSE); if (m_bRounded != XPFB_UNKNOWN) { BOOL bVal = (CXaraFileRegularShape::IsRounded(pShape) != 0); if (bVal != m_bRounded) return(FALSE); } if (m_bStellated != XPFB_UNKNOWN && CXaraFileRegularShape::IsStellated(pShape) != m_bStellated) return(FALSE); if (m_bReformed != XPFB_UNKNOWN && CXaraFileRegularShape::IsReformed(pShape) != m_bReformed) return(FALSE); return(TRUE); } BOOL XPFCEllipse::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); NodeRegularShape* pShape = (NodeRegularShape*)pNode; if (!CXaraFileRegularShape::IsEllipse(pShape)) return(FALSE); // Now test the property attributes if (m_bComplex != XPFB_UNKNOWN && CXaraFileRegularShape::IsSimple(pShape) == m_bComplex) return(FALSE); return(TRUE); } BOOL XPFCPolygon::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); NodeRegularShape* pShape = (NodeRegularShape*)pNode; if (CXaraFileRegularShape::IsEllipse(pShape) || CXaraFileRegularShape::IsRectangle(pShape)) return(FALSE); // Now test the property attributes if (m_bRounded != XPFB_UNKNOWN && CXaraFileRegularShape::IsRounded(pShape) != m_bRounded) return(FALSE); if (m_bStellated != XPFB_UNKNOWN && CXaraFileRegularShape::IsStellated(pShape) != m_bStellated) return(FALSE); if (m_bReformed != XPFB_UNKNOWN && CXaraFileRegularShape::IsReformed(pShape) != m_bReformed) return(FALSE); return(TRUE); } BOOL XPFCBitmap::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); NodeBitmap* pBitmap = (NodeBitmap*)pNode; // Now test the property attributes if (m_bComplex != XPFB_UNKNOWN) { // if (CXaraFileRegularShape::IsSimple(pBitmap) == m_bComplex) return(FALSE); } if (m_bContone != XPFB_UNKNOWN) { BOOL bContone = (pBitmap->GetStartColour() != NULL) || (pBitmap->GetEndColour() != NULL); if (m_bContone != bContone) return(FALSE); } return(TRUE); } BOOL XPFCText::DoesNodeMatch(Node* pNode) { // If we aren't the correct type of node then return if (!XPFCComplexClass::DoesNodeMatch(pNode)) return(FALSE); TextStory* pStory = (TextStory*)pNode; // Now test the property attributes if (m_bOnPath != XPFB_UNKNOWN) { // Check if the text is on a path BOOL bOnPath = (pStory->GetTextPath() != NULL); if (bOnPath != m_bOnPath) return(FALSE); } if (m_bComplex != XPFB_UNKNOWN) { // Check the story matrix for any rotation or shear Matrix mStory = pStory->GetStoryMatrix(); ANGLE Rot = 0; ANGLE Shear = 0; mStory.Decompose(NULL, NULL, &Rot, &Shear, NULL, NULL); BOOL bComplex = !(Rot == 0 && Shear == 0); if (bComplex != m_bComplex) return(FALSE); } if (m_bPlain != XPFB_UNKNOWN) { // Scan story for non-plain attributes BOOL bPlain = IsTextStoryPlain(pStory); TRACEUSER( "Gerry", _T("IsTextStoryPlain returned %s\n"), bPlain ? _T("true") : _T("false")); if (bPlain != m_bPlain) return(FALSE); } if (m_bAutoKern != XPFB_UNKNOWN) { // Check if the story is auto-kerned if (pStory->IsAutoKerning() != m_bAutoKern) return(FALSE); } if (m_bJustified != XPFB_UNKNOWN) { // Check if the story uses non-left justification BOOL bJustified = IsNodeJustified(pNode); if (bJustified != m_bJustified) return(FALSE); } return(TRUE); } /**************************************************************************** > BOOL XPFCText::IsNodeJustified(Node* pNode) Author: Gerry_Iles (Xara Group Ltd) Created: 25/09/2005 Returns: TRUE if the node contains non-"left justified" text, FALSE if it only uses left justify Purpose: This determines if a text story uses non-left justification ****************************************************************************/ BOOL XPFCText::IsNodeJustified(Node* pRootNode) { // TRACEUSER( "Gerry", _T("IsNodeJustified(%s)\n"), pRootNode->GetRuntimeClass()->m_lpszClassName); // If this isn't a renderable ink node then get out if (!pRootNode->IS_KIND_OF(NodeRenderableInk)) return(FALSE); NodeRenderableInk* pInkNode = (NodeRenderableInk*)pRootNode; // We scan through the tree looking for any AttrTxtJustification nodes Node* pNode = pRootNode->FindFirstDepthFirst(); while (pNode) { // Check this node if (pNode->IsAnAttribute() && pNode->IS_KIND_OF(AttrTxtJustification)) { AttrTxtJustification* pAttr = (AttrTxtJustification*)pNode; if (pAttr->Value.justification != JLEFT) return(TRUE); } // Move on to the next node pNode = pNode->FindNextDepthFirst(pRootNode); } // No justification in the story so test the applied justification ignoring children AttrTxtJustification* pAttr = (AttrTxtJustification*)(pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTxtJustification), TRUE)); if (pAttr && pAttr->Value.justification != JLEFT) return(TRUE); // We've got this far so there are no non-left attributes and we can return FALSE return(FALSE); } BOOL XPFCFill::DoAttributesMatch(RenderRegion* pRegion) { // If this item specifies the shape property if (m_Shape != XPFB_UNKNOWN) { // Get the fill attribute from the render region ColourFillAttribute* pFill = (ColourFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_FILLGEOMETRY)); if (m_Shape != pFill->GetGeometryShape()) return(FALSE); } // If this item specifies the repeat property if (m_Repeat != XPFB_UNKNOWN) { // Get the fill repeat attribute from the render region INT32 Shape = ((ColourFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_FILLGEOMETRY)))->GetGeometryShape(); if (Shape != FILLSHAPE_FLAT) { INT32 Repeat = ((FillMappingAttribute*)(pRegion->GetCurrentAttribute(ATTR_FILLMAPPING)))->Repeat; switch (Repeat) { case XPFP_FILLREPEAT_REPEAT: if (Shape >= FILLSHAPE_FLAT && Shape <= FILLSHAPE_DIAMOND) Repeat = XPFP_FILLREPEAT_SIMPLE; break; case XPFP_FILLREPEAT_REPEATINV: if (Shape >= FILLSHAPE_FLAT && Shape <= FILLSHAPE_DIAMOND) Repeat = XPFP_FILLREPEAT_SIMPLE; break; case XPFP_FILLREPEAT_REPEATEXTRA: if (Shape >= FILLSHAPE_BITMAP && Shape <= FILLSHAPE_PLASMA) Repeat = XPFP_FILLREPEAT_SIMPLE; break; } if (m_Repeat != Repeat) return(FALSE); } } // If this item specifies the multistage property if (m_bMultistage != XPFB_UNKNOWN) { // Get the fill attribute from the render region ColourFillAttribute* pFill = (ColourFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_FILLGEOMETRY)); BOOL bMulti = (pFill->GetColourRamp() != NULL && pFill->GetColourRamp()->GetCount() > 0); if (m_bMultistage != bMulti) return(FALSE); } // If this item specifies the effect property if (m_Effect != XPFB_UNKNOWN) { ColourFillAttribute* pFill = ((ColourFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_FILLGEOMETRY))); INT32 Shape = pFill->GetGeometryShape(); if (Shape != FILLSHAPE_FLAT && Shape != FILLSHAPE_3POINT && Shape != FILLSHAPE_4POINT) { BOOL bCheckEffect = TRUE; // If it is a bitmap or fractal fill and has no colours then ignore the effect if (Shape == FILLSHAPE_BITMAP || Shape == FILLSHAPE_CLOUDS || Shape == FILLSHAPE_PLASMA) { if (pFill->GetStartColour() == NULL && pFill->GetEndColour() == NULL) bCheckEffect = FALSE; } if (bCheckEffect) { // Get the fill effect from the render region EFFECTTYPE Effect = pRegion->GetFillEffect(); if (m_Effect != Effect) return(FALSE); } } } // If this item specifies the profile property if (m_bProfile != XPFB_UNKNOWN) { // Get the fill attribute from the render region ColourFillAttribute* pFill = (ColourFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_FILLGEOMETRY)); CProfileBiasGain DefaultProfile; BOOL bProfile = !(*(pFill->GetProfilePtr()) == DefaultProfile); if (m_bProfile != bProfile) return(FALSE); } // If this item specifies the contone property if (m_bContone != XPFB_UNKNOWN) { // Get the fill attribute from the render region ColourFillAttribute* pFill = (ColourFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_FILLGEOMETRY)); if (pFill->GetGeometryShape() == FILLSHAPE_BITMAP) { BOOL bContone = (pFill->GetStartColour() != NULL) || (pFill->GetEndColour() != NULL); if (m_bContone != bContone) return(FALSE); } } return(TRUE); } BOOL XPFCFillTrans::DoAttributesMatch(RenderRegion* pRegion) { // If this item specifies the shape property if (m_Shape != XPFB_UNKNOWN) { // Get the transp attribute from the render region TranspFillAttribute* pTrans = (TranspFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY)); if (m_Shape != pTrans->GetGeometryShape()) return(FALSE); } // If this item specifies the type property if (m_Type != XPFB_UNKNOWN) { // Get the transp attribute from the render region TranspFillAttribute* pTrans = (TranspFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY)); // Get the type INT32 Type = pTrans->GetTranspType(); // If we are flat, mix and 0% trans if (Type == TT_Mix && pTrans->GetGeometryShape() == FILLSHAPE_FLAT && *(pTrans->GetStartTransp()) == 0) { // We are actually type none Type = TT_NoTranspType; } if (m_Type != Type) return(FALSE); } // If this item specifies the repeat property if (m_Repeat != XPFB_UNKNOWN) { // Get the transp and repeat attributes from the render region INT32 Repeat = ((TranspFillMappingAttribute*)(pRegion->GetCurrentAttribute(ATTR_TRANSPFILLMAPPING)))->Repeat; INT32 Shape = ((TranspFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY)))->GetGeometryShape(); switch (Repeat) { case XPFP_FILLREPEAT_REPEAT: if (Shape >= FILLSHAPE_FLAT && Shape <= FILLSHAPE_DIAMOND) Repeat = XPFP_FILLREPEAT_SIMPLE; break; case XPFP_FILLREPEAT_REPEATINV: if (Shape >= FILLSHAPE_FLAT && Shape <= FILLSHAPE_DIAMOND) Repeat = XPFP_FILLREPEAT_SIMPLE; break; case XPFP_FILLREPEAT_REPEATEXTRA: if (Shape >= FILLSHAPE_BITMAP && Shape <= FILLSHAPE_PLASMA) Repeat = XPFP_FILLREPEAT_SIMPLE; break; } if (m_Repeat != Repeat) return(FALSE); } // If this item specifies the profile property if (m_bProfile != XPFB_UNKNOWN) { // Get the fill attribute from the render region TranspFillAttribute* pFill = (TranspFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY)); CProfileBiasGain DefaultProfile; BOOL bProfile = !(*(pFill->GetProfilePtr()) == DefaultProfile); if (m_bProfile != bProfile) return(FALSE); } return(TRUE); } BOOL XPFCLine::DoAttributesMatch(RenderRegion* pRegion) { StrokeColourAttribute* pStrokeCol = (StrokeColourAttribute*)(pRegion->GetCurrentAttribute(ATTR_STROKECOLOUR)); BOOL bNoStroke = pStrokeCol->Colour.IsTransparent(); // If this item specifies the dash property if (m_bDash != XPFB_UNKNOWN) { DashPatternAttribute NoDash; // Get the dash pattern attribute from the render region DashPatternAttribute* pDash = (DashPatternAttribute*)(pRegion->GetCurrentAttribute(ATTR_DASHPATTERN)); if (bNoStroke) pDash = &NoDash; // If the attribute is the "no dash" and m_bDash is TRUE or // the attribute is not "no dash" and m_bDash is FALSE // then we do not match if (m_bDash != NoDash.IsDifferent(pDash)) return(FALSE); } // If this item specifies the arrowhead property if (m_bArrowhead != XPFB_UNKNOWN) { StartArrowAttribute DefStart; EndArrowAttribute DefEnd; // Get the arrow attributes from the render region StartArrowAttribute* pStart = (StartArrowAttribute*)(pRegion->GetCurrentAttribute(ATTR_STARTARROW)); if (bNoStroke) pStart = &DefStart; EndArrowAttribute* pEnd = (EndArrowAttribute*)(pRegion->GetCurrentAttribute(ATTR_ENDARROW)); if (bNoStroke) pEnd = &DefEnd; BOOL bHasStart = DefStart.IsDifferent(pStart); BOOL bHasEnd = DefEnd.IsDifferent(pEnd); if (m_bArrowhead != (bHasStart | bHasEnd)) return(FALSE); } // If this item specifies the cap property if (m_Cap != XPFB_UNKNOWN) { // Get the dash pattern attribute from the render region StartCapAttribute* pCap = (StartCapAttribute*)(pRegion->GetCurrentAttribute(ATTR_STARTCAP)); if (m_Cap != pCap->StartCap) return(FALSE); } // If this item specifies the join property if (m_Join != XPFB_UNKNOWN) { // Get the dash pattern attribute from the render region JoinTypeAttribute* pJoin = (JoinTypeAttribute*)(pRegion->GetCurrentAttribute(ATTR_JOINTYPE)); if (m_Join != pJoin->JoinType) return(FALSE); } // If this item specifies the stroke property if (m_bStroke != XPFB_UNKNOWN) { StrokeTypeAttrValue DefStroke; VariableWidthAttrValue DefVarWidth; // Get the attributes from the render region StrokeTypeAttrValue* pStroke = (StrokeTypeAttrValue*)(pRegion->GetCurrentAttribute(ATTR_STROKETYPE)); VariableWidthAttrValue* pVarWidth = (VariableWidthAttrValue*)(pRegion->GetCurrentAttribute(ATTR_VARWIDTH)); if (bNoStroke) { pStroke = &DefStroke; pVarWidth = &DefVarWidth; } BOOL bStroke = !(((*pStroke) == DefStroke) && ((*pVarWidth) == DefVarWidth)); if (m_bStroke != bStroke) return(FALSE); } // If this item specifies the brush property if (m_bBrush != XPFB_UNKNOWN) { BrushAttrValue DefBrush; // Get the dash pattern attribute from the render region BrushAttrValue* pBrush = (BrushAttrValue*)(pRegion->GetCurrentAttribute(ATTR_BRUSHTYPE)); if (bNoStroke) pBrush = &DefBrush; if (m_bBrush != DefBrush.IsDifferent(pBrush)) return(FALSE); } return(TRUE); } BOOL XPFCLineTrans::DoAttributesMatch(RenderRegion* pRegion) { // If this item specifies the type property if (m_Type != XPFB_UNKNOWN) { StrokeColourAttribute* pStrokeCol = (StrokeColourAttribute*)(pRegion->GetCurrentAttribute(ATTR_STROKECOLOUR)); BOOL bNoStroke = pStrokeCol->Colour.IsTransparent(); // Get the transp attribute from the render region StrokeTranspAttribute* pTrans = (StrokeTranspAttribute*)(pRegion->GetCurrentAttribute(ATTR_STROKETRANSP)); // Get the type INT32 Type = pTrans->GetTranspType(); // If we have no stroke colour or are mix and 0% trans if (bNoStroke || (Type == TT_Mix && *(pTrans->GetStartTransp()) == 0)) { // We are actually type none Type = TT_NoTranspType; } if (m_Type != Type) return(FALSE); } return(TRUE); } BOOL XPFCFeather::DoesNodeMatch(Node* pNode) { AttrFeather* pAttr = (AttrFeather*)(pNode->FindFirstChild(CC_RUNTIME_CLASS(AttrFeather))); if (pAttr && (pAttr->Value.GetFeatherSize() != 0)) return(TRUE); return(FALSE); } BOOL XPFCFeather::DoAttributesMatch(RenderRegion* pRegion) { // Get the feather attribute from the render region OffscreenAttrValue* pAttr = pRegion->GetCurrentOffscreenAttr(); if (!IS_A(pAttr, FeatherAttrValue)) return(FALSE); FeatherAttrValue* pFeather = (FeatherAttrValue*)pAttr; if (pFeather->GetFeatherSize() == 0) return(FALSE); return(TRUE); } BOOL CapabilityTree::IsRasteriseCommonTrans(UINT32 Type) { String_16 TransStr; if (Type == TT_StainGlass) TransStr = _T("stained"); else if (Type == TT_Bleach) TransStr = _T("bleach"); else if (Type == TT_CONTRAST) TransStr = _T("contrast"); else if (Type == TT_SATURATION) TransStr = _T("saturation"); else if (Type == TT_LUMINOSITY) TransStr = _T("luminosity"); else if (Type == TT_HUE) TransStr = _T("hue"); else return(FALSE); if (camStrstr(m_CommonTrans, TransStr) != NULL) return(TRUE); return(FALSE); } // Pass 1 can return the following convert types: // Spread: native, bitmap, simple // Layer: native, bitmap, simple // Objects: native, remove, simple // Attributes: native, remove // All other types are returned as native for processing in later passes XPFConvertType CapabilityTree::GetConvertTypePass1(Node* pNode, XPFRenderRegion* pRegion) { if (pNode->IsAnAttribute()) { return(XPFCONVTYPE_NATIVE); } // First we need to check for spreads and layers, returning the appropriate type if (pNode->IsSpread()) return(m_SpreadType); XPFCapability* pItem = GetObjects(); XPFConvertType Type = GetObjectsType(); while (pItem) { XPFConvertType ItemType = pItem->GetConvertTypeForNode(pNode); if (ItemType != XPFCONVTYPE_UNKNOWN) Type = ItemType; pItem = pItem->GetNext(); } if (Type != XPFCONVTYPE_NATIVE && Type != XPFCONVTYPE_REMOVE && Type != XPFCONVTYPE_SIMPLE && Type != XPFCONVTYPE_BITMAP && Type != XPFCONVTYPE_REFORMAT) Type = XPFCONVTYPE_NATIVE; return(Type); } // Pass 2 can return the following convert types: // This pass is mainly concerned with the stroked conversion type // The current state of attributes in the render region is scanned and if they result // in the stroked conversion type then that is returned otherwise native is returned XPFConvertType CapabilityTree::GetConvertTypePass2(Node* pNode, XPFRenderRegion* pRegion) { XPFConvertType Type = GetAttributesType(); XPFCapability* pItem = GetAttributes(); while (pItem) { XPFConvertType ItemType = pItem->GetConvertTypeForAttrs(pRegion); if (ItemType == XPFCONVTYPE_STROKED) Type = ItemType; pItem = pItem->GetNext(); } if (Type != XPFCONVTYPE_NATIVE && Type != XPFCONVTYPE_STROKED) Type = XPFCONVTYPE_NATIVE; return(Type); } // Pass 3 is concerned with the bitmapfill and bitmaptrans conversion types // The current state of attributes in the render region is scanned and if they result // in the bitmapfill conversion type then that is returned otherwise native is returned void CapabilityTree::GetConvertTypePass3(Node* pNode, XPFRenderRegion* pRegion, BOOL* pbFill, BOOL* pbTrans, BOOL* pbFillTrans) { XPFConvertType FillType = GetAttributesType(); XPFConvertType TransType = FillType; XPFConvertType BothType = FillType; XPFCapability* pItem = GetAttributes(); while (pItem) { XPFConvertType ItemType = pItem->GetConvertTypeForAttrs(pRegion); if (ItemType == XPFCONVTYPE_BITMAPFILL) FillType = ItemType; if (ItemType == XPFCONVTYPE_BITMAPTRANS) TransType = ItemType; if (ItemType == XPFCONVTYPE_BITMAPFILLTRANS) BothType = ItemType; pItem = pItem->GetNext(); } *pbFill = (FillType == XPFCONVTYPE_BITMAPFILL); *pbTrans = (TransType == XPFCONVTYPE_BITMAPTRANS); *pbFillTrans = (BothType == XPFCONVTYPE_BITMAPFILLTRANS); } // Pass 4 is concerned with the bitmap conversion type // The object and the current state of attributes in the render region is scanned and if they result // in the bitmap conversion type then that is returned otherwise native is returned XPFConvertType CapabilityTree::GetConvertTypePass4(Node* pNode, XPFRenderRegion* pRegion) { // This pass must NOT convert any spreads or layers to bitmap as that will // have been done during the first pass but the spread/layer node will still // be present in the tree if (pNode->IsSpread() || pNode->IsLayer()) return(XPFCONVTYPE_NATIVE); XPFConvertType Type = GetObjectsType(); XPFCapability* pItem = GetObjects(); while (pItem) { XPFConvertType ItemType = pItem->GetConvertTypeForNode(pNode); if (ItemType == XPFCONVTYPE_BITMAP) Type = ItemType; pItem = pItem->GetNext(); } if (Type != XPFCONVTYPE_NATIVE && Type != XPFCONVTYPE_BITMAP) Type = XPFCONVTYPE_NATIVE; return(Type); } // Pass 5 is concerned with the bitmapspan conversion type // The current state of attributes in the render region is scanned and if they result // in the bitmapspan conversion type then that is returned otherwise native is returned XPFConvertType CapabilityTree::GetConvertTypePass5(Node* pNode, XPFRenderRegion* pRegion) { XPFConvertType Type = GetAttributesType(); XPFCapability* pItem = GetAttributes(); while (pItem) { XPFConvertType ItemType = pItem->GetConvertTypeForAttrs(pRegion); if (ItemType == XPFCONVTYPE_BITMAPSPAN) Type = ItemType; pItem = pItem->GetNext(); } if (Type != XPFCONVTYPE_NATIVE && Type != XPFCONVTYPE_BITMAPSPAN) Type = XPFCONVTYPE_NATIVE; return(Type); }