Пример #1
0
BOOL NodeSimpleShape::DoBecomeA(BecomeA* pBecomeA)
{
	// Check for a NULL entry param
	ERROR2IF_PF(pBecomeA == NULL,FALSE,("pBecomeA is NULL"));

	// This lump checks that the Reason is one that we understand
	// It also makes sure that we don't have a NULL UndoOp ptr
	BOOL ValidReason = (pBecomeA->GetReason() == BECOMEA_REPLACE || pBecomeA->GetReason() == BECOMEA_PASSBACK);
	ERROR2IF_PF(!ValidReason,FALSE,("Unkown BecomeA reason %d",pBecomeA->GetReason()));

	// pBecomeA->Reason is one that we understand.

	BOOL 		Success = TRUE;			// Our success flag (Important that this defaults to TRUE)
	NodePath* 	pNewNodePath = NULL;	// Ptr to a new NodePath, if we get to make one.

	if (pBecomeA->BAPath())
	{
		// We need to create a new NodePath, no matter what the reason.
		
		// Allocate a new NodePath node
		ALLOC_WITH_FAIL(pNewNodePath, (new NodePath), pBecomeA->GetUndoOp()); 
		Success = (pNewNodePath != NULL);

		// Initialise the path
		if (Success) CALL_WITH_FAIL(pNewNodePath->InkPath.Initialise(InkPath.GetNumCoords(),12), pBecomeA->GetUndoOp(), Success);
		if (Success) CALL_WITH_FAIL(pNewNodePath->InkPath.CopyPathDataFrom(&InkPath), pBecomeA->GetUndoOp(), Success);

		// If Success is TRUE, then we now have a new NodePath object that contains this shape's path

		if (Success)
		{
		 	switch (pBecomeA->GetReason())
			{
		 		case BECOMEA_REPLACE :
				{
					// It's a BECOMEA_REPLACE, so replace this node with the new NodePath in an undoable way

					// Can't do it in an undoable way without an Undo Op
					ERROR2IF_PF(pBecomeA->GetUndoOp() == NULL,FALSE,("GetUndoOp() returned NULL"));

					// Firstly, hide this node
					NodeHidden* pNodeHidden; 
					Success = pBecomeA->GetUndoOp()->DoHideNode(this, TRUE, &pNodeHidden);

					if (Success)
					{
						// Insert the new NodePath into the tree, next to the hidden node
						pNewNodePath->AttachNode(pNodeHidden,NEXT);

						// Copy the node's attributes
						CALL_WITH_FAIL(CopyChildrenTo(pNewNodePath), pBecomeA->GetUndoOp(), Success); 

						if (Success)
						{
							// Set the bounds  
							pNewNodePath->InvalidateBoundingRect();
							pNewNodePath->SetSelected(IsSelected());

							// Create a hide node action to hide the node when we undo 
							HideNodeAction* UndoHideNodeAction;     
							Success = (HideNodeAction::Init(pBecomeA->GetUndoOp(),
											  		 pBecomeA->GetUndoOp()->GetUndoActionList(),
									 				 pNewNodePath, 
									 				 TRUE, 		 // Include subtree size 
							  		 				 ( Action**)(&UndoHideNodeAction))
							  		  				 != AC_FAIL);
						}
					}

					if (Success)
						pBecomeA->PassBack(pNewNodePath, this);
				}
				break;

				case BECOMEA_PASSBACK :
					Success = pBecomeA->PassBack(pNewNodePath,this);
				break;

				default:
					break;
			}
		}
	}

	if (!Success)
	{
		if (pNewNodePath != NULL)
		{
			// Delete all the NodePath's children (if it has any) and unlink it from the tree (if it's linked)
			// This is all done by CascadeDelete()
			pNewNodePath->CascadeDelete(); 
			delete pNewNodePath;
			pNewNodePath = NULL;
		}
	}

	return Success;
}
Пример #2
0
NodeRenderableBounded *CDRArrowheadStore::GetConvertedNode(DWORD Reference, INT32 *Distance, BOOL *NotPresent)
{
	// set up the not present thingy
	*NotPresent = FALSE;
	
	// find the correct chunk
	CDRArrowheadStoredItem *Item;
	INT32 Size;

	if(IsEmpty())
		return 0;		// no items in the list
	
	Item = (CDRArrowheadStoredItem *)GetHead();

	// scan though the list looking for the reference
	while(Item != 0)
	{
		if(CDRDATA_DWORD(*((DWORD *)(Item->Block))) == Reference)
		{
			Size = Item->Size;
			break;
		}

		Item = (CDRArrowheadStoredItem *)GetNext(Item);
	}
	
	// did we find a chunk?
	if(Item == 0)
	{
		*NotPresent = TRUE;
		return 0;
	}

	// locate the coordinates
	cdrfArrowhead *Arrow = (cdrfArrowhead *)Item->Block;
	cdrfCoord *Coords = (cdrfCoord *)(Item->Block + CDRDATA_WORD(Arrow->CoordsOffset) + cdrfARROWHEAD_COORDOFF_CORRECT);

	// store the distance from the definitons
	*Distance = CDRDATA_SWORD(Arrow->Distance);

	// check to see if a cached pointer is available
	if(Item->pNode != 0)
		return Item->pNode;

	// OK, convert that arrowhead

	// this is not particularly pleasant. We need to scan though the coords creating a path,
	// each sub path must be a seperate path unless the next subpath has the same closedness
	// as the previous one, in which case it's a sub path.
	// this is because closed sub paths have different attributes to open ones. It's a nasty
	// system, and rather overcomplicated, but never mind.

	INT32 ThisType = GCN_LASTSUB_NONE;		// the type of this subpath
	INT32 LastType = GCN_LASTSUB_NONE;		// the type of the last subpath
	
	NodePath *FirstPath = 0;				// the first path in my set of paths
	NodePath *LastPath = 0;					// the last path in my set of paths
	NodePath *ThisPath = 0;					// the path I'm currently working on

	// check that the first node type is a move to avoid stuffing up my next bit
	if((Arrow->NodeTypes[0] & cdrfPATHCOORDTYPE_MASK) != cdrfPATHCOORDTYPE_MOVE)
	{
		// for now, if the first element isn't a move, pretend that it doesn't exist
		*NotPresent = TRUE;
		return 0;
	}

	INT32 CoordType;

	INT32 l;
	
	UINT32 Control1 = 0;		// number of first control point
	UINT32 Control2 = 0;		// of second
	DocCoord co, cn1, cn2;	// coordinates
	PathFlags Flags;

	INT32 NNodes = CDRDATA_WORD(Arrow->NNodes);
	BOOL NeedMoveTo = TRUE;

	// convert all the coordinates
	for(l = 0; l < NNodes; l++)
	{
		CoordType = Arrow->NodeTypes[l] & cdrfPATHCOORDTYPE_MASK;

		if(CoordType == cdrfPATHCOORDTYPE_MOVE || l == 0)
		{
			// start a new path!
			LastType = ThisType;

			// first of all, what type of path is this?
			if((Arrow->NodeTypes[l] & cdrfPATHCOORDATTR_CLOSE) != 0)
				ThisType = GCN_LASTSUB_CLOSED;
			else
				ThisType = GCN_LASTSUB_OPEN;

			// OK, do we need to start a new path?
			if(ThisType != LastType)
			{
				// yep, attach the last one we did
				if(ThisPath != 0)
				{
					// check that the path is OK
					if(!ThisPath->InkPath.EnsureValid())
					{
						// no, it's completely knackered
						delete ThisPath;
						ThisPath = 0;
					} else {	
						// finish off the path
						ThisPath->InvalidateBoundingRect();				

						if(FirstPath == 0)
							FirstPath = ThisPath;

						if(LastPath != 0)
							ThisPath->AttachNode(LastPath, NEXT);

						LastPath = ThisPath;

						ThisPath = 0;
					}
				}

				// get a new path
				ThisPath = new NodePath;

				if(ThisPath == 0)
					return 0;			// no path created. A bit of a pity

				// set it up ready for conversion
				if(!ThisPath->SetUpPath())
					return 0;
		
				ThisPath->InkPath.FindStartOfPath();

				// set whether it's filled or not
				if(ThisType == GCN_LASTSUB_CLOSED)
				{
					ThisPath->InkPath.IsFilled = TRUE;
					ThisPath->InkPath.IsStroked = FALSE;
				} else {
					ThisPath->InkPath.IsFilled = FALSE;
					ThisPath->InkPath.IsStroked = TRUE;
				}
				
			}

		}

		co.x = CDRDATA_SWORD(Coords[l].X);
		co.y = CDRDATA_SWORD(Coords[l].Y);

		// ensure we get all the move tos we need.
		if(NeedMoveTo && CoordType != cdrfPATHCOORDTYPE_MOVE)
		{
			if(!ThisPath->InkPath.InsertMoveTo(co))
				return 0;
		}

		NeedMoveTo = FALSE;

		// convert the coordinates
		switch(CoordType)
		{
			case cdrfPATHCOORDTYPE_MOVE:
				// add a move to this path
				if(!ThisPath->InkPath.InsertMoveTo(co))
					return 0;
				break;
			
			case cdrfPATHCOORDTYPE_LINETO:
				// add a line to this coord to the path
				if(!ThisPath->InkPath.InsertLineTo(co))
					return 0;
				break;
			
			case cdrfPATHCOORDTYPE_CURVE:
				// check we have some control points for this curve
				// a control point cannot be the first coord, so it's OK to check against 0
				if(Control1 == 0 || Control2 == 0)
				{
TRACEUSER( "Ben", _T("No control points for curve element\n"));
					return 0;
				}

				// convert the control points
				cn1.x = CDRDATA_SWORD(Coords[Control1].X);
				cn1.y = CDRDATA_SWORD(Coords[Control1].Y);
				cn2.x = CDRDATA_SWORD(Coords[Control2].X);
				cn2.y = CDRDATA_SWORD(Coords[Control2].Y);
				
				// create the curve
				Flags.IsSelected = FALSE;
				Flags.IsSmooth = Flags.IsRotate = ((Arrow->NodeTypes[l] & cdrfPATHCOORDATTR_SMOOTH) != 0)?TRUE:FALSE;
				Flags.IsEndPoint;
				
				// insert it into the path
				if(!ThisPath->InkPath.InsertCurveTo(cn1, cn2, co, &Flags))
					return 0;
				break;

			case cdrfPATHCOORDTYPE_CONTROL:
				// shuffle the control points we've already got and add the new one
				Control1 = Control2;
				Control2 = l;
				break;
			
			default:
				break;
		}
		
		// is this a close subpath situtation?
		if((Arrow->NodeTypes[l] & cdrfPATHCOORDATTR_CLOSE) != 0)
		{
			// close the sub path
			if(CoordType != cdrfPATHCOORDTYPE_MOVE)
			{
				if(!ThisPath->InkPath.CloseSubPath())
					return 0;

				// check the next coord type
				NeedMoveTo = TRUE;
			}
		}
	}

	// finish off the last path
	ThisPath->InvalidateBoundingRect();				

	// finish off this path we're doing
	if(ThisPath != 0)
	{
		if(FirstPath == 0)
			FirstPath = ThisPath;

		if(LastPath != 0)
			ThisPath->AttachNode(LastPath, NEXT);

		LastPath = ThisPath;

		ThisPath = 0;
	}

	// make up a nice group if there's more than one path
	NodeRenderableBounded *ToInsert = 0;
	if(FirstPath == LastPath)
	{
		ToInsert = FirstPath;
	} else {
		ToInsert = new NodeGroup;

		if(ToInsert == 0)
			return 0;

		FirstPath->InsertChainSimple(ToInsert, FIRSTCHILD);
	}

	Item->pNode = ToInsert;

	return ToInsert;
}