Ejemplo n.º 1
0
Chapter* DocCoord::FindEnclosingChapter(Document *pDocument, 
										DocCoord* ChapterPos, 
										XLONG* ChapterDepth,
										View *pView)
{
	Chapter* CurrentChapter = Node::FindFirstChapter(pDocument);
	// Search all chapters
	*ChapterDepth = 0;
	DocRect CurrentChaptersPasteboardRect;

	while (CurrentChapter != NULL)
	{
		CurrentChaptersPasteboardRect = CurrentChapter->GetPasteboardRect(TRUE, pView);

		if (CurrentChaptersPasteboardRect.ContainsRectCoord(*this))
		{
			// Chapter position is the top left hand corner of the chapters pasteboard
			ChapterPos->x = CurrentChaptersPasteboardRect.LowCorner().x;
			ChapterPos->y = CurrentChaptersPasteboardRect.HighCorner().y;
			return (CurrentChapter);
		}

        (*ChapterDepth) += CurrentChaptersPasteboardRect.Height();
		CurrentChapter = CurrentChapter->FindNextChapter();
    }

	// The DocCoord was not found in any chapter
	ERROR3("DocCoord::FindEnclosingChapter: Coord wasn't in any chapter. See the function help for debugging tips");
	return(NULL);
}
Ejemplo n.º 2
0
void OpDragBox::DragPointerMove(DocCoord dcMousePos, ClickModifiers cmods, Spread* pSpread, BOOL bSolidDrag)
{
	// If the mouse has moved to another spread than translate its position into the
	// new spread's coordinate system.
	if (pSpread != m_pStartSpread && pSpread != NULL)
	{
		dcMousePos = MakeRelativeToSpread(m_pStartSpread, pSpread, dcMousePos);
	}

	// Calculate the new drag rectangle.
	DocRect drNewDragBox = CalcDragBox(m_dcStartPos, dcMousePos);
	ERROR3IF(!drNewDragBox.IsValid(), "Invalid drag box in OpDragBox::DragPointerMove");

	// Call the appropriate update function, according to whether we are drawing solid
	// drag boxes or unfilled drag boxes.
	if (m_fDoSolidDragBoxes)
	{
		UpdateSolidDragBox(drNewDragBox);
	}
	else
	{
		UpdateUnfilledDragBox(drNewDragBox);
	}
	
	// Update our record of the last drag box and call the derived class.
	if (!OnPointerMoved(m_pStartSpread, m_drLastDragBox = drNewDragBox, cmods))
	{
		// Cancel the drag and operation.
		EndDrag();
		End();
	}
}
Ejemplo n.º 3
0
void NodeBrush::RenderObjectBlobs(RenderRegion* pRegion)
{
#if !defined(EXCLUDE_FROM_RALPH)
    // Find out about the groups bounding rect
    DocRect BoundingRect = GetBoundingRect();

    // Inflate the bounds by the width of a blob
    DocRect TempRect;
    GetApplication()->GetBlobManager()->GetBlobRect(BoundingRect.lo,&TempRect);
    INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*3)/4;
    BoundingRect.Inflate(Delta);

    // Find out where to draw the blobs
    DocCoord Low  = BoundingRect.LowCorner();
    DocCoord High = BoundingRect.HighCorner();

    // Set the colours of the blobs
    pRegion->SetFillColour(COLOUR_UNSELECTEDBLOB);
    pRegion->SetLineColour(COLOUR_NONE);

    // Draw all the blobs
    pRegion->DrawBlob(Low, BT_UNSELECTED);
    pRegion->DrawBlob(High, BT_UNSELECTED);
    pRegion->DrawBlob(DocCoord(Low.x, High.y), BT_UNSELECTED);
    pRegion->DrawBlob(DocCoord(High.x, Low.y), BT_UNSELECTED);

    // for some reason the NBP is never called, there is probably a
    // proper fix for this but I don't have time right now, so render
    // the nodeblend path here
    m_pNodeBrushPath->RenderObjectBlobs(pRegion);


#endif
}
Ejemplo n.º 4
0
XLONG Chapter::GetChapterDepth()
{
	XLONG Depth	= 0;

	// Loop through document tree calculating the logical coordinate offset for the
	// current chapter 	

//	Chapter *pChapter = Node::FindFirstChapter(FindOwnerDoc());
	Node* pNode = FindParent();
	ERROR2IF(!(pNode->IsNodeDocument()), 0, "Parent of Chapter is not NodeDocument");
	Chapter *pChapter = (Chapter*)pNode->FindFirstChild(CC_RUNTIME_CLASS(Chapter));

	ENSURE(pChapter != NULL, "Couldn't find first chapter in Chapter::GetChapterDepth");
	
	while ((pChapter != NULL) && (pChapter != this))
	{		
                                         				
		ENSURE(pChapter->IsKindOf(CC_RUNTIME_CLASS(Chapter)), 
				"Chapter's sibling is not a Chapter");

		const DocRect ChapRect = pChapter->GetPasteboardRect();
            
        // Accumulate logical offset
		Depth += ChapRect.Height();						
			
		pChapter = (Chapter *) pChapter->FindNext();
	}

	return Depth;
}
Ejemplo n.º 5
0
BOOL NodeSimpleShape::IsNearControlHandle(DocCoord Coord, INT32* CoordNum)
{
#if !defined(EXCLUDE_FROM_RALPH)
	// Find the blob manager
	BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
	if (pBlobMgr==NULL)
		return FALSE;

	// Find out about the size of a blob
	DocRect BlobRect;
	pBlobMgr->GetBlobRect(Coord, &BlobRect);

	// Check to see if it is near any of the blobs
	for (INT32 i=0; i<4; i++)
	{
		// Check for collision with the control points
		if (BlobRect.ContainsCoord(Parallel[i]))
		{
			// Tell them which control point it waas over
			*CoordNum = i;

			// we have used that click up, so tell the world
			return TRUE;
		}
	}
#endif	
	// was not over any of the control points
	return FALSE;
}
Ejemplo n.º 6
0
void LibraryFile::DoScrollRedraw(void)
{
	// Scroll / redraw the newly added groups...
	if(FirstLibraryAdded != NULL && LastLibraryAdded != NULL)
	{
		SGLibGroup *FirstGroup = FirstLibraryAdded->ParentGroup;
		SGLibGroup *SecondGroup = LastLibraryAdded->ParentGroup;
	
		if(FirstGroup != NULL && SecondGroup != NULL)
		{
			// Redraw whatever we need to and reformat the gallery ready for poking...
			ParentGallery->ReformatAndRedrawIfNecessary();

			// Calculate where the new folders are...
			DocRect ScrollToRect;
			FirstGroup->GetFormatRect(&ScrollToRect);
			if(SecondGroup != FirstGroup)
			{
				DocRect TempRect;
				FirstGroup->GetFormatRect(&TempRect);				
				ScrollToRect = ScrollToRect.Union(TempRect);
			}

			// Actually do the scroll...
			ParentGallery->ScrollToShow(&ScrollToRect, TRUE);
		}
	}
}
Ejemplo n.º 7
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.º 8
0
BOOL NativePrefsDlg::InitDialog ()
{
	ERROR2IF ( mpParams == NULL, FALSE,
			   "NativePrefsDlg::InitDialog called after duff initialisation?!" );

	//First, do we have a selection?
	Application *pApp = GetApplication();

	ERROR2IF(pApp == NULL, FALSE,"NativePrefsDlg::InitDialog -  no application!");
	
	SelRange *pRange = pApp->FindSelection();
	
	ERROR2IF(pRange == NULL, FALSE,"NativePrefsDlg::InitDialog - no selection range!");
	DocRect ClipRect = pRange->GetBoundingRect();

	BOOL fThereIsASelection=!ClipRect.IsEmpty();

	//Now, is there a selection?
	if (fThereIsASelection)
	{
		// Yes. So ungrey both the buttons for selecting the nodes to export.
		EnableGadget(_R(IDC_NATIVEOPTS_SELECT), TRUE);
		EnableGadget(_R(IDC_NATIVEOPTS_DRAWING), TRUE);

		//Now, which of those buttons should be selected?
		switch ( mpParams->GetExportSel () )
		{
		case SELECTION:
			// Choose the export pair of buttons.
			SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), FALSE);
			SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), TRUE);
			break;

		default:
		case DRAWING:
			// Choose the export pair of buttons.
			SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), TRUE);
			SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), FALSE);
			break;
		}
	}
	else
	{
		//No. So grey the SELECTION button and ungrey
		//the DRAWING button
		EnableGadget(_R(IDC_NATIVEOPTS_SELECT), FALSE);
		EnableGadget(_R(IDC_NATIVEOPTS_DRAWING), TRUE);

		// And we must select the DRAWING button for the export area controls.
		SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), TRUE);
		SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), FALSE);
	}

	return TRUE;
}
Ejemplo n.º 9
0
Trans2DMatrix* BlendHelpers::GetRotateMatrix(NodeRenderableBounded* pNode,double Angle)
{
	Trans2DMatrix* pMatrix = NULL;

	if (pNode != NULL && fmod(Angle,360.0) != 0.0)
	{
		DocRect BoundsStart = pNode->GetBoundingRect();
		DocCoord Centre = BoundsStart.Centre();
		pMatrix = new Trans2DMatrix(Centre,Angle);
	}

	return pMatrix;
}
Ejemplo n.º 10
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.º 11
0
void OpDragBox::UpdateSolidDragBox(const DocRect& drNewDragBox)
{
	// Set up four update rectangles.  We will xor none, some, or all of these rectangles to
	// produce the new drag box.
	DocRect drUpdate[4];
	INT32 nHowMany;

	// Find the intersection of the last and new rectangles.  We will exclude this from
	// any xoring as it is already xored.
	DocRect drCommonDragBox = drNewDragBox.Intersection(m_drLastDragBox);

	// Calculate the rectangles that need to be xored to change the last into the new
	// drag box.  This depends on how they overlap.
	if (drCommonDragBox.IsEmpty())
	{
		// There's no intersection between the last drag box and the new drag box, even
		// though they share a common corner.  So xor the full extent of both drag rects.
		drUpdate[0] = m_drLastDragBox;
		drUpdate[1] = drNewDragBox;
		nHowMany = 2;
	}
	else if (drNewDragBox.ContainsRect(m_drLastDragBox))
	{
		// The new drag rect completely contains the last one, so clip out the last.
		nHowMany = ((DocRect&) drNewDragBox).SplitRect(m_drLastDragBox, drUpdate);
	}
	else if (m_drLastDragBox.ContainsRect(drNewDragBox))
	{
		// The last drag rect completely contains the new one, so clip out the new.
		nHowMany = m_drLastDragBox.SplitRect(drNewDragBox, drUpdate);
	}
	else
	{
		// The drag rectangles overlap but neither completely contains the other, so set
		// the xor rectangles to be each drag rectangle less the common drag rectangle.
		nHowMany = m_drLastDragBox.SplitRect(drCommonDragBox, &drUpdate[0]);
		nHowMany += ((DocRect&) drNewDragBox).SplitRect(drCommonDragBox, &drUpdate[nHowMany]);
	}

	// Sanity check.
	ERROR3IF(nHowMany < 0 || nHowMany > 4,
				"Wrong number of split rects in OpDragBox::UpdateSolidDragBox\n");

	// Draw the xor rects.
	for (INT32 i = 0; i < nHowMany; i++)
	{
		DrawXorRect(drUpdate[i], m_pStartSpread, drUpdate[i]);
	}
}
Ejemplo n.º 12
0
BOOL PrintPSRenderRegion::WriteClipRegion(KernelDC *pDC, const DocRect& Rect)
{
	if (!Rect.IsValid() || Rect.IsEmpty())
		return TRUE;

	DocCoord c0,c1;
	c0=Rect.lo;
	c1=Rect.hi;
	BOOL ok = pDC->OutputCoord(c0);
	ok = ok && pDC->OutputCoord(c1);
	ok = ok && pDC->OutputToken(TEXT("Cp"));
	ok = ok && pDC->OutputNewLine();

	return ok;
}
Ejemplo n.º 13
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.º 14
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.º 15
0
DocRect NodeBrush::GetBlobBoundingRect()
{

#if !defined(EXCLUDE_FROM_RALPH)
    // Find the base class blob bounding rectangle
    DocRect Rect = NodeGroup::GetBlobBoundingRect();

    // inflate it by the width of a blob (plus a bit)
    DocRect TempRect;
    GetApplication()->GetBlobManager()->GetBlobRect(Rect.lo,&TempRect);
    INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*1)/1;
    Rect.Inflate(Delta);

    return Rect;
#else
    return DocRect(0,0,0,0);
#endif

}
Ejemplo n.º 16
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.º 17
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.º 18
0
DocRect NodeSimpleShape::GetBlobBoundingRect()
{
#if !defined(EXCLUDE_FROM_RALPH)
	// Find the Shapes bounding rectangle
	DocRect Rect = GetBoundingRect();

	// Find the blob manager
	BlobManager* pBlobMgr = GetApplication()->GetBlobManager();

	// And if we can find the current view, add on the size of a selection blob
	if (pBlobMgr!= NULL)
	{
		// Wee need to add in each of the blobs. there is a blob on each corner
		// of the parallelogram
		DocRect BlobSize;
		pBlobMgr->GetBlobRect(Parallel[0], &BlobSize);
		Rect = Rect.Union(BlobSize);
		
		// Next corner of the parallelogram
		pBlobMgr->GetBlobRect(Parallel[1], &BlobSize);
		Rect = Rect.Union(BlobSize);

		// and the next
		pBlobMgr->GetBlobRect(Parallel[2], &BlobSize);
		Rect = Rect.Union(BlobSize);

		// and the last one
		pBlobMgr->GetBlobRect(Parallel[3], &BlobSize);
		Rect = Rect.Union(BlobSize);
	}

	// Make sure we include the Bounds of our children
	IncludeChildrensBoundingRects(&Rect);

	// return the rectangle with the blobs included
	return Rect;
#else
	return DocRect(0,0,0,0);
#endif
}
Ejemplo n.º 19
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.º 20
0
void OpDragBox::DrawXorRect(const DocRect& drClip, Spread* pspdXor, const DocRect& drXor) const
{
	// Check if we have nothing to do.
	if (drXor.IsEmpty()) return;

	// Ask the derived class what colour its drag box is.  If we are doing solid drags we
	// want to use the same colour to fill the box as well, otherwise we fill with no colour.
	StockColour scLineColour = GetBoxColour();
	StockColour scFillColour = (m_fDoSolidDragBoxes) ? scLineColour : COLOUR_NONE;
	
	// Xor the rect on all supplied render-regions.
	RenderRegion* pRegion = DocView::RenderOnTop(&((DocRect&) drClip), pspdXor, ClippedEOR);
	while (pRegion != NULL)
	{
		// Set the line and fill colours.
		pRegion->SetLineColour(scLineColour);
		pRegion->SetFillColour(scFillColour);

		// Draw the xored drag box and go on to the next render-region.
		pRegion->DrawDragRect(&((DocRect&) drXor));
		pRegion = DocView::GetNextOnTop(&((DocRect&) drClip));
	}
}
Ejemplo n.º 21
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.º 22
0
AttrFillGeometry* FillGeometryNudger::MutateFill(AttrFillGeometry* FillToMutate)
{
	if (!FillToMutate->IsVisible() ||
		FillToMutate->GetSelectionCount() == 0)
		return NULL;

	// Make a copy of this Fill to change
	AttrFillGeometry* NewFill = (AttrFillGeometry*)FillToMutate->SimpleCopy();
	if (NewFill == NULL)
		return NULL;

	// Construct the translation matrix
	Trans2DMatrix TransMat(X_NudgeDistance, Y_NudgeDistance);
	
	BOOL isARampBlob = FALSE;

	// And apply it to the fill
	
	NewFill->TransformSelectedControlPoints(TransMat, &isARampBlob);

	if (LastNudgeType == FillToMutate->GetRuntimeClass())
	{
		BOOL IsSame = TRUE;

		if (FillToMutate->GetStartPoint() && 
			*FillToMutate->GetStartPoint() != LastNudgeStart)
			IsSame = FALSE;	

		if (FillToMutate->GetEndPoint() && 
			*FillToMutate->GetEndPoint() != LastNudgeEnd)
			IsSame = FALSE;	

		if (FillToMutate->GetEndPoint2() && 
			*FillToMutate->GetEndPoint2() != LastNudgeEnd2)
			IsSame = FALSE;	

		if (IsSame)
			return NewFill;
	}

	Node *pNode = FillToMutate;
	while ((pNode != NULL) && !pNode->IsSpread())
		pNode = pNode->FindParent();

	if (pNode == NULL)
		return NewFill;			// We're not really in the tree

	Spread* pSpread = (Spread*)pNode;

	DocRect OldBounds = FillToMutate->GetBlobBoundingRect();
	DocRect NewBounds = NewFill->GetBlobBoundingRect();

	DocRect Bounds = OldBounds.Union(NewBounds);

	RenderRegion* pRegion = DocView::RenderOnTop(&Bounds, pSpread, UnclippedEOR);
	while (pRegion)
	{
		if (!isARampBlob)
		{
			// MUST do a full redraw of the fill blobs
			FillToMutate->RenderFillBlobs(pRegion);
			NewFill->RenderFillBlobs(pRegion);
		}
		else
		{
			FillToMutate->DisableRampRedraw ();
			FillToMutate->RenderFillBlobs(pRegion);
			FillToMutate->EnableRampRedraw ();
			NewFill->DisableRampRedraw ();
			NewFill->RenderFillBlobs(pRegion);
			NewFill->EnableRampRedraw ();
		}

		// Get the Next render region
		pRegion = DocView::GetNextOnTop(&Bounds);
	}

	AttrFillGeometry::LastRenderedMesh = NULL;

	LastNudgeType 	= FillToMutate->GetRuntimeClass();

	if (FillToMutate->GetStartPoint())
		LastNudgeStart 	= *FillToMutate->GetStartPoint();

	if (FillToMutate->GetEndPoint())
		LastNudgeEnd 	= *FillToMutate->GetEndPoint();

	if (FillToMutate->GetEndPoint2())
		LastNudgeEnd2 	= *FillToMutate->GetEndPoint2();

	return NewFill; 
}
Ejemplo n.º 23
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.º 24
0
/********************************************************************************************
>	void BitmapExportPaletteControl::DrawCell(DocRect *pCellRect, DocColour colour, INT32 flags,
					RenderRegion *pRender, bool webSafe, bool selected, bool highlight)
	Author:		Jonathan_Payne (Xara Group Ltd) <*****@*****.**>
	Created:	12/12/2000
	Purpose:	Draw a palette cell with the given options
	Inputs:		pCellRect	- The rect to draw the palette cell in
				colour		- The colour of the palette entry to draw
				flags		- The flags of that palette entry (locked, transparency, etc)
				pRender		- The render region to render with (tested with an OS rr)
				webSafe		- Is the colour web safe (ie do we draw the web safe mark)
				selected	- Do we draw the cell as the selected cell?
********************************************************************************************/
void BitmapExportPaletteControl::DrawCell(DocRect *pCellRect, DocColour colour, INT32 flags, RenderRegion *pRender,
												bool webSafe, bool selected)
{
	pRender->SetLineColour(COLOUR_BLACK);
	pRender->SetFillColour(colour);
	pRender->DrawRect(pCellRect);

	if (selected)
	{
		pRender->SetFillColour(COLOUR_TRANS);

		DocRect cell = *pCellRect; // make temp copy

		// Draw the outer line in white
		pRender->SetLineColour(COLOUR_WHITE);
		cell.Inflate(-1 * m_nPixelSize);
		pRender->DrawRect(&cell);

		// Draw the inner line in black
		pRender->SetLineColour(COLOUR_BLACK);
		cell.Inflate(-1 * m_nPixelSize);
		pRender->DrawRect(&cell);
	}

	if (flags & DELETED_COLOUR)
	{
		//  Draw a mark to show that this palette entry has been deleted

		// Draw a black line from top left to bottom right
		pRender->SetLineColour(COLOUR_BLACK);
		pRender->DrawLine(	DocCoord(pCellRect->lo.x, pCellRect->hi.y + m_nPixelSize),
							DocCoord(pCellRect->hi.x + m_nPixelSize, pCellRect->lo.y));

		// Draw a white line from top right to bottom left
		pRender->SetLineColour(COLOUR_WHITE);
		pRender->DrawLine(	DocCoord(pCellRect->hi.x + m_nPixelSize, pCellRect->hi.y + m_nPixelSize),
							DocCoord(pCellRect->lo.x + m_nPixelSize, pCellRect->lo.y + m_nPixelSize));

		return; // Stop before rending any other marks
	}

	if (flags & LOCKED_COLOUR)
	{
		//  Draw a mark to show that this palette entry has been
		//  edited by the user.

		pRender->SetLineColour(COLOUR_BLACK);
		pRender->SetFillColour(COLOUR_WHITE);
		
		// Draw a rectangle in the bottom left corner of the cell
		DocRect markRect;
		markRect.hi.x	= pCellRect->lo.x + m_nPixelSize * 2;
		markRect.lo.x	= pCellRect->lo.x;
		markRect.hi.y	= pCellRect->lo.y + m_nPixelSize * 2;
		markRect.lo.y	= pCellRect->lo.y;
		pRender->DrawRect(&markRect);
	}

	if (flags & TRANSPARENT_COLOUR)
	{
		//  Draw a mark to show that this palette entry is transparent

		pRender->SetLineColour(COLOUR_BLACK);
		pRender->SetFillColour(COLOUR_WHITE);
		
		// Draw a rectangle in the top left corner of the cell
		DocRect markRect;
		markRect.hi.x	= pCellRect->lo.x + m_nPixelSize * 2;
		markRect.lo.x	= pCellRect->lo.x;
		markRect.hi.y	= pCellRect->hi.y;
		markRect.lo.y	= pCellRect->hi.y - m_nPixelSize * 2;
		pRender->DrawRect(&markRect);
	}
	
	if (webSafe)
	{
		//  Draw a mark to show that this palette entry is web-safe

		pRender->SetLineColour(COLOUR_BLACK);
		pRender->SetFillColour(COLOUR_WHITE);

		DocRect markRect = *pCellRect;
		markRect.Inflate(-4 * m_nPixelSize);
		pRender->DrawRect(&markRect);
	}
}
Ejemplo n.º 25
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.º 26
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.º 27
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.º 28
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.º 29
0
BOOL ColourDragInformation::OnPageDrop(ViewDragTarget* pDragTarget)
{
	PageDropInfo ThePageDropInfo;
	((ViewDragTarget*)pDragTarget)->GetDropInfo(&ThePageDropInfo);

	DocCoord DragPos 			= ThePageDropInfo.DropPos;
	ObjectDragTarget TargetType = ThePageDropInfo.TargetHit;
	NodeRenderableInk* ThisNode = ThePageDropInfo.pObjectHit;

	// DMc 4/10/99
	// test for dragging & dropping onto a bevel/shadow/other compound node which
	// is grouped
	if (ThisNode)
	{
		if (ThisNode->FindParent())
		{
			if (!ThisNode->FindParent()->PromoteHitTestOnChildrenToMe())
			{
				// any compounds with their 'promotehittest' stuff set above me ?
				Node * pNode = ThisNode->FindParent();
				
				while (pNode)
				{
					if (pNode->IsAnObject())
					{
						if (pNode->PromoteHitTestOnChildrenToMe())
						{
							ThisNode = (NodeRenderableInk *)pNode;
						}
					}
					
					pNode = pNode->FindParent();
				}
			}
		}
	}

	NodeAttribute *Attrib = NULL;
	
	// Get a colour to apply to the Selected doc
	IndexedColour *IxColToApply = GetColourForDocument(NULL);

	// And make a DocColour to apply
	DocColour ColourToApply(COLOUR_TRANS);
	if (IxColToApply != NULL)
		ColourToApply.MakeRefToIndexedColour(IxColToApply);


 	if (TargetType == LINE_TARGET) // apply a stroke colour
	{
		// Apply a stroke colour to the object(s) we have been dropped onto
		Attrib = new AttrStrokeColourChange;
		if (Attrib == NULL)
			return FALSE;

		((AttrStrokeColourChange *)Attrib)->SetStartColour(&ColourToApply);
		AttributeManager::ApplyAttribToNode(ThisNode, Attrib);
	}
	else		  
	{
		// Apply a fill colour to the object(s) we have been dropped onto
		// This always used to be the case. If there were no objects then we
		// just set the current fill colour to be the new one.
		// Now, if no objects are the target then apply a page background colour
		// otherwise if control is held down set the current fill colour.
		
		BOOL Constrain = FALSE;

		// get object bounds
		DocRect pSimpleBounds;
		if (ThisNode)
			pSimpleBounds = ThisNode->GetBoundingRect();
		else
		{
			pSimpleBounds.MakeEmpty();
			// See if the control key is pressed
			Constrain = KeyPress::IsConstrainPressed();
		}

		// No node(s) are targetted so see if the constrain key is pressed or not
		if (ThisNode == NULL && Constrain)
		{
			// Use the colour to set the background
			// We should use the document given to us by the page info class
			OpBackgroundParam Param;
			Param.pDocColour = &ColourToApply;
			Param.pDoc = ThePageDropInfo.pDoc;			
			Param.pSpread = ThePageDropInfo.pSpread;
			
			// Obtain a pointer to the op descriptor for the create operation 
			OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_BACKGROUND);

			// Invoke the operation, passing in our parameters
			pOpDesc->Invoke(&Param);
		}
		else
		{
			// Apply the colour either to the targetted node(s) or as the current
			// fill colour, if no nodes are targetted.
			Attrib = new AttrColourDrop(DragPos, pSimpleBounds, ColourToApply);
			if (Attrib == NULL)
				return FALSE;

			if (ThisNode)
				((AttrColourDrop*)Attrib)->SetObjectDroppedOn(ThisNode);

			AttributeManager::ApplyAttribToNode(ThisNode, Attrib);
		}
	}

	return TRUE;
}
Ejemplo n.º 30
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;
}