r14284 by fschmid - Part of Bug-Nr 4293: "Improved support for gradients", added support for elliptical gradients and skewing of linear gradients.

scribus-commit scribus-commit at lists.scribus.net
Thu Nov 12 15:16:40 CET 2009


Revision: 14284
Author: fschmid
Date: 2009-11-12T06:56:08.420386Z
Commit message: Part of Bug-Nr 4293: "Improved support for gradients", added support for elliptical gradients and skewing of linear gradients.

Changeset: 
M  /trunk/Scribus/scribus/scpainter.cpp
M  /trunk/Scribus/scribus/ui/propertiespalette.cpp
M  /trunk/Scribus/scribus/pageitem.cpp
M  /trunk/Scribus/scribus/scribusXml.cpp
M  /trunk/Scribus/scribus/scpainter.h
M  /trunk/Scribus/scribus/ui/propertiespalette.h
M  /trunk/Scribus/scribus/pageitem.h
M  /trunk/Scribus/scribus/pageitem_line.cpp
M  /trunk/Scribus/scribus/canvasmode_editgradient.cpp
M  /trunk/Scribus/scribus/ui/gradientmanager.cpp
M  /trunk/Scribus/scribus/plugins/xarimplugin/importxar.cpp
M  /trunk/Scribus/scribus/pageitem_polyline.cpp
M  /trunk/Scribus/scribus/scribusstructs.h
M  /trunk/Scribus/scribus/scpreview.cpp
M  /trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.cpp
M  /trunk/Scribus/scribus/canvasmode_editgradient.h
M  /trunk/Scribus/scribus/pdflib_core.cpp
M  /trunk/Scribus/scribus/pslib.cpp
M  /trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
M  /trunk/Scribus/scribus/pageitem_textframe.cpp
M  /trunk/Scribus/scribus/canvas.cpp
M  /trunk/Scribus/scribus/pageitem_pathtext.cpp
M  /trunk/Scribus/scribus/ui/gradientpreview.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/plugins/fileloader/scribus150format/scribus150format_save.cpp
M  /trunk/Scribus/scribus/canvasmode_copyproperties.cpp

Diffs:
Index: scribus/canvasmode_editgradient.cpp
===================================================================
--- scribus/canvasmode_editgradient.cpp	(revision 14283)
+++ scribus/canvasmode_editgradient.cpp	(revision 14284)
@@ -176,8 +176,8 @@
 		PageItem *currItem = m_doc->m_Selection->itemAt(0);
 		double newX = mousePointDoc.x(); //m->x();
 		double newY = mousePointDoc.y(); //m->y();
-		double dx = fabs(Mxp - newX) + 5.0 / m_canvas->scale();
-		double dy = fabs(Myp - newY) + 5.0 / m_canvas->scale();
+//		double dx = fabs(Mxp - newX) + 5.0 / m_canvas->scale();
+//		double dy = fabs(Myp - newY) + 5.0 / m_canvas->scale();
 		FPoint np(Mxp - newX, Myp - newY, 0, 0, currItem->rotation(), 1, 1, true);
 		if (m_view->editStrokeGradient)
 		{
@@ -215,6 +215,25 @@
 					}
 				}
 			}
+			if (m_gradientPoint == useGradientSkew)
+			{
+				double radEnd = distance(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+				double rotEnd = xy2Deg(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+				QTransform m;
+				m.translate(currItem->GrStrokeStartX, currItem->GrStrokeStartY);
+				m.rotate(rotEnd);
+				m.rotate(-90);
+				m.rotate(currItem->GrStrokeSkew);
+				m.translate(radEnd * currItem->GrStrokeScale, 0);
+				QPointF shP = m.map(QPointF(0,0));
+				QPointF shR = QPointF(shP.x() -np.x(), shP.y() - np.y());
+				double radNew = distance(shR.x() - currItem->GrStrokeStartX, shR.y() - currItem->GrStrokeStartY);
+				double rotNew = xy2Deg(shR.x() - currItem->GrStrokeStartX, shR.y() - currItem->GrStrokeStartY) + 90;
+				currItem->GrStrokeSkew = rotNew - rotEnd;
+				double newScale = radNew / radEnd;
+				if ((newScale > 0) && (newScale <= 1))
+					currItem->GrStrokeScale = newScale;
+			}
 			if (m_gradientPoint == useGradientEnd)
 			{
 				currItem->GrStrokeEndX -= np.x(); // (Mxp - newX); // / m_canvas->scale();
@@ -267,6 +286,25 @@
 					}
 				}
 			}
+			if (m_gradientPoint == useGradientSkew)
+			{
+				double radEnd = distance(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+				double rotEnd = xy2Deg(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+				QTransform m;
+				m.translate(currItem->GrStartX, currItem->GrStartY);
+				m.rotate(rotEnd);
+				m.rotate(-90);
+				m.rotate(currItem->GrSkew);
+				m.translate(radEnd * currItem->GrScale, 0);
+				QPointF shP = m.map(QPointF(0,0));
+				QPointF shR = QPointF(shP.x() -np.x(), shP.y() - np.y());
+				double radNew = distance(shR.x() - currItem->GrStartX, shR.y() - currItem->GrStartY);
+				double rotNew = xy2Deg(shR.x() - currItem->GrStartX, shR.y() - currItem->GrStartY) + 90;
+				currItem->GrSkew = rotNew - rotEnd;
+				double newScale = radNew / radEnd;
+				if ((newScale > 0) && (newScale <= 1))
+					currItem->GrScale = newScale;
+			}
 			if (m_gradientPoint == useGradientEnd)
 			{
 				currItem->GrEndX -= np.x();
@@ -285,9 +323,46 @@
 		}
 		Mxp = newX;
 		Myp = newY;
-		m_view->RefreshGradient(currItem, dx * m_canvas->scale(), dy * m_canvas->scale());
+//		m_view->RefreshGradient(currItem, dx * m_canvas->scale(), dy * m_canvas->scale());
 		m_ScMW->propertiesPalette->updateColorSpecialGradient();
 		currItem->update();
+		QRectF upRect;
+		if (m_view->editStrokeGradient)
+		{
+			upRect = QRectF(QPointF(currItem->GrStrokeStartX, currItem->GrStrokeStartY), QPointF(currItem->GrStrokeEndX, currItem->GrStrokeEndY));
+			double radEnd = distance(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+			double rotEnd = xy2Deg(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+			QTransform m;
+			m.translate(currItem->GrStrokeStartX, currItem->GrStrokeStartY);
+			m.rotate(rotEnd);
+			m.rotate(-90);
+			m.rotate(currItem->GrStrokeSkew);
+			m.translate(radEnd * currItem->GrStrokeScale, 0);
+			QPointF shP = m.map(QPointF(0,0));
+			upRect |= upRect.united(QRectF(shP, QPointF(currItem->GrStrokeEndX, currItem->GrStrokeEndY)).normalized());
+			upRect |= upRect.united(QRectF(shP, QPointF(currItem->GrStrokeStartX, currItem->GrStrokeStartY)).normalized());
+			upRect |= QRectF(shP, QPointF(0, 0)).normalized();
+			upRect |= QRectF(shP, QPointF(currItem->width(), currItem->height())).normalized();
+		}
+		else
+		{
+			upRect = QRectF(QPointF(currItem->GrStartX, currItem->GrStartY), QPointF(currItem->GrEndX, currItem->GrEndY));
+			double radEnd = distance(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+			double rotEnd = xy2Deg(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+			QTransform m;
+			m.translate(currItem->GrStartX, currItem->GrStartY);
+			m.rotate(rotEnd);
+			m.rotate(-90);
+			m.rotate(currItem->GrSkew);
+			m.translate(radEnd * currItem->GrScale, 0);
+			QPointF shP = m.map(QPointF(0,0));
+			upRect |= QRectF(shP, QPointF(currItem->GrEndX, currItem->GrEndY)).normalized();
+			upRect |= QRectF(shP, QPointF(currItem->GrStartX, currItem->GrStartY)).normalized();
+			upRect |= QRectF(shP, QPointF(0, 0)).normalized();
+			upRect |= QRectF(shP, QPointF(currItem->width(), currItem->height())).normalized();
+		}
+		upRect.translate(currItem->xPos(), currItem->yPos());
+		m_doc->regionsChanged()->update(upRect.adjusted(-10.0, -10.0, 10.0, 10.0));
 	}
 }
 
@@ -317,28 +392,49 @@
 	PageItem *currItem = m_doc->m_Selection->itemAt(0);
 	itemMatrix.translate(currItem->xPos(), currItem->yPos());
 	itemMatrix.rotate(currItem->rotation());
-	QPointF gradientStart, gradientEnd, gradientFocal;
+	QPointF gradientStart, gradientEnd, gradientFocal, gradientScale;
 	if (m_view->editStrokeGradient)
 	{
 		gradientStart = QPointF(currItem->GrStrokeStartX, currItem->GrStrokeStartY);
 		gradientEnd = QPointF(currItem->GrStrokeEndX, currItem->GrStrokeEndY);
 		gradientFocal = QPointF(currItem->GrStrokeFocalX, currItem->GrStrokeFocalY);
+		double radEnd = distance(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+		double rotEnd = xy2Deg(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+		QTransform m;
+		m.translate(currItem->GrStrokeStartX, currItem->GrStrokeStartY);
+		m.rotate(rotEnd);
+		m.rotate(-90);
+		m.rotate(currItem->GrStrokeSkew);
+		m.translate(radEnd * currItem->GrStrokeScale, 0);
+		gradientScale = m.map(QPointF(0,0));
 	}
 	else
 	{
 		gradientStart = QPointF(currItem->GrStartX, currItem->GrStartY);
 		gradientEnd = QPointF(currItem->GrEndX, currItem->GrEndY);
 		gradientFocal = QPointF(currItem->GrFocalX, currItem->GrFocalY);
+		double radEnd = distance(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+		double rotEnd = xy2Deg(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+		QTransform m;
+		m.translate(currItem->GrStartX, currItem->GrStartY);
+		m.rotate(rotEnd);
+		m.rotate(-90);
+		m.rotate(currItem->GrSkew);
+		m.translate(radEnd * currItem->GrScale, 0);
+		gradientScale = m.map(QPointF(0,0));
 	}
 	gradientStart = itemMatrix.map(gradientStart);
 	gradientEnd = itemMatrix.map(gradientEnd);
 	gradientFocal = itemMatrix.map(gradientFocal);
+	gradientScale = itemMatrix.map(gradientScale);
 	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;
+	else if (m_canvas->hitsCanvasPoint(m->globalPos(), gradientScale))
+		m_gradientPoint = useGradientSkew;
 	m_canvas->m_viewMode.m_MouseButtonPressed = true;
 	qApp->changeOverrideCursor(QCursor(Qt::CrossCursor));
 }
Index: scribus/pdflib_core.cpp
===================================================================
--- scribus/pdflib_core.cpp	(revision 14283)
+++ scribus/pdflib_core.cpp	(revision 14284)
@@ -5792,12 +5792,7 @@
 	QList<int> colorShades;
 	QStringList spotColorSet;
 	VGradient gradient;
-	double StartX;
-	double StartY;
-	double EndX;
-	double EndY;
-	double FocalX;
-	double FocalY;
+	double StartX, StartY, EndX, EndY, FocalX, FocalY, Gscale, Gskew;
 	int GType;
 	if (stroke)
 	{
@@ -5808,6 +5803,8 @@
 		EndY = currItem->GrStrokeEndY;
 		FocalX = currItem->GrStrokeFocalX;
 		FocalY = currItem->GrStrokeFocalY;
+		Gscale = currItem->GrStrokeScale;
+		Gskew = currItem->GrStrokeSkew;
 		gradient = currItem->stroke_gradient;
 	}
 	else
@@ -5819,6 +5816,8 @@
 		EndY = currItem->GrEndY;
 		FocalX = currItem->GrFocalX;
 		FocalY = currItem->GrFocalY;
+		Gscale = currItem->GrScale;
+		Gskew = currItem->GrSkew;
 		gradient = currItem->fill_gradient;
 	}
 	QList<VColorStop*> cstops = gradient.colorStops();
@@ -5831,6 +5830,33 @@
 	bool spotMode = false;
 	mpa.translate(currItem->xPos() - ActPageP->xOffset(), ActPageP->height() - (currItem->yPos() - ActPageP->yOffset()));
 	mpa.rotate(-currItem->rotation());
+	QTransform qmatrix;
+	if (Gskew == 90)
+		Gskew = 1;
+	else if (Gskew == 180)
+		Gskew = 0;
+	else if (Gskew == 270)
+		Gskew = -1;
+	else if (Gskew == 390)
+		Gskew = 0;
+	else
+		Gskew = tan(M_PI / 180.0 * Gskew);
+	if (GType == 6)
+	{
+		mpa.translate(StartX, -StartY);
+		mpa.shear(Gskew, 0);
+		mpa.translate(-StartX, StartY);
+	}
+	else
+	{
+		double rotEnd = xy2Deg(EndX - StartX, EndY - StartY);
+		mpa.translate(StartX, -StartY);
+		mpa.rotate(-rotEnd);
+		mpa.shear(-Gskew, 0);
+		mpa.translate(0, -StartY * (1.0 - Gscale));
+		mpa.translate(-StartX, StartY);
+		mpa.scale(1, Gscale);
+	}
 	bool transparencyFound = false;
 	for (uint cst = 0; cst < gradient.Stops(); ++cst)
 	{
@@ -5871,6 +5897,7 @@
 		StartObj(patObject);
 		PutDoc("<<\n/Type /Pattern\n");
 		PutDoc("/PatternType 2\n");
+		PutDoc("/Matrix ["+FToStr(mpa.m11())+" "+FToStr(mpa.m12())+" "+FToStr(mpa.m21())+" "+FToStr(mpa.m22())+" 0 0]\n");
 		PutDoc("/Shading\n");
 		PutDoc("<<\n");
 		if (GType == 6)
Index: scribus/pageitem_line.cpp
===================================================================
--- scribus/pageitem_line.cpp	(revision 14283)
+++ scribus/pageitem_line.cpp	(revision 14284)
@@ -83,16 +83,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));
+							p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
 						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), GrStrokeScale, GrStrokeSkew);
 					}
 				}
 				else if (lineColor() != CommonStrings::None)
Index: scribus/canvasmode_copyproperties.cpp
===================================================================
--- scribus/canvasmode_copyproperties.cpp	(revision 14283)
+++ scribus/canvasmode_copyproperties.cpp	(revision 14284)
@@ -155,7 +155,7 @@
 	SeleItem(m);
 	if (GetItem(&currItem))
 	{
-		double sx, sy, ex, ey, r, skx, sky, fx, fy, ss;
+		double sx, sy, ex, ey, r, skx, sky, fx, fy, ss, sk;
 		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, fx, fy, ss);
-		currItem->setGradientVector(sx, sy, ex, ey, fx, fy, ss);
+		m_doc->ElemToLink->gradientVector(sx, sy, ex, ey, fx, fy, ss, sk);
+		currItem->setGradientVector(sx, sy, ex, ey, fx, fy, ss, sk);
 		// 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, fx, fy, ss);
-		currItem->setStrokeGradientVector(sx, sy, ex, ey, fx, fy, ss);
+		m_doc->ElemToLink->strokeGradientVector(sx, sy, ex, ey, fx, fy, ss, sk);
+		currItem->setStrokeGradientVector(sx, sy, ex, ey, fx, fy, ss, sk);
 		currItem->setStrokeGradientType(m_doc->ElemToLink->strokeGradientType());
 		// Update Item
 		m_doc->ElemToLink = currItem;
Index: scribus/pageitem_polyline.cpp
===================================================================
--- scribus/pageitem_polyline.cpp	(revision 14283)
+++ scribus/pageitem_polyline.cpp	(revision 14284)
@@ -122,16 +122,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));
+							p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
 						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), GrStrokeScale, GrStrokeSkew);
 					}
 				}
 				else if (lineColor() != CommonStrings::None)
Index: scribus/scribusXml.cpp
===================================================================
--- scribus/scribusXml.cpp	(revision 14283)
+++ scribus/scribusXml.cpp	(revision 14284)
@@ -192,6 +192,7 @@
 			OB->GrFocalX = attrAsDbl(attrs, "GRFOCALX", 0.0);
 			OB->GrFocalY = attrAsDbl(attrs, "GRFOCALY", 0.0);
 			OB->GrScale  = attrAsDbl(attrs, "GRSCALE", 1.0);
+			OB->GrSkew   = attrAsDbl(attrs, "GRSKEW", 0.0);
 			if (OB->GrColor.isEmpty())
 				OB->GrColor = "Black";
 			OB->GrColor2 = attrAsString(attrs, "GRCOLOR2","Black");
@@ -212,6 +213,7 @@
 		OB->GrStrokeFocalX = attrAsDbl(attrs, "GRFOCALXS", 0.0);
 		OB->GrStrokeFocalY = attrAsDbl(attrs, "GRFOCALYS", 0.0);
 		OB->GrStrokeScale  = attrAsDbl(attrs, "GRSCALES", 1.0);
+		OB->GrStrokeSkew   = attrAsDbl(attrs, "GRSKEWS", 1.0);
 	}
 	OB->Rot        = attrAsDbl(attrs, "ROT", 0.0);
 	OB->PLineArt   = Qt::PenStyle    ( attrAsInt(attrs, "PLINEART", 0) );
@@ -2370,6 +2372,7 @@
 		writer.writeAttribute("GRFOCALX", item->GrFocalX);
 		writer.writeAttribute("GRFOCALY", item->GrFocalY);
 		writer.writeAttribute("GRSCALE" , item->GrScale);
+		writer.writeAttribute("GRSKEW"  , item->GrSkew);
 	}
 	if (item->GrTypeStroke > 0)
 	{
@@ -2380,6 +2383,7 @@
 		writer.writeAttribute("GRFOCALXS", item->GrStrokeFocalX);
 		writer.writeAttribute("GRFOCALYS", item->GrStrokeFocalY);
 		writer.writeAttribute("GRSCALES" , item->GrStrokeScale);
+		writer.writeAttribute("GRSKEWS"  , item->GrStrokeSkew);
 	}
 
 	if (item->effectsInUse.count() != 0)
Index: scribus/canvas.cpp
===================================================================
--- scribus/canvas.cpp	(revision 14283)
+++ scribus/canvas.cpp	(revision 14284)
@@ -32,6 +32,7 @@
 #include "scribusview.h"
 #include "selection.h"
 #include "util.h"
+#include "util_math.h"
 #include "units.h"
 
 #define DRAW_DEBUG_LINES 0
@@ -1169,6 +1170,19 @@
 		psx->drawPoint(QPointF(currItem->GrStrokeEndX, currItem->GrStrokeEndY));
 		if (currItem->GrTypeStroke == 7)
 			psx->drawPoint(QPointF(currItem->GrStrokeFocalX, currItem->GrStrokeFocalY));
+		double radEnd = distance(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+		double rotEnd = xy2Deg(currItem->GrStrokeEndX - currItem->GrStrokeStartX, currItem->GrStrokeEndY - currItem->GrStrokeStartY);
+		QTransform m;
+		m.translate(currItem->GrStrokeStartX, currItem->GrStrokeStartY);
+		m.rotate(rotEnd);
+		m.rotate(-90);
+		m.rotate(currItem->GrStrokeSkew);
+		m.translate(radEnd * currItem->GrStrokeScale, 0);
+		QPointF shP = m.map(QPointF(0,0));
+		psx->setPen(QPen(Qt::blue, 1.0 / m_viewMode.scale, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
+		psx->drawLine(QPointF(currItem->GrStrokeStartX, currItem->GrStrokeStartY), shP);
+		psx->setPen(QPen(Qt::magenta, 8.0 / m_viewMode.scale, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
+		psx->drawPoint(shP);
 	}
 	else
 	{
@@ -1178,6 +1192,21 @@
 		psx->drawPoint(QPointF(currItem->GrEndX, currItem->GrEndY));
 		if (currItem->GrType == 7)
 			psx->drawPoint(QPointF(currItem->GrFocalX, currItem->GrFocalY));
+		double radEnd = distance(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+		double rotEnd = xy2Deg(currItem->GrEndX - currItem->GrStartX, currItem->GrEndY - currItem->GrStartY);
+		QTransform m;
+		m.translate(currItem->GrStartX, currItem->GrStartY);
+		m.rotate(rotEnd);
+		m.rotate(-90);
+		m.rotate(currItem->GrSkew);
+		m.translate(radEnd * currItem->GrScale, 0);
+		QPointF shP = m.map(QPointF(0,0));
+		psx->setPen(QPen(Qt::blue, 1.0 / m_viewMode.scale, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
+		psx->drawLine(QPointF(currItem->GrStartX, currItem->GrStartY), shP);
+		psx->setPen(QPen(Qt::magenta, 8.0 / m_viewMode.scale, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
+		psx->drawPoint(shP);
+		
+		
 	}
 }
 
Index: scribus/pageitem_pathtext.cpp
===================================================================
--- scribus/pageitem_pathtext.cpp	(revision 14283)
+++ scribus/pageitem_pathtext.cpp	(revision 14284)
@@ -129,16 +129,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));
+							p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
 						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), GrStrokeScale, GrStrokeSkew);
 					}
 				}
 				else if (lineColor() != CommonStrings::None)
Index: scribus/pageitem.h
===================================================================
--- scribus/pageitem.h	(revision 14283)
+++ scribus/pageitem.h	(revision 14284)
@@ -357,6 +357,7 @@
 	double GrFocalX;
 	double GrFocalY;
 	double GrScale;
+	double GrSkew;
 	int Cols;
 	double ColGap;
 	double gridOffset_;
@@ -597,13 +598,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, double &focalX, double &focalY, double &scale) const;
-	void setGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale);
+	void gradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const;
+	void setGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew);
 
 	int strokeGradientType() const { return GrTypeStroke; }
 	void setStrokeGradientType(int val) { GrTypeStroke = val; }
-	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);
+	void strokeGradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const;
+	void setStrokeGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew);
 	// 
 	bool fillEvenOdd() const { return fillRule; }
 	void setFillEvenOdd(bool val) { fillRule = val; }
@@ -1383,6 +1384,7 @@
 	double GrStrokeFocalX;
 	double GrStrokeFocalY;
 	double GrStrokeScale;
+	double GrStrokeSkew;
 
 	/** Inline Image */
 	bool isInlineImage;
Index: scribus/scribusstructs.h
===================================================================
--- scribus/scribusstructs.h	(revision 14283)
+++ scribus/scribusstructs.h	(revision 14284)
@@ -92,6 +92,7 @@
 	double GrFocalX;
 	double GrFocalY;
 	double GrScale;
+	double GrSkew;
 	VGradient stroke_gradient;
 	int GrTypeStroke;
 	double GrStrokeStartX;
@@ -101,6 +102,7 @@
 	double GrStrokeFocalX;
 	double GrStrokeFocalY;
 	double GrStrokeScale;
+	double GrStrokeSkew;
 	QString TxtStroke;
 	QString TxtFill;
 	int ShTxtStroke;
Index: scribus/scpainter.cpp
===================================================================
--- scribus/scpainter.cpp	(revision 14283)
+++ scribus/scpainter.cpp	(revision 14284)
@@ -8,6 +8,7 @@
 #include "scpainter.h"
 #include "util_color.h"
 #include "util.h"
+#include "util_math.h"
 
 #ifdef HAVE_CAIRO
 	#include <cairo.h>
@@ -798,7 +799,7 @@
 	strokeMode = stroke;
 }
 
-void ScPainter::setGradient(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc)
+void ScPainter::setGradient(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc, double scale, double skew)
 {
 	fill_gradient.setType(mode);
 	fill_gradient.setOrigin(orig);
@@ -808,6 +809,17 @@
 	stroke_gradient.setOrigin(orig);
 	stroke_gradient.setVector(vec);
 	stroke_gradient.setFocalPoint(foc);
+	gradientScale = scale;
+	if (skew == 90)
+		gradientSkew = 1;
+	else if (skew == 180)
+		gradientSkew = 0;
+	else if (skew == 270)
+		gradientSkew = -1;
+	else if (skew == 390)
+		gradientSkew = 0;
+	else
+		gradientSkew = tan(M_PI / 180.0 * skew);
 }
 
 void ScPainter::fillTextPath()
@@ -1035,6 +1047,27 @@
 				qStopColor.getRgbF(&r, &g, &b);
 				cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a);
 			}
+			cairo_matrix_t matrix;
+			QTransform qmatrix;
+			if (fill_gradient.type() == VGradient::radial)
+			{
+				double rotEnd = xy2Deg(x2 - x1, y2 - y1);
+				qmatrix.translate(x1, y1);
+				qmatrix.rotate(rotEnd);
+				qmatrix.shear(gradientSkew, 0);
+				qmatrix.translate(0, y1 * (1.0 - gradientScale));
+				qmatrix.translate(-x1, -y1);
+				qmatrix.scale(1, gradientScale);
+			}
+			else
+			{
+				qmatrix.translate(x1, y1);
+				qmatrix.shear(-gradientSkew, 0);
+				qmatrix.translate(-x1, -y1);
+			}
+			cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
+			cairo_matrix_invert(&matrix);
+			cairo_pattern_set_matrix (pat, &matrix);
 			cairo_set_source (m_cr, pat);
 			cairo_clip_preserve (m_cr);
 			cairo_paint_with_alpha (m_cr, fill_trans);
@@ -1153,6 +1186,27 @@
 				qStopColor.getRgbF(&r, &g, &b);
 				cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a);
 			}
+			cairo_matrix_t matrix;
+			QTransform qmatrix;
+			if (stroke_gradient.type() == VGradient::radial)
+			{
+				double rotEnd = xy2Deg(x2 - x1, y2 - y1);
+				qmatrix.translate(x1, y1);
+				qmatrix.rotate(rotEnd);
+				qmatrix.shear(gradientSkew, 0);
+				qmatrix.translate(0, y1 * (1.0 - gradientScale));
+				qmatrix.translate(-x1, -y1);
+				qmatrix.scale(1, gradientScale);
+			}
+			else
+			{
+				qmatrix.translate(x1, y1);
+				qmatrix.shear(-gradientSkew, 0);
+				qmatrix.translate(-x1, -y1);
+			}
+			cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy());
+			cairo_matrix_invert(&matrix);
+			cairo_pattern_set_matrix (pat, &matrix);
 			cairo_set_source (m_cr, pat);
 			cairo_stroke_preserve( m_cr );
 			cairo_pattern_destroy (pat);
Index: scribus/pageitem.cpp
===================================================================
--- scribus/pageitem.cpp	(revision 14283)
+++ scribus/pageitem.cpp	(revision 14284)
@@ -92,6 +92,7 @@
 	GrFocalX(other.GrFocalX),
 	GrFocalY(other.GrFocalY),
 	GrScale(other.GrScale),
+	GrSkew(other.GrSkew),
 	Cols(other.Cols),
 	ColGap(other.ColGap),
 	PLineArt(other.PLineArt),
@@ -267,7 +268,8 @@
 	GrStrokeEndY(other.GrStrokeEndY),
 	GrStrokeFocalX(other.GrStrokeFocalX),
 	GrStrokeFocalY(other.GrStrokeFocalY),
-	GrStrokeScale(other.GrStrokeScale)
+	GrStrokeScale(other.GrStrokeScale),
+	GrStrokeSkew(other.GrStrokeSkew)
 {
 	QString tmp;
 	m_Doc->TotalItems++;
@@ -339,6 +341,7 @@
 	GrFocalX = 0;
 	GrFocalY = 0;
 	GrScale = 1;
+	GrSkew = 0;
 	gradientVal = "";
 	GrTypeStroke = 0;
 	GrStrokeStartX = 0;
@@ -348,6 +351,7 @@
 	GrStrokeFocalX = 0;
 	GrStrokeFocalY = 0;
 	GrStrokeScale = 1;
+	GrStrokeSkew = 0;
 	gradientStrokeVal = "";
 	patternVal = "";
 	patternScaleX = 100;
@@ -1167,11 +1171,11 @@
 						case 3:
 						case 4:
 						case 6:
-							p->setGradient(VGradient::linear, FPoint(GrStartX, GrStartY), FPoint(GrEndX, GrEndY));
+							p->setGradient(VGradient::linear, FPoint(GrStartX, GrStartY), FPoint(GrEndX, GrEndY), FPoint(GrStartX, GrStartY), GrScale, GrSkew);
 							break;
 						case 5:
 						case 7:
-							p->setGradient(VGradient::radial, FPoint(GrStartX, GrStartY), FPoint(GrEndX, GrEndY), FPoint(GrFocalX, GrFocalY));
+							p->setGradient(VGradient::radial, FPoint(GrStartX, GrStartY), FPoint(GrEndX, GrEndY), FPoint(GrFocalX, GrFocalY), GrScale, GrSkew);
 							break;
 					}
 				}
@@ -1293,9 +1297,9 @@
 								p->setStrokeMode(ScPainter::Gradient);
 								p->stroke_gradient = stroke_gradient;
 								if (GrTypeStroke == 6)
-									p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY));
+									p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
 								else
-									p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY));
+									p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY), GrStrokeScale, GrStrokeSkew);
 							}
 							p->strokePath();
 						}
@@ -2370,7 +2374,7 @@
 		patternVal = newPattern;
 }
 
-void PageItem::gradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale) const
+void PageItem::gradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const
 {
 	startX = GrStartX;
 	startY = GrStartY;
@@ -2379,9 +2383,10 @@
 	focalX = GrFocalX;
 	focalY = GrFocalY;
 	scale  = GrScale;
+	skew   = GrSkew;
 }
 
-void PageItem::setGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale)
+void PageItem::setGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew)
 {
 	GrStartX = startX;
 	GrStartY = startY;
@@ -2390,6 +2395,7 @@
 	GrFocalX = focalX;
 	GrFocalY = focalY;
 	GrScale  = scale;
+	GrSkew   = skew;
 }
 
 void PageItem::setStrokeGradient(const QString &newGradient)
@@ -2398,7 +2404,7 @@
 		gradientStrokeVal = newGradient;
 }
 
-void PageItem::strokeGradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale) const
+void PageItem::strokeGradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const
 {
 	startX = GrStrokeStartX;
 	startY = GrStrokeStartY;
@@ -2407,9 +2413,10 @@
 	focalX = GrStrokeFocalX;
 	focalY = GrStrokeFocalY;
 	scale  = GrStrokeScale;
+	skew   = GrStrokeSkew;
 }
 
-void PageItem::setStrokeGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale)
+void PageItem::setStrokeGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew)
 {
 	GrStrokeStartX = startX;
 	GrStrokeStartY = startY;
@@ -2418,6 +2425,7 @@
 	GrStrokeFocalX = focalX;
 	GrStrokeFocalY = focalY;
 	GrStrokeScale  = scale;
+	GrStrokeSkew   = skew;
 }
 
 void PageItem::setPatternTransform(double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY)
@@ -4281,6 +4289,7 @@
 	Buffer->GrFocalX = GrFocalX;
 	Buffer->GrFocalY = GrFocalY;
 	Buffer->GrScale = GrScale;
+	Buffer->GrSkew = GrSkew;
 	Buffer->Rot = Rot;
 	Buffer->PLineArt = PLineArt;
 	Buffer->PLineEnd = PLineEnd;
@@ -5248,9 +5257,9 @@
 					p->setFillMode(ScPainter::Gradient);
 					p->fill_gradient = stroke_gradient;
 					if (GrTypeStroke == 6)
-						p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY));
+						p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
 					else
-						p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY));
+						p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY), GrStrokeScale, GrStrokeSkew);
 				}
 				p->fillPath();
 			}
Index: scribus/pageitem_textframe.cpp
===================================================================
--- scribus/pageitem_textframe.cpp	(revision 14283)
+++ scribus/pageitem_textframe.cpp	(revision 14284)
@@ -2659,16 +2659,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));
+								p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
 							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), GrStrokeScale, GrStrokeSkew);
 						}
 						p->strokePath();
 					}
Index: scribus/ui/cpalette.cpp
===================================================================
--- scribus/ui/cpalette.cpp	(revision 14283)
+++ scribus/ui/cpalette.cpp	(revision 14284)
@@ -90,12 +90,25 @@
 	freeGradientLayout->addWidget( gFX, 2, 1 );
 	gFY = new ScrSpinBox( -3000, 3000, this, 0);
 	freeGradientLayout->addWidget( gFY, 2, 3 );
+	GTextSK = new QLabel("Skew:", this );
+	freeGradientLayout->addWidget( GTextSK, 3, 0, 1, 2 );
+	gSk = new ScrSpinBox( -89, 89, this, 6);
+	gSk->setValue( 0 );
+	freeGradientLayout->addWidget( gSk, 3, 2, 1, 2 );
+	GTextSC = new QLabel("Factor:", this );
+	freeGradientLayout->addWidget( GTextSC, 4, 0, 1, 2 );
+	gSc = new ScrSpinBox( 0.01, 100, this, 0);
+	gSc->setSuffix(" %");
+	gSc->setValue( 100 );
+	freeGradientLayout->addWidget( gSc, 4, 2, 1, 2 );
 	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()));
+	connect(gSk, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	connect(gSc, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	languageChange();
 }
 
@@ -113,8 +126,10 @@
 {
 	GTextFX->hide();
 	GTextFY->hide();
+	GTextSC->hide();
 	gFX->hide();
 	gFY->hide();
+	gSc->hide();
 	resize(minimumSizeHint());
 }
 
@@ -122,8 +137,10 @@
 {
 	GTextFX->show();
 	GTextFY->show();
+	GTextSC->show();
 	gFX->show();
 	gFY->show();
+	gSc->show();
 	resize(minimumSizeHint());
 }
 
@@ -133,7 +150,7 @@
 	resize(minimumSizeHint());
 }
 
-void GradientVectorDialog::setValues(double x1, double y1, double x2, double y2, double fx, double fy, double sg)
+void GradientVectorDialog::setValues(double x1, double y1, double x2, double y2, double fx, double fy, double sg, double sk)
 {
 	disconnect(gX1, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	disconnect(gX2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
@@ -141,23 +158,29 @@
 	disconnect(gY2, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	disconnect(gFX, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	disconnect(gFY, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	disconnect(gSk, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	disconnect(gSc, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 	gX1->setValue(x1);
 	gX2->setValue(x2);
 	gY1->setValue(y1);
 	gY2->setValue(y2);
 	gFX->setValue(fx);
 	gFY->setValue(fy);
+	gSk->setValue(sk);
+	gSc->setValue(sg * 100.0);
 	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()));
+	connect(gSk, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
+	connect(gSc, SIGNAL(valueChanged(double)), this, SLOT(changeSpecial()));
 }
 
 void GradientVectorDialog::changeSpecial()
 {
-	emit NewSpecial(gX1->value(), gY1->value(), gX2->value(), gY2->value(), gFX->value(), gFY->value(), 1.0);
+	emit NewSpecial(gX1->value(), gY1->value(), gX2->value(), gY2->value(), gFX->value(), gFY->value(), gSc->value() / 100.0, gSk->value());
 }
 
 void GradientVectorDialog::unitChange(int unitIndex)
@@ -405,7 +428,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, double, double, double)), this, SIGNAL(NewSpecial(double, double, double, double, double, double, double)));
+	connect(CGradDia, SIGNAL(NewSpecial(double, double, double, double, double, double, double, double)), this, SIGNAL(NewSpecial(double, 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()));
@@ -696,7 +719,7 @@
 		p->setLineWidth(1);
 		p->setFillMode(2);
 		p->fill_gradient = it.value();
-		p->setGradient(VGradient::linear, FPoint(0,6), FPoint(48, 6));
+		p->setGradient(VGradient::linear, FPoint(0,6), FPoint(48, 6), FPoint(0,0), 1, 0);
 		p->drawRect(0, 0, 48, 12);
 		p->end();
 		delete p;
@@ -973,7 +996,7 @@
 	if (gradEditButton->isChecked())
 	{
 		CGradDia->unitChange(currentDoc->unitIndex());
-		CGradDia->setValues(currentItem->GrStartX, currentItem->GrStartY, currentItem->GrEndX, currentItem->GrEndY, currentItem->GrFocalX, currentItem->GrFocalY, currentItem->GrScale);
+		CGradDia->setValues(currentItem->GrStartX, currentItem->GrStartY, currentItem->GrEndX, currentItem->GrEndY, currentItem->GrFocalX, currentItem->GrFocalY, currentItem->GrScale, currentItem->GrSkew);
 		if (currentItem->GrType == 6)
 			CGradDia->hideExtraWidgets();
 		else
@@ -993,7 +1016,7 @@
 	if (gradEditButtonStroke->isChecked())
 	{
 		CGradDia->unitChange(currentDoc->unitIndex());
-		CGradDia->setValues(currentItem->GrStrokeStartX, currentItem->GrStrokeStartY, currentItem->GrStrokeEndX, currentItem->GrStrokeEndY, currentItem->GrStrokeFocalX, currentItem->GrStrokeFocalY, currentItem->GrStrokeScale);
+		CGradDia->setValues(currentItem->GrStrokeStartX, currentItem->GrStrokeStartY, currentItem->GrStrokeEndX, currentItem->GrStrokeEndY, currentItem->GrStrokeFocalX, currentItem->GrStrokeFocalY, currentItem->GrStrokeScale, currentItem->GrStrokeSkew);
 		if (currentItem->GrTypeStroke == 6)
 			CGradDia->hideExtraWidgets();
 		else
@@ -1020,10 +1043,10 @@
 	}
 }
 
-void Cpalette::setSpecialGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg)
+void Cpalette::setSpecialGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg, double sk)
 {
 	if (CGradDia)
-		CGradDia->setValues(x1, y1, x2, y2, fx, fy, sg);
+		CGradDia->setValues(x1, y1, x2, y2, fx, fy, sg, sk);
 }
 
 void Cpalette::changePatternProps()
Index: scribus/ui/cpalette.h
===================================================================
--- scribus/ui/cpalette.h	(revision 14283)
+++ scribus/ui/cpalette.h	(revision 14284)
@@ -59,12 +59,12 @@
 
 public slots:
 	void languageChange();
-	void setValues(double x1, double y1, double x2, double y2, double fx, double fy, double sg);
+	void setValues(double x1, double y1, double x2, double y2, double fx, double fy, double sg, double sk);
 	void changeSpecial();
 	void unitChange(int unitIndex);
 
 signals:
-	void NewSpecial(double, double, double, double, double, double, double);
+	void NewSpecial(double, double, double, double, double, double, double, double);
 
 protected:
 	QGridLayout* freeGradientLayout;
@@ -74,12 +74,16 @@
 	QLabel* GTextY2;
 	QLabel* GTextFX;
 	QLabel* GTextFY;
+	QLabel* GTextSK;
+	QLabel* GTextSC;
 	ScrSpinBox* gY1;
 	ScrSpinBox* gX2;
 	ScrSpinBox* gX1;
 	ScrSpinBox* gY2;
 	ScrSpinBox* gFX;
 	ScrSpinBox* gFY;
+	ScrSpinBox* gSk;
+	ScrSpinBox* gSc;
 };
 
 class SCRIBUS_API PatternPropsDialog : public QDialog
@@ -183,7 +187,7 @@
 	void editGradientVector();
 	void editGradientVectorStroke();
 	void setActiveGradDia(bool active);
-	void setSpecialGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg);
+	void setSpecialGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg, double sk);
 	void changePatternProps();
 	void changePatternPropsStroke();
 	void unitChange(double, double, int unitIndex);
@@ -198,7 +202,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, double, double, double);
+	void NewSpecial(double, double, double, double, double, double, double, double);
 	void NewTrans(double);
 	void NewTransS(double);
 	void NewBlend(int);
Index: scribus/ui/gradientmanager.cpp
===================================================================
--- scribus/ui/gradientmanager.cpp	(revision 14283)
+++ scribus/ui/gradientmanager.cpp	(revision 14284)
@@ -91,7 +91,7 @@
 		p->setLineWidth(1);
 		p->setFillMode(2);
 		p->fill_gradient = it.value();
-		p->setGradient(VGradient::linear, FPoint(0,6), FPoint(48, 6));
+		p->setGradient(VGradient::linear, FPoint(0,6), FPoint(48, 6), FPoint(0, 0), 1.0, 0.0);
 		p->drawRect(0, 0, 48, 12);
 		p->end();
 		delete p;
Index: scribus/ui/gradientpreview.cpp
===================================================================
--- scribus/ui/gradientpreview.cpp	(revision 14283)
+++ scribus/ui/gradientpreview.cpp	(revision 14284)
@@ -93,7 +93,7 @@
 	p->setLineWidth(1);
 	p->setFillMode(2);
 	p->fill_gradient = fill_gradient;
-	p->setGradient(VGradient::linear, FPoint(0,20), FPoint(width()-20,20));
+	p->setGradient(VGradient::linear, FPoint(0,20), FPoint(width()-20,20), FPoint(0, 0), 1.0, 0.0);
 	p->drawRect(0, 0, width()-20, 37);
 	p->end();
 	delete p;
Index: scribus/ui/propertiespalette.h
===================================================================
--- scribus/ui/propertiespalette.h	(revision 14283)
+++ scribus/ui/propertiespalette.h	(revision 14284)
@@ -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, double fx, double fy, double sg);
+	void NewSpGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg, double sk);
 	void toggleGradientEdit(bool);
 	void DoRevert();
 	void doClearCStyle();
Index: scribus/ui/propertiespalette.cpp
===================================================================
--- scribus/ui/propertiespalette.cpp	(revision 14283)
+++ scribus/ui/propertiespalette.cpp	(revision 14284)
@@ -67,10 +67,11 @@
 #include "undomanager.h"
 #include "util.h"
 #include "util_icon.h"
+#include "util_math.h"
 #include "text/nlsconfig.h"
 #include "dasheditor.h"
 
-using namespace std;
+//using namespace std;
 
 
 LineFormatValue::LineFormatValue() : m_Line(), m_doc(NULL), m_name() {};
@@ -1588,7 +1589,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, double, double, double)), this, SLOT(NewSpGradient(double, double, double, double, double, double, double )));
+	connect( Cpal, SIGNAL(NewSpecial(double, double, double, double, double, double, double, double)), this, SLOT(NewSpGradient(double, 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 +4588,7 @@
 	}
 }
 
-void PropertiesPalette::NewSpGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg)
+void PropertiesPalette::NewSpGradient(double x1, double y1, double x2, double y2, double fx, double fy, double sg, double sk)
 {
 	if (!m_ScMW || m_ScMW->ScriptRunning)
 		return;
@@ -4602,7 +4603,8 @@
 			CurItem->GrStrokeEndY = y2 / m_unitRatio;
 			CurItem->GrStrokeFocalX = fx / m_unitRatio;
 			CurItem->GrStrokeFocalY = fy / m_unitRatio;
-			CurItem->GrStrokeScale = sg / m_unitRatio;
+			CurItem->GrStrokeScale = sg;
+			CurItem->GrStrokeSkew = sk;
 			if (CurItem->GrTypeStroke == 6)
 			{
 				CurItem->GrStrokeFocalX = CurItem->GrStrokeStartX;
@@ -4610,6 +4612,19 @@
 			}
 			CurItem->update();
 			upRect = QRectF(QPointF(CurItem->GrStrokeStartX, CurItem->GrStrokeStartY), QPointF(CurItem->GrStrokeEndX, CurItem->GrStrokeEndY));
+			double radEnd = distance(CurItem->GrStrokeEndX - CurItem->GrStrokeStartX, CurItem->GrStrokeEndY - CurItem->GrStrokeStartY);
+			double rotEnd = xy2Deg(CurItem->GrStrokeEndX - CurItem->GrStrokeStartX, CurItem->GrStrokeEndY - CurItem->GrStrokeStartY);
+			QTransform m;
+			m.translate(CurItem->GrStrokeStartX, CurItem->GrStrokeStartY);
+			m.rotate(rotEnd);
+			m.rotate(-90);
+			m.rotate(CurItem->GrStrokeSkew);
+			m.translate(radEnd * CurItem->GrStrokeScale, 0);
+			QPointF shP = m.map(QPointF(0,0));
+			upRect = upRect.united(QRectF(shP, QPointF(CurItem->GrStrokeEndX, CurItem->GrStrokeEndY)).normalized());
+			upRect = upRect.united(QRectF(shP, QPointF(CurItem->GrStrokeStartX, CurItem->GrStrokeStartY)).normalized());
+			upRect |= QRectF(shP, QPointF(0, 0)).normalized();
+			upRect |= QRectF(shP, QPointF(CurItem->width(), CurItem->height())).normalized();
 		}
 		else
 		{
@@ -4619,7 +4634,8 @@
 			CurItem->GrEndY = y2 / m_unitRatio;
 			CurItem->GrFocalX = fx / m_unitRatio;
 			CurItem->GrFocalY = fy / m_unitRatio;
-			CurItem->GrScale = sg / m_unitRatio;
+			CurItem->GrScale = sg;
+			CurItem->GrSkew = sk;
 			if (CurItem->GrTypeStroke == 6)
 			{
 				CurItem->GrFocalX = CurItem->GrStartX;
@@ -4627,6 +4643,19 @@
 			}
 			CurItem->update();
 			upRect = QRectF(QPointF(CurItem->GrStartX, CurItem->GrStartY), QPointF(CurItem->GrEndX, CurItem->GrEndY));
+			double radEnd = distance(CurItem->GrEndX - CurItem->GrStartX, CurItem->GrEndY - CurItem->GrStartY);
+			double rotEnd = xy2Deg(CurItem->GrEndX - CurItem->GrStartX, CurItem->GrEndY - CurItem->GrStartY);
+			QTransform m;
+			m.translate(CurItem->GrStartX, CurItem->GrStartY);
+			m.rotate(rotEnd);
+			m.rotate(-90);
+			m.rotate(CurItem->GrSkew);
+			m.translate(radEnd * CurItem->GrScale, 0);
+			QPointF shP = m.map(QPointF(0,0));
+			upRect |= QRectF(shP, QPointF(CurItem->GrEndX, CurItem->GrEndY)).normalized();
+			upRect |= QRectF(shP, QPointF(CurItem->GrStartX, CurItem->GrStartY)).normalized();
+			upRect |= QRectF(shP, QPointF(0, 0)).normalized();
+			upRect |= QRectF(shP, QPointF(CurItem->width(), CurItem->height())).normalized();
 		}
 		upRect.translate(CurItem->xPos(), CurItem->yPos());
 		doc->regionsChanged()->update(upRect.adjusted(-10.0, -10.0, 10.0, 10.0));
@@ -5638,7 +5667,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, currItem->GrFocalX * dur, currItem->GrFocalY * dur, currItem->GrScale);
+		Cpal->setSpecialGradient(currItem->GrStartX * dur, currItem->GrStartY * dur, currItem->GrEndX * dur, currItem->GrEndY * dur, currItem->GrFocalX * dur, currItem->GrFocalY * dur, currItem->GrScale, currItem->GrSkew);
 }
 
 void PropertiesPalette::updateSpinBoxConstants()
Index: scribus/plugins/xarimplugin/importxar.cpp
===================================================================
--- scribus/plugins/xarimplugin/importxar.cpp	(revision 14283)
+++ scribus/plugins/xarimplugin/importxar.cpp	(revision 14284)
@@ -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(), gc->GradFillX1 - item->xPos(), gc->GradFillY1 - item->yPos(), 1.0);
+				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, 0.0);
 			}
 		}
 	}
Index: scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(revision 14283)
+++ scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(revision 14284)
@@ -1192,6 +1192,7 @@
 				docu.writeAttribute("GRFOCALX", item->GrFocalX);
 				docu.writeAttribute("GRFOCALY", item->GrFocalY);
 				docu.writeAttribute("GRSCALE" , item->GrScale);
+				docu.writeAttribute("GRSKEW" , item->GrSkew);
 			}
 		}
 		if (!item->gradient().isEmpty())
@@ -1207,6 +1208,7 @@
 			docu.writeAttribute("GRFOCALXS", item->GrStrokeFocalX);
 			docu.writeAttribute("GRFOCALYS", item->GrStrokeFocalY);
 			docu.writeAttribute("GRSCALES" , item->GrStrokeScale);
+			docu.writeAttribute("GRSKEWS" , item->GrStrokeSkew);
 		}
 		if (!item->strokePattern().isEmpty())
 		{
Index: scribus/plugins/fileloader/scribus150format/scribus150format.cpp
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(revision 14283)
+++ scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(revision 14284)
@@ -2777,6 +2777,7 @@
 			currItem->GrFocalX = attrs.valueAsDouble("GRFOCALX", 0.0);
 			currItem->GrFocalY = attrs.valueAsDouble("GRFOCALY", 0.0);
 			currItem->GrScale  = attrs.valueAsDouble("GRSCALE", 1.0);
+			currItem->GrSkew  = attrs.valueAsDouble("GRSKEW", 0.0);
 			GrColor = attrs.valueAsString("GRCOLOR","");
 			if (!GrColor.isEmpty())
 			{
@@ -2837,6 +2838,7 @@
 	currItem->GrStrokeFocalX = attrs.valueAsDouble("GRFOCALXS", 0.0);
 	currItem->GrStrokeFocalY = attrs.valueAsDouble("GRFOCALYS", 0.0);
 	currItem->GrStrokeScale  = attrs.valueAsDouble("GRSCALES", 1.0);
+	currItem->GrStrokeScale  = attrs.valueAsDouble("GRSKEWS", 0.0);
 	QString GrNameS = "";
 	GrNameS = attrs.valueAsString("GRNAMES","");
 	if (!GrNameS.isEmpty())
Index: scribus/plugins/svgexplugin/svgexplugin.cpp
===================================================================
--- scribus/plugins/svgexplugin/svgexplugin.cpp	(revision 14283)
+++ scribus/plugins/svgexplugin/svgexplugin.cpp	(revision 14284)
@@ -1601,6 +1601,35 @@
 					grad.setAttribute("fx", FToStr(Item->GrFocalX));
 					grad.setAttribute("fy", FToStr(Item->GrFocalY));
 				}
+				double gradientSkew;
+				if (Item->GrSkew == 90)
+					gradientSkew = 1;
+				else if (Item->GrSkew == 180)
+					gradientSkew = 0;
+				else if (Item->GrSkew == 270)
+					gradientSkew = -1;
+				else if (Item->GrSkew == 390)
+					gradientSkew = 0;
+				else
+					gradientSkew = tan(M_PI / 180.0 * Item->GrSkew);
+				QTransform qmatrix;
+				if (Item->GrType == 6)
+				{
+					qmatrix.translate(Item->GrStartX, Item->GrStartY);
+					qmatrix.shear(-gradientSkew, 0);
+					qmatrix.translate(-Item->GrStartX, -Item->GrStartY);
+				}
+				else
+				{
+					double rotEnd = xy2Deg(Item->GrEndX - Item->GrStartX, Item->GrEndY - Item->GrStartY);
+					qmatrix.translate(Item->GrStartX, Item->GrStartY);
+					qmatrix.rotate(rotEnd);
+					qmatrix.shear(gradientSkew, 0);
+					qmatrix.translate(0, Item->GrStartY * (1.0 - Item->GrScale));
+					qmatrix.translate(-Item->GrStartX, -Item->GrStartY);
+					qmatrix.scale(1, Item->GrScale);
+				}
+				grad.setAttribute("gradientTransform", MatrixToStr(qmatrix));
 				grad.setAttribute("id", "Grad"+IToStr(GradCount));
 				grad.setAttribute("gradientUnits", "userSpaceOnUse");
 				QList<VColorStop*> cstops = Item->fill_gradient.colorStops();
@@ -1840,6 +1869,35 @@
 			itcl.setAttribute("stop-color", SetColor(cstops.at(cst)->name, cstops.at(cst)->shade));
 			grad.appendChild(itcl);
 		}
+		double gradientSkew;
+		if (Item->GrStrokeSkew == 90)
+			gradientSkew = 1;
+		else if (Item->GrStrokeSkew == 180)
+			gradientSkew = 0;
+		else if (Item->GrStrokeSkew == 270)
+			gradientSkew = -1;
+		else if (Item->GrStrokeSkew == 390)
+			gradientSkew = 0;
+		else
+			gradientSkew = tan(M_PI / 180.0 * Item->GrStrokeSkew);
+		QTransform qmatrix;
+		if (Item->GrType == 6)
+		{
+			qmatrix.translate(Item->GrStrokeStartX, Item->GrStrokeStartY);
+			qmatrix.shear(-gradientSkew, 0);
+			qmatrix.translate(-Item->GrStrokeStartX, -Item->GrStrokeStartY);
+		}
+		else
+		{
+			double rotEnd = xy2Deg(Item->GrStrokeEndX - Item->GrStrokeStartX, Item->GrStrokeEndY - Item->GrStrokeStartY);
+			qmatrix.translate(Item->GrStrokeStartX, Item->GrStrokeStartY);
+			qmatrix.rotate(rotEnd);
+			qmatrix.shear(gradientSkew, 0);
+			qmatrix.translate(0, Item->GrStrokeStartY * (1.0 - Item->GrStrokeScale));
+			qmatrix.translate(-Item->GrStrokeStartX, -Item->GrStrokeStartY);
+			qmatrix.scale(1, Item->GrStrokeScale);
+		}
+		grad.setAttribute("gradientTransform", MatrixToStr(qmatrix));
 		grad.setAttribute("id", "Grad"+IToStr(GradCount));
 		grad.setAttribute("gradientUnits", "userSpaceOnUse");
 		globalDefs.appendChild(grad);
Index: scribus/scpreview.cpp
===================================================================
--- scribus/scpreview.cpp	(revision 14283)
+++ scribus/scpreview.cpp	(revision 14284)
@@ -235,6 +235,10 @@
 				OB.GrStartY = ScCLocale::toDoubleC(pg.attribute("GRSTARTY"), 0.0);
 				OB.GrEndX = ScCLocale::toDoubleC(pg.attribute("GRENDX"), 0.0);
 				OB.GrEndY = ScCLocale::toDoubleC(pg.attribute("GRENDY"), 0.0);
+				OB.GrFocalX = ScCLocale::toDoubleC(pg.attribute("GRFOCALX"), 0.0);
+				OB.GrFocalY = ScCLocale::toDoubleC(pg.attribute("GRFOCALY"), 0.0);
+				OB.GrScale  = ScCLocale::toDoubleC(pg.attribute("GRSCALE"), 1.0);
+				OB.GrSkew   = ScCLocale::toDoubleC(pg.attribute("GRSKEW"), 0.0);
 				OB.GrColor = pg.attribute("GRCOLOR","");
 				if (!OB.GrColor.isEmpty())
 				{
@@ -533,35 +537,35 @@
 				case 1:
 					gra.setPoints(2, 0, 0, OB.Width, 0);
 					gra.map(grm);
-					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
+					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1), FPoint(0,0), 1, 0);
 					break;
 				case 2:
 					gra.setPoints(2, 0, 0, OB.Height, 0);
 					grm.rotate(90);
 					gra.map(grm);
-					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
+					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1), FPoint(0,0), 1, 0);
 					break;
 				case 3:
 					gra.setPoints(2, 0, 0, OB.Width, OB.Height);
 					gra.map(grm);
-					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
+					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1), FPoint(0,0), 1, 0);
 					break;
 				case 4:
 					gra.setPoints(2, 0, OB.Height, OB.Width, 0);
 					gra.map(grm);
-					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
+					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1), FPoint(0,0), 1, 0);
 					break;
 				case 5:
 					if (OB.Width > OB.Height)
 						gv = FPoint(OB.Width, OB.Height / 2.0);
 					else
 						gv = FPoint(OB.Width / 2.0, OB.Height);
-					pS->setGradient(VGradient::radial, FPoint(OB.Width / 2.0,OB.Height / 2.0), gv, FPoint(OB.Width / 2.0,OB.Height / 2.0));
+					pS->setGradient(VGradient::radial, FPoint(OB.Width / 2.0,OB.Height / 2.0), gv, FPoint(OB.Width / 2.0,OB.Height / 2.0), 1, 0);
 					break;
 				case 6:
 					gra.setPoints(2, OB.GrStartX, OB.GrStartY, OB.GrEndX, OB.GrEndY);
 					gra.map(grm);
-					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
+					pS->setGradient(VGradient::linear, gra.point(0), gra.point(1), FPoint(0,0), 1, 0);
 					break;
 				}
 			}
Index: scribus/pslib.cpp
===================================================================
--- scribus/pslib.cpp	(revision 14283)
+++ scribus/pslib.cpp	(revision 14284)
@@ -3459,7 +3459,7 @@
 
 void PSLib::HandleGradientFillStroke(PageItem *c, bool gcr, bool stroke, bool forArrow)
 {
-	double StartX, StartY, EndX, EndY, FocalX, FocalY;
+	double StartX, StartY, EndX, EndY, FocalX, FocalY, Gscale, Gskew;
 	int GType;
 	VGradient gradient;
 	QList<double> StopVec;
@@ -3475,6 +3475,8 @@
 		EndY = c->GrStrokeEndY;
 		FocalX = c->GrStrokeFocalX;
 		FocalY = c->GrStrokeFocalY;
+		Gscale = c->GrStrokeScale;
+		Gskew = c->GrStrokeSkew;
 		gradient = c->stroke_gradient;
 	}
 	else
@@ -3486,6 +3488,8 @@
 		EndY = c->GrEndY;
 		FocalX = c->GrFocalX;
 		FocalY = c->GrFocalY;
+		Gscale = c->GrScale;
+		Gskew = c->GrSkew;
 		gradient = c->fill_gradient;
 		if (GType == 8)
 		{
@@ -3696,7 +3700,35 @@
 	PutStream(">>\n");
 	PutStream(">>\n");
 	PutStream(">>\n");
-	PutStream("[1 0 0 1 0 0] makepattern setpattern\n");
+	QTransform qmatrix;
+	if (Gskew == 90)
+		Gskew = 1;
+	else if (Gskew == 180)
+		Gskew = 0;
+	else if (Gskew == 270)
+		Gskew = -1;
+	else if (Gskew == 390)
+		Gskew = 0;
+	else
+		Gskew = tan(M_PI / 180.0 * Gskew);
+	if (GType == 6)
+	{
+		qmatrix.translate(StartX, -StartY);
+		qmatrix.shear(Gskew, 0);
+		qmatrix.translate(-StartX, StartY);
+	}
+	else
+	{
+		double rotEnd = xy2Deg(EndX - StartX, EndY - StartY);
+		qmatrix.translate(StartX, -StartY);
+		qmatrix.rotate(-rotEnd);
+		qmatrix.shear(-Gskew, 0);
+		qmatrix.translate(0, -StartY * (1.0 - Gscale));
+		qmatrix.translate(-StartX, StartY);
+		qmatrix.scale(1, Gscale);
+	}
+	PutStream("["+ToStr(qmatrix.m11())+" "+ToStr(qmatrix.m12())+" "+ToStr(qmatrix.m21())+" "+ToStr(qmatrix.m22())+" "+ToStr(qmatrix.dx())+" "+ToStr(qmatrix.dy())+"] makepattern setpattern\n");
+//	PutStream("[1 0 0 1 0 0] makepattern setpattern\n");
 	if (forArrow)
 	{
 		if (fillRule)
Index: scribus/pageitem_desaxe.cpp
===================================================================
--- scribus/pageitem_desaxe.cpp	(revision 14283)
+++ scribus/pageitem_desaxe.cpp	(revision 14284)
@@ -310,6 +310,7 @@
 			gradientV.insert("GRFOCALX", toXMLString(GrFocalX));
 			gradientV.insert("GRFOCALY", toXMLString(GrFocalY));
 			gradientV.insert("GRSCALE", toXMLString(GrScale));
+			gradientV.insert("GRSKEW", toXMLString(GrSkew));
 			gradientV.insert("GRNAME", toXMLString(gradient()));
 			handler.begin("Gradient", gradientV);
 			QList<VColorStop*> cstops = fill_gradient.colorStops();
@@ -336,6 +337,7 @@
 			gradientV.insert("GRFOCALXS", toXMLString(GrStrokeFocalX));
 			gradientV.insert("GRFOCALYS", toXMLString(GrStrokeFocalY));
 			gradientV.insert("GRSCALES", toXMLString(GrStrokeScale));
+			gradientV.insert("GRSKEWS", toXMLString(GrStrokeSkew));
 			gradientV.insert("GRNAMES", toXMLString(strokeGradient()));
 			handler.begin("GradientS", gradientV);
 			QList<VColorStop*> cstops = fill_gradient.colorStops();
@@ -582,6 +584,7 @@
 			item->GrStrokeFocalX = parseDouble(attr["GRFOCALXS"]);
 			item->GrStrokeFocalY = parseDouble(attr["GRFOCALYS"]);
 			item->GrStrokeScale = parseDouble(attr["GRSCALES"]);
+			item->GrStrokeSkew = parseDouble(attr["GRSKEwS"]);
 			item->setStrokeGradient(attr["GRNAMES"]);
 			item->stroke_gradient.clearStops();
 		}
@@ -596,6 +599,7 @@
 			item->GrFocalX = parseDouble(attr["GRFOCALX"]);
 			item->GrFocalY = parseDouble(attr["GRFOCALY"]);
 			item->GrScale = parseDouble(attr["GRSCALE"]);
+			item->GrSkew = parseDouble(attr["GRSKEW"]);
 			item->setGradient(attr["GRNAME"]);
 			item->fill_gradient.clearStops();
 		}
Index: scribus/canvasmode_editgradient.h
===================================================================
--- scribus/canvasmode_editgradient.h	(revision 14283)
+++ scribus/canvasmode_editgradient.h	(revision 14284)
@@ -55,7 +55,8 @@
 		noPointDefined,
 		useGradientStart,
 		useGradientEnd,
-		useGradientFocal
+		useGradientFocal,
+		useGradientSkew
 	} eGradientPoint;
 
 	inline bool GetItem(PageItem** pi);
Index: scribus/scpainter.h
===================================================================
--- scribus/scpainter.h	(revision 14283)
+++ scribus/scpainter.h	(revision 14284)
@@ -69,7 +69,7 @@
 	virtual bool fillRule() { return m_fillRule; }
 	virtual void setFillMode( int fill );
 	virtual void setStrokeMode( int stroke );
-	virtual void setGradient( VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc = FPoint(0,0));
+	virtual void setGradient( VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc, double scale, double skew);
 	virtual void setPattern(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY);
 	virtual void setClipPath();
 
@@ -158,6 +158,8 @@
 	double patternSkewY;
 	bool patternMirrorX;
 	bool patternMirrorY;
+	double gradientScale;
+	double gradientSkew;
 	/*! \brief Stroking */
 	QColor m_stroke;
 	double stroke_trans;




More information about the scribus-commit mailing list