[Date Prev][Date Next][Thread Prev][Thread Next][Thread Index]

[XaraXtreme-commits] Commit Complete



Commit by  : gerry
Repository : xara
Revision   : 1366
Date       : Mon Jun 26 12:18:21 BST 2006

Changed paths:
   M /Trunk/XaraLX/Kernel/bitmap.h
   M /Trunk/XaraLX/Kernel/rndrgn.cpp
   M /Trunk/XaraLX/Kernel/rndrgn.h
   M /Trunk/XaraLX/Kernel/xpfcaps.cpp
   M /Trunk/XaraLX/Kernel/xpfcaps.h
   M /Trunk/XaraLX/Kernel/xpfilter.cpp
   M /Trunk/XaraLX/Kernel/xpfilter.h
   M /Trunk/XaraLX/Kernel/xpfrgn.cpp
   M /Trunk/XaraLX/Kernel/xpfrgn.h
   M /Trunk/XaraLX/PreComp/camtypes.h
   M /Trunk/XaraLX/wxOil/oilbitmap.cpp
   M /Trunk/XaraLX/wxOil/oilbitmap.h
   M /Trunk/XaraLX/wxOil/xpoilflt.cpp
   M /Trunk/XaraLX/wxOil/xrc/EN/xpfres-strings.xrc

Updates to conversion system to support commontrans and onlycontent attributes and generate masked bitmaps


Diff:
Index: Trunk/XaraLX/Kernel/xpfilter.h
===================================================================
--- Trunk/XaraLX/Kernel/xpfilter.h	(revision 1365)
+++ Trunk/XaraLX/Kernel/xpfilter.h	(revision 1366)
@@ -222,6 +222,7 @@
 	BOOL m_bSaveXPEBitmaps;
 
 	BoundsWriteLevel m_BoundsLevel;
+	INT32 m_BitmapCompression;
 
 	List m_BitmapList;
 	INT32 m_BitmapCount;
Index: Trunk/XaraLX/Kernel/xpfcaps.h
===================================================================
--- Trunk/XaraLX/Kernel/xpfcaps.h	(revision 1365)
+++ Trunk/XaraLX/Kernel/xpfcaps.h	(revision 1366)
@@ -141,6 +141,9 @@
 
 typedef INT32 XPFProp;
 
+#define XPFP_CONTENTONLY_TEXT 1
+#define XPFP_CONTENTONLY_PLAINTEXT 2
+
 #define XPFP_UNKNOWN -1
 #define XPFP_SHADOWTYPE_WALL 1
 #define XPFP_SHADOWTYPE_FLOOR 2
@@ -247,6 +250,9 @@
 	virtual BOOL DoAttributesMatch(RenderRegion* pRegion) { return(FALSE); }
 	virtual BOOL DoesColourMatch(DocColour* pColour) { return(FALSE); }
 
+	BOOL AreAllChildrenText(Node* pRootNode, BOOL bPlain);
+	BOOL IsTextStoryPlain(Node* pNode);
+
 protected:
 	XPFCapability* m_pNext;
 	XPFCapability* m_pChild;
@@ -313,7 +319,8 @@
 				XPFBOOL bPrintable, 
 				XPFBOOL bActive, 
 				XPFBOOL bBackground, 
-				XPFBOOL bGuide)
+				XPFBOOL bGuide,
+				XPFProp ContentOnly)
 		: XPFCComplexClass(CC_RUNTIME_CLASS(Layer), ConvertType)
 	{
 		m_bVisible = bVisible;
@@ -322,6 +329,7 @@
 		m_bActive = bActive;
 		m_bBackground = bBackground;
 		m_bGuide = bGuide;
+		m_ContentOnly = ContentOnly;
 	}
 	virtual ~XPFCLayer()
 	{
@@ -337,6 +345,7 @@
 	XPFBOOL m_bActive;
 	XPFBOOL m_bBackground;
 	XPFBOOL m_bGuide;
+	XPFProp m_ContentOnly;
 };
 
 
@@ -693,7 +702,6 @@
 
 protected:
 	virtual BOOL DoesNodeMatch(Node* pNode);
-	BOOL IsNodePlain(Node* pNode);
 	BOOL IsNodeJustified(Node* pNode);
 
 protected:
@@ -1023,6 +1031,7 @@
 		m_bSelection = FALSE;
 		m_RasteriseDPI = 96.0;
 		m_bRasteriseAlpha = TRUE;
+		m_BitmapCompression = 200;
 		m_SpreadType = XPFCONVTYPE_NATIVE;
 		m_pObjects = NULL;
 		m_ObjectsType = XPFCONVTYPE_NATIVE;
@@ -1071,10 +1080,12 @@
 	
 	void SetSpreadType(XPFConvertType Type) { m_SpreadType = Type; }
 
-	void SetRasterise(double DPI, BOOL bAlpha)
+	void SetRasterise(double DPI, BOOL bAlpha, INT32 Compression, const String_256& CommonTrans)
 	{
 		m_RasteriseDPI = DPI;
 		m_bRasteriseAlpha = bAlpha;
+		m_BitmapCompression = Compression;
+		m_CommonTrans = CommonTrans;
 	}
 
 	void SetObjectsTree(XPFCapability* pObjects, XPFConvertType ObjectsType)
@@ -1103,6 +1114,10 @@
 
 	double GetRasteriseDPI() { return(m_RasteriseDPI); }
 	BOOL GetRasteriseAlpha() { return(m_bRasteriseAlpha); }
+	BOOL GetBitmapCompression() { return(m_BitmapCompression); }
+	BOOL HasRasteriseCommonTrans() { return(!m_CommonTrans.IsEmpty()); }
+	// Move this into cpp file when implemented
+	BOOL IsRasteriseCommonTrans(UINT32 Type);
 
 	XPFCapability* GetObjects(void) const { return(m_pObjects); }
 	XPFCapability* GetAttributes(void) const { return(m_pAttributes); }
@@ -1119,6 +1134,8 @@
 
 	double m_RasteriseDPI;
 	BOOL m_bRasteriseAlpha;
+	INT32 m_BitmapCompression;
+	String_256 m_CommonTrans;
 
 	XPFConvertType m_SpreadType;
 	
Index: Trunk/XaraLX/Kernel/xpfcaps.cpp
===================================================================
--- Trunk/XaraLX/Kernel/xpfcaps.cpp	(revision 1365)
+++ Trunk/XaraLX/Kernel/xpfcaps.cpp	(revision 1366)
@@ -187,7 +187,157 @@
 }
 
 
+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) <camelotdev@xxxxxxxx>
+	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)
"), 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
"));
+				}
+				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));
@@ -221,6 +371,17 @@
 	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);
 }
 
@@ -506,8 +667,8 @@
 	if (m_bPlain != XPFB_UNKNOWN)
 	{
 		// Scan story for non-plain attributes
-		BOOL bPlain = IsNodePlain(pStory);
-		TRACEUSER( "Gerry", _T("IsNodePlain returned %s
"), bPlain ? _T("true") : _T("false"));
+		BOOL bPlain = IsTextStoryPlain(pStory);
+		TRACEUSER( "Gerry", _T("IsTextStoryPlain returned %s
"), bPlain ? _T("true") : _T("false"));
 		if (bPlain != m_bPlain)
 			return(FALSE);
 	}
@@ -533,128 +694,6 @@
 
 /****************************************************************************
 
->	BOOL XPFCText::IsNodePlain(Node* pNode)
-
-	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
-	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 XPFCText::IsNodePlain(Node* pNode)
-{
-//	TRACEUSER( "Gerry", _T("IsNodePlain(%s)
"), pNode->GetRuntimeClass()->m_lpszClassName);
-
-	// If the node has children then we must loop through them testing each
-	Node* pChild = pNode->FindFirstChild();
-	while (pChild)
-	{
-		if (!IsNodePlain(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
"));
-				}
-				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 XPFCText::IsNodeJustified(Node* pNode)
 
 	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
@@ -1028,6 +1067,32 @@
 }
 
 
+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
@@ -1128,6 +1193,12 @@
 
 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)
Index: Trunk/XaraLX/Kernel/rndrgn.cpp
===================================================================
--- Trunk/XaraLX/Kernel/rndrgn.cpp	(revision 1365)
+++ Trunk/XaraLX/Kernel/rndrgn.cpp	(revision 1366)
@@ -382,6 +382,8 @@
 	m_fOwned = FALSE;
 	ScaleFactor = FIXED16(1);
 
+	m_bForceMix = FALSE;
+
 //	double m_dboostm = 1.0;
 //	double m_dboostc = 0.0;
 
@@ -485,6 +487,8 @@
 	m_countTotal = 0;
 	m_countStored = 0;
 
+	m_bForceMix = FALSE;
+
 #ifdef _DEBUG
 	m_CurrentContextLevel = 0;
 	m_TraceOutContextLevels = FALSE;
@@ -592,6 +596,8 @@
 	m_countTotal = other.m_countTotal;
 	m_countStored = other.m_countStored;
 
+	m_bForceMix = other.m_bForceMix;
+
 #ifdef _DEBUG
 	m_CurrentContextLevel = 0;
 	m_TraceOutContextLevels = FALSE;
@@ -2620,8 +2626,43 @@
 
 void RenderRegion::SetLineTransp(StrokeTranspAttribute *pAttr, BOOL Temp)
 {
+	StrokeTranspAttribute* pNewAttr = NULL;
+	if (m_bForceMix)
+	{
+		UINT32 Type = pAttr->GetTranspType();
+		if (Type != TT_NoTranspType &&
+			Type != TT_Mix &&
+			Type != TT_DARKEN &&
+			Type != TT_LIGHTEN &&
+			Type != TT_BRIGHTNESS &&
+			Type != TT_BEVEL)
+		{
+			if (Temp)
+			{
+				pNewAttr = pAttr;
+			}
+			else
+			{
+				pNewAttr = (StrokeTranspAttribute*)(pAttr->GetRuntimeClass()->CreateObject());
+				if (pNewAttr)
+				{
+					pNewAttr->SimpleCopy(pAttr);
+				}
+			}
+
+		}
+	}
+
+	if (pNewAttr)
+	{
+		pNewAttr->SetTranspType(TT_Mix);
+		Temp = TRUE;
+	}
+	else
+		pNewAttr = pAttr;
+
 	// Save the current attribute and set up the new one
-	if (SaveAttribute(ATTR_STROKETRANSP, pAttr, Temp))
+	if (SaveAttribute(ATTR_STROKETRANSP, pNewAttr, Temp))
 	{
 		// The line attributes need to be reset before drawing anything.
 		SetLineAttributes(CHANGEATTR_STROKETRANSP);
@@ -2996,15 +3037,50 @@
 
 void RenderRegion::SetTranspFillGeometry(TranspFillAttribute *pAttr, BOOL Temp)
 {
+	TranspFillAttribute* pNewAttr = NULL;
+	if (m_bForceMix)
+	{
+		UINT32 Type = pAttr->GetTranspType();
+		if (Type != TT_NoTranspType &&
+			Type != TT_Mix &&
+			Type != TT_DARKEN &&
+			Type != TT_LIGHTEN &&
+			Type != TT_BRIGHTNESS &&
+			Type != TT_BEVEL)
+		{
+			if (Temp)
+			{
+				pNewAttr = pAttr;
+			}
+			else
+			{
+				pNewAttr = (TranspFillAttribute*)(pAttr->GetRuntimeClass()->CreateObject());
+				if (pNewAttr)
+				{
+					pNewAttr->SimpleCopy(pAttr);
+				}
+			}
+
+		}
+	}
+
+	if (pNewAttr)
+	{
+		pNewAttr->SetTranspType(TT_Mix);
+		Temp = TRUE;
+	}
+	else
+		pNewAttr = pAttr;
+
 	// Save the current attribute
-	if (SaveAttribute(ATTR_TRANSPFILLGEOMETRY, pAttr, Temp))
+	if (SaveAttribute(ATTR_TRANSPFILLGEOMETRY, pNewAttr, Temp))
 	{
 		// The fill attributes need to be reset before drawing anything.
 		SetFillAttributes(CHANGEATTR_TRANSP_GEOMETRY);
 
 		// The capture system needs to know about non-MIX transparencies being set
 		// because it can't capture them in RGBT bitmaps...
-		UINT32 ttype = pAttr->GetTranspType();
+		UINT32 ttype = pNewAttr->GetTranspType();
 		ERROR3IF(ttype<TT_NoTranspType || ttype>TT_MAX, "Someone's trying to set an unknown transp type!");
 
 //		if (!(ttype==TT_NoTranspType || ttype==TT_Mix))
Index: Trunk/XaraLX/Kernel/xpfilter.cpp
===================================================================
--- Trunk/XaraLX/Kernel/xpfilter.cpp	(revision 1365)
+++ Trunk/XaraLX/Kernel/xpfilter.cpp	(revision 1366)
@@ -141,6 +141,7 @@
 	m_ProgressOffset = 0;
 	m_bSaveXPEBitmaps = TRUE;	// For now we will default this to saving out the bitmaps
 	m_BoundsLevel = BWL_NONE;
+	m_BitmapCompression = 200;      // Default to full PNG quality
 	m_BitmapCount = 0;
 }
 
@@ -382,6 +383,9 @@
 	// Update our bounds write level
 	m_BoundsLevel = PlugCaps.GetBoundsLevel();
 
+	// Update our bitmap compression setting
+	m_BitmapCompression = PlugCaps.GetBitmapCompression();
+
 	KernelBitmap::SetCreateTracker(&m_BitmapList);
 
 	// Convert the document according to the capabilites
@@ -765,7 +769,7 @@
 INT32 PluginNativeFilter::GetBitmapCompression()
 {
 	// Always use a lossless format such as PNG in native files
-	return 200;
+	return m_BitmapCompression;
 }
 
 /********************************************************************************************
Index: Trunk/XaraLX/Kernel/bitmap.h
===================================================================
--- Trunk/XaraLX/Kernel/bitmap.h	(revision 1365)
+++ Trunk/XaraLX/Kernel/bitmap.h	(revision 1366)
@@ -399,6 +399,8 @@
 	virtual	BOOL		RebuildXPEBitmap();
 	virtual BOOL		NeedsXPERebuild();
 
+	virtual void CopyFullyTransparentFrom(OILBitmap* pBitmap) = 0;
+
 protected:
 	String_256 m_BitmapName;
 	UINT32 m_BitmapAnimDelay;
Index: Trunk/XaraLX/Kernel/rndrgn.h
===================================================================
--- Trunk/XaraLX/Kernel/rndrgn.h	(revision 1365)
+++ Trunk/XaraLX/Kernel/rndrgn.h	(revision 1366)
@@ -712,6 +712,8 @@
 	void SetImmediateRender(BOOL SetVal)	{RenderFlags.bImmediateRender = SetVal;}
 	BOOL GetImmediateRender() const			{return RenderFlags.bImmediateRender;}
 
+	void SetForceMixTransparency(BOOL bForceMix) { m_bForceMix = bForceMix; }
+
 	/////////////////////////////////////////////////////////////////////
 	//
 	// New Capture system
@@ -933,6 +935,9 @@
 	// Used to record a connection to a filter
 	Filter* m_pFilter;
 
+	// Used to force all non-alpha compatible transparency to mix
+	BOOL m_bForceMix;
+
 //	double m_dboostm;
 //	double m_dboostc;
 
Index: Trunk/XaraLX/Kernel/xpfrgn.h
===================================================================
--- Trunk/XaraLX/Kernel/xpfrgn.h	(revision 1365)
+++ Trunk/XaraLX/Kernel/xpfrgn.h	(revision 1366)
@@ -107,6 +107,7 @@
 class TextStory;
 class TextLine;
 class FormatRegion;
+class CommonTransInfo;
 
 /********************************************************************************************
 
@@ -124,7 +125,7 @@
 	CC_DECLARE_DYNAMIC(XPFRenderRegion);
 
 	// Construction and destruction
-	XPFRenderRegion(PluginNativeFilter* pFilter, CapabilityTree* pPlugCaps);
+	XPFRenderRegion(PluginNativeFilter* pFilter, CapabilityTree* pPlugCaps, CommonTransInfo* pTransInfo = NULL);
 	~XPFRenderRegion();
 
 	virtual BOOL AttachDevice(View*, CNativeDC*, Spread* SpreadToAttach = NULL);
@@ -177,9 +178,25 @@
 protected:
 	PluginNativeFilter* m_pFilter;
 	double m_PixelsPerInch;
+	CommonTransInfo* m_pTransInfo;
 };
 
 
+class CommonTransInfo
+{
+public:
+	CommonTransInfo();
+
+	BOOL IsCommonType() { return(m_bCommonType); }
+	void UpdateCommonType(UINT32 Type);
+	UINT32 GetCommonType();
+
+protected:
+	BOOL m_bCommonType;
+	UINT32 m_CommonType;
+};
+
+
 class SpanListItem : public ListItem
 {
 public:
@@ -257,7 +274,7 @@
 	void RemoveChildAttrs(Node* pNode, CCRuntimeClass* pClass);
 	NodeAttribute* FindChildAttr(Node* pNode, CCRuntimeClass* pClass);
 
-	NodeBitmap* RenderNodesToBitmap(Node* pFirstNode, Node* pLastNode, BOOL bNonAlphaTrans);
+	Node* RenderNodesToBitmap(Node* pFirstNode, Node* pLastNode, BOOL bNonAlphaTrans);
 	KernelBitmap* RenderFillToBitmap(Node* pNode, DocRect& BoundsRect);
 	KernelBitmap* RenderTransToBitmap(Node* pNode, DocRect& BoundsRect, UINT32* pTransType);
 	KernelBitmap* RenderFillAndTransToBitmap(Node* pNode, DocRect& BoundsRect);
@@ -267,6 +284,7 @@
 	BOOL CopyAttributesFromNode(Node* pDestNode, Node* pSrcNode);
 
 	BOOL DoesNodeUseNonAlphaTrans(Node* pRootNode);
+	BOOL FindCommonTransTypeToApply(Node* pFirstNode, Node* pLastNode, UINT32* pCommonType);
 
 private:
 	INT32 m_ConvertPass;
@@ -301,117 +319,10 @@
 		m_RenderState = RS_BEFORESPAN;
 	}
 
-	virtual BOOL BeforeNode(RenderRegion* pRegion, Node* pNode)
-	{
-//		char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
-//		TRACE( _T("XPFSpanRC# BeforeNode    0x%08x - %s  %s
"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
-		
-		BOOL bRender = FALSE;
-		switch (m_RenderState)
-		{
-			case RS_BEFORESPAN:
-				if (m_bBackground || pNode->IsAnAttribute() || pNode->IsANodeClipView())
-				{
-					// Let it render normally
-					bRender = TRUE;
-				}
-				break;
+	virtual BOOL BeforeNode(RenderRegion* pRegion, Node* pNode);
+	virtual BOOL BeforeSubtree(RenderRegion* pRegion, Node* pNode, Node** ppNextNode, BOOL bClip, SubtreeRenderState* pState);
+	virtual BOOL AfterSubtree(RenderRegion* pRegion, Node* pNode);
 
-			case RS_INSPAN:
-				bRender = TRUE;
-				break;
-			
-			case RS_AFTERSPAN:
-				// Must skip everything until the end
-				bRender = FALSE;
-				break;
-
-			default:
-				TRACE( _T("XPFSpanRC# Bad RenderState in BeforeNode
"));
-				break;
-		}			
-//		TRACE( _T("XPFSpanRC# BeforeNode    0x%08x - %s	returning %s
", pNode, pNode->GetRuntimeClass()->m_lpszClassName, bRender ? "true" : "false"));
-		return(bRender);
-	}
-
-	virtual BOOL BeforeSubtree(RenderRegion* pRegion, Node* pNode, Node** ppNextNode, BOOL bClip, SubtreeRenderState* pState)
-	{
-//		char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
-//		TRACE( _T("XPFSpanRC# BeforeSubtree 0x%08x - %s  %s
"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
-
-		switch (m_RenderState)
-		{
-			case RS_BEFORESPAN:
-				if (pNode == m_pFirstNode)
-				{
-//					TRACE( _T("XPFSpanRC# Start of span
"));
-					// Change state to be in the span
-					m_RenderState = RS_INSPAN;
-				}
-				else if (!pNode->IsAnAttribute() && !m_bBackground && !pNode->IsNodeInSubtree(m_pFirstNode))
-				{
-					// The first node isn't in this subtree so don't bother rendering it
-					*pState = SUBTREE_NORENDER;
-					return(TRUE);
-				}
-				break;
-
-			case RS_INSPAN:
-				break;
-
-			case RS_AFTERSPAN:
-				// Don't render this subtree
-				*pState = SUBTREE_NORENDER;
-				return(TRUE);
-				break;
-
-			default:
-				TRACE( _T("XPFSpanRC# Bad RenderState in BeforeSubtree
"));
-				break;
-		}			
-		
-		return(FALSE);
-	}
-		
-	virtual BOOL AfterSubtree(RenderRegion* pRegion, Node* pNode)
-	{
-//		char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
-//		TRACE( _T("XPFSpanRC# AfterSubtree    0x%08x - %s  %s
"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
-
-		// By default we do want RenderAfterSubtree to be called
-		BOOL bStopRender = FALSE;
-		switch (m_RenderState)
-		{
-			case RS_BEFORESPAN:
-				if (!m_bBackground && !pNode->IsNodeInSubtree(m_pFirstNode))
-				{
-					// The first node isn't in this subtree so don't bother rendering it
-					bStopRender = TRUE;
-				}
-				break;
-
-			case RS_INSPAN:
-				if (pNode == m_pLastNode)
-				{
-//					TRACE( _T("XPFSpanRC# End of span
"));
-					// Change state to be after the span
-					m_RenderState = RS_AFTERSPAN;
-				}
-				break;
-			
-			case RS_AFTERSPAN:
-				// Must skip everything until the end
-				bStopRender = TRUE;
-				break;
-
-			default:
-				TRACE( _T("XPFSpanRC# Bad RenderState in AfterSubtree
"));
-				break;
-		}			
-//		TRACE( _T("XPFSpanRC# AfterSubtree  0x%08x - %s	returning %s
", pNode, pNode->GetRuntimeClass()->m_lpszClassName, bStopRender ? "true" : "false"));
-		return(bStopRender);
-	}
-
 protected:
 	Node* m_pFirstNode;					// pointer to first node in span
 	Node* m_pLastNode;					// pointer to last node in span
Index: Trunk/XaraLX/Kernel/xpfrgn.cpp
===================================================================
--- Trunk/XaraLX/Kernel/xpfrgn.cpp	(revision 1365)
+++ Trunk/XaraLX/Kernel/xpfrgn.cpp	(revision 1366)
@@ -135,7 +135,9 @@
 
 /********************************************************************************************
 
->	XPFRenderRegion::XPFRenderRegion(PluginNativeFilter* pFilter, CapabilityTree* pPlugCaps)
+>	XPFRenderRegion::XPFRenderRegion(PluginNativeFilter* pFilter, 
+										CapabilityTree* pPlugCaps, 
+										CommonTransInfo* pTransInfo)
 
 	Author:		Rik_Heywood (Xara Group Ltd) <camelotdev@xxxxxxxx>
 	Created:	6/4/95
@@ -144,10 +146,11 @@
 
 ********************************************************************************************/
 
-XPFRenderRegion::XPFRenderRegion(PluginNativeFilter* pFilter, CapabilityTree* pPlugCaps)
+XPFRenderRegion::XPFRenderRegion(PluginNativeFilter* pFilter, CapabilityTree* pPlugCaps, CommonTransInfo* pTransInfo)
 {
 	m_pFilter = pFilter;
-	m_PixelsPerInch = pPlugCaps->GetRasteriseDPI();
+	m_PixelsPerInch = pPlugCaps ? pPlugCaps->GetRasteriseDPI() : 96.0;
+	m_pTransInfo = pTransInfo;
 }
 
 
@@ -238,6 +241,41 @@
 
 void XPFRenderRegion::DrawPathToOutputDevice(Path* pPathToRender, PathShape)
 {
+	if (m_pTransInfo && m_pTransInfo->IsCommonType())
+	{
+		// Path rendering happens in two parts, the fill and the stroke
+		// so these must be checked separately
+
+		if (pPathToRender->IsFilled)
+		{
+			// Get the fill attribute
+			FillGeometryAttribute* pFillAttr = (FillGeometryAttribute*) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
+			
+			// If it is not a no-colour flat fill then
+
+			if (!IS_A(pFillAttr, FlatFillAttribute) || !(RR_FILLCOLOUR().IsTransparent()))
+			{
+				// Get the current Transparency Fill Geometry
+				TranspFillAttribute* pTransAttr = RR_FILLTRANSP();
+
+				// And update the common type object
+				m_pTransInfo->UpdateCommonType(pTransAttr->GetTranspType());
+			}
+		}
+
+		if (pPathToRender->IsStroked)
+		{
+			// If the stroke colour is not transparent
+			if (!(RR_STROKECOLOUR().IsTransparent()))
+			{
+				// Get the current Transparency Fill Geometry
+				StrokeTranspAttribute* pTransAttr = RR_STROKETRANSP();
+
+				// And update the common type object
+				m_pTransInfo->UpdateCommonType(pTransAttr->GetTranspType());
+			}
+		}
+	}
 }
 
 
@@ -1031,7 +1069,7 @@
 					BOOL bNonAlphaTrans = DoesNodeUseNonAlphaTrans(pNode);
 					TRACEUSER("Gerry", _T("XPFRC# Converting %s to bitmap (%s)
"), pNode->GetRuntimeClass()->m_lpszClassName, bNonAlphaTrans ? _T("NonAlpha") : _T("Alpha"));
 
-					NodeBitmap* pNodeToAttach = RenderNodesToBitmap(pNode, pNode, bNonAlphaTrans);
+					Node* pNodeToAttach = RenderNodesToBitmap(pNode, pNode, bNonAlphaTrans);
 					if (pNodeToAttach)
 					{
 						// Attach the new node into the output tree
@@ -1500,40 +1538,44 @@
 	// transparency types (anywhere in its subtree)
 
 	// If this isn't a renderable ink node then get out
-	if (!pRootNode->IS_KIND_OF(NodeRenderableInk))
-		return(FALSE);
+	// It might be a layer or spread which are paper nodes!
+//	if (!pRootNode->IS_KIND_OF(NodeRenderableInk))
+//		return(FALSE);
 
-	NodeRenderableInk* pInkNode = (NodeRenderableInk*)pRootNode;
-	// Basically, it just needs to check any transparency attributes
-	// First it needs to check the attributes applied above this node in the tree
+	if (pRootNode->IsAnObject())
+	{
+		NodeRenderableInk* pInkNode = (NodeRenderableInk*)pRootNode;
+		// Basically, it just needs to check any transparency attributes
+		// First it needs to check the attributes applied above this node in the tree
 
-	AttrStrokeTransp* pStrkAttr = (AttrStrokeTransp*)(pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeTransp), TRUE));
-	if (pStrkAttr)
-	{
-		UINT32 Type = pStrkAttr->GetTranspType();
-		if (Type != TT_NoTranspType &&
-			Type != TT_Mix &&
-			Type != TT_DARKEN &&
-			Type != TT_LIGHTEN &&
-			Type != TT_BRIGHTNESS &&
-			Type != TT_BEVEL)
+		AttrStrokeTransp* pStrkAttr = (AttrStrokeTransp*)(pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeTransp), TRUE));
+		if (pStrkAttr)
 		{
-			return(TRUE);
+			UINT32 Type = pStrkAttr->GetTranspType();
+			if (Type != TT_NoTranspType &&
+				Type != TT_Mix &&
+				Type != TT_DARKEN &&
+				Type != TT_LIGHTEN &&
+				Type != TT_BRIGHTNESS &&
+				Type != TT_BEVEL)
+			{
+				return(TRUE);
+			}
 		}
-	}
 
-	AttrFillGeometry* pFillAttr = (AttrFillGeometry*)(pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry), TRUE));
-	if (pFillAttr)
-	{
-		UINT32 Type = pFillAttr->GetTranspType();
-		if (Type != TT_NoTranspType &&
-			Type != TT_Mix &&
-			Type != TT_DARKEN &&
-			Type != TT_LIGHTEN &&
-			Type != TT_BRIGHTNESS &&
-			Type != TT_BEVEL)
+		AttrFillGeometry* pFillAttr = (AttrFillGeometry*)(pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry), TRUE));
+		if (pFillAttr)
 		{
-			return(TRUE);
+			UINT32 Type = pFillAttr->GetTranspType();
+			if (Type != TT_NoTranspType &&
+				Type != TT_Mix &&
+				Type != TT_DARKEN &&
+				Type != TT_LIGHTEN &&
+				Type != TT_BRIGHTNESS &&
+				Type != TT_BEVEL)
+			{
+				return(TRUE);
+			}
 		}
 	}
 
@@ -2028,12 +2070,12 @@
 
 			// Render the node span to a bitmap
 			BOOL bNonAlphaTrans = DoesNodeUseNonAlphaTrans(pNode);
-			NodeBitmap* pNodeBmp = RenderNodesToBitmap(pNode, pNode, bNonAlphaTrans);
-			if (!pNodeBmp)
+			Node* pNewNode = RenderNodesToBitmap(pNode, pNode, bNonAlphaTrans);
+			if (!pNewNode)
 				return(FALSE);
 
 			// Attach the new node as the previous of the first in the span
-			pNodeBmp->AttachNode(pNode, PREV);
+			pNewNode->AttachNode(pNode, PREV);
 
 			// Delete the node we have just replaced
 			pNode->CascadeDelete();
@@ -2081,12 +2123,12 @@
 		TRACEUSER( "Gerry", _T("SpanListItem 0x%08x (%s) to 0x%08x (%s)
"), pItem->m_pFirstNode, pItem->m_pFirstNode->GetRuntimeClass()->m_lpszClassName, pItem->m_pLastNode, pItem->m_pLastNode->GetRuntimeClass()->m_lpszClassName);
 
 		// Render the node span to a bitmap
-		NodeBitmap* pNodeBmp = RenderNodesToBitmap(pItem->m_pFirstNode, pItem->m_pLastNode, pItem->m_bNonAlphaTrans);
-		if (!pNodeBmp)
+		Node* pNewNode = RenderNodesToBitmap(pItem->m_pFirstNode, pItem->m_pLastNode, pItem->m_bNonAlphaTrans);
+		if (!pNewNode)
 			return(FALSE);
 
 		// Attach the new node as the previous of the first in the span
-		pNodeBmp->AttachNode(pItem->m_pFirstNode, PREV);
+		pNewNode->AttachNode(pItem->m_pFirstNode, PREV);
 
 		// Delete all the nodes in the span
 		Node* pNode = pItem->m_pFirstNode;
@@ -2115,10 +2157,75 @@
 }
 
 
+/****************************************************************************
 
+>	BOOL XPFRenderCallback::FindCommonTransTypeToApply(Node* pFirstNode, Node* pLastNode, UINT32* pCommonType)
+
+	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
+	Created:	15/06/2006
+
+	Inputs:		pFirstNode	- pointer to a Node
+				pLastNode	- pointer to a Node
+				pCommonType	- pointer to a UINT32
+	Returns:	TRUE if ok, FALSE if bother
+	Purpose:	
+
+****************************************************************************/
+
+BOOL XPFRenderCallback::FindCommonTransTypeToApply(Node* pFirstNode, Node* pLastNode, UINT32* pCommonType)
+{
+	// If CommonTrans isn't set then return false
+	if (!m_pCapTree->HasRasteriseCommonTrans())
+		return(FALSE);
+	
+	// Render the node span using an XPFRenderRegion and XPFSpanRenderCallback
+	// to track the transparency used
+	View *pView = View::GetCurrent();
+	Spread* pSpread = pFirstNode->FindParentSpread();;
+
+	CommonTransInfo TransInfo;
+	
+	// Create and set up a new XPFRenderRegion
+	XPFRenderRegion XPFRegion(NULL, NULL, &TransInfo);
+
+	// Attach a device to the scanning render region
+	// Since this rr does no real rendering, it does not need a Device context
+	XPFRegion.AttachDevice(pView, NULL, pSpread);
+
+	// Start the render region and return if it fails
+	if (XPFRegion.StartRender())
+	{			
+		TRACEUSER( "Gerry", _T("Rendering nodes from 0x%08x to 0x%08x
"), pFirstNode, pLastNode);
+		XPFSpanRenderCallback SpanCallback(pFirstNode, pLastNode, FALSE);
+		// Call RenderTree to do the rendering
+		XPFRegion.RenderTree(pSpread, FALSE, FALSE, &SpanCallback);
+
+		// Thats all the nodes rendered, so stop rendering
+		XPFRegion.StopRender();
+
+		// Check the CommonTransInfo
+		if (TransInfo.IsCommonType())
+		{
+			UINT32 CommonType = TransInfo.GetCommonType();
+			if (CommonType != TT_Mix)
+			{
+				*pCommonType = CommonType;
+				return(TRUE);
+			}
+		}
+	}
+	else
+	{
+		ERROR2(FALSE, "StartRender failed");
+	}
+
+	return(FALSE);
+}
+
+
 /****************************************************************************
 
->	NodeBitmap* XPFRenderCallback::RenderNodesToBitmap(Node* pFirstNode, Node* pLastNode, BOOL bNonAlphaTrans)
+>	Node* XPFRenderCallback::RenderNodesToBitmap(Node* pFirstNode, Node* pLastNode, BOOL bNonAlphaTrans)
 
 	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
 	Created:	31/10/2005
@@ -2134,14 +2241,49 @@
 
 ****************************************************************************/
 
-NodeBitmap* XPFRenderCallback::RenderNodesToBitmap(Node* pFirstNode, Node* pLastNode, BOOL bNonAlphaTrans)
+Node* XPFRenderCallback::RenderNodesToBitmap(Node* pFirstNode, Node* pLastNode, BOOL bNonAlphaTrans)
 {
+	// First we detect the single layer case for various bits of special handling
+	BOOL bOldLayerVisibility = FALSE;
+	Layer* pSingleLayer = NULL;
+	Spread* pSingleSpread = NULL;
+	if (pFirstNode == pLastNode)
+	{
+		if (pFirstNode->IsLayer())
+		{
+			pSingleLayer = (Layer*)pFirstNode;
+			bOldLayerVisibility = pSingleLayer->GetVisibleFlagState();
+			pSingleLayer->SetVisible(TRUE);
+		}
+		if (pFirstNode->IsSpread())
+		{
+			pSingleSpread = (Spread*)pFirstNode;
+		}
+	}
+	
 	// Find the bounding rect of the nodes and determine if the background needs
 	// to be rendered
 	DocRect SpanBounds;
-	BOOL bBackground = bNonAlphaTrans;
-	if (!m_pCapTree->GetRasteriseAlpha())
+	BOOL bBackground = FALSE;
+	BOOL bForceMix = FALSE;
+	BOOL bAlpha = m_pCapTree->GetRasteriseAlpha();
+	UINT32 TransToApply = TT_NoTranspType;
+	if (!bAlpha)
+	{
 		bBackground = TRUE;
+	}
+	else
+	{
+		if (FindCommonTransTypeToApply(pFirstNode, pLastNode, &TransToApply))
+		{
+			bBackground = FALSE;
+			bForceMix = TRUE;
+		}
+		else
+		{
+			bBackground = bNonAlphaTrans;
+		}
+	}
 
 	Node* pNode = pFirstNode;
 	while (pNode)
@@ -2165,59 +2307,125 @@
 	FIXED16 TempScale(1.0);
 	double Dpi = m_pCapTree->GetRasteriseDPI();
 
-	// Make sure that SpanBounds wont end up as a zero-sized rectangle
+	// Make sure that SpanBounds is an exact multiple of pixels and is at 
+	// pixel multiples and is not zero-sized
 	double MPPerPix = 72000.0 / Dpi;
+
+	INT32 IntVal = (INT32)floor((double)SpanBounds.lo.x / MPPerPix);
+	SpanBounds.lo.x = (INT32)floor((double)IntVal * MPPerPix);
+	IntVal = (INT32)floor((double)SpanBounds.lo.y / MPPerPix);
+	SpanBounds.lo.y = (INT32)floor((double)IntVal * MPPerPix);
+	IntVal = (INT32)ceil((double)SpanBounds.hi.x / MPPerPix);
+	SpanBounds.hi.x = (INT32)ceil((double)IntVal * MPPerPix);
+	IntVal = (INT32)ceil((double)SpanBounds.hi.y / MPPerPix);
+	SpanBounds.hi.y = (INT32)ceil((double)IntVal * MPPerPix);
+
 	if (SpanBounds.Width() < MPPerPix)
-		SpanBounds.hi.x = SpanBounds.lo.x + (INT32)(MPPerPix + 0.5);
+		SpanBounds.hi.x = (INT32)ceil((double)SpanBounds.lo.x + MPPerPix);
 	if (SpanBounds.Height() < MPPerPix)
-		SpanBounds.hi.y = SpanBounds.lo.y + (INT32)(MPPerPix + 0.5);
+		SpanBounds.hi.y = (INT32)ceil((double)SpanBounds.lo.y + MPPerPix);
 
+	// Create a full 32bpp RGBA for the mask
+	// This is so that the antialiased pixels are handled correctly in the mask
+	// Rendering into a 1bpp mask only sets half of the edge pixels that an 
+	// anti-aliased render does and the mask spreading feature doesn't correctly 
+	// account for the difference
+	GRenderBitmap MaskBitmap(SpanBounds, ViewTrans, TempScale, 32, Dpi);
+	if (bBackground && bAlpha)
+	{
+		MaskBitmap.m_DoCompression = TRUE;
+		MaskBitmap.AttachDevice(pView, NULL, pSpread);
+
+		if (MaskBitmap.StartRender())
+		{
+			// Save the context here so we can clear everything up later
+			MaskBitmap.SaveContext();
+
+			// Best quality please
+			QualityAttribute *pQualAttr = new QualityAttribute();
+			pQualAttr->QualityValue.SetQuality(QUALITY_MAX);
+			MaskBitmap.SetQuality(pQualAttr, TRUE);
+
+			XPFSpanRenderCallback MaskCallback(pFirstNode, pLastNode, FALSE);
+			MaskBitmap.RenderTree(pSpread, FALSE, FALSE, &MaskCallback);
+
+			// Save the context here so we can clear everything up later
+			MaskBitmap.RestoreContext();
+
+			// Tell the render region we are done rendering
+			MaskBitmap.StopRender();
+		}
+	}
+
 	GRenderBitmap BitmapRR(SpanBounds, ViewTrans, TempScale, 32, Dpi);
 	if (!bBackground)
 		BitmapRR.m_DoCompression = TRUE;
+	BitmapRR.SetForceMixTransparency(bForceMix);
+	BitmapRR.SetUsingSmoothedBitmaps(TRUE);		// Make sure we do high quality
 	BitmapRR.AttachDevice(pView, NULL, pSpread);
 
 	// Start rendering into the bitmap
-	if (!BitmapRR.StartRender())
+	if (BitmapRR.StartRender())
 	{
-		ERROR2(NULL, "StartRender failed in RenderNodesToBitmap");
-	}
+		// Save the context here so we can clear everything up later
+		BitmapRR.SaveContext();
 
-	// Save the context here so we can clear everything up later
-	BitmapRR.SaveContext();
+		if (bBackground)
+		{
+			// Draw required background
+			DocRect DrawRect = SpanBounds;
+			// Inflate the rect by 2 pixels
+			DrawRect.Inflate( (INT32)(2*72000.0/Dpi + 0.5) );
 
-	if (bBackground)
-	{
-		// Draw required background
-		DocRect DrawRect = SpanBounds;
-		// Inflate the rect by 2 pixels
-		DrawRect.Inflate( (INT32)(2*72000.0/Dpi + 0.5) );
+			BitmapRR.SaveContext();
+			DocColour White(255,255,255);
+			BitmapRR.SetFillColour(White);
+			BitmapRR.DrawRect(&DrawRect);
+			BitmapRR.RestoreContext();
+		}
 
-		BitmapRR.SaveContext();
-		BitmapRR.SetFillColour(COLOUR_WHITE);
-		BitmapRR.DrawRect(&DrawRect);
-		BitmapRR.RestoreContext();
-	}
+		// Best quality please
+		QualityAttribute *pQualAttr = new QualityAttribute();
+		pQualAttr->QualityValue.SetQuality(QUALITY_MAX);
+		BitmapRR.SetQuality(pQualAttr, TRUE);
 
-	// Best quality please
-	QualityAttribute *pQualAttr = new QualityAttribute();
-	pQualAttr->QualityValue.SetQuality(QUALITY_MAX);
-	BitmapRR.SetQuality(pQualAttr, TRUE);
+		// Render the relevant span of the tree
+		TRACEUSER("Gerry", _T("Rendering nodes from 0x%08x to 0x%08x%s
"), pFirstNode, pLastNode, bBackground ? _T(" with background") : _T(""));
+		XPFSpanRenderCallback SpanCallback(pFirstNode, pLastNode, bBackground);
+		BitmapRR.RenderTree(pSpread, FALSE, FALSE, &SpanCallback);
 
-	// Render the relevant span of the tree
-	TRACEUSER("Gerry", _T("Rendering nodes from 0x%08x to 0x%08x%s
"), pFirstNode, pLastNode, bBackground ? _T(" with background") : _T(""));
-	XPFSpanRenderCallback SpanCallback(pFirstNode, pLastNode, bBackground);
-	BitmapRR.RenderTree(pSpread, FALSE, FALSE, &SpanCallback);
+		// This should stop any captures
+		BitmapRR.RestoreContext();
 
-	// This should stop any captures
-	BitmapRR.RestoreContext();
+		// Stop rendering
+		BitmapRR.StopRender();
 
-	// Stop rendering
-	BitmapRR.StopRender();
+		// Reset the layer visiblity to the correct value
+		if (pSingleLayer)
+			pSingleLayer->SetVisible(bOldLayerVisibility);
+	}
+	else
+	{
+		ERROR2(NULL, "StartRender failed in RenderNodesToBitmap");
+	}
 
+	// Get the rendered OILBitmap
 	OILBitmap* pFullBitmap = BitmapRR.ExtractBitmap();
-	String_256 BmpName = m_pFilter->GetNewBitmapName();
+	String_256 BmpName(m_pFilter->GetNewBitmapName());
 	pFullBitmap->SetName(BmpName);
+
+	if (bBackground && bAlpha)
+	{
+		// Merge in the mask info to knock out the surrounding areas
+		OILBitmap* pMaskBitmap = MaskBitmap.ExtractBitmap();
+		pFullBitmap->CopyFullyTransparentFrom(pMaskBitmap);
+
+		// We can't delete an OILBitmap directly so we create a 
+		// KernelBitmap and then delete that
+		KernelBitmap* pTempBmp = KernelBitmap::MakeKernelBitmap(pMaskBitmap);
+		delete pTempBmp;
+	}
+	
 	KernelBitmap* pRealBmp = KernelBitmap::MakeKernelBitmap(pFullBitmap);
 
 	// Attach the bitmap to this document or a copy will be created when 
@@ -2232,16 +2440,55 @@
 
 	// Create a NodeBitmap not in the tree
 	NodeBitmap* pNodeBmp = new NodeBitmap();
-	if (!pNodeBmp)
-	{
-		return(NULL);
-	}
+	ERROR2IF(!pNodeBmp, NULL, "Failed to create NodeBitmap");
 
 	pNodeBmp->SetUpPath();
 	pNodeBmp->CreateShape(SpanBounds);
 	pNodeBmp->BitmapRef.Attach(pRealBmp);		// Attach the correct bitmap
 	pNodeBmp->ApplyDefaultBitmapAttrs(NULL);	// Apply the correct attrs
 
+	// If we should be applying a non-mix transparency then do so
+	if (TransToApply != TT_NoTranspType && TransToApply != TT_Mix)
+	{
+		AttrFlatTranspFill* pTrans = new AttrFlatTranspFill(pNodeBmp, FIRSTCHILD);
+		if (pTrans)
+		{
+			pTrans->SetTranspType(TransToApply);
+			UINT32 TransVal = 0;
+			pTrans->SetStartTransp(&TransVal);
+		}
+	}
+
+	if (pSingleSpread)
+	{
+		// Copy the spread and create a default layer
+		Spread* pNewSpread = (Spread*)(pSingleSpread->PublicCopy());
+		ERROR2IF(!pNewSpread, NULL, "Failed to create Spread");
+
+		Layer* pNewLayer = new Layer(pNewSpread, FIRSTCHILD, String_256("Layer 1"));
+		ERROR2IF(!pNewLayer, NULL, "Failed to create Layer");
+
+		// Attach the NodeBitmap as the first child of the new layer
+		pNodeBmp->AttachNode(pNewLayer, FIRSTCHILD);
+
+		// Return the new spread node
+		return(pNewSpread);
+	}
+
+	if (pSingleLayer)
+	{
+		// Create a shallow copy of the layer
+		Layer* pNewLayer = (Layer*)(pSingleLayer->PublicCopy());
+		ERROR2IF(!pNewLayer, NULL, "Failed to create Layer");
+
+		// Attach the NodeBitmap as the first child of the new layer
+		pNodeBmp->AttachNode(pNewLayer, FIRSTCHILD);
+
+		// Return the new layer node
+		return(pNewLayer);
+	}
+
+	// Just return the NodeBitmap
 	return(pNodeBmp);
 }
 
@@ -2658,6 +2905,200 @@
 
 /****************************************************************************
 
+>	BOOL XPFSpanRenderCallback::BeforeNode(RenderRegion* pRegion, Node* pNode)
+
+	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
+	Created:	19/06/2006
+
+	Inputs:		pRegion		- pointer to a RenderRegion
+				pNode		- pointer to a Node
+	Returns:	TRUE if ok, FALSE if bother
+	Purpose:	
+
+****************************************************************************/
+
+BOOL XPFSpanRenderCallback::BeforeNode(RenderRegion* pRegion, Node* pNode)
+{
+//	char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
+//	TRACE( _T("XPFSpanRC# BeforeNode    0x%08x - %s  %s
"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
+	
+	BOOL bRender = FALSE;
+	switch (m_RenderState)
+	{
+		case RS_BEFORESPAN:
+			if (m_bBackground || pNode->IsAnAttribute() || pNode->IsANodeClipView())
+			{
+				// Let it render normally
+				bRender = TRUE;
+			}
+			break;
+
+		case RS_INSPAN:
+			bRender = TRUE;
+			break;
+		
+		case RS_AFTERSPAN:
+			// Must skip everything until the end
+			bRender = FALSE;
+			break;
+
+		default:
+			TRACE( _T("XPFSpanRC# Bad RenderState in BeforeNode
"));
+			break;
+	}			
+
+//	TRACE( _T("XPFSpanRC# BeforeNode    0x%08x - %s	returning %s
", pNode, pNode->GetRuntimeClass()->m_lpszClassName, bRender ? "true" : "false"));
+	return(bRender);
+}
+
+
+/****************************************************************************
+
+>	BOOL XPFSpanRenderCallback::BeforeSubtree(RenderRegion* pRegion, Node* pNode, Node** ppNextNode, BOOL bClip, SubtreeRenderState* pState)
+
+	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
+	Created:	19/06/2006
+
+	Inputs:		pRegion		- pointer to a RenderRegion
+				pNode		- pointer to a Node
+				ppNextNode	- pointer to a pointer to a Node
+				bClip		- 
+				pState		- pointer to a SubtreeRenderState
+	Returns:	TRUE if ok, FALSE if bother
+	Purpose:	
+
+****************************************************************************/
+
+BOOL XPFSpanRenderCallback::BeforeSubtree(RenderRegion* pRegion, Node* pNode, Node** ppNextNode, BOOL bClip, SubtreeRenderState* pState)
+{
+//	char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
+//	TRACE( _T("XPFSpanRC# BeforeSubtree 0x%08x - %s  %s
"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
+
+	switch (m_RenderState)
+	{
+		case RS_BEFORESPAN:
+			if (pNode == m_pFirstNode)
+			{
+//				TRACE( _T("XPFSpanRC# Start of span
"));
+				// Change state to be in the span
+				m_RenderState = RS_INSPAN;
+			}
+			else if (!pNode->IsAnAttribute() && !m_bBackground && !pNode->IsNodeInSubtree(m_pFirstNode))
+			{
+				// The first node isn't in this subtree so don't bother rendering it
+				*pState = SUBTREE_NORENDER;
+				return(TRUE);
+			}
+			break;
+
+		case RS_INSPAN:
+			break;
+
+		case RS_AFTERSPAN:
+			// Don't render this subtree
+			*pState = SUBTREE_NORENDER;
+			return(TRUE);
+			break;
+
+		default:
+			TRACE( _T("XPFSpanRC# Bad RenderState in BeforeSubtree
"));
+			break;
+	}			
+	
+	return(FALSE);
+}
+		
+
+/****************************************************************************
+
+>	BOOL XPFSpanRenderCallback::AfterSubtree(RenderRegion* pRegion, Node* pNode)
+
+	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
+	Created:	19/06/2006
+
+	Inputs:		pRegion		- pointer to a RenderRegion
+				pNode		- pointer to a Node
+	Returns:	TRUE if ok, FALSE if bother
+	Purpose:	
+
+****************************************************************************/
+
+BOOL XPFSpanRenderCallback::AfterSubtree(RenderRegion* pRegion, Node* pNode)
+{
+//	char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
+//	TRACE( _T("XPFSpanRC# AfterSubtree    0x%08x - %s  %s
"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
+
+	// By default we do want RenderAfterSubtree to be called
+	BOOL bStopRender = FALSE;
+	switch (m_RenderState)
+	{
+		case RS_BEFORESPAN:
+			if (!m_bBackground && !pNode->IsNodeInSubtree(m_pFirstNode))
+			{
+				// The first node isn't in this subtree so don't bother rendering it
+				bStopRender = TRUE;
+			}
+			break;
+
+		case RS_INSPAN:
+			if (pNode == m_pLastNode)
+			{
+//				TRACE( _T("XPFSpanRC# End of span
"));
+				// Change state to be after the span
+				m_RenderState = RS_AFTERSPAN;
+			}
+			break;
+		
+		case RS_AFTERSPAN:
+			// Must skip everything until the end
+			bStopRender = TRUE;
+			break;
+
+		default:
+			TRACE( _T("XPFSpanRC# Bad RenderState in AfterSubtree
"));
+			break;
+	}			
+//	TRACE( _T("XPFSpanRC# AfterSubtree  0x%08x - %s	returning %s
", pNode, pNode->GetRuntimeClass()->m_lpszClassName, bStopRender ? "true" : "false"));
+	return(bStopRender);
+}
+
+
+
+CommonTransInfo::CommonTransInfo()
+{
+	m_bCommonType = TRUE;
+	m_CommonType = TT_NoTranspType;
+}
+
+void CommonTransInfo::UpdateCommonType(UINT32 Type)
+{
+	if (m_bCommonType)
+	{
+		if (Type == TT_NoTranspType ||
+			Type == TT_DARKEN ||
+			Type == TT_LIGHTEN ||
+			Type == TT_BRIGHTNESS ||
+			Type == TT_BEVEL)
+		{
+			Type = TT_Mix;		// These are all mix
+		}
+
+		if (m_CommonType == TT_NoTranspType)
+			m_CommonType = Type;
+		else if (m_CommonType != Type)
+			m_bCommonType = FALSE;
+	}
+}
+
+UINT32 CommonTransInfo::GetCommonType()
+{
+	return(m_bCommonType ? m_CommonType : TT_NoTranspType);
+}
+
+
+
+/****************************************************************************
+
 >	XPFView::~XPFView()
 
 	Author:		Gerry_Iles (Xara Group Ltd) <camelotdev@xxxxxxxx>
Index: Trunk/XaraLX/wxOil/oilbitmap.cpp
===================================================================
--- Trunk/XaraLX/wxOil/oilbitmap.cpp	(revision 1365)
+++ Trunk/XaraLX/wxOil/oilbitmap.cpp	(revision 1366)
@@ -4270,4 +4270,34 @@
 }
 
 
+void CWxBitmap::CopyFullyTransparentFrom(OILBitmap* pBitmap)
+{
+	if (GetWidth() != pBitmap->GetWidth() ||
+		GetHeight() != pBitmap->GetHeight() ||
+		GetBPP() != 32 ||
+		pBitmap->GetBPP() != 32)
+	{
+		ERROR3("Incompatible bitmaps passed to CopyFullyTransparentFrom");
+		return;
+	}
 
+	// Pointers to the pixel we are dealing with
+	UINT32* pMask = (UINT32*)(pBitmap->GetBitmapBits());
+	UINT32* pDest = (UINT32*)GetBitmapBits();
+
+	// Loop through all the pixels
+	for (UINT32 j=0; j < pBitmap->GetHeight(); j++)
+	{
+		for (UINT32 i=0; i < pBitmap->GetWidth(); i++)
+		{
+			// If this bit is background then set the corresponding pixel 
+			// in the output bitmap to fully transparent black
+			if (*pMask == 0xFF000000)
+				*pDest = 0xFF000000;
+
+			// Move to the next pixel
+			pMask++;
+			pDest++;
+		}
+	}
+}
Index: Trunk/XaraLX/wxOil/xpoilflt.cpp
===================================================================
--- Trunk/XaraLX/wxOil/xpoilflt.cpp	(revision 1365)
+++ Trunk/XaraLX/wxOil/xpoilflt.cpp	(revision 1366)
@@ -204,6 +204,9 @@
 								{_T("bevel"), TT_BEVEL},
 								{NULL, XPFP_UNKNOWN}};
 
+PropMapEntry aContentOnly[] = { {_T("text"), XPFP_CONTENTONLY_TEXT},
+								{_T("plaintext"), XPFP_CONTENTONLY_PLAINTEXT},
+								{NULL, XPFP_UNKNOWN}};
 
 
 /********************************************************************************************
@@ -710,60 +713,69 @@
 		{
 			// ignore it
 		}
-		else if (strChildName == _T("Options"))
+		else if (strChildName == _T("Private"))
 		{
 			if (Phase > 0)
 			{
 				ERROR1(FALSE, _R(IDE_XPF_BADXML_PHASE0));
 			}
-			bOK = ReadOptions(pChild, pCapTree);		// Read the options attributes
+			// Ignore the entire element
 			Phase = 1;
 		}
-		else if (strChildName == _T("Rasterise"))
+		else if (strChildName == _T("Options"))
 		{
 			if (Phase > 1)
 			{
 				ERROR1(FALSE, _R(IDE_XPF_BADXML_PHASE1));
 			}
-			bOK = ReadRasterise(pChild, pCapTree);		// Read the dpi and alpha attributes
+			bOK = ReadOptions(pChild, pCapTree);		// Read the options attributes
 			Phase = 2;
 		}
-		else if (strChildName == _T("Spread"))
+		else if (strChildName == _T("Rasterise"))
 		{
 			if (Phase > 2)
 			{
 				ERROR1(FALSE, _R(IDE_XPF_BADXML_PHASE2));
 			}
-			bOK = ReadSpread(pChild, pCapTree);		// Read the as attribute
+			bOK = ReadRasterise(pChild, pCapTree);		// Read the dpi and alpha attributes
 			Phase = 3;
 		}
-		else if (strChildName == _T("Objects"))
+		else if (strChildName == _T("Spread"))
 		{
 			if (Phase > 3)
 			{
 				ERROR1(FALSE, _R(IDE_XPF_BADXML_PHASE3));
 			}
-			bOK = ReadObjects(pChild, pCapTree);		// Build the tree of XPFCapability derived objects
+			bOK = ReadSpread(pChild, pCapTree);		// Read the as attribute
 			Phase = 4;
 		}
-		else if (strChildName == _T("Attributes"))
+		else if (strChildName == _T("Objects"))
 		{
 			if (Phase > 4)
 			{
 				ERROR1(FALSE, _R(IDE_XPF_BADXML_PHASE4));
 			}
-			bOK = ReadAttributes(pChild, pCapTree);	// Build the tree of XPFCapability derived objects
+			bOK = ReadObjects(pChild, pCapTree);		// Build the tree of XPFCapability derived objects
 			Phase = 5;
 		}
-		else if (strChildName == _T("Colour"))
+		else if (strChildName == _T("Attributes"))
 		{
 			if (Phase > 5)
 			{
 				ERROR1(FALSE, _R(IDE_XPF_BADXML_PHASE5));
 			}
-			bOK = ReadColour(pChild, pCapTree);		// Build the tree of XPFColour objects
+			bOK = ReadAttributes(pChild, pCapTree);	// Build the tree of XPFCapability derived objects
 			Phase = 6;
 		}
+		else if (strChildName == _T("Colour"))
+		{
+			if (Phase > 6)
+			{
+				ERROR1(FALSE, _R(IDE_XPF_BADXML_PHASE6));
+			}
+			bOK = ReadColour(pChild, pCapTree);		// Build the tree of XPFColour objects
+			Phase = 7;
+		}
 		else
 		{
 			ERROR1(FALSE, _R(IDE_XPF_BADXML_UNEXPECTED_PHASE));
@@ -816,6 +828,8 @@
 {
 	double DPI = 96.0;
 	BOOL bAlpha = TRUE;
+	long Compression = 200;
+	String_256 CommonTrans;
 	wxString str;
 
 	str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"dpi"));
@@ -830,8 +844,20 @@
 		bAlpha = (str == _T("true"));
 	}
 
-	pCapTree->SetRasterise(DPI, bAlpha);
+	str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"compression"));
+	if (!str.IsEmpty())
+	{
+		str.ToLong(&Compression);
+	}
 
+	str = CXMLUtils::ConvertToWXString(xmlGetProp(pNode, (xmlChar*)"commontrans"));
+	if (!str.IsEmpty())
+	{
+		CommonTrans = str;
+	}
+
+	pCapTree->SetRasterise(DPI, bAlpha, (INT32)Compression, CommonTrans);
+
 	return TRUE;
 }
 
@@ -1203,7 +1229,9 @@
 		bOK = GetXPFBOOL(pNode, _T("background"), &bBackground);
 		XPFBOOL bGuide = XPFB_UNKNOWN;
 		bOK = GetXPFBOOL(pNode, _T("guide"), &bGuide);
-		pCap = new XPFCLayer(AsType, bVisible, bLocked, bPrintable, bActive, bBackground, bGuide);
+		XPFProp ContentOnly = XPFP_UNKNOWN;
+		bOK = GetXPFProp(pNode, _T("onlycontent"), aContentOnly, &ContentOnly);
+		pCap = new XPFCLayer(AsType, bVisible, bLocked, bPrintable, bActive, bBackground, bGuide, ContentOnly);
 	}
 	else if (strName == _T("Contour"))
 	{
Index: Trunk/XaraLX/wxOil/oilbitmap.h
===================================================================
--- Trunk/XaraLX/wxOil/oilbitmap.h	(revision 1365)
+++ Trunk/XaraLX/wxOil/oilbitmap.h	(revision 1366)
@@ -235,6 +235,8 @@
 	virtual UINT32 GetHorizontalDPI();
 	virtual UINT32 GetVerticalDPI();
 
+	virtual void CopyFullyTransparentFrom(OILBitmap* pBitmap);
+
 	// these are public but MUST NOT be used from kernel code
 
 	LPBITMAPINFO		BMInfo;		// The information on the bitmap
Index: Trunk/XaraLX/wxOil/xrc/EN/xpfres-strings.xrc
===================================================================
--- Trunk/XaraLX/wxOil/xrc/EN/xpfres-strings.xrc	(revision 1365)
+++ Trunk/XaraLX/wxOil/xrc/EN/xpfres-strings.xrc	(revision 1366)
@@ -13,43 +13,49 @@
 			<object class="sizeritem">
 				<flag>wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE</flag>
 				<object class="wxStaticText" name="IDE_XPF_BADXML_PHASE0">
-					<label>Expected Options node</label>
+					<label>Unexpected Private node</label>
 				</object>
 			</object>
 			<object class="sizeritem">
 				<flag>wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE</flag>
 				<object class="wxStaticText" name="IDE_XPF_BADXML_PHASE1">
-					<label>Expected Rasterise node</label>
+					<label>Unexpected Options node</label>
 				</object>
 			</object>
 			<object class="sizeritem">
 				<flag>wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE</flag>
 				<object class="wxStaticText" name="IDE_XPF_BADXML_PHASE2">
-					<label>Expected Spread node</label>
+					<label>Unexpected Rasterise node</label>
 				</object>
 			</object>
 			<object class="sizeritem">
 				<flag>wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE</flag>
 				<object class="wxStaticText" name="IDE_XPF_BADXML_PHASE3">
-					<label>Expected Objects node</label>
+					<label>Unexpected Spread node</label>
 				</object>
 			</object>
 			<object class="sizeritem">
 				<flag>wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE</flag>
 				<object class="wxStaticText" name="IDE_XPF_BADXML_PHASE4">
-					<label>Expected Attributes node</label>
+					<label>Unexpected Objects node</label>
 				</object>
 			</object>
 			<object class="sizeritem">
 				<flag>wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE</flag>
 				<object class="wxStaticText" name="IDE_XPF_BADXML_PHASE5">
-					<label>Expected Colours node</label>
+					<label>Unexpected Attributes node</label>
 				</object>
 			</object>
 			<object class="sizeritem">
 				<flag>wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE</flag>
+				<object class="wxStaticText" name="IDE_XPF_BADXML_PHASE6">
+					<label>Unexpected Colours node</label>
+				</object>
+			</object>
+			<object class="sizeritem">
+				<flag>wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE</flag>
 				<object class="wxStaticText" name="IDE_XPF_UNEXPECTED_PHASE">
-					<label>Unexpected phase node</label>
+					<label>Unexpected element</label>
 				</object>
 			</object>
 			<object class="sizeritem">
Index: Trunk/XaraLX/PreComp/camtypes.h
===================================================================
--- Trunk/XaraLX/PreComp/camtypes.h	(revision 1365)
+++ Trunk/XaraLX/PreComp/camtypes.h	(revision 1366)
@@ -140,10 +140,17 @@
 #include "ccobject.h"
 #include "errors.h"
 #include "camstring.h"
+
+#include "ccfile.h"
+#include "list.h"
+#include "listitem.h"
+#include "fixmem.h"
+#include "memblk.h"
+
+#if !defined(EXCLUDE_FROM_XARLIB)
+
 #include "paldefs.h"
-#if !defined(EXCLUDE_FROM_XARLIB)
 #include "app.h"
-
 #include "document.h"
 #include "docview.h"
 #include "range.h"
@@ -153,14 +160,20 @@
 #include "ink.h"
 #include "nodeattr.h"
 #include "attrval.h"
-#include "paths.h"
 #include "undoop.h"
 #include "bars.h"
 #include "sgallery.h"
 
+#endif
+
+#include "paths.h"
+#include "cxfdefs.h"
+#include "cxfrech.h"
+#include "cxfrec.h"
+
+#if !defined(EXCLUDE_FROM_XARLIB)
 // Alex added these which are included by more than 100 files
 #include "camfiltr.h"
-#include "cxfrech.h"
 #include "npaper.h"
 #include "iprofile.h"
 #include "biasgain.h"
@@ -170,13 +183,13 @@
 #include "nodecomp.h"
 #include "rrcaps.h"
 #include "fillval.h"
-#include "cxfdefs.h"
 #include "becomea.h"
-#include "cxfrec.h"
 #include "group.h"
 
 #endif
 
+
+
 //-----------------------------------------------------------------------------------------//
 // Some globally useful coordinate values...
 


Xara