Ejemplo n.º 1
0
SubtreeRenderState NodeEffect::RenderSubtree(RenderRegion* pRender, Node** ppNextNode, BOOL bClip)
{
	if (pRender == NULL)							// If no render region supplied, assume we need to be rendered
		return SUBTREE_ROOTANDCHILDREN;

	// Go find out about my bounding rectangle
	DocRect BoundingRect = GetBoundingRect();
	DocRect ClipRect = pRender->GetClipRect();

	if (bClip && !ClipRect.IsIntersectedWith(BoundingRect))	// If not within the clipping rect then
		return SUBTREE_NORENDER;					// Don't render us or our children

	// Ask Helper function to set up cacheing for me...
// AMB wonders whethere this was commented out during porting - 20051212
//	if (RenderCached(pRender))						// If we can find a cached bitmap for this node and render it
//	{
//		return SUBTREE_NORENDER;					// Then tell the renderer to move on without doing any more...
//	}

	return SUBTREE_ROOTANDCHILDREN;					// Else we must render ourselves and our children
}
Ejemplo n.º 2
0
void BitmapExportPaletteControl::RenderPalette(DocRect *pPaletteSize, RenderRegion *pRender, INT32 controlHeight,
											   DocRect* pClipRect)
{
	INT32 nColours = m_Palette.GetNumberOfColours();

	// See if the background needs rendering
	if (nColours < m_NumberOfColoursAtLastRedraw)
		RenderGrey(pPaletteSize, pRender);

	m_NumberOfColoursAtLastRedraw = nColours;

	pRender->SetLineColour(COLOUR_BLACK);

	DocRect cell;

	// Draw each cell in turn
	for (INT32 i = 0; i < nColours; ++i)
	{
		GetRectForCell(i, &cell, controlHeight);
		if (cell.IsIntersectedWith(*pClipRect))
		{
			BYTE r, g, b;
			r = m_Palette.GetRed(i);
			g = m_Palette.GetGreen(i);
			b = m_Palette.GetBlue(i);
			DrawCell(&cell, DocColour(r, g, b), m_Palette.GetFlags(i), pRender,
				IsColourWebSafe(r, g, b), i == m_SelectedCell);
		}
	}

	// Draw the mouse over high light
	if (m_MouseOverCell != INVALID_COLOUR_VALUE)
	{
		GetRectForCell(m_MouseOverCell, &cell, controlHeight);
		pRender->SetFillColour(COLOUR_TRANS);
		pRender->SetLineColour(COLOUR_WHITE);
		pRender->DrawRect(&cell);
	}

}
Ejemplo n.º 3
0
BOOL OpNudge::IsNudgeOK(BOOL dx,BOOL dy)
{
    // Get the selection
    SelRange* pSel = GetApplication()->FindSelection();
    ERROR2IF(pSel == NULL,FALSE,"Awooga, NULL sel range");

    // Find out the bounding rectangle of the selection
    DocRect BoundingRect = pSel->GetBoundingRect();

    // Find out the Pasteboard rect
    DocRect PasteRect;
    Spread* pSpread = pOurDoc->GetSelectedSpread();
    if (pSpread==NULL)
        PasteRect = BoundingRect;
    else
    {
        // Try to make the pasteboard grow if necessary to include the new object position
        // This is very quick if the pasteboard is large enough already.
        pSpread->ExpandPasteboardToInclude(BoundingRect);

        // And re-read the bounding rectangle of the selection, as the pasteboard resize may have
        // caused the origin of our entire coordinate space to have moved! Argh!
        BoundingRect = pSel->GetBoundingRect();
//		BoundingRect.Translate(dx,dy);

        // This is in Document Coords, so we need to convert it
        PasteRect = pSpread->GetPasteboardRect();
        pSpread->DocCoordToSpreadCoord(&PasteRect);
    }

    // Assume the nudge will be OK.
    BOOL NudgeOK = TRUE;

    if (PasteRect.ContainsRect(BoundingRect))
    {
        // Untranslated bounds fit inside pasteboard rect, so we must complain if the bounds
        // do not fit *after* translation

        // Translate the bounds by the nudge values
        BoundingRect.Translate(dx,dy);

        // Do the translated bounds still fit entirely in the pasteboard rect?
        NudgeOK = PasteRect.ContainsRect(BoundingRect);
    }
    else
    {
        // The original bounds overlap the pasteboard rect, so we must complain if the user
        // nudges the bounds completely out of sight

        if (PasteRect.IsIntersectedWith(BoundingRect))
        {
            // The original bounds intersect with the pasteboard rect
            BoundingRect.Translate(dx,dy);

            // Only allow the nudge if the translated bounds still overlap with the spread.
            NudgeOK = PasteRect.IsIntersectedWith(BoundingRect);
        }
    }

    // If the nudge is OK, we may need to scroll the DocView?

    /*	Jim, 12/9/96 - removed this because we don't want to scroll to show opn nudges

    	if (NudgeOK)
    	{
    		DocCoord Coord(0,0);

    		// If nudging left or right, pick the min or max X coord
    		if (dx != 0)
    		{
    			if (dx < 0)
    				Coord.x = BoundingRect.lox;
    			else
    				Coord.x = BoundingRect.hix;
    		}

    		// If nudging up or down, pick the max or min Y coord
    		if (dy != 0)
    		{
    			if (dy < 0)
    				Coord.y = BoundingRect.loy;
    			else
    				Coord.y = BoundingRect.hiy;
    		}

    		// If we have picked a coord, ensure that this coord is visible in the selected spread
    		// of the selected DocView
    		if (Coord != DocCoord(0,0))
    		{
    			DocView* pDocView = DocView::GetSelected();
    			if (pDocView != NULL)
    				pDocView->ScrollToShow(&Coord);
    		}
    	}
    */
    return NudgeOK;
}
Ejemplo n.º 4
0
void PathProcessorStrokeAirbrush::ProcessPath(Path *pPath,
											  RenderRegion *pRender,
											  PathShape ShapePath)
{
	PORTNOTETRACE("other","PathProcessorStrokeAirbrush::ProcessPath - do nothing");
#ifndef EXCLUDE_FROM_XARALX
	ERROR3IF(pPath == NULL || pRender == NULL, "Illegal NULL Params");

	// --- 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 regions
	// BLOCK
	{
		StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR);
		if (pRender->DrawingMode != DM_COPYPEN || pRender->IsHitDetect()
			|| !pPath->IsStroked || pStrokeColour == NULL || pStrokeColour->Colour.IsTransparent())
		{
			pRender->DrawPath(pPath, this, ShapePath);
			return;
		}
	}

	// --- If the quality is set low, strokes are just rendered as centrelines
	// BLOCK
	{
		QualityAttribute *pQuality = (QualityAttribute *) pRender->GetCurrentAttribute(ATTR_QUALITY);
		if (pQuality != NULL && pQuality->QualityValue.GetLineQuality() != Quality::FullLine)
		{
			pRender->DrawPath(pPath, this, ShapePath);
			return;
		}
	}

	// --- If the attribute which created us is not the current StrokeType attribute, then
	// we have been overridden by a different stroke type, so we do nothing.
	// BLOCK
	{
		StrokeTypeAttrValue *pTypeAttr = (StrokeTypeAttrValue *) pRender->GetCurrentAttribute(ATTR_STROKETYPE);
		if (pTypeAttr != NULL && pTypeAttr != GetParentAttr())
		{
			pRender->DrawPath(pPath, this, ShapePath);
			return;
		}
	}

	// --- Get the current line width from the render region
	// In case of failure, we initialise with suitable defaults
	INT32 LineWidth = 5000;
	// BLOCK
	{
		LineWidthAttribute *pWidthAttr = (LineWidthAttribute *) pRender->GetCurrentAttribute(ATTR_LINEWIDTH);
		if (pWidthAttr != NULL)
			LineWidth = pWidthAttr->LineWidth;
	}

	// Obtain an optimal number of steps for the line
	// When printing, we do heaps of steps to get top quality out the other end
	View *pView	= pRender->GetRenderView();
	ERROR3IF(pView == NULL, "No render view?!");

	INT32 NumSteps = MaxAirbrushSteps;
	if (!pRender->IsPrinting())
		GetNumSteps(pView, LineWidth);

	// --- Now, create a transparency mask bitmap for the airbrush
	Spread *pSpread	= pRender->GetRenderSpread();
//	ERROR3IF(pSpread == NULL, "No render spread!?");	// This can happen, rendering into a gallery

	// Get the render region's clip rectangle in Spread Coords. We don't need to
	// render anything bigger than this size, so it is the upper limit on our bitmap area.
	DocRect ClipRegion = pRender->GetClipRect();

	// Intersect this with the path bounding rectangle to get the actual region we need to redraw
	// The smaller this is, the faster we go and the less memory we use.
	//DocRect PathRect = pPath->GetBoundingRect();
	DocRect PathRect = pPath->GetBlobRect();
	PathRect.Inflate(LineWidth);

	BOOL Intersects = ClipRegion.IsIntersectedWith(PathRect);
	if(!Intersects)
	{
		// Don't bother drawing anything - it's clipped out
		return;
	}

	ClipRegion = ClipRegion.Intersection(PathRect);

	// Round the ClipRegion edges up so they all lie exactly on screen pixel boundaries.
	// If we don't do this, then there can be a sub-pixel rounding error between the ClipRegion
	// and the actual bitmap size, so that the bitmap is scaled slightly when we plot it.
	// By making sure it's pixelised, we guarantee that the bitmap & clipregion are exactly equal sizes.
	// (It doesn't matter if the bitmap is a bit bigger than necessary)
	ClipRegion.Inflate(pRender->GetScaledPixelWidth());
	ClipRegion.lo.Pixelise(pView);
	ClipRegion.hi.Pixelise(pView);

	// Get the current view's rendering matrix and view scale
	Matrix ConvMatrix = pRender->GetMatrix();//pView->ConstructRenderingMatrix(pSpread);
	FIXED16 ViewScale = pView->GetViewScale();

	// Generate a 256-colour greyscale palette
	LOGPALETTE *pPalette = MakeGreyScalePalette();
	if(pPalette == NULL)
	{
		pRender->DrawPath(pPath, this, ShapePath);
		return;
	}

	// Work out the DPI to use. Rather than just asking for PixelWidth or DPI from the
	// render region, we have to do a load of non-object-oriented stuff instead...
	double dpi = 96.0;
	if (pRender->IsPrinting())
	{
		// we are printing, so ask the print options
		PrintControl *pPrintControl = pView->GetPrintControl();
		if (pPrintControl != NULL)
			dpi = (double) pPrintControl->GetDotsPerInch();
	}
	else if (IS_A(pRender, CamelotEPSRenderRegion))
	{
		// Use DPI as set in EPS export options dialog.
		dpi = (double) EPSFilter::XSEPSExportDPI;
	}
	else
	{
		ERROR3IF(pRender->GetPixelWidth() <= 0, "Stupid (<1 millipoint) Pixel Width!");
		if (pRender->GetPixelWidth() > 0)
			dpi = (double) (72000.0 / (double)pRender->GetPixelWidth());
	}

	GRenderBitmap *pMaskRegion = new GRenderBitmap(ClipRegion, ConvMatrix, ViewScale, 8, dpi,
													pRender->IsPrinting(), XARADITHER_ORDERED_GREY,
													pPalette, FALSE);
	if (pMaskRegion == NULL)
	{
		pRender->DrawPath(pPath, this, ShapePath);
		return;
	}

	BOOL PathIsFilled = FALSE;		// Will be set TRUE if this path should be filled at the bottom of the function

	//BLOCK
	{
		// Change the GDraw context in this render region so as to preserve the state
		// of the main render region. This is because GRenderRegions currently use
		// a single static GDrawContext! This also sets it up with a nice greyscale palette
		// so that we get the output we desire.
		pMaskRegion->UseGreyscaleContextDangerous();

		// Attach our DC to the view and render region...
		if (pMaskRegion->AttachDevice(pView, NULL, pSpread))
		{
			pMaskRegion->StartRender();

			// We must save & restore the attribute state around all our rendering because
			// attributes otherwise stay on the renderstack until we delete the RndRgn, and as our
			// ones are on the program stack, they will have ceased to exist before then, which
			// makes for a wicked explosion.
			pMaskRegion->SaveContext();

/////////////////////////////////////////////////////////////////////////////////////
			// --- Main Airbrush rendering loop

			// Make sure we've got an intensity function to use. This will create a new one if necessary
			ValueFunction *pvValueFunction = GetIntensityFunction();
			if (pvValueFunction == NULL)
			{
				ERROR3("Failed to set an intensity function on an airbrush stroke");
				pRender->DrawPath(pPath, this, ShapePath);
				return;
			}


			if(!RenderAirBrush(pPath, pMaskRegion, LineWidth, NumSteps, pvValueFunction,
							   pRender, ShapePath))
			{
				// Airbrush failed - just render the path without the airbrush effect
				pRender->DrawPath(pPath, this, ShapePath);
				return;
			}

			pMaskRegion->RestoreContext();

			// --- ClipRect test code

/////////////////////////////////////////////////////////////////////////////////////


			// --- We have drawn the airbrushed stroke - now, if the path is filled, we
			// will render the filled area, so that in semi-transparent cases, the
			// stroke will not "show through" from behind the filled area.			
			if (pPath->IsFilled)
			{
				ColourFillAttribute *pCFAttr = (ColourFillAttribute   *) pRender->GetCurrentAttribute(ATTR_FILLGEOMETRY);
				if (pCFAttr != NULL && (!pCFAttr->Colour.IsTransparent() || pCFAttr->IsABitmapFill()))
				{
					PathIsFilled = TRUE;

					pMaskRegion->SaveContext();

					ColourFillAttribute *pFillAttr = NULL;
					FillMappingAttribute *pMapAttr = NULL;

					// Obtain the object's transparent fill geometry
					TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY);
					if (pTransAttr != NULL)
					{
						// Get a non-transparent version of the fill geometry
						pFillAttr = pTransAttr->MakeSimilarNonTranspFillGeometry(1.0);
						
						// Convert a fill mapping
						TranspFillMappingAttribute *pTransMapAttr = (TranspFillMappingAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLMAPPING);
						if(pTransMapAttr != NULL)
							pMapAttr = pTransMapAttr->MakeSimilarNonTranspFillMapping();
					}

					// Setup region and draw path into it
					if (pFillAttr != NULL)
					{
						pMaskRegion->SetFillGeometry(pFillAttr, TRUE);

						if(pMapAttr != NULL)
							pMaskRegion->SetFillMapping(pMapAttr, TRUE);
					}
					else
						pMaskRegion->SetFillColour(DocColour(0, 0, 0));

					pMaskRegion->SetLineColour(DocColour(COLOUR_TRANS));
					pMaskRegion->DrawPath(pPath, NULL, ShapePath);

					pMaskRegion->RestoreContext();
				}
			}

			pMaskRegion->StopRender();
		}

		pMaskRegion->StopUsingGreyscaleContextDangerous();
	}

	// Extract the transparency mask bitmap from the render region
	OILBitmap *pOilBmp = pMaskRegion->ExtractBitmap();

	// We no longer need the RenderRegion, so scrap it.
	delete pMaskRegion;
	pMaskRegion = NULL;
	pPalette = NULL;

	// Now, render a rectangle to the output render region, using the transparency mask
	if (pOilBmp == NULL)
		return;

	KernelBitmap *pMask	= new KernelBitmap(pOilBmp, TRUE);

	if (pMask != NULL)
	{
		// Make sure the bitmap knows it's already a greyscale, else it will spend a lot of
		// time "converting" itself to a greyscale, and what's more, corrupting the grey levels
		// so that 255 (invisible) becomes 254 (slightly visible). Arrrrrgh!
		pMask->SetAsGreyscale();

		// Create a transparency attribute from our mask bitmap
		BitmapTranspFillAttribute Trans;

		// We don't call pTrans->AttachBitmap because it seems to be stupid, and causes ructions
		// when we try to attach a temporary bitmap. We thus do the same thing, but avoiding
		// its attempts to automatically screw us about.
		Trans.BitmapRef.Detach();
		Trans.BitmapRef.SetBitmap(pMask);

		Trans.SetStartPoint(&ClipRegion.lo);
		DocCoord EndPoint(ClipRegion.hi.x, ClipRegion.lo.y);
		Trans.SetEndPoint(&EndPoint);
		DocCoord EndPoint2(ClipRegion.lo.x, ClipRegion.hi.y);
		Trans.SetEndPoint2(&EndPoint2);

		UINT32 TValue = 0;
		Trans.SetStartTransp(&TValue);
		TValue = 255;
		Trans.SetEndTransp(&TValue);

		// Use the same transparency type as is set on the object being rendered (if any)
		{
			TranspFillAttribute *pTransAttr = (TranspFillAttribute *) pRender->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY);

			if (pTransAttr != NULL)
				Trans.SetTranspType(pTransAttr->GetTranspType());
			else
				Trans.SetTranspType(TT_Mix);		// By default, we'll use Mix transparency
			
		}

		// --- OK, we finally got here! Render the stroke, using the transparency mask we just made
		pRender->SaveContext();

			Trans.Render(pRender);

			// Render the path. If it is filled, then we render the entire thing (fill & stroke) using
			// the current fill geometry (to get a shadow/feather effect)
			if (PathIsFilled)
			{
				// Render the entire thing (fill & stroke) in one go. We render a rectangle over the cliprect
				// so that we do everything in one go (we can't render the fill &7 stroke separately, or
				// the transparency will overlap & it'll look wrong)
				pRender->SetLineColour(DocColour(COLOUR_TRANS));		// Don't render a line

				Path Rect;
				Rect.Initialise();
				Rect.AddMoveTo(ClipRegion.lo);
				Rect.AddLineTo(DocCoord(ClipRegion.hix, ClipRegion.loy));
				Rect.AddLineTo(ClipRegion.hi);
				Rect.AddLineTo(DocCoord(ClipRegion.lox, ClipRegion.hiy));
				Rect.AddLineTo(ClipRegion.lo);
				Rect.IsFilled  = TRUE;
				Rect.IsStroked = FALSE;
				pRender->DrawPath(&Rect, this, ShapePath);
			}
			else
			{
				// Otherwise, create a filled-outline path for the entire stroke, and render it
				// !!!!****ToDo - for now, strokes always render flat-filled with the stroke colour
				StrokeColourAttribute *pStrokeColour = (StrokeColourAttribute *) pRender->GetCurrentAttribute(ATTR_STROKECOLOUR);
				if (pStrokeColour != NULL)
					pRender->SetFillColour(pStrokeColour->Colour);

				// Fill the holes
				pRender->SetWindingRule(NonZeroWinding);

				Path *pOutput = CreateVarWidthStroke(pPath, pRender, LineWidth);
				if (pOutput != NULL)
				{
					pRender->DrawPath(pOutput, NULL, ShapePath);
					delete pOutput;
					pOutput = NULL;
				}
			}

		pRender->RestoreContext();

		// Delete the kernel bitmap. This auto-deletes the OIL bitmap for us
		delete pMask;
	}
#endif
}
Ejemplo n.º 5
0
void OpAlign::DoWithParam(OpDescriptor* pOp, OpParam* pAlignParam)
{
	// DMc alterations so that this works with compound nodes	
	SelRange   Selection(*(GetApplication()->FindSelection()));

	RangeControl rg = Selection.GetRangeControlFlags();
	rg.PromoteToParent = TRUE;
	Selection.Range::SetRangeControl(rg);

	DocRect		SelRect   = Selection.GetBoundingRect();
	DocRect		TargetRect;
	TargetRect.MakeEmpty();
	INT32        NumObjs   = Selection.Count();
	AlignParam* pAlign    =(AlignParam*)pAlignParam;

	BOOL moved=FALSE;					// set to TRUE if any object is moved
	BeginSlowJob(-1,FALSE);
	BOOL OK=DoStartTransOp(FALSE);

	// find parent spread of first object in selection
	Node*   pFirstNode=NULL;
	Spread* pSpread   =NULL;
	if (OK)
	{
		pFirstNode=Selection.FindFirst();
		if (pFirstNode!=NULL)
			pSpread=pFirstNode->FindParentSpread();
		OK=(pSpread!=NULL);
		if (!OK)
			ERROR2RAW("OpAlign::DoWithParam() - could not find parent spread");
	}

	// Find the size of the target rectangle
	if (pAlign->target==ToSelection)
		TargetRect=SelRect;
	else
	{
		Page* pPage=pSpread->FindFirstPageInSpread();
		while (pPage)
		{
			DocRect PageRect=pPage->GetPageRect();
			if (pAlign->target==ToSpread || SelRect.IsIntersectedWith(PageRect))
				TargetRect=TargetRect.Union(PageRect);
			pPage=pPage->FindNextPage();
		}
	}

	// allocate all dynamic memory required
	Node**	 pObj=NULL;
	ObjInfo* x   =NULL;
	ObjInfo* y   =NULL;
	INT32*    dx  =NULL;
	INT32*    dy  =NULL;
	if (OK)			ALLOC_WITH_FAIL(pObj,(Node**)  CCMalloc(NumObjs*sizeof(Node*)),  this);
	if (pObj!=NULL)	ALLOC_WITH_FAIL(x,   (ObjInfo*)CCMalloc(NumObjs*sizeof(ObjInfo)),this);
	if (   x!=NULL) ALLOC_WITH_FAIL(y,   (ObjInfo*)CCMalloc(NumObjs*sizeof(ObjInfo)),this);
	if (   y!=NULL) ALLOC_WITH_FAIL(dx,  (INT32*)   CCMalloc(NumObjs*sizeof(INT32)),   this);
	if (  dx!=NULL) ALLOC_WITH_FAIL(dy,  (INT32*)   CCMalloc(NumObjs*sizeof(INT32)),   this);
	OK=(dy!=NULL);

	// if memory claimed OK and target rect not empty proceed with op
	// (ie. do nothing if 'within page(s)' when no object on a page)
	DocRect EmptyRect;
	if (OK && TargetRect!=EmptyRect)
	{
		// create an array of pointers to objects (nodes) to be affected
		Node* pNode=Selection.FindFirst();
		INT32  i=0;
		while (pNode!=NULL)
		{
			if (pNode->IsBounded() && !((NodeRenderableBounded*)pNode)->GetBoundingRect(TRUE).IsEmpty())
				pObj[i++]=pNode;
			pNode=Selection.FindNext(pNode);
		}
		NumObjs=i;

		// cache x & y info in separate arrays so they can be sorted separately
		XLONG SumObjWidths =0;
		XLONG SumObjHeights=0;
		for (i=0; i<NumObjs; i++)
		{
			DocRect ObjRect=((NodeRenderableBounded*)pObj[i])->GetBoundingRect();
			x[i].i=i;
			x[i].lo=ObjRect.lo.x;
			x[i].hi=ObjRect.hi.x;
			SumObjWidths+=ObjRect.hi.x-ObjRect.lo.x;
			y[i].i=i;
			y[i].lo=ObjRect.lo.y;
			y[i].hi=ObjRect.hi.y;
			SumObjHeights+=ObjRect.hi.y-ObjRect.lo.y;
		}

		// for each object, calculate the x and y displacements independently
		AlignOneAxis(pAlign->h,NumObjs,SumObjWidths, TargetRect.lo.x,TargetRect.hi.x,x,dx);
		AlignOneAxis(pAlign->v,NumObjs,SumObjHeights,TargetRect.lo.y,TargetRect.hi.y,y,dy);

		// apply the x and y displacements simultaneously to each object
		for (i=0; i<NumObjs; i++)
			if (dx[i]!=0 || dy[i]!=0)
			{
				moved=TRUE;
				Trans2DMatrix* pMatrix=new Trans2DMatrix(dx[i],dy[i]);
				DoTransformNode((NodeRenderableInk*)pObj[i],pMatrix);
			}
	}

	// free up any memory which was allocated
	CCFree(dx);
	CCFree(dy);
	CCFree(x);
	CCFree(y);
	CCFree(pObj);

	if (moved)
	{
		Document::GetSelected()->ForceRedraw(pSpread, TargetRect);
		GetApplication()->UpdateSelection();
	}
	else
		FailAndExecute();
	End();
	EndSlowJob();
}