Example #1
0
BOOL FreeHandEPSFilter::AddNewNode(Node *pNewNode)
{
	if(IS_A(pNewNode, NodePath))
		pLastPathSeen = (NodePath *)pNewNode;
	
	// check to see if we want to handle this
	if((ComplexPathMode == FALSE) || (pNewNode == 0) || (pNode == 0) || (!IS_A(pNewNode, NodePath)))
		return EPSFilter::AddNewNode(pNewNode);

	// check to see if this is the first...
	if(HadFirstOfComplexPath == FALSE)
	{
		HadFirstOfComplexPath = TRUE;
		return EPSFilter::AddNewNode(pNewNode);
	}

	// find the last child of the node
	Node *pLastChild = pNode->FindLastChild();
	if(pLastChild == 0 || !IS_A(pLastChild, NodePath))
		return EPSFilter::AddNewNode(pNewNode);

	// we know that both of these things are NodePaths.
	Path *pTarget = &((NodePath *)pLastChild)->InkPath;
	Path *pAddition = &((NodePath *)pNewNode)->InkPath;

	// work out the new flags for the target
	BOOL TargetFilled = pTarget->IsFilled;
	BOOL TargetStroked = pTarget->IsStroked;
	if(pAddition->IsFilled)		TargetFilled = TRUE;
	if(pAddition->IsStroked)	TargetStroked = TRUE;

	// add this new path to the old one...
	if(!pTarget->MergeTwoPaths(*pAddition))
		return FALSE;

	// check that the thing we just added isn't already there
	if(!RemoveLastSubPathIfNotUnique(pTarget))
		return FALSE;

	// set it's flags
	pTarget->IsFilled = TargetFilled;
	pTarget->IsStroked = TargetStroked;

	// vape it's attributes
	pLastChild->DeleteChildren(pLastChild->FindFirstChild());

	// apply some new ones
	SetPathFilled(TargetFilled);
	if(!AddAttributes((NodePath *)pLastChild, TargetStroked, TargetFilled))
		return FALSE;

	// hide the nice additional path
	//if(!ImportInfo.pOp->DoHideNode(pNewNode, TRUE))
	//	return FALSE;
	pNewNode->CascadeDelete();
	delete pNewNode;

	// set the last seen path bollox
	pLastPathSeen = (NodePath *)pLastChild;

	// done!
	return TRUE;
}
Example #2
0
/********************************************************************************************

>	BOOL BlendHelpers::BlendPaths(BlendNodeParam * pParam, Path * pPath)

	Author:		David_McClarnon (Xara Group Ltd) <*****@*****.**>
	Created:	21/2/2000
	Inputs:		The blend node parameter
	Outputs:	The blended path is stored in three arrays: the coords, the verbs, and the flags.
				The arrays are:
	
					pTempCoords
					pTempVerbs
					pTempFlags

					ArrayLength = the length of all three arrays

				This allows the caller to decide what to do with the blended path in a very flexible way.

	Returns:	TRUE if successful, FALSE otherwise
	Purpose:	Blends two BlendPath objects by the amount specified in BlendRatio
	SeeAlso:	-
********************************************************************************************/
BOOL BlendHelpers::BlendPaths(BlendNodeParam * pParam, Path * pPath)
{
	// Check entry params
	BlendPath * pBlendPathStart = pParam->GetStartBlendPath();
	BlendPath * pBlendPathEnd   = pParam->GetEndBlendPath();

	ERROR2IF(!pBlendPathStart->GetBlendNode()->IsNodePath(), FALSE,
		"Start blend path's node isn't a node path");

	ERROR2IF(!pBlendPathEnd->GetBlendNode()->IsNodePath(), FALSE,
		"End blend path's node isn't a node path");

	BOOL    ok = (pBlendPathStart != NULL && pBlendPathEnd != NULL);
 	if (ok) ok = (pBlendPathStart->GetBlendNode() != NULL && pBlendPathEnd->GetBlendNode() != NULL);
	ERROR3IF(!ok,"One or more NULL entry params");
	if (!ok) return FALSE;

	// Get the types of the two paths
	PathTypeEnum PathTypeStart = pBlendPathStart->GetPathType();
	PathTypeEnum PathTypeEnd   = pBlendPathEnd  ->GetPathType();
	
	// The blended path will be closed if either of the paths is a shape
	BOOL Closed = (PathTypeStart == PATHTYPE_SHAPE) || (PathTypeEnd == PATHTYPE_SHAPE);

	Path * pPathStart = NULL;

	// Find the paths associated with the start and end blend paths
	if (pBlendPathStart->GetBlendNode()->IsNodePath())
	{
		pPathStart = &(((NodePath *)pBlendPathStart->GetBlendNode())->InkPath);
	}

	Path * pPathEnd = NULL;

	if (pBlendPathEnd->GetBlendNode()->IsNodePath())
	{
		pPathEnd   = &(((NodePath *)pBlendPathEnd->GetBlendNode())->InkPath);
	}

	// Calculate how large the arrays have to be to store the blended path definition
	INT32 DestPathSize = ((pPathStart->GetNumCoords()+pPathEnd->GetNumCoords())*3)+500;

	// Get some arrays used to hold the blended path data, and error if any are NULL
	DocCoord*  	pDestCoords = GetCoordArray(DestPathSize);
	PathVerb*  	pDestVerbs  = GetVerbArray(DestPathSize);
	PathFlags* 	pDestFlags  = GetFlagArray(DestPathSize);
	UINT32* 		pBuff 		= GetGBlendBuff(DestPathSize);
	if (pDestCoords == NULL || pDestVerbs == NULL || pDestFlags == NULL || pBuff == NULL)
		return FALSE;

	// This section copes with the case when blending a line with a shape.
	// In this case we need to get a temp path the is actually a shape version of the line.
	// The line is simply reversed back onto itself to form a shape that would look identical to the 
	// line if rendered.  This allows the line to appear to open up to the shape when blended.
	Path Shape;
	if (PathTypeStart != PathTypeEnd)
	{
		BOOL ok = FALSE;
		if (!Shape.Initialise()) return FALSE;

		// if going from a line to a shape, convert the start path to a shape
		if (PathTypeStart == PATHTYPE_LINE && PathTypeEnd == PATHTYPE_SHAPE)
		{
			ok = NodeBlender::ConvertLineToShape(pPathStart,&Shape);
			pPathStart = &Shape;
		}

		// if going from a shape to a line, convert the end path to a shape
		if (PathTypeStart == PATHTYPE_SHAPE && PathTypeEnd == PATHTYPE_LINE)
		{
			ok = NodeBlender::ConvertLineToShape(pPathEnd,&Shape);
			pPathEnd = &Shape;
		}

		if (!ok) return FALSE;
	}

	// The blend should do a one-to-one mapping when the OneToOne flag is set AND both paths
	// have the same number of elements
	BOOL OneToOne = FALSE;
	if (pParam->GetOneToOne())
		OneToOne = (pBlendPathStart->GetNumElements() == pBlendPathEnd->GetNumElements());

	// Now actually blend the two paths

	GBlend GBlendObj;

	// Define the blend
	GBlendObj.Define(	(PPOINT)pPathStart->GetCoordArray(),	// Specify the start path
						pPathStart->GetVerbArray(),
						pPathStart->GetNumCoords(),

						(PPOINT)pPathEnd  ->GetCoordArray(),	// Specify the end path
						pPathEnd  ->GetVerbArray(),
						pPathEnd  ->GetNumCoords(),

						OneToOne,								// The one-to-one flag
						1024,								// Flatness

						pBuff,									// Buffer for GBlend to use
						DestPathSize*sizeof(UINT32));			// The buffer size

	// Blend the paths
	m_ArrayLength = GBlendObj.Blend(pParam->GetBlendRatio(),	// The blend ratio, 0.0 < BlendRatio < 1.0
									(PPOINT)pDestCoords,		// Array to store blended coords
									pDestVerbs,					// Array to store blended verbs
									DestPathSize);				// The num elements in the two arrays


	// If we're blending a line to another line, we need to make sure that the blended line
	// is going in a direction that corresponds to the source lines.  This ensures attributes
	// that depend on this direction (e.g. start and end arrows) look correct.
	//
	// When creating blend paths of lines, we can detect if the blend path has been reversed,
	// in relation to the original path, by the original mapping value.
	// If it's 0 it has NOT been reversed, otherwise it's been reversed.
	//
	// If the blend ratio is <=0.5, the blended path is closest to the start blend path,
	// so we look at the start blend path's original mapping.
	//
	// If blend ration > 0.5, look at the end blend path's original mapping.
	//
	// The (BlendRation <= 0.5) cut-off point is the same as the cut-off point used in the blending
	// of attributes.
	if (pBlendPathStart->IsLine() && pBlendPathEnd->IsLine())
	{
		BlendPath* pBlendPath;
		if (pParam->GetBlendRatio() <= 0.5) 
			pBlendPath = pBlendPathStart;
		else
			pBlendPath = pBlendPathEnd;

		if (pBlendPath->GetOrigMapping() != 0)
			NodeBlender::ReversePath(pDestCoords,pDestVerbs,m_ArrayLength);
	}

	// We need to do some work on the blended path
	if (!NodeBlender::ProcessBlendedPath(pDestCoords,pDestVerbs,pDestFlags,m_ArrayLength,Closed))
		return FALSE;

	Path RetnPath;
	RetnPath.Initialise(m_ArrayLength);

	BOOL Filled  = pPathStart->IsFilled  || pPathEnd->IsFilled;
	BOOL Stroked = pPathStart->IsStroked || pPathEnd->IsStroked;

	RetnPath.MergeTwoPaths(pDestCoords,pDestVerbs,pDestFlags,m_ArrayLength,Filled);

	pPath->ClearPath();
	pPath->CloneFrom(RetnPath);
	pPath->IsFilled = Filled;
	pPath->IsStroked = Stroked;
	
	return TRUE;
}