Beispiel #1
0
bool XARGenerator::OutputFillRadialGradient(const Style& style, const Transformation& trans, const RectD& boundings)
{
	bool ok = true;
	CXaraFileRecord Rec(0);

	const Gradient* pGradient = style.GetFillGradient();
	const GradientStopList& stops = pGradient->stops;

	if (stops.GetCount() < 1) {
#if SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "gradient '%s' has no stop points, giving up\n", (const char *)pGradient->xmlId.mb_str(wxConvUTF8));
#endif
		return false;
	}

#if SVGDEBUG
	svgtrace(DBGTRACE_GRADIENTS, "using radial fill gradient '%s' with %d colours\n", (const char *)pGradient->xmlId.mb_str(wxConvUTF8), stops.GetCount());
	svgtrace(DBGTRACE_GRADIENTS, "gradient trans: ");
	DebugDumpTransformation(DBGTRACE_GRADIENTS, trans);
#endif

    // center, major and minor axis points of gradient
	DocCoord pC, pMaj, pMin;
	DetermineRadialGradientPoints(pGradient, trans, boundings, pC, pMaj, pMin);

	if (stops.GetCount() < 3) { // 1 or 2 stops
		wxColour col1, col2;
		double fOpacity1, fOpacity2;
		if (stops.GetCount() == 1) {
			GradientStop* pStop1 = stops.GetFirst()->GetData();
			col2 = col1 = pStop1->stopColour;
			fOpacity1 = fOpacity2 = pStop1->stopOpacity;
		} else { // stops.GetCount() == 2
			GradientStop* pStop1 = stops.GetFirst()->GetData();
			GradientStop* pStop2 = stops.GetLast()->GetData();
			col1 = pStop1->stopColour;
			col2 = pStop2->stopColour;
			fOpacity1 = pStop1->stopOpacity;
			fOpacity2 = pStop2->stopOpacity;
		}

#if SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "stop points: %d, %d and %d, %d\n", pMaj.x, pMaj.y, pMin.x, pMin.y);
#endif

		UINT32 iRecNo1 = DefineColour(col1);
		UINT32 iRecNo2 = DefineColour(col2);

		Rec.Reinit(TAG_ELLIPTICALFILL, TAG_ELLIPTICALFILL_SIZE);
		ok = Rec.WriteCoord(pC);
		ok = Rec.WriteCoord(pMaj);
		ok = Rec.WriteCoord(pMin);
		ok = Rec.WriteReference(iRecNo1);
		ok = Rec.WriteReference(iRecNo2);
		ok = Rec.WriteDOUBLE(0.0); // bias
		ok = Rec.WriteDOUBLE(0.0); // gain
		ok = m_pExporter->WriteRecord(&Rec);

		if (fOpacity1 != 1.0 || fOpacity2 != 1.0) {
			// the fill has also alpha transparency
			BYTE bOpacity1 = (BYTE)((1.0-fOpacity1)*255.0);
			BYTE bOpacity2 = (BYTE)((1.0-fOpacity2)*255.0);

			Rec.Reinit(TAG_ELLIPTICALTRANSPARENTFILL, TAG_ELLIPTICALTRANSPARENTFILL_SIZE);
			ok = Rec.WriteCoord(pC);
			ok = Rec.WriteCoord(pMaj);
			ok = Rec.WriteCoord(pMin);
			ok = Rec.WriteBYTE(bOpacity1);
			ok = Rec.WriteBYTE(bOpacity2);
			ok = Rec.WriteBYTE(0x01); // mix
			ok = Rec.WriteDOUBLE(0.0); // bias
			ok = Rec.WriteDOUBLE(0.0); // gain
			ok = m_pExporter->WriteRecord(&Rec);
		}
	} else { // stops.GetCount() > 2
		// XXX ?
	}

	return true;
}
Beispiel #2
0
bool XARGenerator::OutputStyles(const Style& style, const Transformation& trans, const RectD& boundings, UINT32 witch)
{
	bool ok = true;
	CXaraFileRecord Rec(0);

	wxString sXmlId = style.GetXmlId();
	if (!sXmlId.IsEmpty()) {
		// XXX how to output object labels in XAR?

#if SVGDEBUG
		svgtrace(DBGTRACE_SHAPES, "object id: %s\n", (const char *)sXmlId.mb_str(wxConvUTF8));
#endif
	}

	// XXX TODO to avoid XAR redundancy, we should look
	// if the styles we are outputting are already the default
	// in Xara's stack

	if (witch & STYLE_FILL_COLOUR) {
		if (style.IsFillColourDefined()) {
			wxColour col = style.GetFillColour();
			if (col.Ok()) {
				UINT32 iRecNo = DefineColour(col);

				Rec.Reinit(TAG_FLATFILL, TAG_FLATFILL_SIZE);
				ok = Rec.WriteReference(iRecNo);
				ok = m_pExporter->WriteRecord(&Rec);

#if SVGDEBUG
				svgtrace(DBGTRACE_STYLES, "fill colour %d,%d,%d\n", col.Red(), col.Green(), col.Blue());
#endif
			} else {
				m_pExporter->WriteZeroSizedRecord(TAG_FLATFILL_NONE);
#if SVGDEBUG
				svgtrace(DBGTRACE_STYLES, "no fill colour\n");
#endif
			}
		} else if (!style.IsFillGradientDefined()) {
			m_pExporter->WriteZeroSizedRecord(TAG_FLATFILL_NONE);
#if SVGDEBUG
			svgtrace(DBGTRACE_STYLES, "no fill colour\n");
#endif
		}
	}

	if (witch & STYLE_FILL_GRADIENT && style.IsFillGradientDefined()) {
		Gradient* pGradient = style.GetFillGradient();

		if (pGradient->type == Gradient::Linear) {
			OutputFillLinearGradient(style, trans, boundings);
		} else if (pGradient->type == Gradient::Radial) {
			OutputFillRadialGradient(style, trans, boundings);
		}
	}

	if (witch & STYLE_FILL_OPACITY && style.IsFillOpacityDefined()) {
		double opacity = style.GetFillOpacity();
		if (opacity < 1.0) {
			BYTE bOpacity = (BYTE)((1.0-opacity)*255.0);

			Rec.Reinit(TAG_FLATTRANSPARENTFILL, TAG_FLATTRANSPARENTFILL_SIZE);
			ok = Rec.WriteBYTE(bOpacity);
			ok = Rec.WriteBYTE(0x01);
			ok = m_pExporter->WriteRecord(&Rec);
		}
	}

	if (witch & STYLE_STROKE_COLOUR) {
		if (style.IsStrokeColourDefined()) {
			wxColour col = style.GetStrokeColour();
			if (col.Ok()) {
				UINT32 iRecNo = DefineColour(col);

				Rec.Reinit(TAG_LINECOLOUR, TAG_LINECOLOUR_SIZE);
				ok = Rec.WriteReference(iRecNo);
				ok = m_pExporter->WriteRecord(&Rec);

#if SVGDEBUG
				svgtrace(DBGTRACE_STYLES, "stroke colour %d,%d,%d\n", col.Red(), col.Green(), col.Blue());
#endif
			} else {
				m_pExporter->WriteZeroSizedRecord(TAG_LINECOLOUR_NONE);
#if SVGDEBUG
				svgtrace(DBGTRACE_STYLES, "no stroke colour\n");
#endif
			}
		} else {
			m_pExporter->WriteZeroSizedRecord(TAG_LINECOLOUR_NONE);
#if SVGDEBUG
			svgtrace(DBGTRACE_STYLES, "no stroke colour\n");
#endif
		}
	}

	if (witch & STYLE_STROKE_WIDTH && style.IsStrokeWidthDefined()) {
		UINT32 iStrokeWidth = style.GetStrokeWidth();
		Rec.Reinit(TAG_LINEWIDTH, TAG_LINEWIDTH_SIZE);
		ok = Rec.WriteINT32(iStrokeWidth);
		ok = m_pExporter->WriteRecord(&Rec);
	}

	if (witch & STYLE_STROKE_LINEJOIN )
	{
		JointType jt;
		if (style.IsStrokeLineJoinDefined()) {
			jt=style.GetStrokeLineJoin();

#if SVGDEBUG
			switch(jt)
			{
				case MitreJoin:
					svgtrace(DBGTRACE_STYLES, "stroke join mitre\n");
				break;
				case BevelledJoin:
					svgtrace(DBGTRACE_STYLES, "stroke join bevel\n");
				break;
				case RoundJoin:
					svgtrace(DBGTRACE_STYLES, "stroke join round\n");
				break;
			}
#endif
		} else {
			jt=MitreJoin;

#if SVGDEBUG
			svgtrace(DBGTRACE_STYLES, "no stroke specified, using mitre\n");
#endif

		}

		Rec.Reinit(TAG_JOINSTYLE, TAG_JOINSTYLE_SIZE);
		ok = Rec.WriteBYTE(BYTE(jt));
		ok = m_pExporter->WriteRecord(&Rec);

	}

	if (witch & STYLE_STROKE_LINECAP && style.IsStrokeLineCapDefined()) {
		LineCapType lct=style.GetStrokeLineCap();
		Rec.Reinit(TAG_STARTCAP, TAG_STARTCAP_SIZE);
		ok = Rec.WriteBYTE(BYTE(lct));
		ok = m_pExporter->WriteRecord(&Rec);

		Rec.Reinit(TAG_ENDCAP, TAG_ENDCAP_SIZE);
		ok = Rec.WriteBYTE(BYTE(lct));
		ok = m_pExporter->WriteRecord(&Rec);

#if SVGDEBUG
		switch(lct)
		{
			case LineCapButt:
				svgtrace(DBGTRACE_STYLES, "stroke cap butt\n");
			break;
			case LineCapRound:
				svgtrace(DBGTRACE_STYLES, "stroke cap round\n");
			break;
			case LineCapSquare:
				svgtrace(DBGTRACE_STYLES, "stroke cap square\n");
			break;
		}
#endif

	}

	if (witch & STYLE_STROKE_OPACITY && style.IsStrokeOpacityDefined()) {
		double opacity = style.GetStrokeOpacity();
		if (opacity < 1.0) {
			BYTE bOpacity = (BYTE)((1.0-opacity)*255.0);
			Rec.Reinit(TAG_LINETRANSPARENCY, TAG_LINETRANSPARENCY_SIZE);
			ok = Rec.WriteBYTE(bOpacity);
			ok = Rec.WriteBYTE(0x01); // mix
			ok = m_pExporter->WriteRecord(&Rec);
		}
	}

	if (witch & STYLE_OPACITY && style.IsOpacityDefined()) {
		double fOpacity = style.GetOpacity();
		if (fOpacity < 1.0) {
			double fFillOpacity = fOpacity;
			double fStrokeOpacity = fOpacity;

			if (style.IsFillOpacityDefined())
				fFillOpacity *= style.GetFillOpacity();
			if (style.IsStrokeOpacityDefined())
				fStrokeOpacity *= style.GetStrokeOpacity();

			BYTE bFillOpacity   = (BYTE)((1.0-fFillOpacity)*255.0);
			BYTE bStrokeOpacity = (BYTE)((1.0-fStrokeOpacity)*255.0);

			Rec.Reinit(TAG_FLATTRANSPARENTFILL, TAG_FLATTRANSPARENTFILL_SIZE);
			ok = Rec.WriteBYTE(bFillOpacity);
			ok = Rec.WriteBYTE(0x01); // mix
			ok = m_pExporter->WriteRecord(&Rec);
			Rec.Reinit(TAG_LINETRANSPARENCY, TAG_LINETRANSPARENCY_SIZE);
			ok = Rec.WriteBYTE(bStrokeOpacity);
			ok = Rec.WriteBYTE(0x01); // mix
			ok = m_pExporter->WriteRecord(&Rec);
		}
	}

	return ok;
}
Beispiel #3
0
bool XARGenerator::OutputFillLinearGradient(const Style& style, const Transformation& trans, const RectD& boundings)
{
	bool ok = true;
	CXaraFileRecord Rec(0);

	const Gradient* pGradient = style.GetFillGradient();
	const GradientStopList& stops = pGradient->stops;

	if (stops.GetCount() < 1) {
#if SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "gradient '%s' has no stop points, giving up\n", (const char *)pGradient->xmlId.mb_str(wxConvUTF8));
#endif
		return false;
	}

#if SVGDEBUG
	svgtrace(DBGTRACE_GRADIENTS, "using linear fill gradient '%s' with %d colours\n", (const char *)pGradient->xmlId.mb_str(wxConvUTF8), stops.GetCount());
	svgtrace(DBGTRACE_GRADIENTS, "gradient trans: ");
	DebugDumpTransformation(DBGTRACE_GRADIENTS, trans);
#endif

    // start and end points of gradient
	DocCoord p1, p2;

	DetermineLinearGradientPoints(pGradient, trans, boundings, p1, p2);

	if (pGradient->units == Gradient::ObjectBoundingBox) {
		// first and last offsets of gradient
		double fOffsetFirst, fOffsetLast;

		if (stops.GetCount() == 1) {
			fOffsetFirst = 0.0;
			fOffsetLast = 1.0;
		} else { // stops.GetCount() > 1
			GradientStop* pStop1 = stops.GetFirst()->GetData();
			GradientStop* pStop2 = stops.GetLast()->GetData();
			fOffsetFirst = pStop1->offset;
			fOffsetLast = pStop2->offset;
		}

#if 0
		// determine vector of direction of object gradient
		double fDX=1.0, fDY=0.0;
		trans.ApplyToCoordinate(fDX, fDY, &fDX, &fDY);
		double fMod = sqrt(fDX*fDX+fDY*fDY);
		fDX /= fMod;
		fDY /= fMod;
#if SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "direction of gradient: %.2f %.2f\n", fDX, fDY);
#endif
#endif

		PointD pLower = boundings.LowerCoord();
		PointD pHigher = boundings.HigherCoord();
		double fWidth = fabs(pHigher.x - pLower.x);
		//double fHeight = fabs(pHigher.x - pLower.x);
		p1.x += (INT32)(fWidth * fOffsetFirst);
		//p1.y += (INT32)(fHeight * fOffsetFirst);
		p2.x -= (INT32)(fWidth * (1.0 - fOffsetLast));
		//p2.y -= (INT32)(fHeight * (1.0 - fOffsetLast));
#ifdef SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "new ObjectBoundingBox %d,%d %d,%d\n", p1.x, p1.y, p2.x, p2.y);
#endif
	}

	if (stops.GetCount() < 3) { // 1 or 2 stops
		wxColour col1, col2;
		double fOpacity1, fOpacity2;
		if (stops.GetCount() == 1) {
			GradientStop* pStop1 = stops.GetFirst()->GetData();
			col2 = col1 = pStop1->stopColour;
			fOpacity1 = fOpacity2 = pStop1->stopOpacity;
		} else { // stops.GetCount() == 2
			GradientStop* pStop1 = stops.GetFirst()->GetData();
			GradientStop* pStop2 = stops.GetLast()->GetData();
			col1 = pStop1->stopColour;
			col2 = pStop2->stopColour;
			fOpacity1 = pStop1->stopOpacity;
			fOpacity2 = pStop2->stopOpacity;
		}

#if SVGDEBUG
		svgtrace(DBGTRACE_GRADIENTS, "stop points: %d, %d and %d, %d\n", p1.x, p1.y, p2.x, p2.y);
#endif

		UINT32 iRecNo1 = DefineColour(col1);
		UINT32 iRecNo2 = DefineColour(col2);

		Rec.Reinit(TAG_LINEARFILL, TAG_LINEARFILL_SIZE);
		ok = Rec.WriteCoord(p1);
		ok = Rec.WriteCoord(p2);
		ok = Rec.WriteReference(iRecNo1);
		ok = Rec.WriteReference(iRecNo2);
		ok = Rec.WriteDOUBLE(0.0); // bias
		ok = Rec.WriteDOUBLE(0.0); // gain
		ok = m_pExporter->WriteRecord(&Rec);

		if (fOpacity1 != 1.0 || fOpacity2 != 1.0) {
			// the fill has also alpha transparency
			BYTE bOpacity1 = (BYTE)((1.0-fOpacity1)*255.0);
			BYTE bOpacity2 = (BYTE)((1.0-fOpacity2)*255.0);

			Rec.Reinit(TAG_LINEARTRANSPARENTFILL, TAG_LINEARTRANSPARENTFILL_SIZE);
			ok = Rec.WriteCoord(p1);
			ok = Rec.WriteCoord(p2);
			ok = Rec.WriteBYTE(bOpacity1);
			ok = Rec.WriteBYTE(bOpacity2);
			ok = Rec.WriteBYTE(0x01); // mix
			ok = Rec.WriteDOUBLE(0.0); // bias
			ok = Rec.WriteDOUBLE(0.0); // gain
			ok = m_pExporter->WriteRecord(&Rec);

		}
	} else { // stops.GetCount() > 2
		// we have more than 2 colours
		size_t size = stops.GetCount();
		double* fvOffsets = new double[size];
		UINT32* ivRecNo = new UINT32[size];
		double* fvOpacity = new double[size];

		bool bHaveTransparency = false;
		for (unsigned int i = 0; i < size; ++i) {
			GradientStop* pStop = stops.Item(i)->GetData();
			ivRecNo[i] = DefineColour(pStop->stopColour);
			fvOffsets[i] = pStop->offset;
			fvOpacity[i] = pStop->stopOpacity;
			if (pStop->stopOpacity < 1.0)
				bHaveTransparency = true;
		}

		Rec.Reinit(TAG_LINEARFILLMULTISTAGE, TAG_LINEARFILLMULTISTAGE_SIZE);
		ok = Rec.WriteCoord(p1);
		ok = Rec.WriteCoord(p2);
		ok = Rec.WriteReference(ivRecNo[0]);
		ok = Rec.WriteReference(ivRecNo[size-1]);
		ok = Rec.WriteINT32((INT32)size-2);
		for (unsigned int i = 1; i < size - 1; ++i) {
			ok = Rec.WriteDOUBLE(fvOffsets[i]);
			ok = Rec.WriteReference(ivRecNo[i]);
		}
		ok = m_pExporter->WriteRecord(&Rec);

		if (bHaveTransparency) {
			if (size == 3) {
				DocCoord pM;
				// calculate middle point position
				pM.x = p1.x + (INT32)((p2.x-p1.x)*fvOffsets[1]);
				pM.y = p1.y + (INT32)((p2.y-p1.y)*fvOffsets[1]);

				// hack: avoid aligned points, otherwise the fill will not work
				if (pM.y == p1.y) {
					pM.y -= 10;
				}

				BYTE bOpacity1 = (BYTE)((1.0-fvOpacity[0])*255.0);
				BYTE bOpacityM = (BYTE)((1.0-fvOpacity[1])*255.0);
				BYTE bOpacity2 = (BYTE)((1.0-fvOpacity[2])*255.0);

				Rec.Reinit(TAG_THREECOLTRANSPARENTFILL, TAG_THREECOLTRANSPARENTFILL_SIZE);
				ok = Rec.WriteCoord(p1);
				ok = Rec.WriteCoord(pM);
				ok = Rec.WriteCoord(p2);
				ok = Rec.WriteBYTE(bOpacity1);
				ok = Rec.WriteBYTE(bOpacityM);
				ok = Rec.WriteBYTE(bOpacity2);
				ok = Rec.WriteBYTE(0x01); // mix
				ok = m_pExporter->WriteRecord(&Rec);

			} else { // size > 3
				// XXX the maximum number of transparent positions in XAR files is 4
				DocCoord pM1, pM2;
				// calculate middle point position
				pM1.x = p1.x + (INT32)((p2.x-p1.x)*fvOffsets[1]); // XXX should get the best offsets
				pM1.y = p1.y + (INT32)((p2.y-p1.y)*fvOffsets[1]); // not simply the first two
				pM2.x = p1.x + (INT32)((p2.x-p1.x)*fvOffsets[2]);
				pM2.y = p1.y + (INT32)((p2.y-p1.y)*fvOffsets[2]);

				// hack: avoid aligned points, otherwise the fill will not work
				if (pM1.y == p1.y) {
					pM1.y -= 10;
				}
				if (pM2.y == p1.y) {
					pM2.y -= 20;
				}

				BYTE bOpacity1  = (BYTE)((1.0-fvOpacity[0])*255.0);
				BYTE bOpacityM1 = (BYTE)((1.0-fvOpacity[1])*255.0);
				BYTE bOpacityM2 = (BYTE)((1.0-fvOpacity[2])*255.0);
				BYTE bOpacity2  = (BYTE)((1.0-fvOpacity[size-1])*255.0);

				Rec.Reinit(TAG_FOURCOLTRANSPARENTFILL, TAG_FOURCOLTRANSPARENTFILL_SIZE);
				ok = Rec.WriteCoord(p1);
				ok = Rec.WriteCoord(pM1);
				ok = Rec.WriteCoord(pM2);
				//ok = Rec.WriteCoord(p2); // XXX this is wrong
				ok = Rec.WriteBYTE(bOpacity1);
				ok = Rec.WriteBYTE(bOpacityM1);
				ok = Rec.WriteBYTE(bOpacityM2);
				ok = Rec.WriteBYTE(bOpacity2);
				ok = Rec.WriteBYTE(0x01); // mix
				ok = m_pExporter->WriteRecord(&Rec);
			}
		}

		delete[] fvOffsets;
		delete[] ivRecNo;
		delete[] fvOpacity;
	}

	return ok;
}