Example #1
0
void XARGenerator::DetermineLinearGradientPoints(const Gradient* pGradient, const Transformation& trans,
												 const RectD& boundings, DocCoord& p1, DocCoord& p2)
{
	if (pGradient->units == Gradient::ObjectBoundingBox) {
		PointD pLower = boundings.LowerCoord();
		PointD pHigher = boundings.HigherCoord();
		p1 = DocCoord((INT32)pLower.x, m_docSize.y - (INT32)pLower.y);
		p2 = DocCoord((INT32)pHigher.x, m_docSize.y - (INT32)pHigher.y);
#ifdef SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "using ObjectBoundingBox %d,%d %d,%d\n", p1.x, p1.y, p2.x, p2.y);
#endif
	} else { // Gradient->units == Gradient::UserSpaceOnUse
		double fX1 = pGradient->x1;
		double fY1 = pGradient->y1;
		double fX2 = pGradient->x2;
		double fY2 = pGradient->y2;
		trans.ApplyToCoordinate(fX1, fY1, &fX1, &fY1);
		trans.ApplyToCoordinate(fX2, fY2, &fX2, &fY2);
		p1 = DocCoord((INT32)fX1, m_docSize.y - (INT32)fY1);
		p2 = DocCoord((INT32)fX2, m_docSize.y - (INT32)fY2);
#if SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "using UserSpaceOnUse %d,%d %d,%d\n", p1.x, p1.y, p2.x, p2.y);
#endif
	}
}
Example #2
0
void NodeEllipse::CreateShape(DocRect NewRect)
{
	// Copy the rectangle into the parallelogram
	Parallel[0] = DocCoord(NewRect.lo.x, NewRect.hi.y);
	Parallel[1] = DocCoord(NewRect.hi.x, NewRect.hi.y);
	Parallel[2] = DocCoord(NewRect.hi.x, NewRect.lo.y);
	Parallel[3] = DocCoord(NewRect.lo.x, NewRect.lo.y);

	// Get an array to put the 12 different coords needed to specify an ellipse
	DocCoord NewCoords[12];

	// Calculate the 3 coordinates along each side of the parallelogram
	CalcEllipseEdge(Parallel[0], Parallel[1], &NewCoords[11], &NewCoords[0], &NewCoords[1]);
	CalcEllipseEdge(Parallel[1], Parallel[2], &NewCoords[2], &NewCoords[3], &NewCoords[4]);
	CalcEllipseEdge(Parallel[2], Parallel[3], &NewCoords[5], &NewCoords[6], &NewCoords[7]);
	CalcEllipseEdge(Parallel[3], Parallel[0], &NewCoords[8], &NewCoords[9], &NewCoords[10]);

	// build a path
	InkPath.ClearPath();
	InkPath.FindStartOfPath();

	// Start at bottom left corner
	PathFlags NewFlags;
	NewFlags.IsRotate = TRUE;
	InkPath.InsertMoveTo(NewCoords[0], &NewFlags);
	InkPath.InsertCurveTo(NewCoords[1], NewCoords[2], NewCoords[3], &NewFlags);
	InkPath.InsertCurveTo(NewCoords[4], NewCoords[5], NewCoords[6], &NewFlags);
	InkPath.InsertCurveTo(NewCoords[7], NewCoords[8], NewCoords[9], &NewFlags);
	InkPath.InsertCurveTo(NewCoords[10], NewCoords[11], NewCoords[0], &NewFlags);

	// Close the path properly
	InkPath.CloseSubPath();
}
Example #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
}
Example #4
0
// sets the height and width of the shape. if this function gets called, we assume that the shape has
// no rotation or skew, so the MajorAxis = (0, Height), MinorAxis = (Width, 0)
BOOL RegularShapeRecordHandler::SetHeightAndWidth(NodeRegularShape *pShape, const INT32 & Height, const INT32 & Width)
{
	ERROR2IF(pShape==NULL, FALSE, "parameter pShape == NULL");

	SetMajorAxis(pShape, DocCoord(0, Height/2));
	SetMinorAxis(pShape, DocCoord(Width/2, 0));
	return TRUE;
}
Example #5
0
bool XARGenerator::OutputHeader()
{
	bool ok = true;

	// Create a CXaraFileRecord object for the document header record
	CXaraFileRecord Rec(TAG_FILEHEADER);
	ok = Rec.Init();
	if (ok) ok = Rec.WriteBuffer((BYTE*)"CXN", 3);
	if (ok) ok = Rec.WriteUINT32(123);				// File size
	if (ok) ok = Rec.WriteUINT32(0);				// Native/Web link ID
	if (ok) ok = Rec.WriteUINT32(0);				// Precompression flags
	if (ok) ok = Rec.WriteASCII(_T("SVGFilter"));	// Producer
	if (ok) ok = Rec.WriteASCII(VERSION_TSTRING);	// Producer version
	if (ok) ok = Rec.WriteASCII(_T(""));			// Producer build
	if (ok) ok = m_pExporter->WriteRecord(&Rec);

	// If any part of the header writing fails then return our own specific error
	if (!ok)
	{
		// XXX Set an appropriate error here
		return false;
	}

	// XXX From this point on the error handling becomes a bit thin

	ok = m_pExporter->WriteZeroSizedRecord(TAG_SPREAD);
	/***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_DOWN);

	if (m_docSize != DocCoord(0, 0)) {
		ok = Rec.Reinit(TAG_SPREADINFORMATION, TAG_SPREADINFORMATION_SIZE);
		ok = Rec.WriteUINT32(m_docSize.x);		// width
		ok = Rec.WriteUINT32(m_docSize.y);		// height
		ok = Rec.WriteUINT32(10000);			// margin
		ok = Rec.WriteUINT32(0);				// bleed
		ok = Rec.WriteBYTE(2);					// flags (1:shadow)
		ok = m_pExporter->WriteRecord(&Rec);
	}

	ok = Rec.Reinit(TAG_VIEWPORT, TAG_VIEWPORT_SIZE);
	ok = Rec.WriteCoord(DocCoord(0, 0));		// bottom-left
	ok = Rec.WriteCoord(DocCoord(m_docSize.x, m_docSize.y));// top-right
	ok = m_pExporter->WriteRecord(&Rec);

	// Write a layer
	ok = m_pExporter->WriteZeroSizedRecord(TAG_LAYER);
	/***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_DOWN);

	ok = Rec.Reinit(TAG_LAYERDETAILS, TAG_LAYERDETAILS_SIZE);
	ok = Rec.WriteBYTE(1|4|8);					// flags (0:visible, 2:printable, 3:active)
	ok = Rec.WriteUnicode(_T("Layer 1"));
	ok = m_pExporter->WriteRecord(&Rec);

	return ok;
}
Example #6
0
bool XARGenerator::OutputPathEntity(const Style& style, const Transformation& trans, PathDataVector& pathVector)
{
	bool ok = true;
	CXaraFileRecord Rec(0);

	if (style.IsFillColourDefined() || style.IsFillGradientDefined()) {
		if (style.IsStrokeColourDefined())
			Rec.Reinit(TAG_PATH_FILLED_STROKED, TAG_PATH_SIZE);
		else
			Rec.Reinit(TAG_PATH_FILLED, TAG_PATH_SIZE);
	} else // if (style.IsStrokeColourDefined())
		Rec.Reinit(TAG_PATH_STROKED, TAG_PATH_SIZE);

	Rec.WriteUINT32(pathVector.GetCount());
	for (unsigned int i = 0; i < pathVector.GetCount(); ++i)
		Rec.WriteBYTE(pathVector[i].m_verb);
	for (unsigned int i = 0; i < pathVector.GetCount(); ++i) {
		PointD p = pathVector[i].m_coord;
		Rec.WriteCoord(DocCoord((INT32)p.x, m_docSize.y - (INT32)p.y));
	}
	ok = m_pExporter->WriteRecord(&Rec);

	RectD boundings = GetMaximumBoundings(pathVector);
	/***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_DOWN);
	OutputStyles(style, trans, boundings, STYLE_FILL_ALL|STYLE_STROKE_ALL|STYLE_OPACITY);
	/***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_UP);

	return ok;
}
Example #7
0
bool XARGenerator::OutputPolygonEntity(const Style& style, const Transformation& trans, const PointDVector& coordVector)
{
	bool ok = true;
	CXaraFileRecord Rec(0);

	if (style.IsFillColourDefined() || style.IsFillGradientDefined()) {
		if (style.IsStrokeColourDefined())
			Rec.Reinit(TAG_PATH_FILLED_STROKED, TAG_PATH_SIZE);
		else
			Rec.Reinit(TAG_PATH_FILLED, TAG_PATH_SIZE);
	} else // if (style.IsStrokeColourDefined())
		Rec.Reinit(TAG_PATH_STROKED, TAG_PATH_SIZE);
	Rec.WriteUINT32(coordVector.GetCount());
	Rec.WriteBYTE(0x06); // moveto
	for (unsigned int i = 1; i < coordVector.GetCount() - 1; ++i)
		Rec.WriteBYTE(0x02); // lineto
	Rec.WriteBYTE(0x03); // lineto + closepath
	for (unsigned int i = 0; i < coordVector.GetCount(); ++i) {
		PointD p = coordVector[i];
		Rec.WriteCoord(DocCoord((INT32)p.x, m_docSize.y - (INT32)p.y));
	}
	ok = m_pExporter->WriteRecord(&Rec);

	RectD boundings = GetMaximumBoundings(coordVector);
	/***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_DOWN);
	OutputStyles(style, trans, boundings, STYLE_FILL_ALL|STYLE_STROKE_ALL|STYLE_OPACITY);
	/***/ ok = m_pExporter->WriteZeroSizedRecord(TAG_UP);

	return ok;
}
Example #8
0
void Trans2DMatrix::InitDecomposedTransforms()
{
	Scale       = 0;	// 0 indicates cached values invalid
	Aspect      = 1;
	Rotation    = 0;
	Skew        = 0;
	Translation = DocCoord(0,0);
}
Example #9
0
BOOL RegularShapeRecordHandler::SetupShape(NodeRegularShape *pShape)
{
	DocCoord Origin = DocCoord(0,0);

	pShape->SetCentrePoint(Origin);
	pShape->SetMinorAxes(Origin);
	pShape->SetMajorAxes(Origin);

	Matrix m = Matrix();	// Identity transform
	pShape->SetTransformMatrix(&m);

	return pShape->SetUpShape();
}
Example #10
0
BOOL ProcessPathToTrapezoids::Process(const ProcessFlags &PFlags,
										TrapTravelType TravelType, JointType JoinStyle)
{
	ERROR2IF(pTraps == NULL, FALSE, "Call Init to initialise the ProcessPathToTrapezoids object first!");

	JoinType		 = JoinStyle;
	PointFollowsJoin = FALSE;
	LastPoint		 = DocCoord(0,0);

	BOOL ok = ProcessPath::Process(PFlags);

	if (ok)
		ok = pTraps->PostProcessLists(this, TravelType);

	return(ok);
}
Example #11
0
ArrowRec::ArrowRec()
{
	ArrowShape 	= NULL;
	Centre 		= DocCoord(0,0);

	LineWidth	= DEFAULT_ARROW_LINEWIDTH;
	ArrowWidth	= 3;
	ArrowHeight	= 3;

	StartArrow = FALSE;
	ScaleWithLineWidth = TRUE;
	ArrowID = 0;

	m_bExtendPath = TRUE;

	IsNull = TRUE;
}
Example #12
0
BOOL ProcessPathDistance::NewPointA(PathVerb Verb, DocCoord* pCoord, UINT32* pPressure)
{
	ERROR2IF(pCoord==NULL,FALSE,"ProcessPathDistance::NewPoint() - pCoord==NULL");
	ERROR2IF(Verb!=PT_LINETO && Verb!=PT_MOVETO,FALSE,"ProcessPathDistance::NewPoint() - unknown path verb");

	
	if (!Found && !ProcFirstPoint && Verb==PT_LINETO)
	{
		double dx=pCoord->x-PrevCoord.x;
		double dy=pCoord->y-PrevCoord.y;
		double LineLength=sqrt(dx*dx+dy*dy);

		double NextDist=CurrentDist+LineLength;
		
		m_LastFoundDistance = CurrentDist;
		//TRACEUSER( "Diccon", _T("m_LastFound = %f\n"), m_LastFoundDistance);
		if (NextDist>=DesiredDist)
		{
			if (LineLength>0)
			{
				double FractOfLine = (DesiredDist-CurrentDist)/LineLength;
				double x = PrevCoord.x+dx*FractOfLine;
				double y = PrevCoord.y+dy*FractOfLine;
				CoordAtDist   = DocCoord((MILLIPOINT)x,(MILLIPOINT)y);
				TangentAtDist = atan2(dy,dx);
				if (pPressure != NULL)
					PressureAtDist = (UINT32)((*pPressure * (1-FractOfLine)) + (m_PrevPressure * FractOfLine));
			}
			else
			{
				CoordAtDist	  =	PrevCoord;
				TangentAtDist = 0;
				if (pPressure != NULL)
					PressureAtDist = m_PrevPressure;
			}
			Found=TRUE;
		}

		CurrentDist=NextDist;
	}
 
	PrevCoord=*pCoord;
	m_PrevPressure = *pPressure;
	return TRUE;
}
Example #13
0
void XARGenerator::DetermineRadialGradientPoints(const Gradient* pGradient, const Transformation& trans,
								const RectD& boundings, DocCoord& pC, DocCoord& pMaj, DocCoord& pMin)
{
	if (pGradient->units == Gradient::ObjectBoundingBox) {
		PointD p1m = (boundings.p11+boundings.p12)*0.5;
		PointD p2m = (boundings.p21+boundings.p22)*0.5;
		PointD p1M = (boundings.p11+boundings.p21)*0.5;
		PointD p2M = (boundings.p12+boundings.p22)*0.5;
		double fCX = p1M.x + (p2M.x-p1M.x)*pGradient->cx;
		double fCY = p2m.y + (p1m.y-p2m.y)*pGradient->cy;
		double fXM = fCX + (p2M.x-p1M.x)*pGradient->r;
		double fYM = fCY;
		double fXm = fCX;
		double fYm = fCY + (p1m.y-p2m.y)*pGradient->r;
		pC = DocCoord((INT32)fCX, (INT32)fCY);
		pMaj = DocCoord((INT32)fXM, m_docSize.y - (INT32)fYM);
		pMin = DocCoord((INT32)fXm, m_docSize.y - (INT32)fYm);
#ifdef SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "using ObjectBoundingBox %d,%d %d,%d (%d,%d)\n", pMaj.x, pMaj.y, pMin.x, pMin.y, pC.x, pC.y);
#endif
	} else { // Gradient->units == Gradient::UserSpaceOnUse
		double fX = pGradient->cx;
		double fY = pGradient->cy;
		double fR = pGradient->r;
		double fX1 = fX + fR;
		double fY1 = fY;
		double fX2 = fX;
		double fY2 = fY + fR;
		trans.ApplyToCoordinate(fX, fY, &fX, &fY);
		trans.ApplyToCoordinate(fX1, fY1, &fX1, &fY1);
		trans.ApplyToCoordinate(fX2, fY2, &fX2, &fY2);
		pC = DocCoord((INT32)fX,  m_docSize.y - (INT32)fY);
		pMaj = DocCoord((INT32)fX1, m_docSize.y - (INT32)fY1);
		pMin = DocCoord((INT32)fX2, m_docSize.y - (INT32)fY2);
#if SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "using UserSpaceOnUse %d,%d %d,%d (%d,%d)\n", pMaj.x, pMaj.y, pMin.x, pMin.y, pC.x, pC.y);
#endif
	}
}
Example #14
0
BOOL ArrowRec::CreateStockArrow(StockArrow ArrowType)
{
	if (ArrowShape != NULL)
	{
		delete ArrowShape;
		ArrowShape = NULL;
	}

	BOOL ok;
	Path* pPath;

	const INT32 Size  = 3;
	const INT32 Width = (72000/2)*3;

	if (ArrowType >= NUM_STOCK_ARROWS)
		ArrowType = SA_STRAIGHTARROW;

	// Set the ArrowID
	ArrowID = ArrowType;

	switch (ArrowType)
	{
		case SA_STRAIGHTARROW:

			/*
			STRAIGHT
			-9 54 m
			-9 0 l
			-9 -54 l
			117 0 l
			-9 54 l
			-9 54 l
			*/

			pPath = new Path();
			if (pPath == NULL)
				return FALSE;

			ok = pPath->Initialise(4);
			if (ok) 	 pPath->FindStartOfPath();
			if (ok) ok = pPath->InsertMoveTo(DocCoord( -9000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( -9000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(117000,      0));
			if (ok) ok = pPath->CloseSubPath();

			if (!ok)
			{
				delete pPath;
				return FALSE;
			}

			pPath->IsFilled  = TRUE;
			pPath->IsStroked = FALSE;

			ArrowShape 	= pPath;
			Centre 		= DocCoord(0,0);
			LineWidth 	= Width;
			ArrowWidth 	= INT32(Size);
			ArrowHeight = INT32(Size);
 			IsNull 		= FALSE;

			StartArrow = FALSE;

			break;

		case SA_ANGLEDARROW:

			/*
			ANGLED
			-26.999 53.999 m
			-9 0 l
			-26.999 -54.001 l
			135 0 l
			-26.999 53.999 l
			*/

			pPath = new Path();
			if (pPath == NULL)
				return FALSE;

			ok = pPath->Initialise(5);
			if (ok) 	 pPath->FindStartOfPath();
			if (ok) ok = pPath->InsertMoveTo(DocCoord(-27000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( -9000,      0));
			if (ok) ok = pPath->InsertLineTo(DocCoord(-27000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(135000,      0));
			if (ok) ok = pPath->CloseSubPath();

			if (!ok)
			{
				delete pPath;
				return FALSE;
			}

			pPath->IsFilled  = TRUE;
			pPath->IsStroked = FALSE;

			ArrowShape 	= pPath;
			Centre 		= DocCoord(0,0);
			LineWidth 	= Width;
			ArrowWidth 	= INT32(Size);
			ArrowHeight = INT32(Size);
 			IsNull 		= FALSE;

			StartArrow = FALSE;

			break;


		case SA_ROUNDEDARROW:

			/*
			ROUND
			-9 0 m
			-9 -45 l
			-9 -51.708 2.808 -56.580 9 -54 c
			117 -9 l
			120.916 -7.369 126 -4.242 126 0 c
			126 4.242 120.916 7.369 117 9 c
			9 54 l
			2.808 56.580 -9 51.708 -9 45 c
			-9 0 l
			*/

			pPath = new Path();
			if (pPath == NULL)
				return FALSE;

			ok = pPath->Initialise(17);
			if (ok) 	 pPath->FindStartOfPath();
			if (ok) ok = pPath->InsertMoveTo( DocCoord(  -9000,      0));
			if (ok) ok = pPath->InsertLineTo( DocCoord(  -9000, -45000));
			if (ok) ok = pPath->InsertCurveTo(DocCoord(  -9000, -51708),
											  DocCoord(   2808, -56580),
											  DocCoord(   9000, -54000));
			if (ok) ok = pPath->InsertLineTo( DocCoord( 117000,  -9000));
			if (ok) ok = pPath->InsertCurveTo(DocCoord( 120916,  -7369),
											  DocCoord( 126000,  -4242),
											  DocCoord( 126000,      0));
			if (ok) ok = pPath->InsertCurveTo(DocCoord( 126000,   4242),
											  DocCoord( 120916,   7369),
											  DocCoord( 117000,   9000));
			if (ok) ok = pPath->InsertLineTo( DocCoord(   9000,  54000));
			if (ok) ok = pPath->InsertCurveTo(DocCoord(   2808,  56580),
											  DocCoord(  -9000,  51708),
											  DocCoord(  -9000,  45000));
			if (ok) ok = pPath->CloseSubPath();

			if (!ok)
			{
				delete pPath;
				return FALSE;
			}

			pPath->IsFilled  = TRUE;
			pPath->IsStroked = FALSE;

			ArrowShape 	= pPath;
			Centre 		= DocCoord(0,0);
			LineWidth 	= Width;
			ArrowWidth 	= INT32(Size);
			ArrowHeight = INT32(Size);
 			IsNull 		= FALSE;

			StartArrow = FALSE;

			break;
	

		case SA_SPOT:

			/*
			BLOB
			-54 0 m
			-54 29.807 -29.807 54 0 54 c
			29.807 54 54 29.807 54 0 c
			54 -29.807 29.807 -54 0 -54 c
			-29.807 -54 -54 -29.807 -54 0 c
			*/

			pPath = new Path();
			if (pPath == NULL)
				return FALSE;

			ok = pPath->Initialise(14);
			if (ok) 	 pPath->FindStartOfPath();
			if (ok) ok = pPath->InsertMoveTo( DocCoord( -54000,      0));
			if (ok) ok = pPath->InsertCurveTo(DocCoord( -54000,  29807),
											  DocCoord( -29807,  54000),
											  DocCoord(      0,  54000));
			if (ok) ok = pPath->InsertCurveTo(DocCoord(  29807,  54000),
											  DocCoord(  54000,  29807),
											  DocCoord(  54000,      0));
			if (ok) ok = pPath->InsertCurveTo(DocCoord(  54000, -29807),
											  DocCoord(  29807, -54000),
											  DocCoord(      0, -54000));
			if (ok) ok = pPath->InsertCurveTo(DocCoord( -29807, -54000),
											  DocCoord( -54000, -29807),
											  DocCoord( -54000,      0));
			if (ok) ok = pPath->CloseSubPath();

			if (!ok)
			{
				delete pPath;
				return FALSE;
			}

			pPath->IsFilled  = TRUE;
			pPath->IsStroked = FALSE;

			ArrowShape 	= pPath;
			Centre 		= DocCoord(0,0);
			LineWidth 	= Width;
			ArrowWidth 	= INT32(Size);
			ArrowHeight = INT32(Size);
 			IsNull 		= FALSE;

			StartArrow = TRUE;

			break;
	

		case SA_DIAMOND:

			/*
			DIAMOND
			-63 0 m
			0 63 l
			63 0 l
			0 -63 l
			-63 0 l
			*/

			pPath = new Path();
			if (pPath == NULL)
				return FALSE;

			ok = pPath->Initialise(5);
			if (ok) 	 pPath->FindStartOfPath();
			if (ok) ok = pPath->InsertMoveTo(DocCoord(-63000,      0));
			if (ok) ok = pPath->InsertLineTo(DocCoord(     0,  63000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 63000,      0));
			if (ok) ok = pPath->InsertLineTo(DocCoord(     0, -63000));
			if (ok) ok = pPath->CloseSubPath();

			if (!ok)
			{
				delete pPath;
				return FALSE;
			}

			pPath->IsFilled  = TRUE;
			pPath->IsStroked = FALSE;

			ArrowShape 	= pPath;
			Centre 		= DocCoord(0,0);
			LineWidth 	= Width;
			ArrowWidth 	= INT32(Size);
			ArrowHeight = INT32(Size);
 			IsNull 		= FALSE;

			StartArrow = TRUE;

			break;
	
		case SA_ARROWFEATHER:

			/*
			FEATHER
			18 -54 m
			108 -54 l
			63 0 l
			108 54 l
			18 54 l
			-36 0 l
			18 -54 l
			*/

			pPath = new Path();
			if (pPath == NULL)
				return FALSE;

			ok = pPath->Initialise(7);
			if (ok) 	 pPath->FindStartOfPath();
			if (ok) ok = pPath->InsertMoveTo(DocCoord( 18000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(108000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 63000,      0));
			if (ok) ok = pPath->InsertLineTo(DocCoord(108000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 18000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(-36000,      0));
			if (ok) ok = pPath->CloseSubPath();

			if (!ok)
			{
				delete pPath;
				return FALSE;
			}

			pPath->IsFilled  = TRUE;
			pPath->IsStroked = FALSE;

			ArrowShape 	= pPath;
			Centre 		= DocCoord(0,0);
			LineWidth 	= Width;
			ArrowWidth 	= INT32(Size);
			ArrowHeight = INT32(Size);
 			IsNull 		= FALSE;

			StartArrow = TRUE;

			break;
	
		case SA_ARROWFEATHER2:

			/*
			FEATHER3
			-35.998 0 m
			18 -54 l
			54 -54 l
			18 -18 l
			27 -18 l
			63 -54 l
			99 -54 l
			63 -18 l
			72 -18 l
			108 -54 l
			144 -54 l
			90 0 l
			144 54 l
			108 54 l
			72 18 l
			63 18 l
			99 54 l
			63 54 l
			27 18 l
			18 18 l
			54 54 l
			18 54 l
			-35.998 0 l
			*/

			pPath = new Path();
			if (pPath == NULL)
				return FALSE;

			ok = pPath->Initialise(23);
			if (ok) 	 pPath->FindStartOfPath();
			if (ok) ok = pPath->InsertMoveTo(DocCoord( -36000,      0));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  18000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  54000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  18000, -18000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  27000, -18000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  63000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  99000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  63000, -18000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  72000, -18000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 108000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 144000, -54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  90000,      0));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 144000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 108000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  72000,  18000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  63000,  18000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  99000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  63000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  27000,  18000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  18000,  18000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  54000,  54000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(  18000,  54000));
			if (ok) ok = pPath->CloseSubPath();

			if (!ok)
			{
				delete pPath;
				return FALSE;
			}

			pPath->IsFilled  = TRUE;
			pPath->IsStroked = FALSE;

			ArrowShape 	= pPath;
			Centre 		= DocCoord(0,0);
			LineWidth 	= Width;
			ArrowWidth 	= INT32(Size);
			ArrowHeight = INT32(Size);
 			IsNull 		= FALSE;

			StartArrow = TRUE;

			break;
	
		case SA_HOLLOWDIAMOND:

			/*
			HOLLOW
			0 45 m
			-45 0 l
			0 -45 l
			45 0 l
			0 45 l
			0 63 m
			-63 0 l
			0 -63 l
			63 0 l
			0 63 l
			*/

			pPath = new Path();
			if (pPath == NULL)
				return FALSE;

			ok = pPath->Initialise(10);
			if (ok) 	 pPath->FindStartOfPath();
			if (ok) ok = pPath->InsertMoveTo(DocCoord(     0,  45000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(-45000,      0));
			if (ok) ok = pPath->InsertLineTo(DocCoord(     0, -45000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 45000,      0));
			if (ok) ok = pPath->CloseSubPath();
			if (ok) ok = pPath->InsertMoveTo(DocCoord(     0,  63000));
			if (ok) ok = pPath->InsertLineTo(DocCoord(-63000,      0));
			if (ok) ok = pPath->InsertLineTo(DocCoord(     0, -63000));
			if (ok) ok = pPath->InsertLineTo(DocCoord( 63000,      0));
			if (ok) ok = pPath->CloseSubPath();

			if (!ok)
			{
				delete pPath;
				return FALSE;
			}

			pPath->IsFilled  = TRUE;
			pPath->IsStroked = FALSE;

			ArrowShape 	= pPath;
			Centre 		= DocCoord(-45000,0);
			LineWidth 	= Width;
			ArrowWidth 	= INT32(Size);
			ArrowHeight = INT32(Size);
 			IsNull 		= FALSE;

			StartArrow = TRUE;

			break;

		default:
			ArrowShape 	= NULL;
			Centre 		= DocCoord(0,0);

			LineWidth	= DEFAULT_ARROW_LINEWIDTH;
			ArrowWidth	= 3;
			ArrowHeight	= 3;

			StartArrow 			= FALSE;
			ScaleWithLineWidth 	= TRUE;
			ArrowID 			= SA_NULLARROW;
 			IsNull 				= TRUE;
			break;
	}

	return TRUE;
}
Example #15
0
INT32 ProcessPathDistance::GetCoordAndTangentWithCache(DocCoord* pCoord, 
													  double* pTangent, BOOL* pFound,
											          double Dist, Path* pPath, UINT32* pPressure)
{
	ERROR2IF(pCoord==NULL && pTangent==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - no output pointers specified!");
	ERROR2IF(pFound==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pFound==NULL");
	ERROR2IF( pPath==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pPath==NULL");
 
	// we wish to continue processing from the last point that we found
	INT32 PrevCoordIndex = m_LastFoundIndex;
	INT32 NumProcessed = m_LastFoundIndex;

	DesiredDist   = Dist;
	CurrentDist   = m_LastFoundDistance;
	Found         = FALSE;
	CoordAtDist   = DocCoord(0,0);
	TangentAtDist = 0;
	PressureAtDist = 0;
	m_bDrawingBrush = TRUE;
	// set up the processpath process.
	ProcessFlags PFlags;
	
	BOOL bPressure = (pPressure != NULL && pPath->HasWidth());
	// if we are already partway along the path then we need to get the
	// previous point as it is needed in NewPoint
	if (NumProcessed > 0)
	{
		DocCoord* pCoords = pPath->GetCoordArray();
		PrevCoord = pCoords[PrevCoordIndex];
		if (bPressure)
		{
			UINT32* pPressureArray = pPath->GetWidthArray();
			if (pPressureArray != NULL)
				m_PrevPressure = pPressureArray[PrevCoordIndex];
			else
			{
				ERROR3("Wheres the pressure array?");
				m_PrevPressure = (UINT32)(MAXPRESSURE / 2);
			}
		}
	}
	
	BOOL ok=ProcessPath::Init(pPath);
	//TRACEUSER( "Diccon", _T("Desired    = %f\n"), Dist);
	//TRACEUSER( "Diccon", _T("Starting   = %f\n"), CurrentDist);

	if (ok)	NumProcessed = Process(PFlags, NumProcessed);

	if (NumProcessed != -1)
	{
		if (Found==FALSE) // this can happen if we are on the first couple of points
		{
			// get last 2 points on line
			DocCoord* pPathCoords=pPath->GetCoordArray();
			ERROR2IF(pPathCoords==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pPathCoords==NULL");
			INT32 NumPathCoords=pPath->GetNumCoords();
			//ERROR2IF(NumPathCoords<2,FALSE,"ProcessPathDistance::GetCoordAndTangent() - NumPathCoords < 2");
			if (NumPathCoords >= 2)
			{
				DocCoord LastCoord=pPathCoords[NumPathCoords-1];
				DocCoord PrevCoord=pPathCoords[NumPathCoords-2];

				double dx=LastCoord.x-PrevCoord.x;
				double dy=LastCoord.y-PrevCoord.y;
				double LineLength=sqrt(dx*dx+dy*dy);

				if (LineLength>0)
				{
					double FractOfLine = (DesiredDist-CurrentDist)/LineLength;
					double x = LastCoord.x+dx*FractOfLine;
					double y = LastCoord.y+dy*FractOfLine;

					CoordAtDist   = DocCoord((MILLIPOINT)x,(MILLIPOINT)y);
					TangentAtDist = atan2(dy,dx);
					Found = TRUE;
				}
				else
				{
					CoordAtDist	  =	LastCoord;
					TangentAtDist = 0;
					Found = TRUE;
				}
			}
			else //if we only have one coordinate so far
			{
				CoordAtDist=pPathCoords[0];
				TangentAtDist = 0;
				Found = TRUE;
			}
		}
		else
		{
			if (Dist<0) Found=FALSE;	// if not actually on path, flag not found on path
			
		}
		*pFound = Found;
		if (pCoord)   *pCoord   = CoordAtDist;
		if (pTangent) *pTangent = TangentAtDist;
		if (pPressure != NULL)
			*pPressure = PressureAtDist;
	}
	//m_LastFoundDistance = CurrentDist;
	//TRACEUSER( "Diccon", _T("Last Index = %d\n"), m_LastFoundIndex);
	//TRACEUSER( "Diccon", _T("Last Dist  = %f\n"), m_LastFoundDistance);

	//TRACEUSER( "Diccon", _T("FOUND      = %d\n"), Found);

	return NumProcessed;
}
Example #16
0
void RenderDemoDlg::RenderControl(ReDrawInfoType* ExtraInfo)
{
	// Go get a render region
	DocRect VirtualSize(-ExtraInfo->dx/2, -ExtraInfo->dy/2, ExtraInfo->dx/2, ExtraInfo->dy/2);
	RenderRegion* pRender = CreateGRenderRegion(&VirtualSize, ExtraInfo);
	if (pRender!=NULL)
	{
		DialogColourInfo RedrawColours;		// Get a supplier for default dlg colours

		// Render stuff in here
		// Build a Linear fill attribute
		LinearFillAttribute MyGradFill;
		MyGradFill.Colour = DocColour(255, 255, 0);
		MyGradFill.EndColour = DocColour(0, 255, 255);
		MyGradFill.StartPoint = DocCoord(0, ExtraInfo->dy);
		MyGradFill.EndPoint = DocCoord(ExtraInfo->dx, 0);

		// Build a path
		Path InkPath;
		InkPath.Initialise(12,12);
		InkPath.FindStartOfPath();

		// Get the coords used to build a shape
		INT32 dx = ExtraInfo->dx / 2;
		INT32 dy = ExtraInfo->dy / 2;
		INT32 Midx = ExtraInfo->dx / 4;
		INT32 Midy = ExtraInfo->dy / 4;

		// build a circle in the middle of the control
		InkPath.InsertMoveTo(DocCoord(Midx, dy));
		InkPath.InsertCurveTo(DocCoord(Midx+Midx/2, dy), DocCoord(dx, Midy+Midy/2), DocCoord(dx, Midy));
		InkPath.InsertCurveTo(DocCoord(dx, Midy-Midy/2), DocCoord(Midx+Midx/2, 0), DocCoord(Midx, 0));
		InkPath.InsertCurveTo(DocCoord(Midx-Midx/2, 0), DocCoord(0, Midy-Midy/2), DocCoord(0, Midy));
		InkPath.InsertCurveTo(DocCoord(0, Midy+Midy/2), DocCoord(Midx-Midx/2, dy), DocCoord(Midx, dy));
		InkPath.IsFilled = TRUE;
		
		// A Grey colour [...hmmm, it's not a very grey grey any more... oragnge more like]
		DocColour Grey(255,200,0);

		// Render the attributes and the a rectangle
		pRender->SaveContext();
		pRender->SetLineColour(Grey);

		// Draw a rectangle to fill in the background - Fill with Dialogue Background colour
		DocRect DrawMe(0, 0, ExtraInfo->dx, ExtraInfo->dy);
		pRender->SetFillColour(RedrawColours.DialogBack());
		pRender->DrawRect(&VirtualSize);

		// Draw some shapes and stuff
		pRender->SetFillGeometry(&MyGradFill, FALSE);
		pRender->DrawPath(&InkPath);

		// Build a path
		Path TriPath;
		TriPath.Initialise(12,12);
		TriPath.FindStartOfPath();

		// build a circle in the middle of the control
		TriPath.InsertMoveTo(VirtualSize.lo);
		TriPath.InsertLineTo(DocCoord(VirtualSize.hi.x, VirtualSize.lo.y));
		TriPath.InsertLineTo(DocCoord(0, VirtualSize.hi.y));
		TriPath.InsertLineTo(VirtualSize.lo);
		TriPath.IsFilled = TRUE;

		LinearFillAttribute MyTriFill;
		MyTriFill.Colour = ShowFirst ? First : Second;
		MyTriFill.EndColour = DocColour(0,0,0);
		MyTriFill.StartPoint = DocCoord(ExtraInfo->dx, 0);
		MyTriFill.EndPoint = DocCoord(0, ExtraInfo->dy);

		pRender->SetFillGeometry(&MyTriFill, FALSE);
		pRender->DrawPath(&TriPath);

		pRender->RestoreContext();

		// Get rid of the render region
		DestroyGRenderRegion(pRender);
	}

	// and animate it!
	if (ShowFirst)
	{
		INT32 Red, Green, Blue;
		First.GetRGBValue(&Red, &Green, &Blue);

		if (Blue>0)
		{
			// Set the colour back again
			Blue -= 10;
			First.SetRGBValue(Red, Green, Blue);

			// redraw it
			InvalidateGadget(_R(IDC_REDRAW_ME));
		}
	}
	else
	{
		// Set the colour back to how it was
		First.SetRGBValue(255, 0, 250);
	}
}
Example #17
0
//#include "trans2d.h" - in camtypes.h [AUTOMATICALLY REMOVED]
//#include "will.h"
//#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
//#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]

class Spread;

DECLARE_SOURCE("$Revision$");

CC_IMPLEMENT_DYNCREATE(OpFillNudge,Operation)
CC_IMPLEMENT_DYNCREATE(FillGeometryNudger, AttrValueChange)

BOOL OpFillNudge::NudgeCols;		// Shall we nudge colour or transparency fills ?

static CCRuntimeClass* LastNudgeType = NULL;
static DocCoord LastNudgeStart = DocCoord(0,0);
static DocCoord LastNudgeEnd = DocCoord(0,0);
static DocCoord LastNudgeEnd2 = DocCoord(0,0);

/********************************************************************************************

>	static void OpFillNudge::NudgeColours(BOOL cols)

	Author:		Will_Cowling (Xara Group Ltd) <*****@*****.**>
	Created:	28/3/94
	Purpose:	Sets whether a nudge will nudge colour or transparency fills.

********************************************************************************************/

void OpFillNudge::NudgeColours(BOOL cols)
{
Example #18
0
void OpFillNudge::Do(OpDescriptor* pOpDesc)
{

	//	Get scaled pixel size 
	FIXED16 ScaledPixelWidth, ScaledPixelHeight;
	GetWorkingView()->GetScaledPixelSize(&ScaledPixelWidth, &ScaledPixelHeight) ;
	PixelNudge=ScaledPixelWidth.MakeDouble() ;

	// Determine the nudge factors based on the OpDescriptor used to invoke the nudge operation
	String OpToken = pOpDesc->Token; 

	if		(OpToken == String(OPTOKEN_NUDGEUPPIXEL1))		{ IsPixelNudgeClass = TRUE; }
	else if	(OpToken == String(OPTOKEN_NUDGEUPPIXEL10))		{ IsPixelNudgeClass = TRUE; }

	else if	(OpToken == String(OPTOKEN_NUDGEDOWNPIXEL1))	{ IsPixelNudgeClass = TRUE; }
	else if	(OpToken == String(OPTOKEN_NUDGEDOWNPIXEL10))	{ IsPixelNudgeClass = TRUE; }

	else if	(OpToken == String(OPTOKEN_NUDGELEFTPIXEL1))	{ IsPixelNudgeClass = TRUE; }
	else if	(OpToken == String(OPTOKEN_NUDGELEFTPIXEL10))	{ IsPixelNudgeClass = TRUE; }

	else if	(OpToken == String(OPTOKEN_NUDGERIGHTPIXEL1))	{ IsPixelNudgeClass = TRUE; }
	else if	(OpToken == String(OPTOKEN_NUDGERIGHTPIXEL10))	{ IsPixelNudgeClass = TRUE; }

	else if	(OpToken == String(OPTOKEN_NUDGEUP1))			{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGEUP5))			{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGEUP10))			{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGEUPFIFTH))		{ IsPixelNudgeClass = FALSE; }

	else if	(OpToken == String(OPTOKEN_NUDGEDOWN1))			{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGEDOWN5))			{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGEDOWN10))		{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGEDOWNFIFTH))		{ IsPixelNudgeClass = FALSE; }

	else if	(OpToken == String(OPTOKEN_NUDGELEFT1))			{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGELEFT5))			{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGELEFT10))		{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGELEFTFIFTH))		{ IsPixelNudgeClass = FALSE; }

	else if	(OpToken == String(OPTOKEN_NUDGERIGHT1))		{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGERIGHT5))		{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGERIGHT10))		{ IsPixelNudgeClass = FALSE; }
	else if	(OpToken == String(OPTOKEN_NUDGERIGHTFIFTH))	{ IsPixelNudgeClass = FALSE; }

	// Setup the Offset DocCoord to contain the X and Y translation values	
	DocCoord Offset;

	if (IsPixelNudgeClass)
	{
		Offset.x=(INT32)GetXPixelDisplacement();
		Offset.y=(INT32)GetYPixelDisplacement();
	}
	else if (!IsPixelNudgeClass)
	{
		//TypeCast from double to INT32
		Offset.x=(INT32) GetXNudgeDisplacement();
		Offset.y=(INT32) GetYNudgeDisplacement();
	}

	if (AttrFillGeometry::SelectionCount == 0)
	{
			// Nothing to Nudge !!
		FailAndExecute();
		End();
		return;
	}

	FillGeometryNudger* FillNudger = new FillGeometryNudger();

	if (FillNudger == NULL)
	{
		FailAndExecute();
		End();
		return;
	}

	FillNudger->MutateColourFills(NudgeCols);
	FillNudger->SetNudgeDistance(Offset.x, Offset.y);

	AttributeManager::AttributeSelected(NULL, FillNudger);

	LastNudgeType 	= NULL;
	LastNudgeStart 	= DocCoord(0,0);
	LastNudgeEnd 	= DocCoord(0,0);
	LastNudgeEnd2 	= DocCoord(0,0);
	
	End();
}
Example #19
0
BOOL ProcessPathToTrapezoids::NewPoint(PathVerb Verb, DocCoord *pCoord)
{
	// Process any join we've just gone past. We have to delay processing of joins
	// until we know which way the curve headed off after the join, which is why
	// we are processing it now. If the new point is a MOVETO, then there is no join
	if (PointFollowsJoin && Verb == PT_LINETO)
	{
		// Find the last edge in the current edge list. If we can't find one, there is
		// nothing to "join to"
		TrapEdgeList *pEdgeList = pTraps->GetLastTrapEdgeList();
		TrapEdge *pEdge = NULL;
		if (pEdgeList != NULL)
			pEdge = pEdgeList->GetLastTrapEdge();

		if (pEdge != NULL)
		{
			switch(JoinType)
			{
				case MitreJoin:
					// A mitred join involves extending the previous and next segments of the outline
					// to their intersection. If there is no intersection, or if the intersection
					// is beyond the "MitreLimit", then we revert to a simple Bevelled join.
					// Otherwise, we need to add 2 line segments (3 trapezoid edges) joining the
					// end of the last segment to the intersection, and then from the intersection
					// to the start of this new segment.
					// These new segments are marked as being part of a join so that they will be
					// stroked as straight line segments rather than interpolating normals to make
					// a smoothed/curved join.

					{
						ERROR3IF(pEdgeList->GetNumEdges() < 2, "Not enough traps for mitred join");
						TrapEdge *pPrevEdge = pEdgeList->GetTrapEdge(pEdgeList->GetNumEdges() - 2);

						BOOL Mitred;
						if (pCoord != NULL)
						{
							Mitred = CalculateMitreIntersection(&pPrevEdge->Centre, &pEdge->Centre, pCoord);
						}
						else
						{
							// No pCoord passed in, so this is the join at the end. Use the 1st point
							// in the subpath as the "next point". (Well, the 2nd in the array, because point
							// 1 is coincident! We use point 2 which is the end of the 1st line)
							DocCoord NextCoord = pEdgeList->GetTrapEdge(1)->Centre;
							Mitred = CalculateMitreIntersection(&pPrevEdge->Centre, &pEdge->Centre, &NextCoord);
						}

						//BLOCK
						{
							// Nasty bodge - Because AddEdge can re-alloc the array, we CANNOT keep pointers
							// to array entries around over calls to AddEdge. We thus copy the edge point
							// into a temporary variable which we can safely use over the 2 calls the AddEdge
							DocCoord Temp = pEdge->Centre;

							// Add a single point for this join - by default this gives a Bevelled join
							pEdgeList->AddEdge(&Temp, TrapJoin_MitredOrBevelled);

							// And if it's Mitred, then add another point for this join
							if (Mitred)
								pEdgeList->AddEdge(&Temp, TrapJoin_MitredOrBevelled);
						}
					}
					break;

				case RoundJoin:
					// To make a rounded join, you might think we need to output a number of trapezoids,
					// but in fact the recursive flattened-mapping algorithm employed by the path
					// stroker will "smooth" a single trapezoid into a proper round join!
					// Thus, we simply insert another trapezoid on the join point (but do NOT mark
					// it as "part of a join") so that it will be mapped as a round join.
					pEdgeList->AddEdge(&pEdge->Centre, TrapJoin_Round);
					break;

				case BevelledJoin:
					// To make a bevelled join, we simply add another TrapEdge on the join point for
					// the start of the next segment, which will be joined with a straight line. 
					// However, the stroking mechanism will actually output that "line" as a round
					// join (due to its recursive flattened-mapping algorithm), so we have to
					// mark this point as "part of a join" so that it simply plonks down the
					// straight segment we want! (Hence the TRUE)
					pEdgeList->AddEdge(&pEdge->Centre, TrapJoin_MitredOrBevelled);
					break;

				default:
					ERROR3("Unsupported join type in ProcessPathToTrapezoids");
					break;
			}			
		}
	}

	// Clear the join flag, as any pending join has been processed
	PointFollowsJoin = FALSE;

	// If the provided coordinate was NULL, then they only wanted to add the join
	// information, so we exit now
	if (pCoord == NULL)
		return(TRUE);

	// Add the new point to the current trapezoid list
	switch(Verb)
	{
		case PT_MOVETO:
			{
				// A MoveTo signifies the start of a new (sub)path, so we start a new TrapList
				TrapEdgeList *pEdgeList = pTraps->AddEdgeList();
				if (pEdgeList == NULL)
					return(FALSE);

				pEdgeList->AddEdge(pCoord);
				LastPoint = *pCoord;
			}
			break;


		case PT_LINETO:
			{
				// Append each new point as a new trapezoid edge in the current TrapList
				// Find the last TrapEdgeList
				TrapEdgeList *pEdgeList = pTraps->GetLastTrapEdgeList();

				if (pEdgeList == NULL)
				{
					// We have started a path with a LineTo!
					// Create a new Trapezoid List (imply that this point is really a MOVETO)
					ERROR3("LINETO added to traplist with no preceding MOVETO");

					LastPoint = DocCoord(0,0);
					pEdgeList = pTraps->AddEdgeList();
					if (pEdgeList == NULL)
						return(FALSE);
				}

				// Append the new point to the current trap list. Check first to eliminate
				// coincident points (places where the source path has coincident points),
				// as we only want coincident points to occur in the special case of joins.
				if (pEdgeList->GetNumEdges() < 1 || LastPoint != *pCoord)
				{
					pEdgeList->AddEdge(pCoord);
					LastPoint = *pCoord;
				}
			}
			break;

		default:
			ERROR3("ProcessPathToTrapezoids only handles MOVETO and LINETO!");
			break;
	}

	return(TRUE);
}
Example #20
0
void ArrangeAlignment::RedrawDiagram(ReDrawInfoType* ExtraInfo)
{
	// objects drawn in the render region must be relatively large in the given coord space
	// else Gavin's curve flattening results in visible straight lines
	// so every dimension is scaled by scale
	INT32 scale=1000;

	// make a render region
	DocRect VirtRendRect;
	VirtRendRect.lo.x=-1*scale;
	VirtRendRect.lo.y=-2*scale;
	VirtRendRect.hi.x=(DiagWidth +1)*scale;
	VirtRendRect.hi.y=(DiagHeight+2)*scale;
	RenderRegion* pRender=CreateGRenderRegion(&VirtRendRect,ExtraInfo);

	if (pRender!=NULL)
	{
		pRender->SaveContext();

		// currently this must be set here before any colour tables calculated
		Quality             AntiAliasQuality(Quality::QualityMax);
		QualityAttribute    AntiAliasQualityAttr(AntiAliasQuality);
		pRender->SetQuality(&AntiAliasQualityAttr,FALSE);

		// Render the background rectangle
		DialogColourInfo RedrawColours;
		pRender->SetLineColour(RedrawColours.DialogBack());
		pRender->SetFillColour(RedrawColours.DialogBack());
		pRender->DrawRect(&VirtRendRect);

		// declared at this scope else RestoreContext() dies!
		RadialFillAttribute Fill;		

		// set up some defaults used by all objects
		Fill.MakeElliptical();
		Fill.Colour=DocColour(255,255,255);
		pRender->SetLineColour(BLACK);
		pRender->SetLineWidth(0);

		for (INT32 i=0; i<DiagRects; i++)
		{
			// reverse order in which objets are rendered (now filled!)
			INT32 j=DiagRects-1-i;

			// set fill colour of each object
			switch (j)
			{
				case  0: Fill.EndColour=DocColour(255,255,0); break;
				case  1: Fill.EndColour=DocColour(0,0,255);   break;
				case  2: Fill.EndColour=DocColour(255,0,0);   break;
				case  3: Fill.EndColour=DocColour(0,160,0);   break;
				default: Fill.EndColour=DocColour(0,0,0);     break;
			}

			// get bound rect of object to be drawn
			INT32 x=DiagRectX[Align.h][j].lo*scale;
			INT32 w=DiagRectX[Align.h][j].hi*scale-x;
			INT32 y=DiagRectY[Align.v][j].lo*scale;
			INT32 h=DiagRectY[Align.v][j].hi*scale-y;

			// create shape and fill geometries
			Path shape;
			shape.Initialise(16,8);
			shape.IsFilled=TRUE;
			shape.FindStartOfPath();
			switch (j)
			{
				case 0:
				{
					// create a rectangle
					shape.InsertMoveTo(DocCoord(x,y));
					shape.InsertLineTo(DocCoord(x,y+h));
					shape.InsertLineTo(DocCoord(x+w,y+h));
					shape.InsertLineTo(DocCoord(x+w,y));
					shape.InsertLineTo(DocCoord(x,y));

//					// create a radial fill
//					Fill.StartPoint=DocCoord(x+w*3/16,y+h*3/4);
//					Fill.EndPoint  =DocCoord(x+w*3/8,y+h/2);
//					Fill.EndPoint2 =DocCoord(x+w*3/8,y+h);
					break;
				}

				case 1:
				{
					// create a pseudo ellipse
					shape.InsertMoveTo( DocCoord(x,y+h/2));
					shape.InsertCurveTo(DocCoord(x,y+h*3/4),  DocCoord(x+w/4,y+h),  DocCoord(x+w/2,y+h));
					shape.InsertCurveTo(DocCoord(x+w*3/4,y+h),DocCoord(x+w,y+h*3/4),DocCoord(x+w,y+h/2));
					shape.InsertCurveTo(DocCoord(x+w,y+h/4),  DocCoord(x+w*3/4,y),  DocCoord(x+w/2,y));
					shape.InsertCurveTo(DocCoord(x+w/4,y),    DocCoord(x,y+h/4),    DocCoord(x,y+h/2));

// 					// create a radial fill
//					Fill.StartPoint=DocCoord(x+w*3/8,y+h*5/8);
//					Fill.EndPoint  =DocCoord(x+w*6/8,y+h/4);
//					Fill.EndPoint2 =DocCoord(x+w*6/8,y+h);
					break;
				}

				default:
				{
					// create a rounded rectangle
					shape.InsertMoveTo( DocCoord(x,y+h/2));
					shape.InsertCurveTo(DocCoord(x,y+h),  DocCoord(x,y+h),  DocCoord(x+w/2,y+h));
					shape.InsertCurveTo(DocCoord(x+w,y+h),DocCoord(x+w,y+h),DocCoord(x+w,y+h/2));
					shape.InsertCurveTo(DocCoord(x+w,y),  DocCoord(x+w,y),  DocCoord(x+w/2,y));
					shape.InsertCurveTo(DocCoord(x,y),    DocCoord(x,y),    DocCoord(x,y+h/2));

// 					// create a radial fill
//					Fill.StartPoint=DocCoord(x+w*3/16,y+h*3/4);
//					Fill.EndPoint  =DocCoord(x+w*3/8,y+h/2);
//					Fill.EndPoint2 =DocCoord(x+w*3/8,y+h);
					break;
				}

			}
//			pRender->SetFillGeometry(&Fill,FALSE);
			pRender->SetFillColour(Fill.EndColour);
			pRender->DrawPath(&shape);
		}

		pRender->RestoreContext();
		DestroyGRenderRegion(pRender);	// also blt's to screen
	}
}
Example #21
0
/********************************************************************************************

	INT32 HTMLExportFilter::WriteCoords(Path* ppthToWrite, TCHAR* pcValue, CCLexFile* pfileToWrite, TCHAR* pcBuffer)

	Author:		Graham_Walmsley (Xara Group Ltd) <*****@*****.**>
	Created:	18/4/97
	Inputs:		ppthToWrite		Pointer to the path to write
				pfileToWrite	The file to write to (may be NULL)
				pcBuffer		The text buffer to write to (may be NULL)
	Returns:	The number of TCHARs written
	Purpose:	Writes out the coordinates of a polygon
				e.g. COORDS="0,0,0,100,100,100,100,0"

********************************************************************************************/
INT32 HTMLExportFilter::WriteCoords(Path* ppthToWrite, TCHAR* pcValue, CCLexFile* pfileToWrite, TCHAR* pcBuffer)
{
	//This is the value we will return
	INT32 lCharsWritten=0;

	//First write out a space
	lCharsWritten+=Write(_R(IDS_HTMLEXPORT_SPACE), pfileToWrite, pcBuffer);

	//Now write out COORDS
	lCharsWritten+=Write(_R(IDS_HTMLEXPORT_COORDS), pfileToWrite, pcBuffer);
				   
	//And an equals sign
	lCharsWritten+=Write(_R(IDS_HTMLEXPORT_EQUALS), pfileToWrite, pcBuffer);

	//And an opening quote
	lCharsWritten+=Write(_R(IDS_HTMLEXPORT_QUOTES), pfileToWrite, pcBuffer);

	//Now we must write out the path's coordinates. So find out how
	//INT32 the path is
	INT32 lNumCoords=ppthToWrite->GetNumCoords();

	//And get its coordinate and verb arrays
	DocCoord* pdcCoords=ppthToWrite->GetCoordArray();
//	PathVerb* ppvVerbs=ppthToWrite->GetVerbArray();

	//Keep a copy of the last coordinate written, to make sure
	//we don't write out two consecutive identical coordinates
	DocCoord dcLastWritten=DocCoord(-1, -1);

	//Now do the following for every coordinate in the path
	//EXCEPT the last, which will be the same as the first
	INT32 lThisCoord=0;

	do
	{
		//If this coordinate isn't the same as the last one we wrote
		if (pdcCoords[lThisCoord]!=dcLastWritten)
		{
			//Write out a comma, unless this is the first coord to be written
			if (lThisCoord>0)
				lCharsWritten+=Write(_R(IDS_HTMLEXPORT_COMMA), pfileToWrite, pcBuffer);

			//Write it out, followed by a comma
			lCharsWritten+=Write(pdcCoords[lThisCoord], pfileToWrite, pcBuffer);
		}

		//Keep a copy of this coordinate
		dcLastWritten=pdcCoords[lThisCoord];

		//And move on to the next coordinate
		ppthToWrite->FindNextEndPoint(&lThisCoord);
				
	}
	while (lThisCoord<lNumCoords-1);


	//Write a closing quote
	lCharsWritten+=Write(_R(IDS_HTMLEXPORT_QUOTES), pfileToWrite, pcBuffer);

	//And return the number of characters written
	return lCharsWritten;
}
Example #22
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);
	}
}
Example #23
0
BOOL EditTab::CommitSection()
{
TRACEUSER( "Neville", _T("commit edit section\n"));
	ERROR2IF(pPrefsDlg == NULL,FALSE,"EditTab::CommitSection called with no dialog pointer");

	BOOL ok = pPrefsDlg->TalkToPage(_R(IDD_OPTSTAB_EDIT));	// The edit page identifier
	if (!ok)
		return TRUE;	// Talk to page failed to return now

	// Section = Edit

	// Ok has been pressed so take the values from this section of the dialog box
	BOOL Valid=FALSE;		// Flag for validity of value
	BOOL State=FALSE;		// Flag for state of button/switch
	BOOL SetOk=TRUE;		// Preference value set ok

	// Section = Attributes

	State = pPrefsDlg->GetLongGadgetValue(_R(IDC_OPTS_ASKSETATTRB), 0, 1, 0, &Valid);
	SetOk = Camelot.SetPrefValue(TEXT("Attributes"),TEXT("AskBeforeSettingCurrentAttr"),&State);
	ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT));

	State = pPrefsDlg->GetLongGadgetValue(_R(IDC_OPTS_LASTATTRB), 0, 1, 0, &Valid);
	SetOk = Camelot.SetPrefValue(TEXT("Attributes"),TEXT("LastAttrAppliedBecomesCurrent"),&State);
	ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT));


	// Set up the units that are used in the currently selected document
	// All units work off the selected document and so we must do nothing if there is no
	// selected document.
	ok = SetUpDocUnits();
	if (!ok)
		return (TRUE);

	// Section = Constraints

	// Now the constraint angle combo box
	// Convert to double uses units and so requires a selected document
	double Angle = 0.0; 		// Angle stored in radians in the preference system
	double AngleInDegrees = 0;	// Angle displayed in degrees to the user
	AngleInDegrees = pPrefsDlg->GetDoubleGadgetValue(_R(IDC_OPTS_ANGLECONST),
													  0, 360, _R(IDE_OPTS_INVALIDANGLE), &Valid);
	if (Valid)
	{
		// Angle in correct range so put it into the preference system
		Angle = AngleInDegrees * PI/180.0;		// convert angle to radians
TRACEUSER( "Neville", _T("commit constraint angle in degrees='%d' angle='%d' Valid ='%d'\n"), AngleInDegrees, Angle, Valid);
		SetOk = Camelot.SetPrefValue(TEXT("Constraints"), TEXT("Constrain Angle"), &Angle);
		ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT));
	}
	else
		return FALSE; 			// Angle incorrect, user has been warned already

	// Now the duplicate distance
	INT32 x = 0;
	INT32 y = 0;
	const INT32 Maxxy = INT_MAX;		// maximum value allowed as the distance
	BOOL bValidX = FALSE;
	BOOL bValidY = FALSE;

	ok = pPrefsDlg->TalkToPage(_R(IDD_OPTSTAB_EDIT));	// The edit page identifier
	x = pPrefsDlg->GetUnitGadgetValue(_R(IDC_OPTS_XDUPLICATE), CurrentScaledUnits,
										 -Maxxy, Maxxy, _R(IDE_OPTS_INVALIDDISTANCE), &bValidX);
/*	if (Valid)
	{
		SetOk = Camelot.SetPrefValue(TEXT("Duplicate"), TEXT("DuplicatePlacementX"), &x);
		ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT));
	}
	else
		return FALSE; 			// Duplicate x incorrect, user has been warned already
*/
	ok = pPrefsDlg->TalkToPage(_R(IDD_OPTSTAB_EDIT));	// The edit page identifier
	y = pPrefsDlg->GetUnitGadgetValue(_R(IDC_OPTS_YDUPLICATE), CurrentScaledUnits,
										 -Maxxy, Maxxy, _R(IDE_OPTS_INVALIDDISTANCE), &bValidY);
/*	if (Valid)
	{
		SetOk = Camelot.SetPrefValue(TEXT("Duplicate"), TEXT("DuplicatePlacementY"), &y);
		ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT));
	}
	else
		return FALSE; 			// Duplicate y incorrect, user has been warned already
*/
	if (bValidX && bValidY)
	{
		pDocument->SetDuplicationOffset(DocCoord(x,y));
		pDocument->SetModified(TRUE);
	}
	else
		return FALSE;

	// Now the nudge size distance
	UINT32 Nudge = 0;
	ok = pPrefsDlg->TalkToPage(_R(IDD_OPTSTAB_EDIT));	// The edit page identifier
	Nudge = pPrefsDlg->GetUnitGadgetValue(_R(IDC_OPTS_NUDGESIZE), CurrentScaledUnits,
											 0, INT_MAX, _R(IDE_OPTS_INVALIDNUDGE), &Valid);
TRACEUSER( "Neville", _T("commit nudge distance='%d' Valid ='%d'\n"),Nudge, Valid);
	if (Valid)
	{
		/*SetOk =*/ pDocument->SetDocNudge (Nudge);//Camelot.SetPrefValue(TEXT("Nudge"), TEXT("StepSize"), &Nudge);
		pDocument->SetModified (TRUE);
		//ERROR2IF(!SetOk,2,_R(IDE_OPTS_SETPREF_EDIT));
	}
	else
		return FALSE; 			// Nudge size incorrect, user has been warned already

	return TRUE;
}
Example #24
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
}
Example #25
0
BOOL ProcessPathDistance::GetCoordAndTangent(DocCoord* pCoord, double* pTangent, BOOL* pFound,
											 double Dist, Path* pPath, UINT32* pPressure)
{
	ERROR2IF(pCoord==NULL && pTangent==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - no output pointers specified!");
	ERROR2IF(pFound==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pFound==NULL");
	ERROR2IF( pPath==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pPath==NULL");

	DesiredDist   = Dist;
	CurrentDist   = 0;
	Found         = FALSE;
	CoordAtDist   = DocCoord(0,0);
	TangentAtDist = 0;
	PressureAtDist = 0;

	// set up the processpath process.
	ProcessFlags PFlags;
	BOOL ok=ProcessPath::Init(pPath);
	if (ok)	ok= Process(PFlags, 0); //ProcessPath::Process(PFlags);

	if (ok)
	{
		if (Found==FALSE)
		{
			// get last 2 points on line
			DocCoord* pPathCoords=pPath->GetCoordArray();
			ERROR2IF(pPathCoords==NULL,FALSE,"ProcessPathDistance::GetCoordAndTangent() - pPathCoords==NULL");
			INT32 NumPathCoords=pPath->GetNumCoords();
			ERROR2IF(NumPathCoords<2,FALSE,"ProcessPathDistance::GetCoordAndTangent() - NumPathCoords < 2");
			DocCoord LastCoord=pPathCoords[NumPathCoords-1];
			DocCoord PrevCoord=pPathCoords[NumPathCoords-2];

			double dx=LastCoord.x-PrevCoord.x;
			double dy=LastCoord.y-PrevCoord.y;
			double LineLength=sqrt(dx*dx+dy*dy);

			if (LineLength>0)
			{
				double FractOfLine = (DesiredDist-CurrentDist)/LineLength;
				double x = LastCoord.x+dx*FractOfLine;
				double y = LastCoord.y+dy*FractOfLine;

				CoordAtDist   = DocCoord((MILLIPOINT)x,(MILLIPOINT)y);
				TangentAtDist = atan2(dy,dx);
			}
			else
			{
				CoordAtDist	  =	LastCoord;
				TangentAtDist = 0;
			}
		}
		else
			if (Dist<0) Found=FALSE;	// if not actually on path, flag not found on path
		

		*pFound = Found;
		if (pCoord)   *pCoord   = CoordAtDist;
		if (pTangent) *pTangent = TangentAtDist;
		if (pPressure != NULL)
		{
			*pPressure = PressureAtDist;
		//	TRACEUSER( "Diccon", _T("Pressure At Dist = %d\n"), PressureAtDist);
		}
	}

	return ok;
}