r14278 by fschmid - Part of Bug-Nr 4293: "Improved support for gradients", added support for focal point different from center point.

scribus-commit scribus-commit at lists.scribus.net
Wed Nov 11 13:46:19 CET 2009


Revision: 14278
Author: fschmid
Date: 2009-11-11T05:43:54.965442Z
Commit message: Part of Bug-Nr 4293: "Improved support for gradients", added support for focal point different from center point.

Changeset: 
M  /trunk/Scribus/scribus/scpainter.cpp
M  /trunk/Scribus/scribus/ui/propertiespalette.cpp
M  /trunk/Scribus/scribus/scribusXml.cpp
M  /trunk/Scribus/scribus/pageitem.cpp
M  /trunk/Scribus/scribus/ui/propertiespalette.h
M  /trunk/Scribus/scribus/pageitem.h
M  /trunk/Scribus/scribus/canvasmode_editgradient.cpp
M  /trunk/Scribus/scribus/plugins/xarimplugin/importxar.cpp
M  /trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.cpp
M  /trunk/Scribus/scribus/scribusstructs.h
M  /trunk/Scribus/scribus/canvasmode_editgradient.h
M  /trunk/Scribus/scribus/pdflib_core.cpp
M  /trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
M  /trunk/Scribus/scribus/pslib.cpp
M  /trunk/Scribus/scribus/canvas.cpp
M  /trunk/Scribus/scribus/ui/cpalette.cpp
M  /trunk/Scribus/scribus/ui/cpalette.h
M  /trunk/Scribus/scribus/pageitem_desaxe.cpp
M  /trunk/Scribus/scribus/canvasmode_copyproperties.cpp
M  /trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp

Diffs:
Index: scribus/canvasmode_editgradient.cpp
===================================================================
--- scribus/canvasmode_editgradient.cpp	(revision 14277)
+++ scribus/canvasmode_editgradient.cpp	(revision 14278)
@@ -185,24 +185,102 @@
 			{
 				currItem->GrStrokeStartX -= np.x(); // (Mxp - newX); // / m_canvas->scale();
 				currItem->GrStrokeStartY -= np.y(); // (Myp - newY); // / m_canvas->scale();
+				currItem->GrStrokeFocalX -= np.x();
+				currItem->GrStrokeFocalY -= np.y();
+				if (currItem->GrTypeStroke == 7)
+				{
+					double radEnd = distance(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+					double radFoc = distance(currItem->GrStrokeFocalX - currItem->GrStrokeStartX, currItem->GrStrokeFocalY - currItem->GrStrokeStartY);
+					if (radFoc >= radEnd)
+					{
+						currItem->GrStrokeStartX += np.x(); // (Mxp - newX); // / m_canvas->scale();
+						currItem->GrStrokeStartY += np.y(); // (Myp - newY); // / m_canvas->scale();
+						currItem->GrStrokeFocalX += np.x(); // (Mxp - newX); // / m_canvas->scale();
+						currItem->GrStrokeFocalY += np.y(); // (Myp - newY); // / m_canvas->scale();
+					}
+				}
 			}
+			if (m_gradientPoint == useGradientFocal)
+			{
+				currItem->GrStrokeFocalX -= np.x();
+				currItem->GrStrokeFocalY -= np.y();
+				if (currItem->GrTypeStroke == 7)
+				{
+					double radEnd = distance(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+					double radFoc = distance(currItem->GrStrokeFocalX - currItem->GrStrokeStartX, currItem->GrStrokeFocalY - currItem->GrStrokeStartY);
+					if (radFoc >= radEnd)
+					{
+						currItem->GrStrokeFocalX += np.x(); // (Mxp - newX); // / m_canvas->scale();
+						currItem->GrStrokeFocalY += np.y(); // (Myp - newY); // / m_canvas->scale();
+					}
+				}
+			}
 			if (m_gradientPoint == useGradientEnd)
 			{
 				currItem->GrStrokeEndX -= np.x(); // (Mxp - newX); // / m_canvas->scale();
 				currItem->GrStrokeEndY -= np.y(); // (Myp - newY); // / m_canvas->scale();
+				if (currItem->GrTypeStroke == 7)
+				{
+					double radEnd = distance(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+					double radFoc = distance(currItem->GrStrokeFocalX - currItem->GrStrokeStartX, currItem->GrStrokeFocalY - currItem->GrStrokeStartY);
+					if (radFoc >= radEnd)
+					{
+						currItem->GrStrokeEndX += np.x(); // (Mxp - newX); // / m_canvas->scale();
+						currItem->GrStrokeEndY += np.y(); // (Myp - newY); // / m_canvas->scale();
+					}
+				}
 			}
 		}
 		else
 		{
 			if (m_gradientPoint == useGradientStart)
 			{
-				currItem->GrStartX -= np.x(); // (Mxp - newX); // / m_canvas->scale();
-				currItem->GrStartY -= np.y(); // (Myp - newY); // / m_canvas->scale();
+				currItem->GrStartX -= np.x();
+				currItem->GrStartY -= np.y();
+				currItem->GrFocalX -= np.x();
+				currItem->GrFocalY -= np.y();
+				if (currItem->GrType == 7)
+				{
+					double radEnd = distance(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+					double radFoc = distance(currItem->GrFocalX - currItem->GrStartX, currItem->GrFocalY - currItem->GrStartY);
+					if (radFoc >= radEnd)
+					{
+						currItem->GrStartX += np.x(); // (Mxp - newX); // / m_canvas->scale();
+						currItem->GrStartY += np.y(); // (Myp - newY); // / m_canvas->scale();
+						currItem->GrFocalX += np.x(); // (Mxp - newX); // / m_canvas->scale();
+						currItem->GrFocalY += np.y(); // (Myp - newY); // / m_canvas->scale();
+					}
+				}
 			}
+			if (m_gradientPoint == useGradientFocal)
+			{
+				currItem->GrFocalX -= np.x();
+				currItem->GrFocalY -= np.y();
+				if (currItem->GrType == 7)
+				{
+					double radEnd = distance(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+					double radFoc = distance(currItem->GrFocalX - currItem->GrStartX, currItem->GrFocalY - currItem->GrStartY);
+					if (radFoc >= radEnd)
+					{
+						currItem->GrFocalX += np.x(); // (Mxp - newX); // / m_canvas->scale();
+						currItem->GrFocalY += np.y(); // (Myp - newY); // / m_canvas->scale();
+					}
+				}
+			}
 			if (m_gradientPoint == useGradientEnd)
 			{
-				currItem->GrEndX -= np.x(); // (Mxp - newX); // / m_canvas->scale();
-				currItem->GrEndY -= np.y(); // (Myp - newY); // / m_canvas->scale();
+				currItem->GrEndX -= np.x();
+				currItem->GrEndY -= np.y();
+				if (currItem->GrType == 7)
+				{
+					double radEnd = distance(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+					double radFoc = distance(currItem->GrFocalX - currItem->GrStartX, currItem->GrFocalY - currItem->GrStartY);
+					if (radFoc >= radEnd)
+					{
+						currItem->GrEndX += np.x(); // (Mxp - newX); // / m_canvas->scale();
+						currItem->GrEndY += np.y(); // (Myp - newY); // / m_canvas->scale();
+					}
+				}
 			}
 		}
 		Mxp = newX;
@@ -239,23 +317,28 @@
 	PageItem *currItem = m_doc->m_Selection->itemAt(0);
 	itemMatrix.translate(currItem->xPos(), currItem->yPos());
 	itemMatrix.rotate(currItem->rotation());
-	QPointF gradientStart, gradientEnd;
+	QPointF gradientStart, gradientEnd, gradientFocal;
 	if (m_view->editStrokeGradient)
 	{
 		gradientStart = QPointF(currItem->GrStrokeStartX, currItem->GrStrokeStartY);
 		gradientEnd = QPointF(currItem->GrStrokeEndX, currItem->GrStrokeEndY);
+		gradientFocal = QPointF(currItem->GrStrokeFocalX, currItem->GrStrokeFocalY);
 	}
 	else
 	{
 		gradientStart = QPointF(currItem->GrStartX, currItem->GrStartY);
 		gradientEnd = QPointF(currItem->GrEndX, currItem->GrEndY);
+		gradientFocal = QPointF(currItem->GrFocalX, currItem->GrFocalY);
 	}
 	gradientStart = itemMatrix.map(gradientStart);
 	gradientEnd = itemMatrix.map(gradientEnd);
+	gradientFocal = itemMatrix.map(gradientFocal);
 	if (m_canvas->hitsCanvasPoint(m->globalPos(), gradientStart))
 		m_gradientPoint = useGradientStart;
 	else if (m_canvas->hitsCanvasPoint(m->globalPos(), gradientEnd))
 		m_gradientPoint = useGradientEnd;
+	else if (m_canvas->hitsCanvasPoint(m->globalPos(), gradientFocal))
+		m_gradientPoint = useGradientFocal;
 	m_canvas->m_viewMode.m_MouseButtonPressed = true;
 	qApp->changeOverrideCursor(QCursor(Qt::CrossCursor));
 }
Index: scribus/pdflib_core.cpp
===================================================================
--- scribus/pdflib_core.cpp	(revision 14277)
+++ scribus/pdflib_core.cpp	(revision 14278)
@@ -5796,6 +5796,8 @@
 	double StartY;
 	double EndX;
 	double EndY;
+	double FocalX;
+	double FocalY;
 	int GType;
 	if (stroke)
 	{
@@ -5804,6 +5806,8 @@
 		StartY = currItem->GrStrokeStartY;
 		EndX = currItem->GrStrokeEndX;
 		EndY = currItem->GrStrokeEndY;
+		FocalX = currItem->GrStrokeFocalX;
+		FocalY = currItem->GrStrokeFocalY;
 		gradient = currItem->stroke_gradient;
 	}
 	else
@@ -5813,6 +5817,8 @@
 		StartY = currItem->GrStartY;
 		EndX = currItem->GrEndX;
 		EndY = currItem->GrEndY;
+		FocalX = currItem->GrFocalX;
+		FocalY = currItem->GrFocalY;
 		gradient = currItem->fill_gradient;
 	}
 	QList<VColorStop*> cstops = gradient.colorStops();
@@ -5876,7 +5882,7 @@
 		if (GType == 6)
 			PutDoc("/Coords ["+FToStr(StartX)+" "+FToStr(-StartY)+" "+FToStr(EndX)+" "+FToStr(-EndY)+"]\n");
 		else
-			PutDoc("/Coords ["+FToStr(StartX)+" "+FToStr(-StartY)+" 0.0 "+FToStr(StartX)+" "+FToStr(-StartY)+" "+FToStr(sqrt(pow(EndX - StartX, 2) + pow(EndY - StartY,2)))+"]\n");
+			PutDoc("/Coords ["+FToStr(FocalX)+" "+FToStr(-FocalY)+" 0.0 "+FToStr(StartX)+" "+FToStr(-StartY)+" "+FToStr(sqrt(pow(EndX - StartX, 2) + pow(EndY - StartY,2)))+"]\n");
 		PutDoc("/Function\n");
 		PutDoc("<<\n");
 		PutDoc("/FunctionType 3\n");
@@ -5997,7 +6003,7 @@
 	if (GType == 6)
 		PutDoc("/Coords ["+FToStr(StartX)+" "+FToStr(-StartY)+" "+FToStr(EndX)+" "+FToStr(-EndY)+"]\n");
 	else
-		PutDoc("/Coords ["+FToStr(StartX)+" "+FToStr(-StartY)+" 0.0 "+FToStr(StartX)+" "+FToStr(-StartY)+" "+FToStr(sqrt(pow(EndX - StartX, 2) + pow(EndY - StartY,2)))+"]\n");
+		PutDoc("/Coords ["+FToStr(FocalX)+" "+FToStr(-FocalY)+" 0.0 "+FToStr(StartX)+" "+FToStr(-StartY)+" "+FToStr(sqrt(pow(EndX - StartX, 2) + pow(EndY - StartY,2)))+"]\n");
 	PutDoc("/Function\n");
 	PutDoc("<<\n");
 	PutDoc("/FunctionType 3\n");
Index: scribus/canvasmode_copyproperties.cpp
===================================================================
--- scribus/canvasmode_copyproperties.cpp	(revision 14277)
+++ scribus/canvasmode_copyproperties.cpp	(revision 14278)
@@ -155,7 +155,7 @@
 	SeleItem(m);
 	if (GetItem(&currItem))
 	{
-		double sx, sy, ex, ey, r, skx, sky;
+		double sx, sy, ex, ey, r, skx, sky, fx, fy, ss;
 		currItem->ColGap = m_doc->ElemToLink->ColGap;
 		currItem->Cols = m_doc->ElemToLink->Cols;
 		currItem->BottomLine = m_doc->ElemToLink->BottomLine;
@@ -181,8 +181,8 @@
 		// Gradient Properties
 		currItem->fill_gradient = m_doc->ElemToLink->fill_gradient;
 		currItem->setGradient(m_doc->ElemToLink->gradient());
-		m_doc->ElemToLink->gradientVector(sx, sy, ex, ey);
-		currItem->setGradientVector(sx, sy, ex, ey);
+		m_doc->ElemToLink->gradientVector(sx, sy, ex, ey, fx, fy, ss);
+		currItem->setGradientVector(sx, sy, ex, ey, fx, fy, ss);
 		// Pattern Properties
 		currItem->setPattern(m_doc->ElemToLink->pattern());
 		m_doc->ElemToLink->patternTransform(sx, sy, ex, ey, r, skx, sky);
@@ -195,8 +195,8 @@
 
 		currItem->stroke_gradient = m_doc->ElemToLink->stroke_gradient;
 		currItem->setStrokeGradient(m_doc->ElemToLink->strokeGradient());
-		m_doc->ElemToLink->strokeGradientVector(sx, sy, ex, ey);
-		currItem->setStrokeGradientVector(sx, sy, ex, ey);
+		m_doc->ElemToLink->strokeGradientVector(sx, sy, ex, ey, fx, fy, ss);
+		currItem->setStrokeGradientVector(sx, sy, ex, ey, fx, fy, ss);
 		currItem->setStrokeGradientType(m_doc->ElemToLink->strokeGradientType());
 		// Update Item
 		m_doc->ElemToLink = currItem;
Index: scribus/scribusXml.cpp
===================================================================
--- scribus/scribusXml.cpp	(revision 14277)
+++ scribus/scribusXml.cpp	(revision 14278)
@@ -189,6 +189,9 @@
 			OB->GrEndX   = attrAsDbl(attrs, "GRENDX", 0.0);
 			OB->GrEndY   = attrAsDbl(attrs, "GRENDY", 0.0);
 			OB->GrColor  = attrAsString(attrs, "GRCOLOR", "Black");
+			OB->GrFocalX = attrAsDbl(attrs, "GRFOCALX", 0.0);
+			OB->GrFocalY = attrAsDbl(attrs, "GRFOCALY", 0.0);
+			OB->GrScale  = attrAsDbl(attrs, "GRSCALE", 1.0);
 			if (OB->GrColor.isEmpty())
 				OB->GrColor = "Black";
 			OB->GrColor2 = attrAsString(attrs, "GRCOLOR2","Black");
@@ -206,6 +209,9 @@
 		OB->GrStrokeStartY = attrAsDbl(attrs, "GRSTARTYS", 0.0);
 		OB->GrStrokeEndX   = attrAsDbl(attrs, "GRENDXS", 0.0);
 		OB->GrStrokeEndY   = attrAsDbl(attrs, "GRENDYS", 0.0);
+		OB->GrStrokeFocalX = attrAsDbl(attrs, "GRFOCALXS", 0.0);
+		OB->GrStrokeFocalY = attrAsDbl(attrs, "GRFOCALYS", 0.0);
+		OB->GrStrokeScale  = attrAsDbl(attrs, "GRSCALES", 1.0);
 	}
 	OB->Rot        = attrAsDbl(attrs, "ROT", 0.0);
 	OB->PLineArt   = Qt::PenStyle    ( attrAsInt(attrs, "PLINEART", 0) );
@@ -2361,6 +2367,9 @@
 		writer.writeAttribute("GRSTARTY", item->GrStartY);
 		writer.writeAttribute("GRENDX"  , item->GrEndX);
 		writer.writeAttribute("GRENDY"  , item->GrEndY);
+		writer.writeAttribute("GRFOCALX", item->GrFocalX);
+		writer.writeAttribute("GRFOCALY", item->GrFocalY);
+		writer.writeAttribute("GRSCALE" , item->GrScale);
 	}
 	if (item->GrTypeStroke > 0)
 	{
@@ -2368,6 +2377,9 @@
 		writer.writeAttribute("GRSTARTYS", item->GrStrokeStartY);
 		writer.writeAttribute("GRENDXS"  , item->GrStrokeEndX);
 		writer.writeAttribute("GRENDYS"  , item->GrStrokeEndY);
+		writer.writeAttribute("GRFOCALXS", item->GrStrokeFocalX);
+		writer.writeAttribute("GRFOCALYS", item->GrStrokeFocalY);
+		writer.writeAttribute("GRSCALES" , item->GrStrokeScale);
 	}
 
 	if (item->effectsInUse.count() != 0)
Index: scribus/canvas.cpp
===================================================================
--- scribus/canvas.cpp	(revision 14277)
+++ scribus/canvas.cpp	(revision 14278)
@@ -1167,6 +1167,8 @@
 		psx->setPen(QPen(Qt::magenta, 8.0 / m_viewMode.scale, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
 		psx->drawPoint(QPointF(currItem->GrStrokeStartX, currItem->GrStrokeStartY));
 		psx->drawPoint(QPointF(currItem->GrStrokeEndX, currItem->GrStrokeEndY));
+		if (currItem->GrTypeStroke == 7)
+			psx->drawPoint(QPointF(currItem->GrStrokeFocalX, currItem->GrStrokeFocalY));
 	}
 	else
 	{
@@ -1174,6 +1176,8 @@
 		psx->setPen(QPen(Qt::magenta, 8.0 / m_viewMode.scale, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
 		psx->drawPoint(QPointF(currItem->GrStartX, currItem->GrStartY));
 		psx->drawPoint(QPointF(currItem->GrEndX, currItem->GrEndY));
+		if (currItem->GrType == 7)
+			psx->drawPoint(QPointF(currItem->GrFocalX, currItem->GrFocalY));
 	}
 }
 
Index: scribus/pageitem.h
===================================================================
--- scribus/pageitem.h	(revision 14277)
+++ scribus/pageitem.h	(revision 14278)
@@ -354,6 +354,9 @@
 	double GrStartY;
 	double GrEndX;
 	double GrEndY;
+	double GrFocalX;
+	double GrFocalY;
+	double GrScale;
 	int Cols;
 	double ColGap;
 	double gridOffset_;
@@ -594,13 +597,13 @@
 	// 0=none, 1,2,3,4=linear, 5=radial, 6=free linear, 7=free radial, 8=pattern 
 	int gradientType() const { return GrType; }
 	void setGradientType(int val) { GrType = val; }
-	void gradientVector(double& startX, double& startY, double& endX, double& endY) const;
-	void setGradientVector(double startX, double startY, double endX, double endY);
+	void gradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale) const;
+	void setGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale);
 
 	int strokeGradientType() const { return GrTypeStroke; }
 	void setStrokeGradientType(int val) { GrTypeStroke = val; }
-	void strokeGradientVector(double& startX, double& startY, double& endX, double& endY) const;
-	void setStrokeGradientVector(double startX, double startY, double endX, double endY);
+	void strokeGradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale) const;
+	void setStrokeGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale);
 	// 
 	bool fillEvenOdd() const { return fillRule; }
 	void setFillEvenOdd(bool val) { fillRule = val; }
@@ -1377,6 +1380,9 @@
 	double GrStrokeStartY;
 	double GrStrokeEndX;
 	double GrStrokeEndY;
+	double GrStrokeFocalX;
+	double GrStrokeFocalY;
+	double GrStrokeScale;
 
 	/** Inline Image */
 	bool isInlineImage;
Index: scribus/scribusstructs.h
===================================================================
--- scribus/scribusstructs.h	(revision 14277)
+++ scribus/scribusstructs.h	(revision 14278)
@@ -89,12 +89,18 @@
 	double GrStartY;
 	double GrEndX;
 	double GrEndY;
+	double GrFocalX;
+	double GrFocalY;
+	double GrScale;
 	VGradient stroke_gradient;
 	int GrTypeStroke;
 	double GrStrokeStartX;
 	double GrStrokeStartY;
 	double GrStrokeEndX;
 	double GrStrokeEndY;
+	double GrStrokeFocalX;
+	double GrStrokeFocalY;
+	double GrStrokeScale;
 	QString TxtStroke;
 	QString TxtFill;
 	int ShTxtStroke;
Index: scribus/scpainter.cpp
===================================================================
--- scribus/scpainter.cpp	(revision 14277)
+++ scribus/scpainter.cpp	(revision 14278)
@@ -1013,10 +1013,12 @@
 			double y1 = fill_gradient.origin().y();
 			double x2 = fill_gradient.vector().x();
 			double y2 = fill_gradient.vector().y();
+			double fx = fill_gradient.focalPoint().x();
+			double fy = fill_gradient.focalPoint().y();
 			if (fill_gradient.type() == VGradient::linear)
 				pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
 			else
-				pat = cairo_pattern_create_radial (x1, y1, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
+				pat = cairo_pattern_create_radial (fx, fy, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
 			QList<VColorStop*> colorStops = fill_gradient.colorStops();
 			QColor qStopColor;
 			for( int offset = 0 ; offset < colorStops.count() ; offset++ )
@@ -1129,10 +1131,12 @@
 			double y1 = stroke_gradient.origin().y();
 			double x2 = stroke_gradient.vector().x();
 			double y2 = stroke_gradient.vector().y();
+			double fx = stroke_gradient.focalPoint().x();
+			double fy = stroke_gradient.focalPoint().y();
 			if (stroke_gradient.type() == VGradient::linear)
 				pat = cairo_pattern_create_linear (x1, y1,  x2, y2);
 			else
-				pat = cairo_pattern_create_radial (x1, y1, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
+				pat = cairo_pattern_create_radial (fx, fy, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
 			QList<VColorStop*> colorStops = stroke_gradient.colorStops();
 			QColor qStopColor;
 			for( int offset = 0 ; offset < colorStops.count() ; offset++ )
@@ -1189,10 +1193,12 @@
 			double y1 = fill_gradient.origin().y();
 			double x2 = fill_gradient.vector().x();
 			double y2 = fill_gradient.vector().y();
+			double fx = fill_gradient.focalPoint().x();
+			double fy = fill_gradient.focalPoint().y();
 			if (fill_gradient.type() == VGradient::linear)
 				pat = QLinearGradient(x1, y1,  x2, y2);
 			else
-				pat = QRadialGradient(x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)), x1, y1);
+				pat = QRadialGradient(x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)), fx, fy);
 			QList<VColorStop*> colorStops = fill_gradient.colorStops();
 			QColor qStopColor;
 			for( int offset = 0 ; offset < colorStops.count() ; offset++ )
@@ -1295,10 +1301,12 @@
 			double y1 = stroke_gradient.origin().y();
 			double x2 = stroke_gradient.vector().x();
 			double y2 = stroke_gradient.vector().y();
+			double fx = stroke_gradient.focalPoint().x();
+			double fy = stroke_gradient.focalPoint().y();
 			if (stroke_gradient.type() == VGradient::linear)
 				pat = QLinearGradient(x1, y1,  x2, y2);
 			else
-				pat = QRadialGradient(x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)), x1, y1);
+				pat = QRadialGradient(x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)), fx, fy);
 			QList<VColorStop*> colorStops = stroke_gradient.colorStops();
 			QColor qStopColor;
 			for( int offset = 0 ; offset < colorStops.count() ; offset++ )
Index: scribus/pageitem.cpp
===================================================================
--- scribus/pageitem.cpp	(revision 14277)
+++ scribus/pageitem.cpp	(revision 14278)
@@ -89,6 +89,9 @@
 	GrStartY(other.GrStartY),
 	GrEndX(other.GrEndX),
 	GrEndY(other.GrEndY),
+	GrFocalX(other.GrFocalX),
+	GrFocalY(other.GrFocalY),
+	GrScale(other.GrScale),
 	Cols(other.Cols),
 	ColGap(other.ColGap),
 	PLineArt(other.PLineArt),
@@ -261,7 +264,10 @@
 	GrStrokeStartX(other.GrStrokeStartX),
 	GrStrokeStartY(other.GrStrokeStartY),
 	GrStrokeEndX(other.GrStrokeEndX),
-	GrStrokeEndY(other.GrStrokeEndY)
+	GrStrokeEndY(other.GrStrokeEndY),
+	GrStrokeFocalX(other.GrStrokeFocalX),
+	GrStrokeFocalY(other.GrStrokeFocalY),
+	GrStrokeScale(other.GrStrokeScale)
 {
 	QString tmp;
 	m_Doc->TotalItems++;
@@ -330,12 +336,18 @@
 	GrStartY = 0;
 	GrEndX = w;
 	GrEndY = 0;
+	GrFocalX = 0;
+	GrFocalY = 0;
+	GrScale = 1;
 	gradientVal = "";
 	GrTypeStroke = 0;
 	GrStrokeStartX = 0;
 	GrStrokeStartY = 0;
 	GrStrokeEndX = w;
 	GrStrokeEndY = 0;
+	GrStrokeFocalX = 0;
+	GrStrokeFocalY = 0;
+	GrStrokeScale = 1;
 	gradientStrokeVal = "";
 	patternVal = "";
 	patternScaleX = 100;
@@ -1148,9 +1160,6 @@
 				{
 					p->setFillMode(ScPainter::Gradient);
 					p->fill_gradient = fill_gradient;
-					QTransform grm;
-					grm.rotate(Rot);
-					FPointArray gra;
 					switch (GrType)
 					{
 						case 1:
@@ -1162,8 +1171,7 @@
 							break;
 						case 5:
 						case 7:
-							gra.setPoints(2, GrStartX, GrStartY, GrEndX, GrEndY);
-							p->setGradient(VGradient::radial, gra.point(0), gra.point(1), gra.point(0));
+							p->setGradient(VGradient::radial, FPoint(GrStartX, GrStartY), FPoint(GrEndX, GrEndY), FPoint(GrFocalX, GrFocalY));
 							break;
 					}
 				}
@@ -1284,16 +1292,10 @@
 							{
 								p->setStrokeMode(ScPainter::Gradient);
 								p->stroke_gradient = stroke_gradient;
-								QTransform grm;
-								grm.rotate(Rot);
-								FPointArray gra;
 								if (GrTypeStroke == 6)
 									p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY));
 								else
-								{
-									gra.setPoints(2, GrStrokeStartX, GrStrokeStartY, GrStrokeEndX, GrStrokeEndY);
-									p->setGradient(VGradient::radial, gra.point(0), gra.point(1), gra.point(0));
-								}
+									p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY));
 							}
 							p->strokePath();
 						}
@@ -2368,20 +2370,26 @@
 		patternVal = newPattern;
 }
 
-void PageItem::gradientVector(double& startX, double& startY, double& endX, double& endY) const
+void PageItem::gradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale) const
 {
 	startX = GrStartX;
 	startY = GrStartY;
 	endX   = GrEndX;
 	endY   = GrEndY;
+	focalX = GrFocalX;
+	focalY = GrFocalY;
+	scale  = GrScale;
 }
 
-void PageItem::setGradientVector(double startX, double startY, double endX, double endY)
+void PageItem::setGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale)
 {
 	GrStartX = startX;
 	GrStartY = startY;
 	GrEndX   = endX;
 	GrEndY   = endY;
+	GrFocalX = focalX;
+	GrFocalY = focalY;
+	GrScale  = scale;
 }
 
 void PageItem::setStrokeGradient(const QString &newGradient)
@@ -2390,20 +2398,26 @@
 		gradientStrokeVal = newGradient;
 }
 
-void PageItem::strokeGradientVector(double& startX, double& startY, double& endX, double& endY) const
+void PageItem::strokeGradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale) const
 {
 	startX = GrStrokeStartX;
 	startY = GrStrokeStartY;
 	endX   = GrStrokeEndX;
 	endY   = GrStrokeEndY;
+	focalX = GrStrokeFocalX;
+	focalY = GrStrokeFocalY;
+	scale  = GrStrokeScale;
 }
 
-void PageItem::setStrokeGradientVector(double startX, double startY, double endX, double endY)
+void PageItem::setStrokeGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale)
 {
 	GrStrokeStartX = startX;
 	GrStrokeStartY = startY;
 	GrStrokeEndX   = endX;
 	GrStrokeEndY   = endY;
+	GrStrokeFocalX = focalX;
+	GrStrokeFocalY = focalY;
+	GrStrokeScale  = scale;
 }
 
 void PageItem::setPatternTransform(double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY)
@@ -4264,6 +4278,9 @@
 	Buffer->GrStartY = GrStartY;
 	Buffer->GrEndX = GrEndX;
 	Buffer->GrEndY = GrEndY;
+	Buffer->GrFocalX = GrFocalX;
+	Buffer->GrFocalY = GrFocalY;
+	Buffer->GrScale = GrScale;
 	Buffer->Rot = Rot;
 	Buffer->PLineArt = PLineArt;
 	Buffer->PLineEnd = PLineEnd;
@@ -5230,16 +5247,10 @@
 				{
 					p->setFillMode(ScPainter::Gradient);
 					p->fill_gradient = stroke_gradient;
-					QTransform grm;
-					grm.rotate(Rot);
-					FPointArray gra;
 					if (GrTypeStroke == 6)
 						p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY));
 					else
-					{
-						gra.setPoints(2, GrStrokeStartX, GrStrokeStartY, GrStrokeEndX, GrStrokeEndY);
-						p->setGradient(VGradient::radial, gra.point(0), gra.point(1), gra.point(0));
-					}
+						p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY));
 				}
 				p->fillPath();
 			}
@@ -5759,19 +5770,25 @@
 				FPointArray gr;
 				gr.addPoint(GrStartX, GrStartY);
 				gr.addPoint(GrEndX, GrEndY);
+				gr.addPoint(GrFocalX, GrFocalY);
 				gr.map(ma);
 				GrStartX = gr.point(0).x();
 				GrStartY = gr.point(0).y();
 				GrEndX = gr.point(1).x();
 				GrEndY = gr.point(1).y();
+				GrFocalX = gr.point(2).x();
+				GrFocalY = gr.point(2).y();
 				FPointArray gr2;
 				gr2.addPoint(GrStrokeStartX, GrStrokeStartY);
 				gr2.addPoint(GrStrokeEndX, GrStrokeEndY);
+				gr2.addPoint(GrStrokeFocalX, GrStrokeFocalY);
 				gr2.map(ma);
 				GrStrokeStartX = gr2.point(0).x();
 				GrStrokeStartY = gr2.point(0).y();
 				GrStrokeEndX = gr2.point(1).x();
 				GrStrokeEndY = gr2.point(1).y();
+				GrStrokeFocalX = gr2.point(2).x();
+				GrStrokeFocalY = gr2.point(2).y();
 				ContourLine.map(ma);
 				if (FrameType > 2)
 				{
@@ -5819,19 +5836,25 @@
 			FPointArray gr;
 			gr.addPoint(GrStartX, GrStartY);
 			gr.addPoint(GrEndX, GrEndY);
+			gr.addPoint(GrFocalX, GrFocalY);
 			gr.map(ma);
 			GrStartX = gr.point(0).x();
 			GrStartY = gr.point(0).y();
 			GrEndX = gr.point(1).x();
 			GrEndY = gr.point(1).y();
+			GrFocalX = gr.point(2).x();
+			GrFocalY = gr.point(2).y();
 			FPointArray gr2;
 			gr2.addPoint(GrStrokeStartX, GrStrokeStartY);
 			gr2.addPoint(GrStrokeEndX, GrStrokeEndY);
+			gr2.addPoint(GrStrokeFocalX, GrStrokeFocalY);
 			gr2.map(ma);
 			GrStrokeStartX = gr2.point(0).x();
 			GrStrokeStartY = gr2.point(0).y();
 			GrStrokeEndX = gr2.point(1).x();
 			GrStrokeEndY = gr2.point(1).y();
+			GrStrokeFocalX = gr2.point(2).x();
+			GrStrokeFocalY = gr2.point(2).y();
 			PoLine.map(ma);
 			ContourLine.map(ma);
 			if (asPathText())
Index: scribus/ui/cpalette.cpp
===================================================================
--- scribus/ui/cpalette.cpp	(revision 14277)
+++ scribus/ui/cpalette.cpp	(revision 14278)
@@ -69,23 +69,33 @@
 	GTextX1 = new QLabel("X1:", this );
 	freeGradientLayout->addWidget( GTextX1, 0, 0 );
 	GTextY1 = new QLabel("Y1:", this );
-	freeGradientLayout->addWidget( GTextY1, 1, 0 );
+	freeGradientLayout->addWidget( GTextY1, 0, 2 );
 	gX1 = new ScrSpinBox( -3000, 3000, this, 0);
 	freeGradientLayout->addWidget( gX1, 0, 1 );
 	gY1 = new ScrSpinBox( -3000, 3000, this, 0);
-	freeGradientLayout->addWidget( gY1, 1, 1 );
+	freeGradientLayout->addWidget( gY1, 0, 3 );
 	GTextX2 = new QLabel("X2:", this );
-	freeGradientLayout->addWidget( GTextX2, 0, 2 );
+	freeGradientLayout->addWidget( GTextX2, 1, 0 );
 	GTextY2 = new QLabel("Y2:", this );
 	freeGradientLayout->addWidget( GTextY2, 1, 2 );
 	gX2 = new ScrSpinBox( -3000, 3000, this, 0);
-	freeGradientLayout->addWidget( gX2, 0, 3 );
+	freeGradientLayout->addWidget( gX2, 1, 1 );
 	gY2 = new ScrSpinBox( -3000, 3000, this, 0);
 	freeGradientLayout->addWidget( gY2, 1, 3 );
+	GTextFX = new QLabel("FX:", this );
+	freeGradientLayout->addWidget( GTextFX, 2, 0 );
+	GTextFY = new QLabel("FY:", this );
+	freeGradientLayout->addWidget( GTextFY, 2, 2 );
+	gFX = new ScrSpinBox( -3000, 3000, this, 0);
+	freeGradientLayout->addWidget( gFX, 2, 1 );
+	gFY = new ScrSpinBox( -3000, 3000, this, 0);
+	freeGradientLayout->addWidget( gFY, 2, 3 );
 	connect(gX1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gX2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gY1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gY2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	connect(gFX, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	connect(gFY, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	languageChange();
 }
 
@@ -99,31 +109,55 @@
 		QWidget::changeEvent(e);
 }
 
+void GradientVectorDialog::hideExtraWidgets()
+{
+	GTextFX->hide();
+	GTextFY->hide();
+	gFX->hide();
+	gFY->hide();
+	resize(minimumSizeHint());
+}
+
+void GradientVectorDialog::showExtraWidgets()
+{
+	GTextFX->show();
+	GTextFY->show();
+	gFX->show();
+	gFY->show();
+	resize(minimumSizeHint());
+}
+
 void GradientVectorDialog::languageChange()
 {
 	setWindowTitle( tr( "Gradient Vector" ));
 	resize(minimumSizeHint());
 }
 
-void GradientVectorDialog::setValues(double x1, double y1, double x2, double y2)
+void GradientVectorDialog::setValues(double x1, double y1, double x2, double y2, double fx, double fy, double sg)
 {
 	disconnect(gX1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	disconnect(gX2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	disconnect(gY1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	disconnect(gY2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	disconnect(gFX, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	disconnect(gFY, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	gX1->setValue(x1);
 	gX2->setValue(x2);
 	gY1->setValue(y1);
 	gY2->setValue(y2);
+	gFX->setValue(fx);
+	gFY->setValue(fy);
 	connect(gX1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gX2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gY1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gY2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	connect(gFX, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	connect(gFY, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 }
 
 void GradientVectorDialog::changeSpecial()
 {
-	emit NewSpecial(gX1->value(), gY1->value(), gX2->value(), gY2->value());
+	emit NewSpecial(gX1->value(), gY1->value(), gX2->value(), gY2->value(), gFX->value(), gFY->value(), 1.0);
 }
 
 void GradientVectorDialog::unitChange(int unitIndex)
@@ -132,14 +166,20 @@
 	disconnect(gX2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	disconnect(gY1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	disconnect(gY2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	disconnect(gFX, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	disconnect(gFY, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	gX1->setNewUnit(unitIndex);
 	gY1->setNewUnit(unitIndex);
 	gX2->setNewUnit(unitIndex);
 	gY2->setNewUnit(unitIndex);
+	gFX->setNewUnit(unitIndex);
+	gFY->setNewUnit(unitIndex);
 	connect(gX1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gX2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gY1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	connect(gY2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	connect(gFX, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	connect(gFY, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 }
 
 PatternPropsDialog::PatternPropsDialog(QWidget* parent, int unitIndex) : QDialog( parent )
@@ -365,7 +405,7 @@
 	connect(gradEditButton, SIGNAL(clicked()), this, SLOT(editGradientVector()));
 	connect(displayAllColors, SIGNAL(clicked()), this, SLOT(ToggleColorDisplay()));
 	connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(slotGrad(int)));
-	connect(CGradDia, SIGNAL(NewSpecial(double, double, double, double)), this, SIGNAL(NewSpecial(double, double, double, double)));
+	connect(CGradDia, SIGNAL(NewSpecial(double, double, double, double, double, double, double)), this, SIGNAL(NewSpecial(double, double, double, double, double, double, double)));
 	connect(CGradDia, SIGNAL(paletteShown(bool)), this, SLOT(setActiveGradDia(bool)));
 	connect(gradientType, SIGNAL(activated(int)), this, SLOT(slotGradType(int)));
 	connect(gradEdit, SIGNAL(gradientChanged()), this, SIGNAL(gradientChanged()));
@@ -933,7 +973,11 @@
 	if (gradEditButton->isChecked())
 	{
 		CGradDia->unitChange(currentDoc->unitIndex());
-		CGradDia->setValues(currentItem->GrStartX, currentItem->GrStartY, currentItem->GrEndX, currentItem->GrEndY);
+		CGradDia->setValues(currentItem->GrStartX, currentItem->GrStartY, currentItem->GrEndX, currentItem->GrEndY, currentItem->GrFocalX, currentItem->GrFocalY, currentItem->GrScale);
+		if (currentItem->GrType == 6)
+			CGradDia->hideExtraWidgets();
+		else
+			CGradDia->showExtraWidgets();
 		CGradDia->show();
 	}
 	else
@@ -949,7 +993,11 @@
 	if (gradEditButtonStroke->isChecked())
 	{
 		CGradDia->unitChange(currentDoc->unitIndex());
-		CGradDia->setValues(currentItem->GrStrokeStartX, currentItem->GrStrokeStartY, currentItem->GrStrokeEndX, currentItem->GrStrokeEndY);
+		CGradDia->setValues(currentItem->GrStrokeStartX, currentItem->GrStrokeStartY, currentItem->GrStrokeEndX, currentItem->GrStrokeEndY, currentItem->GrStrokeFocalX, currentItem->GrStrokeFocalY, currentItem->GrStrokeScale);
+		if (currentItem->GrTypeStroke == 6)
+			CGradDia->hideExtraWidgets();
+		else
+			CGradDia->showExtraWidgets();
 		CGradDia->show();
 	}
 	else
@@ -972,10 +1020,10 @@
 	}
 }
 
-void Cpalette::setSpecialGradient(double x1, double y1, double x2, double y2)
+void Cpalette::setSpecialGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg)
 {
 	if (CGradDia)
-		CGradDia->setValues(x1, y1, x2, y2);
+		CGradDia->setValues(x1, y1, x2, y2, fx, fy, sg);
 }
 
 void Cpalette::changePatternProps()
Index: scribus/ui/cpalette.h
===================================================================
--- scribus/ui/cpalette.h	(revision 14277)
+++ scribus/ui/cpalette.h	(revision 14278)
@@ -54,15 +54,17 @@
 	GradientVectorDialog( QWidget* parent);
 	~GradientVectorDialog() {};
 	virtual void changeEvent(QEvent *e);
+	void hideExtraWidgets();
+	void showExtraWidgets();
 
 public slots:
 	void languageChange();
-	void setValues(double x1, double y1, double x2, double y2);
+	void setValues(double x1, double y1, double x2, double y2, double fx, double fy, double sg);
 	void changeSpecial();
 	void unitChange(int unitIndex);
 
 signals:
-	void NewSpecial(double, double, double, double);
+	void NewSpecial(double, double, double, double, double, double, double);
 
 protected:
 	QGridLayout* freeGradientLayout;
@@ -70,10 +72,14 @@
 	QLabel* GTextY1;
 	QLabel* GTextX2;
 	QLabel* GTextY2;
+	QLabel* GTextFX;
+	QLabel* GTextFY;
 	ScrSpinBox* gY1;
 	ScrSpinBox* gX2;
 	ScrSpinBox* gX1;
 	ScrSpinBox* gY2;
+	ScrSpinBox* gFX;
+	ScrSpinBox* gFY;
 };
 
 class SCRIBUS_API PatternPropsDialog : public QDialog
@@ -177,7 +183,7 @@
 	void editGradientVector();
 	void editGradientVectorStroke();
 	void setActiveGradDia(bool active);
-	void setSpecialGradient(double x1, double y1, double x2, double y2);
+	void setSpecialGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg);
 	void changePatternProps();
 	void changePatternPropsStroke();
 	void unitChange(double, double, int unitIndex);
@@ -192,7 +198,7 @@
 	void NewPatternProps(double, double, double, double, double, double, double, bool, bool);
 	void NewPatternS(QString);
 	void NewPatternPropsS(double, double, double, double, double, double, double, bool, bool);
-	void NewSpecial(double, double, double, double);
+	void NewSpecial(double, double, double, double, double, double, double);
 	void NewTrans(double);
 	void NewTransS(double);
 	void NewBlend(int);
Index: scribus/ui/propertiespalette.h
===================================================================
--- scribus/ui/propertiespalette.h	(revision 14277)
+++ scribus/ui/propertiespalette.h	(revision 14278)
@@ -289,7 +289,7 @@
 	void DoFlow();
 	void MakeIrre(int f, int c, qreal *vals);
 	void NewTDist();
-	void NewSpGradient(double x1, double y1, double x2, double y2);
+	void NewSpGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg);
 	void toggleGradientEdit(bool);
 	void DoRevert();
 	void doClearCStyle();
Index: scribus/ui/propertiespalette.cpp
===================================================================
--- scribus/ui/propertiespalette.cpp	(revision 14277)
+++ scribus/ui/propertiespalette.cpp	(revision 14278)
@@ -1588,7 +1588,7 @@
 	connect( BottomLine, SIGNAL( clicked() ), this, SLOT( HandleTLines() ) );
 //	connect( colgapLabel, SIGNAL( clicked() ), this, SLOT( HandleGapSwitch() ) );
 	connect(colgapLabel, SIGNAL(activated(int)), this, SLOT(HandleGapSwitch()));
-	connect( Cpal, SIGNAL(NewSpecial(double, double, double, double )), this, SLOT(NewSpGradient(double, double, double, double )));
+	connect( Cpal, SIGNAL(NewSpecial(double, double, double, double, double, double, double)), this, SLOT(NewSpGradient(double, double, double, double, double, double, double )));
 	connect( Cpal, SIGNAL(editGradient(bool)), this, SLOT(toggleGradientEdit(bool)));
 	connect(startArrow, SIGNAL(activated(int)), this, SLOT(setStartArrow(int )));
 	connect(endArrow, SIGNAL(activated(int)), this, SLOT(setEndArrow(int )));
@@ -4587,7 +4587,7 @@
 	}
 }
 
-void PropertiesPalette::NewSpGradient(double x1, double y1, double x2, double y2)
+void PropertiesPalette::NewSpGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg)
 {
 	if (!m_ScMW || m_ScMW->ScriptRunning)
 		return;
@@ -4600,6 +4600,14 @@
 			CurItem->GrStrokeStartY = y1 / m_unitRatio;
 			CurItem->GrStrokeEndX = x2 / m_unitRatio;
 			CurItem->GrStrokeEndY = y2 / m_unitRatio;
+			CurItem->GrStrokeFocalX = fx / m_unitRatio;
+			CurItem->GrStrokeFocalY = fy / m_unitRatio;
+			CurItem->GrStrokeScale = sg / m_unitRatio;
+			if (CurItem->GrTypeStroke == 6)
+			{
+				CurItem->GrStrokeFocalX = CurItem->GrStrokeStartX;
+				CurItem->GrStrokeFocalY = CurItem->GrStrokeStartY;
+			}
 			CurItem->update();
 			upRect = QRectF(QPointF(CurItem->GrStrokeStartX, CurItem->GrStrokeStartY), QPointF(CurItem->GrStrokeEndX, CurItem->GrStrokeEndY));
 		}
@@ -4609,6 +4617,14 @@
 			CurItem->GrStartY = y1 / m_unitRatio;
 			CurItem->GrEndX = x2 / m_unitRatio;
 			CurItem->GrEndY = y2 / m_unitRatio;
+			CurItem->GrFocalX = fx / m_unitRatio;
+			CurItem->GrFocalY = fy / m_unitRatio;
+			CurItem->GrScale = sg / m_unitRatio;
+			if (CurItem->GrTypeStroke == 6)
+			{
+				CurItem->GrFocalX = CurItem->GrStartX;
+				CurItem->GrFocalY = CurItem->GrStartY;
+			}
 			CurItem->update();
 			upRect = QRectF(QPointF(CurItem->GrStartX, CurItem->GrStartY), QPointF(CurItem->GrEndX, CurItem->GrEndY));
 		}
@@ -5622,7 +5638,7 @@
 	double dur=doc->unitRatio();
 	PageItem *currItem=doc->m_Selection->itemAt(0);
 	if (currItem)
-		Cpal->setSpecialGradient(currItem->GrStartX * dur, currItem->GrStartY * dur, currItem->GrEndX * dur, currItem->GrEndY * dur);
+		Cpal->setSpecialGradient(currItem->GrStartX * dur, currItem->GrStartY * dur, currItem->GrEndX * dur, currItem->GrEndY * dur, currItem->GrFocalX * dur, currItem->GrFocalY * dur, currItem->GrScale);
 }
 
 void PropertiesPalette::updateSpinBoxConstants()
Index: scribus/plugins/xarimplugin/importxar.cpp
===================================================================
--- scribus/plugins/xarimplugin/importxar.cpp	(revision 14277)
+++ scribus/plugins/xarimplugin/importxar.cpp	(revision 14278)
@@ -1379,7 +1379,7 @@
 			{
 				item->GrType = gc->FillGradientType;
 				item->fill_gradient = gc->FillGradient;
-				item->setGradientVector(gc->GradFillX1 - item->xPos(), gc->GradFillY1 - item->yPos(), gc->GradFillX2 - item->xPos(), gc->GradFillY2 - item->yPos());
+				item->setGradientVector(gc->GradFillX1 - item->xPos(), gc->GradFillY1 - item->yPos(), gc->GradFillX2 - item->xPos(), gc->GradFillY2 - item->yPos(), gc->GradFillX1 - item->xPos(), gc->GradFillY1 - item->yPos(), 1.0);
 			}
 		}
 	}
Index: scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(revision 14277)
+++ scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(revision 14278)
@@ -1189,6 +1189,9 @@
 				docu.writeAttribute("GRSTARTY", item->GrStartY);
 				docu.writeAttribute("GRENDX", item->GrEndX);
 				docu.writeAttribute("GRENDY", item->GrEndY);
+				docu.writeAttribute("GRFOCALX", item->GrFocalX);
+				docu.writeAttribute("GRFOCALY", item->GrFocalY);
+				docu.writeAttribute("GRSCALE" , item->GrScale);
 			}
 		}
 		if (!item->gradient().isEmpty())
@@ -1201,6 +1204,9 @@
 			docu.writeAttribute("GRSTARTYS", item->GrStrokeStartY);
 			docu.writeAttribute("GRENDXS", item->GrStrokeEndX);
 			docu.writeAttribute("GRENDYS", item->GrStrokeEndY);
+			docu.writeAttribute("GRFOCALXS", item->GrStrokeFocalX);
+			docu.writeAttribute("GRFOCALYS", item->GrStrokeFocalY);
+			docu.writeAttribute("GRSCALES" , item->GrStrokeScale);
 		}
 		if (!item->strokePattern().isEmpty())
 		{
Index: scribus/plugins/fileloader/scribus150format/scribus150format.cpp
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(revision 14277)
+++ scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(revision 14278)
@@ -2774,6 +2774,9 @@
 			currItem->GrStartY = attrs.valueAsDouble("GRSTARTY", 0.0);
 			currItem->GrEndX   = attrs.valueAsDouble("GRENDX", 0.0);
 			currItem->GrEndY   = attrs.valueAsDouble("GRENDY", 0.0);
+			currItem->GrFocalX = attrs.valueAsDouble("GRFOCALX", 0.0);
+			currItem->GrFocalY = attrs.valueAsDouble("GRFOCALY", 0.0);
+			currItem->GrScale  = attrs.valueAsDouble("GRSCALE", 1.0);
 			GrColor = attrs.valueAsString("GRCOLOR","");
 			if (!GrColor.isEmpty())
 			{
@@ -2831,6 +2834,9 @@
 	currItem->GrStrokeStartY = attrs.valueAsDouble("GRSTARTYS", 0.0);
 	currItem->GrStrokeEndX   = attrs.valueAsDouble("GRENDXS", 0.0);
 	currItem->GrStrokeEndY   = attrs.valueAsDouble("GRENDYS", 0.0);
+	currItem->GrStrokeFocalX = attrs.valueAsDouble("GRFOCALXS", 0.0);
+	currItem->GrStrokeFocalY = attrs.valueAsDouble("GRFOCALYS", 0.0);
+	currItem->GrStrokeScale  = attrs.valueAsDouble("GRSCALES", 1.0);
 	QString GrNameS = "";
 	GrNameS = attrs.valueAsString("GRNAMES","");
 	if (!GrNameS.isEmpty())
Index: scribus/plugins/svgexplugin/svgexplugin.cpp
===================================================================
--- scribus/plugins/svgexplugin/svgexplugin.cpp	(revision 14277)
+++ scribus/plugins/svgexplugin/svgexplugin.cpp	(revision 14278)
@@ -1584,56 +1584,25 @@
 			}
 			else
 			{
-				if ((Item->GrType == 5) || (Item->GrType == 7))
-					grad = docu.createElement("radialGradient");
-				else
+				if (Item->GrType == 6)
+				{
 					grad = docu.createElement("linearGradient");
-				grad.setAttribute("id", "Grad"+IToStr(GradCount));
-				grad.setAttribute("gradientUnits", "userSpaceOnUse");
-				switch (Item->GrType)
+					grad.setAttribute("x1", FToStr(Item->GrStartX));
+					grad.setAttribute("y1", FToStr(Item->GrStartY));
+					grad.setAttribute("x2", FToStr(Item->GrEndX));
+					grad.setAttribute("y2", FToStr(Item->GrEndY));
+				}
+				else
 				{
-					case 1:
-						grad.setAttribute("x1", "0");
-						grad.setAttribute("y1", FToStr(Item->height() / 2.0));
-						grad.setAttribute("x2", FToStr(Item->width()));
-						grad.setAttribute("y2", FToStr(Item->height() / 2.0));
-						break;
-					case 2:
-						grad.setAttribute("x1", FToStr(Item->width()/ 2.0));
-						grad.setAttribute("y1", "0");
-						grad.setAttribute("x2", FToStr(Item->width()/ 2.0));
-						grad.setAttribute("y2", FToStr(Item->height()));
-						break;
-					case 3:
-						grad.setAttribute("x1", "0");
-						grad.setAttribute("y1", "0");
-						grad.setAttribute("x2", FToStr(Item->width()));
-						grad.setAttribute("y2", FToStr(Item->height()));
-						break;
-					case 4:
-						grad.setAttribute("x1", "0");
-						grad.setAttribute("y1", FToStr(Item->height()));
-						grad.setAttribute("x2", FToStr(Item->width()));
-						grad.setAttribute("y2", "0");
-						break;
-					case 5:
-						grad.setAttribute("r", FToStr(qMax(Item->width() / 2.0, Item->height() / 2.0)));
-						grad.setAttribute("cx", FToStr(Item->width() / 2.0));
-						grad.setAttribute("cy", FToStr(Item->height() / 2.0));
-						break;
-					case 6:
-						grad.setAttribute("x1", FToStr(Item->GrStartX));
-						grad.setAttribute("y1", FToStr(Item->GrStartY));
-						grad.setAttribute("x2", FToStr(Item->GrEndX));
-						grad.setAttribute("y2", FToStr(Item->GrEndY));
-						break;
-					case 7:
-						grad.setAttribute("r", FToStr(sqrt(pow(Item->GrEndX - Item->GrStartX, 2) + pow(Item->GrEndY - Item->GrStartY,2))));
-						grad.setAttribute("r", FToStr(qMax(Item->width() / 2.0, Item->height() / 2.0)));
-						grad.setAttribute("cx", FToStr(Item->GrStartX));
-						grad.setAttribute("cy", FToStr(Item->GrStartY));
-						break;
+					grad = docu.createElement("radialGradient");
+					grad.setAttribute("r", FToStr(sqrt(pow(Item->GrEndX - Item->GrStartX, 2) + pow(Item->GrEndY - Item->GrStartY,2))));
+					grad.setAttribute("cx", FToStr(Item->GrStartX));
+					grad.setAttribute("cy", FToStr(Item->GrStartY));
+					grad.setAttribute("fx", FToStr(Item->GrFocalX));
+					grad.setAttribute("fy", FToStr(Item->GrFocalY));
 				}
+				grad.setAttribute("id", "Grad"+IToStr(GradCount));
+				grad.setAttribute("gradientUnits", "userSpaceOnUse");
 				QList<VColorStop*> cstops = Item->fill_gradient.colorStops();
 				for (uint cst = 0; cst < Item->fill_gradient.Stops(); ++cst)
 				{
@@ -1848,6 +1817,8 @@
 			grad.setAttribute("r", FToStr(sqrt(pow(Item->GrStrokeEndX - Item->GrStrokeStartX, 2) + pow(Item->GrStrokeEndY - Item->GrStrokeStartY,2))));
 			grad.setAttribute("cx", FToStr(Item->GrStrokeStartX));
 			grad.setAttribute("cy", FToStr(Item->GrStrokeStartY));
+			grad.setAttribute("fx", FToStr(Item->GrStrokeFocalX));
+			grad.setAttribute("fy", FToStr(Item->GrStrokeFocalY));
 		}
 		else
 		{
Index: scribus/pslib.cpp
===================================================================
--- scribus/pslib.cpp	(revision 14277)
+++ scribus/pslib.cpp	(revision 14278)
@@ -3459,7 +3459,7 @@
 
 void PSLib::HandleGradientFillStroke(PageItem *c, bool gcr, bool stroke, bool forArrow)
 {
-	double StartX, StartY, EndX, EndY;
+	double StartX, StartY, EndX, EndY, FocalX, FocalY;
 	int GType;
 	VGradient gradient;
 	QList<double> StopVec;
@@ -3473,6 +3473,8 @@
 		StartY = c->GrStrokeStartY;
 		EndX = c->GrStrokeEndX;
 		EndY = c->GrStrokeEndY;
+		FocalX = c->GrStrokeFocalX;
+		FocalY = c->GrStrokeFocalY;
 		gradient = c->stroke_gradient;
 	}
 	else
@@ -3482,6 +3484,8 @@
 		StartY = c->GrStartY;
 		EndX = c->GrEndX;
 		EndY = c->GrEndY;
+		FocalX = c->GrFocalX;
+		FocalY = c->GrFocalY;
 		gradient = c->fill_gradient;
 		if (GType == 8)
 		{
@@ -3584,7 +3588,7 @@
 	if (GType == 6)
 		PutStream("/Coords ["+ToStr(StartX)+" "+ToStr(-StartY)+" "+ToStr(EndX)+" "+ToStr(-EndY)+"]\n");
 	else
-		PutStream("/Coords ["+ToStr(StartX)+" "+ToStr(-StartY)+" 0.0 "+ToStr(StartX)+" "+ToStr(-StartY)+" "+ToStr(sqrt(pow(EndX - StartX, 2) + pow(EndY - StartY,2)))+"]\n");
+		PutStream("/Coords ["+ToStr(FocalX)+" "+ToStr(-FocalY)+" 0.0 "+ToStr(StartX)+" "+ToStr(-StartY)+" "+ToStr(sqrt(pow(EndX - StartX, 2) + pow(EndY - StartY,2)))+"]\n");
 	PutStream("/Function\n");
 	PutStream("<<\n");
 	PutStream("/FunctionType 3\n");
Index: scribus/pageitem_desaxe.cpp
===================================================================
--- scribus/pageitem_desaxe.cpp	(revision 14277)
+++ scribus/pageitem_desaxe.cpp	(revision 14278)
@@ -307,6 +307,9 @@
 			gradientV.insert("GRSTARTY", toXMLString(GrStartY));
 			gradientV.insert("GRENDX", toXMLString(GrEndX));
 			gradientV.insert("GRENDY", toXMLString(GrEndY));
+			gradientV.insert("GRFOCALX", toXMLString(GrFocalX));
+			gradientV.insert("GRFOCALY", toXMLString(GrFocalY));
+			gradientV.insert("GRSCALE", toXMLString(GrScale));
 			gradientV.insert("GRNAME", toXMLString(gradient()));
 			handler.begin("Gradient", gradientV);
 			QList<VColorStop*> cstops = fill_gradient.colorStops();
@@ -330,6 +333,9 @@
 			gradientV.insert("GRSTARTYS", toXMLString(GrStrokeStartY));
 			gradientV.insert("GRENDXS", toXMLString(GrStrokeEndX));
 			gradientV.insert("GRENDYS", toXMLString(GrStrokeEndY));
+			gradientV.insert("GRFOCALXS", toXMLString(GrStrokeFocalX));
+			gradientV.insert("GRFOCALYS", toXMLString(GrStrokeFocalY));
+			gradientV.insert("GRSCALES", toXMLString(GrStrokeScale));
 			gradientV.insert("GRNAMES", toXMLString(strokeGradient()));
 			handler.begin("GradientS", gradientV);
 			QList<VColorStop*> cstops = fill_gradient.colorStops();
@@ -573,6 +579,9 @@
 			item->GrStrokeStartY = parseDouble(attr["GRSTARTYS"]);
 			item->GrStrokeEndX = parseDouble(attr["GRENDXS"]);
 			item->GrStrokeEndY = parseDouble(attr["GRENDYS"]);
+			item->GrStrokeFocalX = parseDouble(attr["GRFOCALXS"]);
+			item->GrStrokeFocalY = parseDouble(attr["GRFOCALYS"]);
+			item->GrStrokeScale = parseDouble(attr["GRSCALES"]);
 			item->setStrokeGradient(attr["GRNAMES"]);
 			item->stroke_gradient.clearStops();
 		}
@@ -584,6 +593,9 @@
 			item->GrStartY = parseDouble(attr["GRSTARTY"]);
 			item->GrEndX = parseDouble(attr["GRENDX"]);
 			item->GrEndY = parseDouble(attr["GRENDY"]);
+			item->GrFocalX = parseDouble(attr["GRFOCALX"]);
+			item->GrFocalY = parseDouble(attr["GRFOCALY"]);
+			item->GrScale = parseDouble(attr["GRSCALE"]);
 			item->setGradient(attr["GRNAME"]);
 			item->fill_gradient.clearStops();
 		}
Index: scribus/canvasmode_editgradient.h
===================================================================
--- scribus/canvasmode_editgradient.h	(revision 14277)
+++ scribus/canvasmode_editgradient.h	(revision 14278)
@@ -54,7 +54,8 @@
 	{
 		noPointDefined,
 		useGradientStart,
-		useGradientEnd
+		useGradientEnd,
+		useGradientFocal
 	} eGradientPoint;
 
 	inline bool GetItem(PageItem** pi);




More information about the scribus-commit mailing list