Ejemplo n.º 1
0
NodeRegularShape * OpBackground::DoCreateRectangle(Spread * pSpread)
{
	ERROR2IF(pSpread == NULL,FALSE,"OpBackground::DoCreateRectangle Bad params error!");

	if (pSpread == NULL)
		return NULL;

	// This assumes that we have already checked to see if there is a page covering rectangle
	// already present on this layer.

	// Create a new rectangle node on the layer
	NodeRegularShape *pShape = new NodeRegularShape;
	if (pShape != NULL)
	{
		BOOL ok = pShape->SetUpShape();

		if (!ok)
		{
			// Do something sensible in here
			delete pShape;
			return NULL;
		}

		// We want to make the rectangle the same size as the current union of
		// all the pages on the current spread
		DocRect Rect;
		pSpread->GetPagesRect(&Rect);

		/* // We must expand the rectangle by a single pixel as the page redraw
		// draws a single pixel line around the outside.
		const MILLIPOINT pixel = (MILLIPOINT)(72000.0/96.0);
		Rect.Inflate(pixel); */

		const INT32 CornerRadius = 0; // No curvature
		
		if (pShape->MakeRectangle(Rect.Width(), Rect.Height(), CornerRadius))
		{
			// Translate centre from 0,0 to required position relative to page
			INT32 XTrans = Rect.lo.x + (Rect.Width()/2);
			INT32 YTrans = Rect.lo.y + (Rect.Height()/2);
			Trans2DMatrix Trans(XTrans, YTrans);

			pShape->Transform(Trans);

			// finish off the shape
			pShape->InvalidateBoundingRect();
		}
	}

	return pShape;
}
Ejemplo n.º 2
0
/********************************************************************************************

>	BOOL MakeBitmapFilter::FindCentreInsertionPosition(Spread** Spread, DocCoord* Position)

	Author:		Will_Cowling (Xara Group Ltd) <*****@*****.**> (from Simon)
	Created:	12/6/96
	Inputs:		-
	Outputs:	Spread:  The spread to place the clipboard objects on
				Position:The centre of the view (Spread coords)
	Purpose:	Finds the centre insertion position for clipboard objects

********************************************************************************************/
BOOL MakeBitmapFilter::FindCentreInsertionPosition(Spread** Spread, DocCoord* Position)
{
	// ---------------------------------------------------------------------------------
	// Find out which spread is in the centre of the view 
	// this is the spread that the pasted objects will be placed on

	// Obtain the current DocView
	DocView* CurDocView = DocView::GetCurrent();

	ENSURE(CurDocView != NULL, "The current DocView is NULL"); 
	if (CurDocView == NULL)
		return FALSE; // No DocView

	// Get the view rect
	WorkRect WrkViewRect = CurDocView->GetViewRect();

	if (WrkViewRect.IsEmpty() || (!WrkViewRect.IsValid()) )
		return FALSE; // Defensive
	
	// Determine the centre of the view
	WorkCoord WrkCentreOfView; 
	WrkCentreOfView.x = WrkViewRect.lox	+ (WrkViewRect.Width()/2); 
	WrkCentreOfView.y = WrkViewRect.loy	+ (WrkViewRect.Height()/2);
	
	// FindEnclosing spread requires an OilCoord
	OilCoord OilCentreOfView = WrkCentreOfView.ToOil(CurDocView->GetScrollOffsets()); 

	// Find out which spread to insert the pasteboard objects onto
	(*Spread) = CurDocView->FindEnclosingSpread(OilCentreOfView);
	if ((*Spread) == NULL)
		return FALSE; // There is no spread

	// Phew
	// ---------------------------------------------------------------------------------
	// Now lets find the spread coordinate of the centre of the view
	DocRect DocViewRect = CurDocView->GetDocViewRect(*Spread);
	
	if ( DocViewRect.IsEmpty() || (!DocViewRect.IsValid()) )
	{
		ERROR3("DocViewRect is invalid");
		return FALSE; // Defensive
	}

	// Find the centre of the DocViewRect
   	DocCoord DocCentreOfView; 
	DocCentreOfView.x = DocViewRect.lox	+ (DocViewRect.Width()/2); 
	DocCentreOfView.y = DocViewRect.loy	+ (DocViewRect.Height()/2);

	// --------------------------------------------------------------------------------
	// Now convert from DocCoords to spread coords

	DocRect PhysSpreadRect = (*Spread)->GetPasteboardRect();
	
	(*Position).x = DocCentreOfView.x - PhysSpreadRect.lo.x; 
	(*Position).y = DocCentreOfView.y - PhysSpreadRect.lo.y;
	
	return TRUE;  
}
Ejemplo n.º 3
0
void LiveEffectsTool::OnMouseMove(DocCoord Coord, Spread* pSpread, ClickModifiers mods)
{
// Stub out this function if the tool isn't wanted
#ifndef NO_ADVANCED_TOOLS		

	// We are interested in any selected paths that the cursor is over
	// we will also be needing the current docview
	SelRange* Selected = GetApplication()->FindSelection();
	Node* pNode = Selected->FindFirst();

	// Check to see if the selection is on the same spread as the mouse
	if (pNode!=NULL)
	{
		// Get the spread and return if it is different from the one with the cursor
		Spread* pNodeSpread = pNode->FindParentSpread();
		if (pNodeSpread!=pSpread)
			return;
	}

	// Find the Blob manager, so we can find out how big a rect to use
	BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
	if (pBlobMgr==NULL)
		return;
	
	// Find the Rect round the mouse pos that counts as a hit
	DocRect BlobRect;
	pBlobMgr->GetBlobRect(Coord, &BlobRect);
	
	// Work out the square of the distance that we will count as 'close' to the line
	INT32 Range = BlobRect.Width() / 2;
	Range *= Range;

//	// loop through the selection
//	while (pNode!=NULL)
//	{
//		// Now find the next selected node
//		pNode = Selected->FindNext(pNode);
//	}

	// We did not find anything good, so set the cursor to the normal one
	ChangeCursor(pNormalCursor);

	// And set the status bar text
	StatusMsg.Load(_R(IDS_LIVEEFFECTSTART), Tool::GetModuleID(GetID()));
	GetApplication()->UpdateStatusBarText(&StatusMsg);

#endif	// NO_ADVANCED_TOOLS
}
Ejemplo n.º 4
0
/********************************************************************************************

>	BOOL TipsDlg::DrawBitmap(ResourceID BitmapID, DocRect& RedrawRect)

	Author:		Colin_Barfoot (Xara Group Ltd) <*****@*****.**>
	Created:	08/08/96
	Inputs:		BitmapID : the resource id of the bitmap to draw
				RedrawRect : the rectangle in which to draw it
	Returns:	TRUE if drawn OK
				FALSE otherwise
	Purpose:	Renders the given bitmap in the given rectangle

********************************************************************************************/
BOOL TipsDlg::DrawBitmap(ResourceID BitmapID, DocRect& RedrawRect)
{
	OILBitmap *pOILBitmap = OILBitmap::Create();
	if (pOILBitmap == NULL)
	{
		return FALSE;
	}

	if (!pOILBitmap->LoadBitmap(BitmapID))
	{
		return FALSE;
	}

	// Centre the bitmap within the RedrawRect
	UINT32 bitmapWidth = pOILBitmap->GetRecommendedWidth();
	UINT32 bitmapHeight = pOILBitmap->GetRecommendedHeight();

	UINT32 xOffset = RedrawRect.lo.x + (RedrawRect.Width() - bitmapWidth) / 2;
	UINT32 yOffset = RedrawRect.lo.y + (RedrawRect.Height() - bitmapHeight) / 2;

	DocCoord lowCorner(xOffset, yOffset);
	DocRect bitmapRect(lowCorner, bitmapWidth, bitmapHeight);

	KernelBitmap bitmap(pOILBitmap, TRUE);
	
	// Now we need to create a temporary NodeBitmap, which we will
	// use to render the bitmap preview.
	NodeBitmap* dummyNode = new NodeBitmap();
	if (dummyNode == NULL)
	{
		return FALSE;
	}

	// Set the NodeBitmap path to be our RedrawRect and attach the Bitmap to it.
	dummyNode->SetUpPath();
	dummyNode->CreateShape(bitmapRect);
	dummyNode->GetBitmapRef()->SetBitmap(&bitmap);

	// Now render the bitmap preview
  	dummyNode->Render(m_pRenderer);
	delete dummyNode;

	// All OK
	return TRUE;
}
Ejemplo n.º 5
0
double CamelotWebFilter::GetSimilarPathTolerance(NodePath* pPath)
{
	double Tolerance = 0.0;

	if (pPath != NULL)
	{
		// Don't get attribute-related bounds because the path might not be in the tree
		// (e.g. it may be generated by the 'convert text to outlines' system which keeps
		// all paths created from text stories in out-of-line groups)
		// The TRUE parameter means don't bother with attributes
		DocRect Rect = pPath->GetBoundingRect(TRUE);
		INT32 MaxDist = min(Rect.Width(),Rect.Height());

		Tolerance = double(MaxDist)*0.01;
		if (Tolerance > GetWebSimilarPathTolerence())
			Tolerance = GetWebSimilarPathTolerence(); 
	}

	return Tolerance;
}
Ejemplo n.º 6
0
BOOL BitmapExportDocument::SetBitmap(KernelBitmap* pBitmap)
{
	TRACEUSER( "Gerry", _T("BitmapExportDocument::SetBitmap()\n"));

	ERROR2IF(pBitmap == NULL, FALSE, "NULL bitmap passed to SetBitmap()\n");
	ERROR2IF(pBitmapNode == NULL, FALSE, "pBitmapNode is NULL in SetBitmap()\n");

	// Attach the bitmap to our node
	//
	// Note: Neville 18/9/97 
	// If the bitmap is a lone bitmap i.e. not attached to any document, then we
	// must attach it properly to this document so that it gets cleaned out
	// rather than memory leaking. If not, then we are just temporarily using
	// the bitmap and so everything should be ok. We need to work in the following
	// situations:-
	// - Selecting multiple bitmaps in the bitmap gallery and saving as animated GIF.
	//	 Here we are passed a list of bitmaps which are already in use in the source
	//   document.
	// - Making a new clipart index for bitmaps. Here we are passed a brand spanking
	//   new bitmap which is not on any lists. This used to memory leak.
	BitmapList* pBmpList = pBitmap->GetParentBitmapList();
	if (pBmpList != NULL)
	{
		// This will memory leak a kernel bitmap each time if it is not on a parent
		// document list. You will also end up with a KernelBitmap which contains
		// a deleted ActualBitmap pointer, which is very bad!
		pBitmapNode->GetBitmapRef()->SetBitmap(pBitmap);
	}
	else
	{
		// This is the same technique that the BaseBitmapFilter uses and so must be correct!
		pBitmapNode->GetBitmapRef()->Attach(pBitmap, this);
		if (pBitmapNode->GetBitmap() != pBitmap)
		{
			// It didn't use the bitmap we gave it, so we can delete it
			delete pBitmap;
		}
	}
	
	BitmapInfo Info;
	pBitmapNode->GetBitmap()->ActualBitmap->GetInfo(&Info);

	// Calculate the rectangle for this bitmap
	// We make it as large as possible (within the ExportRect)
	// without changing the aspect ration

	INT32 RectWidth = ExportRect.Width();
	INT32 RectHeight = ExportRect.Height();

	double xScale = (double) RectWidth / (double) Info.RecommendedWidth;
	double yScale = (double) RectHeight / (double) Info.RecommendedHeight;

	DocRect BitmapRect;

	BitmapRect.lo.x = 0;
	BitmapRect.lo.y = 0;

	if (xScale < yScale)
	{
		// Bitmap will be full width
		BitmapRect.hi.x = RectWidth;
		BitmapRect.hi.y = (INT32) ((double) Info.RecommendedHeight * xScale);

		// Center the bitmap vertically in the rectangle
		BitmapRect.Translate(0, (RectHeight - BitmapRect.Height()) / 2);
	}
	else
	{
		// Bitmap will be full height
		BitmapRect.hi.x = (INT32) ((double) Info.RecommendedWidth * yScale);
		BitmapRect.hi.y = RectHeight;

		// Center the bitmap horizontally in the rectangle
		BitmapRect.Translate((RectWidth - BitmapRect.Width()) / 2, 0);
	}

	// Delete the node's path
	// Because CreateShape inserts a rectangle at the beginning of the path
	pBitmapNode->InkPath.DeleteFromElement(0);

	// And create the shape
	pBitmapNode->CreateShape(BitmapRect);

	return(TRUE);
}
Ejemplo n.º 7
0
void PathProcessorStrokeVector::ProcessPath(Path *pPath,
											RenderRegion *pRender,
											PathShape ShapePath)
{
	PORTNOTETRACE("other","PathProcessorStrokeVector::ProcessPath - do nothing");
#ifndef EXCLUDE_FROM_XARALX
	ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params");

	// Get the RenderRegion SubRenderContext and see if we're returning part-way through a background render
	VectorStrokeSubRenderContext *pSubRenderContext = (VectorStrokeSubRenderContext *)pRender->GetSubRenderState();
	if (pSubRenderContext != NULL && !IS_A(pSubRenderContext, VectorStrokeSubRenderContext))
	{
		// We can't use the sub render context, because it's not ours!
		pSubRenderContext = NULL;
	}

	// --- If we don't have a valid stroke definition, then get the base class to render
	// the stroke as a simple flat-filled stroke.
	StrokeDefinition *pStrokeDef = StrokeComponent::FindStroke(StrokeID);
	if (pStrokeDef == NULL)
	{
		PathProcessorStroke::ProcessPath(pPath, pRender);
		return;
	}

	// --- See if we have to create a new SubRenderContext, or if we can use the one passed in.
	// We always store all relevant variables in a SubRenderContext object so that we can easily
	// return control to the RenderRegion without having to copy lots of local values in/out.
	const BOOL CreateSubRenderContext = (pSubRenderContext == NULL);
	if (CreateSubRenderContext)
	{
		pSubRenderContext = new VectorStrokeSubRenderContext;
		if (pSubRenderContext == NULL)
		{
			pRender->DrawPath(pPath, this, ShapePath);
			return;
		}

		// --- If the provided path is not stroked, then we'll just pass it straight through
		// We also don't touch it if we're doing EOR rendering, or click hit detection
		if (!pPath->IsStroked || pRender->DrawingMode != DM_COPYPEN || pRender->IsHitDetect())
		{
			delete pSubRenderContext;
			pRender->DrawPath(pPath, this, ShapePath);
			return;
		}

		// --- If the quality is set low, or if the current stroke attribute is not our "parent"
		// attribute (so we're not the "current" stroker) then strokes are just rendered as centrelines
		// BLOCK
		{
			QualityAttribute *pQuality = (QualityAttribute *) pRender->GetCurrentAttribute(ATTR_QUALITY);
			StrokeTypeAttrValue *pTypeAttr = (StrokeTypeAttrValue *) pRender->GetCurrentAttribute(ATTR_STROKETYPE);

			if ((pQuality != NULL && pQuality->QualityValue.GetLineQuality() != Quality::FullLine) ||
				(pTypeAttr != NULL && pTypeAttr != GetParentAttr()))
			{
				delete pSubRenderContext;
				pRender->DrawPath(pPath, this, ShapePath);
				return;
			}
		}

		// --- We don't expect the input path to be stroked AND filled on entry
		ERROR3IF(pPath->IsFilled, "PathProcessor expected RenderRegion to handle IsFilled case");

		// --- Get the current line width & Join Style from the render region
		// BLOCK
		{
			LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) pRender->GetCurrentAttribute(ATTR_LINEWIDTH);
			if (pWidthAttr != NULL)
				pSubRenderContext->LineWidth = pWidthAttr->LineWidth;

			JoinTypeAttribute *pJoinAttr = (JoinTypeAttribute *) pRender->GetCurrentAttribute(ATTR_JOINTYPE);
			if (pJoinAttr != NULL)
				pSubRenderContext->JoinStyle = pJoinAttr->JoinType;
		}
	}

	// --- Create a new path to be rendered in place of the provided path
	// Note that I use a large allocation size so that reallocation need not be done
	// frequently, which also helps reduce memory fragmentation.
	Path *pOutput = new Path;
	if (pOutput == NULL)
	{
		if (!pRender->IsSubRenderStateLocked())
			pRender->SetSubRenderState(NULL);
		delete pSubRenderContext;
		pRender->DrawPath(pPath, this, ShapePath);
		return;
	}

	pOutput->Initialise(128, 128);


	// --- Find our Variable Width function
	if (CreateSubRenderContext)
	{
		// --- Get the variable line width descriptor from the render region
		VariableWidthAttrValue *pVarWidthAttr = (VariableWidthAttrValue *) pRender->GetCurrentAttribute(ATTR_VARWIDTH);
		if (pVarWidthAttr != NULL)
			pSubRenderContext->pValFunc = pVarWidthAttr->GetWidthFunction();
	}

	ValueFunction *pValFunc = pSubRenderContext->pValFunc;

	// If we couldn't find a proper value function, then we'll default to constant-width.
	// We keep a static Constant function around always, because it's thread-safe and because
	// that saves us the overhead of creating and deleting it on the stack each time we're called
	static ValueFunctionConstant Constant(1.0);
	if (pValFunc == NULL)
		pValFunc = &Constant;


	// --- Find our brush clipart tree
	Node *pBrush = pStrokeDef->GetStrokeTree();
	ERROR3IF(!IS_A(pBrush, Spread), "Brush does not start with a Spread Node!");
	DocRect BrushBounds = ((Spread *)pBrush)->GetBoundingRect();

	// Get a PathStroker to map paths onto the destination stroke with
	PathStrokerVector Stroker(pValFunc, pSubRenderContext->LineWidth,
								LineCapButt, &BrushBounds);

	// Work out if this is a repeating stroke, and if so, how often it repeats
	if (CreateSubRenderContext)
	{
		if (pStrokeDef->IsRepeating())
		{
			// The repeat distance is calculated as a number of millipoints per repeat of the
			// stroke, such that it retains the correct aspect ratio. That is, the ratio of
			// brush width to height is the same as RepeatDist to LineWidth
			pSubRenderContext->RepeatDist = (INT32) (Stroker.GetScaleFactor() * (double)BrushBounds.Width());
			if (pSubRenderContext->RepeatDist < 1000)		// I absolutely refuse to repeat it more than
				pSubRenderContext->RepeatDist = 1000;		// once every 1pt, as this is plenty small enough

			// Suss the path length out
			ProcessLength GenerateLength(100);
			double Length = 0;
			BOOL ok = GenerateLength.PathLength(pPath, &Length);

			// Ask the stroke def for its number of brush repeats - 0 means work it out
			INT32 NumberOfRepeats = pStrokeDef->NumRepeats();
			if(NumberOfRepeats == 0 && pSubRenderContext->RepeatDist > 0)
			{
				// Work out the optimal number of repeats along the path
				NumberOfRepeats = (INT32)(floor((Length/pSubRenderContext->RepeatDist) + 0.5));
			}

			// Don't got dividing by zero now...			
			if(NumberOfRepeats <= 0)
				NumberOfRepeats = 1;
		
			// Alter the repeat distance to accomodate this number of repeats
			pSubRenderContext->RepeatDist = (INT32)(Length / (double)NumberOfRepeats);
		}

		// Generate the set of trapezoids for the dest path
		ProcessPathToTrapezoids GenerateTraps(100);
		pSubRenderContext->pOutputTraps = new TrapsList(pSubRenderContext->RepeatDist);

		BOOL Failed = (pSubRenderContext->pOutputTraps == NULL);
		if (!Failed && !GenerateTraps.Init(pPath, pSubRenderContext->pOutputTraps))
			Failed = TRUE;

		ProcessFlags PFlags(TRUE, FALSE, FALSE);	// Flags are: Flatten, !QuantiseLines, !QuantiseAll
		if (!Failed && !GenerateTraps.Process(PFlags, TrapTravel_Parametric, pSubRenderContext->JoinStyle))
			Failed = TRUE;

		if (Failed)
		{
			pRender->DrawPath(pPath, this, ShapePath);
			if (!pRender->IsSubRenderStateLocked())
				pRender->SetSubRenderState(NULL);
			delete pSubRenderContext;
			return;
		}
	}

	ERROR3IF(pSubRenderContext->pOutputTraps == NULL || pValFunc == NULL,
				"Vector stroke SubRenderContext was not properly uninitialised!");

	// --- Handle background rendering. We always store all critical information in a SubRenderContext.
	// If we have to break into rendering because of background rendering, we give the context to the RndRgn
	// to keep for next time. However, when we finish rendering everything, we need to clean up - we will
	// assume that we'll make it to the end, and chnage this variable if we get interrupted.
	BOOL DeleteSubRenderContext = TRUE;

	// Lock the sub-render context so that nobody "inside" the brush uses it
	const BOOL SRContextLocked = pRender->IsSubRenderStateLocked();
	if (!SRContextLocked)
		pRender->LockSubRenderState(TRUE);

	// --- Now "render" the brush clipart tree via our Stroker
	for ( ;
			pSubRenderContext->Index < pSubRenderContext->pOutputTraps->GetNumTraps() && DeleteSubRenderContext;
			pSubRenderContext->Index++)
	{
		// Find the trapezoid edge list for this pass
		TrapEdgeList *pEdgeList = pSubRenderContext->pOutputTraps->GetTrapEdgeList(pSubRenderContext->Index);
		if (pEdgeList->GetNumEdges() < 2)
		{
			ERROR3("No map traps when stroking! Subpath stripped\n");
			continue;
		}

		// And render away
		pRender->SaveContext();

		Node* pNode = pBrush->FindFirstForUnclippedInkRender(pRender);
		while (pNode)
		{
			// Prepare the stroker to stroke this sub-stroke
			Stroker.PrepareToStroke(pEdgeList);

			if (pNode->IsAnAttribute())
			{
				// If we are overriding the fill/transparency with the one applied to the stroke,
				// then we simply throw away all fill/transparency attributes as we render
				// (We do this on the fly rather than as we make the brush so that the user can
				// toggle this mode on and off at any time if they change their mind)
				BOOL RenderIt = TRUE;
				if ( (pStrokeDef->OverrideFill()  && ((NodeAttribute *)pNode)->IsAColourFill())	||
					 (pStrokeDef->OverrideFill()  && ((NodeAttribute *)pNode)->IsAStrokeColour()) ||
					 (pStrokeDef->OverrideTrans() && ((NodeAttribute *)pNode)->IsAStrokeTransp()) ||
					 (pStrokeDef->OverrideTrans() && ((NodeAttribute *)pNode)->IsATranspFill()) )
				{
					RenderIt = FALSE;
				}

				if (RenderIt)
				{
					// We must modify all attributes to lie in the destination stroke.
					// This includes fill/trans geometry endpoints, line widths, and
					// also possibly modifying transparency levels to allow a flat transparency
					// to be applied to the whole stroke.
					AttributeValue *pAttrValue = ((NodeAttribute *)pNode)->GetAttributeValue();
					AttributeValue *pNewValue  = pAttrValue->MouldIntoStroke(&Stroker, 1.0);
					//****!!!!TODO - Just above, we have the chance to handle transparency better
					// - we could at least scale all transparencies by passing a flat scale factor into
					// the MouldIntoStroke call.

					if (pNewValue != NULL)
						pNewValue->Render(pRender, TRUE);		// The RndRgn will delete this when it's done with
					else
						pNode->Render(pRender);					// No change, so render the original attribute
				}
			}
			else if (pNode->IsNodePath())
			{
				// Stroke the trapezoids into the output path
				pOutput->ClearPath();
				if (!Stroker.StrokePath(&((NodePath *)pNode)->InkPath, pOutput))
					break;

				pRender->SetWindingRule(NonZeroWinding);
				pRender->DrawPath(pOutput, this, ShapePath);
			}
//				else
//					TRACEUSER( "Jason", _T("\nBrush node %s not rendered\n"), pNode->GetRuntimeClass()->m_lpszClassName);

			pNode = pNode->FindNextForUnclippedInkRender(pRender);
		}

		pRender->RestoreContext();

		// --- Now check if we should break into rendering for background rendering purposes
		// If the Sub-render-context is locked, then we're inside a blend or something, and it's too dangerous
		// for us to store our sub-render state, so we have no choice but to render until we finish.
		// BLOCK
		if (!SRContextLocked && IS_A(pRender, GRenderDIB))
		{
			View *pView = pRender->GetRenderView();
			if (pView != NULL && !pRender->RenderTreeCanContinue())
			{
				// We have been interrupted by the background redraw system.
				// We will immediately exit, storing our SubRenderContext away into the
				// RenderRegion for the next time it calls us (see below).
				DeleteSubRenderContext = FALSE;

				// Drop through and let the loop condition handle exit
			}
		}
	}

	// If we locked the sub-render context, then we must restore it
	if (!SRContextLocked)
		pRender->LockSubRenderState(FALSE);

	// If we have finished rendering everything, then we vape our sub render context.
	// (We even check if we were interrupted just as we finished the final iteration)
	if (DeleteSubRenderContext || pSubRenderContext->Index >= pSubRenderContext->pOutputTraps->GetNumTraps())
	{
		if (!SRContextLocked)
			pRender->SetSubRenderState(NULL);
		delete pSubRenderContext;
		pSubRenderContext = NULL;
	}
	else
	{
		if (!SRContextLocked)
			pRender->SetSubRenderState(pSubRenderContext);
	}

	delete pOutput;
	pOutput = NULL;
#endif
}
Ejemplo n.º 8
0
/********************************************************************************************

>	BOOL MakeBitmapFilter::InsertBitmapIntoDocument(UndoableOperation *pOp, KernelBitmap* KernelBmp, Document* DestDoc)

	Author:		Will_Cowling (Xara Group Ltd) <*****@*****.**>
	Created:	11/6/96
	Purpose:	Exports the current selection as a bitmap, via the virtual fns of the
				inherited class.
	Returns:	TRUE if worked, FALSE if failed.
	SeeAlso:	GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport;

********************************************************************************************/
BOOL MakeBitmapFilter::InsertBitmapIntoDocument(UndoableOperation *pOp, KernelBitmap* KernelBmp, Document* DestDoc)
{
	Spread *pSpread;
	DocCoord Origin;

	// Remember the selection rect, before we change it
	DocRect SelRect = GetApplication()->FindSelection()->GetBoundingRect();

	// For now, position Draw objects on 1st page of spread 1
PORTNOTE("spread", "Multi-spread warning!")
	pSpread = GetFirstSpread(DestDoc);
	Page *pPage = (Page *) pSpread->FindFirstPageInSpread();
	ERROR3IF(!pPage->IsKindOf(CC_RUNTIME_CLASS(Page)),
		   "MakeBitmapFilter::InsertBitmapIntoDocument: Could not find first Page");

	// Use bottom left of page as origin
	DocRect PageRect = pPage->GetPageRect();
	Origin.x = PageRect.lo.x;
	Origin.y = PageRect.hi.y;

	// Get a new NodeBitmap object to import into.
	NodeBitmap *pNodeBitmap = new NodeBitmap;
	if ((pNodeBitmap == NULL) || (!pNodeBitmap->SetUpPath(12,12)))
		return FALSE;

	// Attach the Imported Bitmap to our Node
	pNodeBitmap->GetBitmapRef()->Attach(KernelBmp, DestDoc); //GetDocument());
	if (pNodeBitmap->GetBitmap() != KernelBmp)
		delete KernelBmp; // It didn't use the bitmap we gave it, so we can delete it

	// Import worked - try to add the bitmap object into the tree.
	// First, set the rectangle to the right size for the bitmap...
	BitmapInfo Info;
	pNodeBitmap->GetBitmap()->ActualBitmap->GetInfo(&Info);

	DocRect BoundsRect;
	BoundsRect.lo = Origin;
	BoundsRect.hi.x = BoundsRect.lo.x + Info.RecommendedWidth;
	BoundsRect.hi.y = BoundsRect.lo.y + Info.RecommendedHeight;

	// And set this in our bitmap node
	pNodeBitmap->CreateShape(BoundsRect);

	// Make sure that there is a layer to put the bitmap onto
	if (!MakeSureLayerExists(DestDoc))
	{
		// There is no layer and one could not be made, so we will have to fail
		delete pNodeBitmap;
		return FALSE;
	}

	// Set the default attrs
	// This MUST be done before the NodeBitmap is Inserted into the tree
	if (!pNodeBitmap->ApplyDefaultBitmapAttrs(pOp))
		return FALSE;

	// Insert the node, but don't invalidate its region
	if (!pOp->DoInsertNewNode(pNodeBitmap, pSpread, FALSE))
	{
		// It didn't work - delete the sub-tree we just created, and report error.
		delete pNodeBitmap;
		return FALSE;
	}

	// bitmap is currently positioned so its bottom left hand
	// corner is at the top left of the page

	// By default we'll move it down so the top-left of the bitmap is on the top-left of the page
	INT32 XTranslate = 0;
	INT32 YTranslate = -Info.RecommendedHeight;

	ClickModifiers ClickMods = ClickModifiers::GetClickModifiers();

	if (ClickMods.Adjust && !SelRect.IsEmpty())
	{
		// If shift is down, then we'll try and place the bitmap exactly on top of the selection
		DocCoord SelectionCentre(SelRect.lo.x + (SelRect.Width()/2), SelRect.lo.y + (SelRect.Height()/2));

		XTranslate = SelectionCentre.x - Origin.x - (Info.RecommendedWidth/2);
		YTranslate = SelectionCentre.y - Origin.y - (Info.RecommendedHeight/2);
	}
	else
	{
		// Otherwise we'll try and centre it within the current view
		Spread* pCurrentSpread;
		DocCoord ViewCentre;

		if (FindCentreInsertionPosition(&pCurrentSpread, &ViewCentre))
		{
/*	Karim 19/01/2000
 *	Ensure that the bmp is pixel-aligned as close to the centre as possible.
 *
			XTranslate = ViewCentre.x - Origin.x - (Info.RecommendedWidth/2);
			YTranslate = ViewCentre.y - Origin.y - (Info.RecommendedHeight/2);
/**/
			DocCoord PixAlignBmpOrigin(	ViewCentre.x - Info.RecommendedWidth/2,
										ViewCentre.y - Info.RecommendedHeight/2 );
			INT32			FullDPI		= GRenderRegion::GetDefaultDPI();
			MILLIPOINT	PixWidth	= (INT32)((IN_MP_VAL / (double)FullDPI) + 0.5);
			PixAlignBmpOrigin.x -= PixAlignBmpOrigin.x % PixWidth;
			PixAlignBmpOrigin.y -= PixAlignBmpOrigin.y % PixWidth;
			XTranslate = PixAlignBmpOrigin.x - Origin.x;
			YTranslate = PixAlignBmpOrigin.y - Origin.y;
		}
	}

	Trans2DMatrix Xlate(XTranslate, YTranslate);
	pNodeBitmap->Transform(Xlate);

	// Ensure Sel Bounds are correct after translation
	GetApplication()->UpdateSelection();

	return TRUE;
}
Ejemplo n.º 9
0
/********************************************************************************************

>	BOOL MakeBitmapFilter::DoCreateBitmap(Operation *pOp, Document *pDoc, KernelBitmap** ppBitmap)

	Author:		Will_Cowling (Xara Group Ltd) <*****@*****.**>
	Created:	11/6/96
	Purpose:	Exports the current selection as a bitmap, via the virtual fns of the
				inherited class.
	Returns:	TRUE if worked, FALSE if failed.
	SeeAlso:	GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport;

********************************************************************************************/
BOOL MakeBitmapFilter::DoCreateBitmap(Operation *pOp, Document *pDoc, KernelBitmap** ppBitmap)
{
	ERROR3IF(ppBitmap == NULL, "NULL bitmap pointer passed to MakeBitmapFilter::DoCreateBitmap");
	if (ppBitmap == NULL)
		return FALSE;

	pTheBitmap = NULL;
	*ppBitmap = NULL;

	// Set the bitmap pointer to null just in case, usually only used by DoExportBitmap
	pExportBitmap = NULL;

	// Get pointer to the spread to export.
PORTNOTE("spread", "Multi-spread warning!")
	pSpread = GetFirstSpread(pDoc);

	// remember the document in the class variable
	TheDocument = pDoc;

	// We must now check if there is a selection present so that we can set up whether the
	// user gets the choice of exporting the selection, drawing or spread if there is a 
	// selection present OR just a choice between the spread or drawing if no selection is
	// present.
	// If have a caret selected in a text story then the selection will be almost zero so trap
	// this case as well. 
	RangeControl rg = GetApplication()->FindSelection()->GetRangeControlFlags();
	rg.PromoteToParent = TRUE;
	GetApplication()->FindSelection()->Range::SetRangeControl(rg);
	SelRange Rng(*(GetApplication()->FindSelection()));

	// now, run through the selection selecting all nodes under all compound nodes
	// if we don't do this then all compound nodes aren't rendered correctly with transparent
	// bitmaps
	Node * pNode = Rng.FindFirst(FALSE);

	while (pNode)
	{
		pNode->SetSelected(FALSE);
		pNode->SetSelected(TRUE);
		pNode = Rng.FindNext(pNode, FALSE);
	}

	rg.PromoteToParent = FALSE;
	GetApplication()->FindSelection()->Range::SetRangeControl(rg);
	GetApplication()->UpdateSelection();

	DocRect ClipRect = GetApplication()->FindSelection()->GetBoundingRect();
	SelectionType Selection = DRAWING;
 	if ( ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize ||
		 ClipRect.Height() < MinExportSize)
		Selection = DRAWING;		// no selection present, so choose drawing by default
	else
		Selection = SELECTION;		// selection present, so choose this by default

	if (Selection != SELECTION)
	{
		BOOL UseDrawingBounds = TRUE;
		
		SelRange* pSel = GetApplication()->FindSelection();
		if (pSel && pSel->Count()==1)
		{
			// Only one thing selected ... Is it the Text Caret per chance ?
			Node* pSelNode = pSel->FindFirst();
			if (pSelNode && pSelNode->IsAVisibleTextNode())
			{
				VisibleTextNode* pTextNode = (VisibleTextNode*)pSelNode;
				if (pTextNode->IsACaret())
				{
				 	// Aha! It's the Caret that's selected.
					// We'll use the bounds of the parent text line instead then ...
					Node* pTextLine = pTextNode->FindParent();
					ERROR3IF(!IS_A(pTextLine, TextLine), "Caret doesn't have a parent text line in DoCreateBitmap");
					
					// Get the bounds of the text line
					ClipRect = ((TextLine*)pTextLine)->GetBoundingRect();				

					Selection = SELECTION;
					UseDrawingBounds = FALSE;
				}		 		
			}
		}

		if (UseDrawingBounds)
		{
			// Work out the size of the rectangle encompassing the drawing (visible layers only)
			ClipRect = GetSizeOfDrawing(pSpread);
		}
	}

	// Create somewhere to put the user options and fill them up
	MakeBitmapExportOptions* pMakeBmpExportOptions = (MakeBitmapExportOptions*)CreateExportOptions();
	if (pMakeBmpExportOptions == NULL)
	{
		Error::SetError(_R(IDS_OUT_OF_MEMORY));
		return FALSE;
	}

	pMakeBmpExportOptions->RetrieveDefaults();
	pMakeBmpExportOptions->SetDepth(32); // create bmp copies shoulda always default to being 32 bit
	pMakeBmpExportOptions->SetSelectionType(Selection);

	// Set the BaseBitmapFilter member so we can use base class functionality - blurghh
	SetExportOptions(pMakeBmpExportOptions);

	BOOL ok = GetExportOptions( (BitmapExportOptions*)pMakeBmpExportOptions );

	BOOL IsAnimation = BmapPrevDlg::m_pExportOptions == NULL;
	BaseBitmapFilter * pNewFilter = this;
	BitmapExportOptions * pExportOptions = BmapPrevDlg::m_pExportOptions;
	if (!IsAnimation)
	{
		pNewFilter = pExportOptions->FindBitmapFilterForTheseExportOptions();
		// from the exporting point of view we should always have been using png options
		// set them to the png options for the export part
		if (pNewFilter)
			pNewFilter->SetExportOptions(pExportOptions);
		// gets the real export options that the prevdlg has set up for us
		BmapPrevDlg::m_pExportOptions = NULL; // take responsibility for this data
	}
	else
	{
		// the animation export didn't bring up the dlg so never set BmapPrevDlg::m_pExportOptions
		// so continue with these options
		pExportOptions = (BitmapExportOptions*)pMakeBmpExportOptions;
	}

	SetExportOptions(pExportOptions);
	

	if (!ok)
	{
		SetExportOptions(NULL); // deletes the filter ptr and nulls it
		delete pExportOptions;
		return FALSE;									// if cancelled
	}


//////////////// SMFIX

	pExportOptions->MarkValid();
	SetDepthToRender(pExportOptions->GetDepth());

	// Set up device context and render region for this export.
	// This will show a progress hourglass for the objects being rendered
	// THis will now also write the data out to file via our ExportRenderNodes function
	if (!PrepareToExport(pSpread, pExportOptions->GetDepth(), pExportOptions->GetDPI(), 
							pExportOptions->GetSelectionType(), pExportOptions->GetDither()))
	{
		pNewFilter->SetExportOptions(NULL);
		SetExportOptions(NULL);
		delete pExportOptions;
		CleanUpAfterExport();
		return FALSE;
	}

	RenderInStrips = FALSE;
	
	if (!ExportRender(ExportRegion))
	{
		pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it
		SetExportOptions(NULL);
		delete pExportOptions;
		CleanUpAfterExport();
		return FALSE;
	}

	// Now get the converted 32Bit BMP
	pTheBitmap = GetTheBitmap(pExportOptions);

	// if we`ve got a transparency index AND we`ve got a 32 Bit Render region with alpha channel info
	// then we can quickly do
	if(pExportOptions->GetDepth() <= 8 && pExportOptions->GetTransparencyIndex() != -1 && pTheBitmap)
	{
		// What we do now is to go throught the bitmap setting the relavent pixels to transparent
		// depending on the alpha channel info held in the 32 bit version.
		if(!ApplyTransparentColoursToBitmap(pTheBitmap,pExportOptions))
		{
			pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it
			return FALSE;
		}

		// Now make sure the bitmap knows that it has a transparent colour!
		pTheBitmap->SetTransparencyIndex(pExportOptions->GetTransparencyIndex());
	}

	// Set pointer to the bitmap we have created
	*ppBitmap = pTheBitmap;

	pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it
	SetExportOptions(NULL);
	delete pExportOptions;
	CleanUpAfterExport();

	return *ppBitmap != NULL;

//////////////// SMFIX
}
Ejemplo n.º 10
0
BOOL FreeHandEPSFilter::ProcessToken()
{
	// Decode the command, and execute it...
	switch (Token)
	{
		// state saving
		case EPSC_vms:
			if(!Import_gsave())
				return FALSE;
			break;

		case EPSC_vmr:
			if(!Import_grestore())
				return FALSE;
			break;

		case EPSC_vmrs:
			if(!Import_grestore())
				return FALSE;
			if(!Import_gsave())
				return FALSE;
			break;

		// tokens to ignore
		case EPSC_FREEHAND_IGNOREDTOKEN:
			break;

		// tokens which should be ignored and one entry discarded
		case EPSC_load:			// the load part of a fill - discard the /clipper before it
		case EPSC_fhsetspreadallow:
			if(!Stack.Discard(1))
				goto EPSError;
			break;

		case EPSC_concat:
			if(!Stack.DiscardArray())
				goto EPSError;
			break;
		
		// complex paths...
		case EPSC_eomode:
			{
				INT32 ComplexStart;

				if(!Stack.Pop(&ComplexStart))
					goto EPSError;

				// is this a start of a complex path?
				if(ComplexStart != TRUE)
				{
					ComplexPathMode = FALSE;
				}
				else
				{
					HadFirstOfComplexPath = FALSE;
					ComplexPathMode = TRUE;
				}
			}
			break;

		case EPSC_true:
			Stack.Push((INT32)TRUE);
			break;

		case EPSC_false:
			Stack.Push((INT32)FALSE);
			break;

		case EPSC_u:
			HadFirstOfComplexPath = FALSE;
			return EPSFilter::ProcessToken();
			break;

		// colours
		case EPSC_Ka:
		case EPSC_ka:
			{
				DocColour Colour;

				if(PopColour(&Colour))
				{
					// Remember this colour for future objects
					if (Token == EPSC_ka)
					{
				    	if (!SetFillColour(Colour))
							goto NoMemory;
					}
					else
					{
						if (!SetLineColour(Colour))
							goto NoMemory;
					}
				}
			    else	
			    	// Invalid colour operands
					goto EPSError;
			}
			break;

		case EPSC_Xa:
		case EPSC_xa:
			{
				DocColour Colour;

				if(PopNamedColour(&Colour))
				{
					// Remember this colour for future objects
					if (Token == EPSC_xa)
					{
				    	if (!SetFillColour(Colour))
							goto NoMemory;
					}
					else
					{
						if (!SetLineColour(Colour))
							goto NoMemory;
					}
				}
			    else	
			    	// Invalid colour operands
					goto EPSError;
			}
			break;

		case EPSC_H:
			if(ComplexPathMode)
			{
				// in complex path mode - make this a filled one, not a discarded one
				Token = EPSC_S; 
			}
			return EPSFilter::ProcessToken();
			break;
		
		case EPSC_h:
			if(ComplexPathMode)
			{
				// in complex path mode - modify and process
				Token = EPSC_s;
				return EPSFilter::ProcessToken();
				break;
			}
			// the hidden path closing operator - a grad fill thingy will follow shortly maybe...
			// this will prevent it being processed now, although it may get processed later on.
			HadhToken = TRUE;
			break;

		// for clipping masks, do some funky stuff
		case EPSC_q:
			// if there's a pending grad fill...
			if(DoingGradFill)
			{
				if(pPath != 0)
				{
					// right then, make a copy of the path...
					NodePath *pPathClone;

					if(!pPath->NodeCopy((Node **)&pPathClone))
					{
						goto NoMemory;
					}

					// copy the flags
					EPSFlagsDefn EPSFlagsClone = EPSFlags;
				
					// send a token to finish and fill the path...
					Token = (pInkPath->IsFilled)?EPSC_f:EPSC_s;
					if(!EPSFilter::ProcessToken())
						return FALSE;

					// restore the old fill
					if(!RestoreCurrentFill())
						goto NoMemory;

					// restore the copy of the path
					pPath = pPathClone;
					pInkPath = &pPath->InkPath;

					// restore the flags
					EPSFlags = EPSFlagsClone;

					// definately want to send an h
					HadhToken = TRUE;
				}

				// done the grad fill
				DoingGradFill = FALSE;

				// restore the old token
				Token = EPSC_q;
			}

			// clipping started - have we got an h token to send?
			if(HadhToken)
				FHEF_SENDh

			// process this
			return EPSFilter::ProcessToken();
			break;

		// for now, if there's no path, don't return a W
		case EPSC_W:
			if(pPath == 0)
			{
				// OK, now we want to get the last path we created, make a copy of it and then install it as the current one
				if(pLastPathSeen == 0)
					goto EPSError;

				// make a copy of it
				NodePath *pClone;
				
				if(!pLastPathSeen->NodeCopy((Node **)&pClone))
					goto NoMemory;

				// delete it's attributes
				pClone->DeleteChildren(pClone->FindFirstChild());

				// make it the current path
				pPath = pClone;
				pInkPath = &pPath->InkPath;
				ThePathType = PATH_NORMAL;
				EPSFlags.NoAttributes = TRUE;
			}
			if(pPath != 0)
				return EPSFilter::ProcessToken();
			break;

		// we may need to modify path closing things if we're doing a grad fill
		case EPSC_s:
		case EPSC_S:
			if(Token == EPSC_S)
			{
				// if we've had an h token but no grad fill, send the h now
				if(HadhToken)
					FHEF_SENDh

				// if we've got a grad fill, modify the token we got
				if(DoingGradFill)
					Token = EPSC_b;
			}
			
			// process the possily modified token normally
			HadhToken = FALSE;
			return EPSFilter::ProcessToken();
			break;

		// modify path closing for grad fills.
		case EPSC_n:
			if(DoingGradFill)
			{
				Token = EPSC_f;			// we want to fill the thing
				HadhToken = FALSE;
				return EPSFilter::ProcessToken();
				break;
			}
   			HadhToken = FALSE;			// ignore h's as this is another end path thingy...

			if(pPath != 0)
				return EPSFilter::ProcessToken();
			break;

		// unset the had h token for other path closing things
		case EPSC_N:
		case EPSC_F:
		case EPSC_f:
		case EPSC_B:
		case EPSC_b:
			HadhToken = FALSE;
			return EPSFilter::ProcessToken();
			break;
		
		// interested in path element things to switch off grad fills
		case EPSC_m:
			if(InText)
			{
				// if we're doing some text, discard the moveto command
				if(!Stack.Discard(2))
					goto EPSError;

				break;
			}
		case EPSC_l:
		case EPSC_L:
		case EPSC_c:
		case EPSC_C:
		case EPSC_v:
		case EPSC_V:
		case EPSC_y:
		case EPSC_Y:
			// maybe we need an h token to be sent
			if(HadhToken)
				FHEF_SENDh
			
			// stop grad fill
			if(DoingGradFill)
			{
				// turn the grad fill state off
				DoingGradFill = FALSE;

				// restore the old fill type
				RestoreCurrentFill();
			}
			return EPSFilter::ProcessToken();
			break;

		
		case EPSC_recfill:
			{
				// get the colours
				DocColour StartColour, EndColour;

				if(!PopColour(&EndColour) ||
						!PopColour(&StartColour))
					goto EPSError;

				// discard the fill type thingy - we can only do colours
				if(!DiscardFillSubType())
					goto EPSError;

				// OK, now a few coords
				DocCoord Centre;
				double Angle;
				DocRect BBox;
				if(!Stack.PopCoordPair(&BBox.hi) ||
						!Stack.PopCoordPair(&BBox.lo) ||
						!Stack.Pop(&Angle) ||
						!Stack.PopCoordPair(&Centre))
					goto EPSError;

				// munge the angle a little and get it into radians
				Angle += 225;
				Angle = (Angle * (2 * PI)) / 360;

				// see if we can get a more accurate BBox
				if(pPath != 0)
				{
					BBox = pPath->GetBoundingRect();
					Centre.x = BBox.lo.x + (BBox.Width() / 2);
					Centre.y = BBox.lo.y + (BBox.Height() / 2);
				}

				// OK, we've got all the stuff we need to do some niceness on it
				BBox.Translate(0 - Centre.x, 0 - Centre.y);
				DocCoord StartPoint, EndPoint;

				StartPoint.x = Centre.x + (INT32)(((double)BBox.lo.x * cos(Angle)) - ((double)BBox.lo.y * sin(Angle)));
				StartPoint.y = Centre.y + (INT32)(((double)BBox.lo.x * sin(Angle)) + ((double)BBox.lo.y * cos(Angle)));
				EndPoint.x = Centre.x + (INT32)(((double)BBox.hi.x * cos(Angle)) - ((double)BBox.hi.y * sin(Angle)));
				EndPoint.y = Centre.y + (INT32)(((double)BBox.hi.x * sin(Angle)) + ((double)BBox.hi.y * cos(Angle)));
		
				// store current fill attribute
				SaveCurrentFill();

				// set the fill
				if(!SetLinearFill(StartColour, EndColour, StartPoint, EndPoint))
					goto NoMemory;

				// say we're doing a grad fill
				DoingGradFill = TRUE;
				HadhToken = FALSE;			// absorb this
			}
			break;

		case EPSC_radfill:
			{
				// get the colours
				DocColour StartColour, EndColour;

				if(!PopColour(&StartColour) ||
						!PopColour(&EndColour))
					goto EPSError;

				// get the radius and centre coordinate
				DocCoord Centre;
				INT32 Radius;
				if(!Stack.PopCoord(&Radius) ||
						!Stack.PopCoordPair(&Centre))
					goto EPSError;

				// store current fill attribute
				SaveCurrentFill();

				// set the fill
				DocCoord EndPoint(Centre.x + Radius, Centre.y);
				if(!SetRadialFill(StartColour, EndColour, Centre, EndPoint))
					goto NoMemory;

				// say we're doing a grad fill
				DoingGradFill = TRUE;
				HadhToken = FALSE;
			}
			break;

		case EPSC_BeginSetup:
			// there's probably a colour list or something in that there setup thingy - search for the spots token
			{
				BOOL Found = FALSE;
				
				while(Found == FALSE)
				{
					if(!EPSFile->GetToken())
						return FALSE;

			 		if(EPSFile->GetTokenType() == TOKEN_NORMAL)
			 		{
			 			if(camStrcmp(TokenBuf, _T("spots")) == 0)
						{
							// check to see if the array is about to start
							if(!EPSFile->GetToken())
								return FALSE;

							if(TokenBuf[0] == '[')
							{
								TRACEUSER( "Ben", _T("Found spots\n"));
								Found = TRUE;
							}
						}
					}
				
					if(camStrncmp(TokenBuf, _T("%%EndSetup"), 10) == 0)
					{
						TRACEUSER( "Ben", _T("Met end of setup without finding spots\n"));
						break;
					}

					if(EPSFile->eof())
						goto EPSError;
			 	}

				if(Found == TRUE)
				{
					InColours = TRUE;
				}
			}
			break;

		case EPSC_def:
			if(InColours)
			{
				// finished the colours...
				TRACEUSER( "Ben", _T("Finished spot colours\n"));			
				// scan for the end of the setup section
				BOOL Found = FALSE;
				
				while(Found == FALSE)
				{
					if(!EPSFile->GetToken())
						return FALSE;

			 		if(EPSFile->GetTokenType() == TOKEN_COMMENT)
			 		{
						if(camStrncmp(TokenBuf, _T("%%EndSetup"), 10) == 0)
						{
							TRACEUSER( "Ben", _T("Found end of setup\n"));
							Found = TRUE;
						}
					}

					if(EPSFile->eof())
						goto EPSError;
			 	}
				
				// get the ] off the stack
				EPSCommand Ignored;
				Stack.PopCmd(&Ignored);

				// empty it...
				Stack.DeleteAll ();
				InColours = FALSE;
			}
			else
			{
				// probably a font type thingy - empty the stack including commands
				Stack.DeleteAll ();
			}
			break;

		case EPSC_newcmykcustomcolor:
			// OK, here's a named colour... add it to those known
			{
				// discard some random thingy
				if(!Stack.Discard())
					goto EPSError;
			
				// get the name
				String_64 ColourName;
				if(!Stack.Pop(&ColourName))
					goto EPSError;

				// get the components
				double C, M, Y, K;
				if(!Stack.Pop(&K) ||
						!Stack.Pop(&Y) ||
						!Stack.Pop(&M) ||
						!Stack.Pop(&C))
					goto EPSError;

				// make the new colour
				ColourCMYK Colour;
				Colour.Cyan = C;
				Colour.Magenta = M;
				Colour.Yellow = Y;
				Colour.Key = K;

				// add it
				if(!pNewColours->AddColour(&ColourName, &Colour))
					goto NoMemory;

				// add it to the list of colours
				// this is a bit of a bodge, but never mind. Shouldn't be that bad.
				IndexedColour *TheNewColour = pNewColours->GetColour(ColourName);

				if(TheNewColour == 0)
					goto NoMemory;

				// add it to the list of colours
				// enough space?
				if((ColourArrayEntries + 1) >= ColourArraySize)
				{
					TRACEUSER( "Ben", _T("Extening colour array\n"));
					IndexedColour **NewPtr = (IndexedColour **)CCRealloc(ColourArray, (ColourArraySize + FHEF_COLOURARRAY_CHUNK) * sizeof(IndexedColour *));

					if(NewPtr == 0)
						goto NoMemory;

					ColourArray = NewPtr;
					ColourArraySize += FHEF_COLOURARRAY_CHUNK;
				}

				// add
				ColourArray[ColourArrayEntries] = TheNewColour;
				ColourArrayEntries++;
			}
			break;

		// ignore text stuff
		case EPSC_makesetfont:
			if(!Stack.DiscardArray())
				goto EPSError;
			if(!Stack.Discard(1))
				goto EPSError;
			InText = TRUE;
			break;

		case EPSC_ts:
			if(!Stack.Discard(6))
				goto EPSError;
			break;

		case EPSC_stob:
		case EPSC_sts:
			Stack.DeleteAll ();
			InText = FALSE;
			break;
				
		default:
			// Token not understood - pass on to base class
			return EPSFilter::ProcessToken();
	}


	// No errors encountered while parsing this token and its operands.
	return TRUE;
	
	
	// Error handlers:
EPSError:
	HandleEPSError();
	return FALSE;

NoMemory:
	HandleNoMemory();
	return FALSE;
}
Ejemplo n.º 11
0
BOOL OpBackground::FixBackgroundLayer(Layer * pBackgroundLayer, const DocRect& NewPagesRect,
									  const DocRect& OldPagesRect)
{
	ERROR2IF(pBackgroundLayer == NULL,FALSE,"OpBackground::FixBackgroundLayer Bad params!");
	
	//BOOL ok = TRUE;

	// There should be a rectangle on the page encompassing the old position of the pages
	// so go and try and find it
	NodeRegularShape * pShape = FindPageRectangle(pBackgroundLayer, OldPagesRect);
	// If no rectangle is found then something might be slightly wrong. Should we error?
	if (pShape)
	{
		const INT32 CornerRadius = 0; // No curvature
		if (pShape->MakeRectangle(NewPagesRect.Width(), NewPagesRect.Height(), CornerRadius))
		{
			// Translate centre from 0,0 to required position relative to page
			INT32 XTrans = NewPagesRect.lo.x + (NewPagesRect.Width()/2);
			INT32 YTrans = NewPagesRect.lo.y + (NewPagesRect.Height()/2);
			Trans2DMatrix Trans(XTrans, YTrans);

			pShape->Transform(Trans);

			// finish off the shape
			pShape->InvalidateBoundingRect();
		}
	
		// Find any bitmap fills and fix up the fill origin etc.
		Node * pNode = pShape->FindFirstChild();
		while (pNode != NULL)
		{
			// Only check and fix bitmap colour fill attributes of the regular shape nodes 
			if (pNode->IS_KIND_OF(AttrBitmapColourFill))
			{
				// Convert the pointer to the correct type
				AttrBitmapColourFill * pBitmapFillAttr = (AttrBitmapColourFill*)pNode;

				// Set the coordinates of the fill end points
				// We want to start the fill at the top left of the regular shape
				// The bounding rect should be roughly what we want
				DocRect Rect = pShape->GetBoundingRect(TRUE, FALSE);
							
				KernelBitmap * pBitmap = ((AttrFillGeometry*)pBitmapFillAttr)->GetBitmap();				
				// Get the size of the bitmap taking into account its DPI
				INT32 Width = pBitmap->GetRecommendedWidth();
				INT32 Height = pBitmap->GetRecommendedHeight();
				// You would think that the handles on the fill correspond to where you place them
				// but oh now the displayed handles are shown at different points. So instead of
				// positioning the start in the centre of the bitmap, you need to position it bottom left
				// The End should be centre and right but needs to be bottom right.
				// The End2 should be centre and top but needs to be top left.

				// We want the start point to be half the height of the bitmap below this
				//DocCoord Start(Rect.lo.x + Width/2, Rect.hi.y - Height/2);
				DocCoord Start(Rect.lo.x, Rect.hi.y - Height);
				// We want the other end point to be same height as the centre point
				// but on the far right of the rectangle i.e the full width across
				//DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height/2);
				DocCoord End(Rect.lo.x + Width, Rect.hi.y - Height);
				// We want the end point to be middle and top of the rectangle
				//DocCoord End2(Rect.lo.x + Width/2, Rect.hi.y);
				DocCoord End2(Rect.lo.x, Rect.hi.y);

				((AttrFillGeometry*)pBitmapFillAttr)->SetStartPoint(&Start);
				((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint(&End);
				((AttrFillGeometry*)pBitmapFillAttr)->SetEndPoint2(&End2);
			}
		
			pNode = pNode->FindNext();
		}		
	}

	return TRUE;
}