r14297 by fschmid - Gradient Masks Part 1: Framework (load, save etc...)

scribus-commit scribus-commit at lists.scribus.net
Mon Nov 16 15:11:12 CET 2009


Revision: 14297
Author: fschmid
Date: 2009-11-16T05:54:20.614396Z
Commit message: Gradient Masks Part 1: Framework (load, save etc...)

Changeset: 
M  /trunk/Scribus/scribus/scpainter.cpp
M  /trunk/Scribus/scribus/pageitem.cpp
M  /trunk/Scribus/scribus/scribusXml.cpp
M  /trunk/Scribus/scribus/scpainter.h
M  /trunk/Scribus/scribus/pageitem.h
M  /trunk/Scribus/scribus/scribusdoc.cpp
M  /trunk/Scribus/scribus/documentchecker.cpp
M  /trunk/Scribus/scribus/plugins/xarimplugin/importxar.cpp
M  /trunk/Scribus/scribus/scribusdoc.h
M  /trunk/Scribus/scribus/scribusview.cpp
M  /trunk/Scribus/scribus/scribusstructs.h
M  /trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
M  /trunk/Scribus/scribus/serializer.cpp
M  /trunk/Scribus/scribus/plugins/xarimplugin/importxar.h
M  /trunk/Scribus/scribus/ui/hruler.cpp
M  /trunk/Scribus/scribus/pageitem_desaxe.cpp
M  /trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp

Diffs:
Index: scribus/documentchecker.cpp
===================================================================
--- scribus/documentchecker.cpp	(revision 14296)
+++ scribus/documentchecker.cpp	(revision 14297)
@@ -109,6 +109,20 @@
 				}
 			}
 		}
+		if ((currItem->GrTypeStroke != 0) && (checkerSettings.checkTransparency))
+		{
+			QList<VColorStop*> colorStops = currItem->stroke_gradient.colorStops();
+			for( int offset = 0 ; offset < colorStops.count() ; offset++ )
+			{
+				if (colorStops[offset]->opacity != 1.0)
+				{
+					itemError.insert(Transparency, 0);
+					break;
+				}
+			}
+		}
+		if ((currItem->GrMask > 0) && (checkerSettings.checkTransparency))
+			itemError.insert(Transparency, 0);
 		if ((currItem->OwnPage == -1) && (checkerSettings.checkOrphans))
 			itemError.insert(ObjectNotOnPage, 0);
 #ifdef HAVE_OSG
@@ -321,6 +335,20 @@
 				}
 			}
 		}
+		if ((currItem->GrTypeStroke != 0) && (checkerSettings.checkTransparency))
+		{
+			QList<VColorStop*> colorStops = currItem->stroke_gradient.colorStops();
+			for( int offset = 0 ; offset < colorStops.count() ; offset++ )
+			{
+				if (colorStops[offset]->opacity != 1.0)
+				{
+					itemError.insert(Transparency, 0);
+					break;
+				}
+			}
+		}
+		if ((currItem->GrMask > 0) && (checkerSettings.checkTransparency))
+			itemError.insert(Transparency, 0);
 		if (((currItem->isAnnotation()) || (currItem->isBookmark)) && (checkerSettings.checkAnnotations))
 			itemError.insert(PDFAnnotField, 0);
 		if ((currItem->OwnPage == -1) && (checkerSettings.checkOrphans))
Index: scribus/serializer.cpp
===================================================================
--- scribus/serializer.cpp	(revision 14296)
+++ scribus/serializer.cpp	(revision 14297)
@@ -475,6 +475,13 @@
 			if (colors.contains(grStop->name))
 				grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
 		}
+		cstops = ite->mask_gradient.colorStops();
+		for (uint cst = 0; cst < ite->mask_gradient.Stops(); ++cst)
+		{
+			grStop = cstops.at(cst);
+			if (colors.contains(grStop->name))
+				grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
+		}
 	}
 	uint masterItemsCount =  m_Doc.MasterItems.count();
 	for (uint c=0; c < masterItemsCount; ++c)
@@ -494,6 +501,13 @@
 			if (colors.contains(grStop->name))
 				grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
 		}
+		cstops = ite->mask_gradient.colorStops();
+		for (uint cst = 0; cst < ite->mask_gradient.Stops(); ++cst)
+		{
+			grStop = cstops.at(cst);
+			if (colors.contains(grStop->name))
+				grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
+		}
 	}
 	uint frameItemsCount = m_Doc.FrameItems.count();
 	for (uint c=0; c < frameItemsCount; ++c)
@@ -513,6 +527,13 @@
 			if (colors.contains(grStop->name))
 				grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
 		}
+		cstops = ite->mask_gradient.colorStops();
+		for (uint cst = 0; cst < ite->mask_gradient.Stops(); ++cst)
+		{
+			grStop = cstops.at(cst);
+			if (colors.contains(grStop->name))
+				grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
+		}
 	}
 	QStringList patterns =m_Doc.docPatterns.keys();
 	for (int c = 0; c < patterns.count(); ++c)
@@ -535,6 +556,13 @@
 				if (colors.contains(grStop->name))
 					grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
 			}
+			cstops = ite->mask_gradient.colorStops();
+			for (uint cst = 0; cst < ite->mask_gradient.Stops(); ++cst)
+			{
+				grStop = cstops.at(cst);
+				if (colors.contains(grStop->name))
+					grStop->color = SetColor(&m_Doc, grStop->name, grStop->shade);
+			}
 		}
 	}
 }
Index: scribus/scribusdoc.cpp
===================================================================
--- scribus/scribusdoc.cpp	(revision 14296)
+++ scribus/scribusdoc.cpp	(revision 14297)
@@ -2727,6 +2727,11 @@
 			if (!results.contains(MasterItems.at(c)->strokePattern()))
 				results.append(MasterItems.at(c)->strokePattern());
 		}
+		if (!MasterItems.at(c)->patternMask().isEmpty())
+		{
+			if (!results.contains(MasterItems.at(c)->patternMask()))
+				results.append(MasterItems.at(c)->patternMask());
+		}
 	}
 	for (int c = 0; c < DocItems.count(); ++c)
 	{
@@ -2737,6 +2742,11 @@
 			if (!results.contains(DocItems.at(c)->strokePattern()))
 				results.append(DocItems.at(c)->strokePattern());
 		}
+		if (!DocItems.at(c)->patternMask().isEmpty())
+		{
+			if (!results.contains(DocItems.at(c)->patternMask()))
+				results.append(DocItems.at(c)->patternMask());
+		}
 	}
 	for (int c = 0; c < FrameItems.count(); ++c)
 	{
@@ -2747,6 +2757,11 @@
 			if (!results.contains(FrameItems.at(c)->strokePattern()))
 				results.append(FrameItems.at(c)->strokePattern());
 		}
+		if (!FrameItems.at(c)->patternMask().isEmpty())
+		{
+			if (!results.contains(FrameItems.at(c)->patternMask()))
+				results.append(FrameItems.at(c)->patternMask());
+		}
 	}
 	for (int c = 0; c < results.count(); ++c)
 	{
@@ -2776,6 +2791,9 @@
 			const QString& pat2 = currItem->strokePattern();
 			if (!pat2.isEmpty() && !results.contains(pat2))
 				results.append(currItem->strokePattern());
+			const QString& pat3 = currItem->patternMask();
+			if (!pat3.isEmpty() && !results.contains(pat3))
+				results.append(currItem->patternMask());
 		}
 		for (int c = 0; c < results.count(); ++c)
 		{
@@ -2806,6 +2824,9 @@
 		const QString& pat2 = pat->items.at(c)->strokePattern();
 		if (!pat2.isEmpty() && !results.contains(pat2))
 			results.append(pat->items.at(c)->strokePattern());
+		const QString& pat3 = pat->items.at(c)->patternMask();
+		if (!pat3.isEmpty() && !results.contains(pat3))
+			results.append(pat->items.at(c)->patternMask());
 	}
 	if (!pats.isEmpty())
 	{
@@ -3400,6 +3421,12 @@
 		QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
 		for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
 			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
+		cstops = ite->stroke_gradient.colorStops();
+		for (uint cst = 0; cst < ite->stroke_gradient.Stops(); ++cst)
+			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
+		cstops = ite->mask_gradient.colorStops();
+		for (uint cst = 0; cst < ite->mask_gradient.Stops(); ++cst)
+			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
 	}
 	uint masterItemsCount=MasterItems.count();
 	for (uint c=0; c<masterItemsCount; ++c)
@@ -3408,6 +3435,12 @@
 		QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
 		for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
 			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
+		cstops = ite->stroke_gradient.colorStops();
+		for (uint cst = 0; cst < ite->stroke_gradient.Stops(); ++cst)
+			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
+		cstops = ite->mask_gradient.colorStops();
+		for (uint cst = 0; cst < ite->mask_gradient.Stops(); ++cst)
+			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
 	}
 	uint frameItemsCount=FrameItems.count();
 	for (uint c=0; c<frameItemsCount; ++c)
@@ -3416,6 +3449,12 @@
 		QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
 		for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
 			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
+		cstops = ite->stroke_gradient.colorStops();
+		for (uint cst = 0; cst < ite->stroke_gradient.Stops(); ++cst)
+			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
+		cstops = ite->mask_gradient.colorStops();
+		for (uint cst = 0; cst < ite->mask_gradient.Stops(); ++cst)
+			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
 	}
 	QStringList patterns = docPatterns.keys();
 	for (int c = 0; c < patterns.count(); ++c)
@@ -3427,6 +3466,12 @@
 			QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
 			for (uint cst = 0; cst < ite->fill_gradient.Stops(); ++cst)
 				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
+			cstops = ite->stroke_gradient.colorStops();
+			for (uint cst = 0; cst < ite->stroke_gradient.Stops(); ++cst)
+				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
+			cstops = ite->mask_gradient.colorStops();
+			for (uint cst = 0; cst < ite->mask_gradient.Stops(); ++cst)
+				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
 			if (ite->asImageFrame())
 				loadPict(ite->Pfile, ite, true, false);
 		}
@@ -7655,7 +7700,6 @@
 //Teaser for jghali
 }
 
-
 void ScribusDoc::itemSelection_SetFillGradient(VGradient& newGradient, Selection* customSelection)
 {
 	Selection* itemSelection = (customSelection!=0) ? customSelection : m_Selection;
@@ -7671,13 +7715,30 @@
 		currItem->fill_gradient = newGradient;
 		currItem->update();
 	}
-	/*if (selectedItemCount>1)
-		regionsChanged()->update(QRectF());*/
 	m_updateManager.setUpdatesEnabled();
 	changed();
 }
 
+void ScribusDoc::itemSelection_SetMaskGradient(VGradient& newGradient, Selection* customSelection)
+{
+	Selection* itemSelection = (customSelection!=0) ? customSelection : m_Selection;
+	assert(itemSelection!=0);
+	uint selectedItemCount=itemSelection->count();
+	if (selectedItemCount == 0)
+		return;
+	m_updateManager.setUpdatesDisabled();
+	for (uint i = 0; i < selectedItemCount; ++i)
+	{
+		PageItem *currItem;
+		currItem = itemSelection->itemAt(i);
+		currItem->mask_gradient = newGradient;
+		currItem->update();
+	}
+	m_updateManager.setUpdatesEnabled();
+	changed();
+}
 
+
 void ScribusDoc::itemSelection_SetOverprint(bool overprint, Selection* customSelection)
 {
 	Selection* itemSelection = (customSelection!=0) ? customSelection : m_Selection;
Index: scribus/scribusXml.cpp
===================================================================
--- scribus/scribusXml.cpp	(revision 14296)
+++ scribus/scribusXml.cpp	(revision 14297)
@@ -215,6 +215,32 @@
 		OB->GrStrokeScale  = attrAsDbl(attrs, "GRSCALES", 1.0);
 		OB->GrStrokeSkew   = attrAsDbl(attrs, "GRSKEWS", 1.0);
 	}
+	OB->GrMask = attrAsInt(attrs, "GRTYPM"  , 0);
+	if (OB->GrMask == 1)
+	{
+		OB->mask_gradient.clearStops();
+		OB->GrMaskStartX = attrAsDbl(attrs, "GRSTARTXM", 0.0);
+		OB->GrMaskStartY = attrAsDbl(attrs, "GRSTARTYM", 0.0);
+		OB->GrMaskEndX   = attrAsDbl(attrs, "GRENDXM", 0.0);
+		OB->GrMaskEndY   = attrAsDbl(attrs, "GRENDYM", 0.0);
+		OB->GrMaskFocalX = attrAsDbl(attrs, "GRFOCALXM", 0.0);
+		OB->GrMaskFocalY = attrAsDbl(attrs, "GRFOCALYM", 0.0);
+		OB->GrMaskScale  = attrAsDbl(attrs, "GRSCALEM", 1.0);
+		OB->GrMaskSkew   = attrAsDbl(attrs, "GRSKEWM", 1.0);
+	}
+	if (OB->GrMask == 2)
+	{
+		OB->patternMaskVal = attrAsString(attrs, "patternM", "");
+		OB->patternMaskScaleX   = attrAsDbl(attrs, "pScaleXM", 100.0);
+		OB->patternMaskScaleY   = attrAsDbl(attrs, "pScaleYM", 100.0);
+		OB->patternMaskOffsetX  = attrAsDbl(attrs, "pOffsetXM", 0.0);
+		OB->patternMaskOffsetY  = attrAsDbl(attrs, "pOffsetYM", 0.0);
+		OB->patternMaskRotation = attrAsDbl(attrs, "pRotationM", 0.0);
+		OB->patternMaskSkewX    = attrAsDbl(attrs, "pSkewXM", 0.0);
+		OB->patternMaskSkewY    = attrAsDbl(attrs, "pSkewYM", 0.0);
+		OB->patternMaskMirrorX  = attrAsBool(attrs, "pMirrorXM", false);
+		OB->patternMaskMirrorY  = attrAsBool(attrs, "pMirrorYM", false);
+	}
 	OB->Rot        = attrAsDbl(attrs, "ROT", 0.0);
 	OB->PLineArt   = Qt::PenStyle    ( attrAsInt(attrs, "PLINEART", 0) );
 	OB->PLineEnd   = Qt::PenCapStyle ( attrAsInt(attrs, "PLINEEND", 0) );
@@ -1242,6 +1268,7 @@
 	bool patternMirrorX;
 	bool patternMirrorY;
 	QString gradNameS;
+	QString gradNameM;
 	while(!sReader.atEnd() && !sReader.hasError())
 	{
 		sReader.readNext();
@@ -1263,6 +1290,7 @@
 			OB.NamedLStyle     = attrAsString(attrs, "NAMEDLST", "");
 			gradName           = attrAsString(attrs, "GRNAME", "");
 			gradNameS          = attrAsString(attrs, "GRNAMES", "");
+			gradNameM          = attrAsString(attrs, "GRNAMEM", "");
 			isGroupControl     = attrAsBool(attrs, "isGroupControl", false);
 			doOverprint        = attrAsBool(attrs, "doOverprint", false);
 			groupsLastItem     = attrAsInt (attrs, "groupsLastItem", 0);
@@ -1441,6 +1469,14 @@
 			OB.GrColor   = "";
 			OB.GrColor2  = "";
 		}
+		if (inItem && sReader.isStartElement() && tagName == "M_CSTOP")
+		{
+			QString name = attrAsString(attrs, "NAME", "");
+			double ramp  = attrAsDbl(attrs, "RAMP", 0.0);
+			int shade    = attrAsInt(attrs, "SHADE", 100);
+			double opa   = attrAsDbl(attrs, "TRANS", 1.0);
+			OB.mask_gradient.addStop(SetColor(doc, name, shade), ramp, 0.5, opa, name, shade);
+		}
 		if (inItem && sReader.isStartElement() && tagName == "Tabs")
 		{
 			ParagraphStyle::TabRecord tb;
@@ -1491,6 +1527,7 @@
 			PageItem* Neu = doc->Items->at(doc->Items->count()-1);
 			Neu->setGradient(gradName);
 			Neu->setStrokeGradient(gradNameS);
+			Neu->setGradientMask(gradNameM);
 			Neu->doOverprint = doOverprint;
 			Neu->setStrokePattern(StrokePattern);
 			Neu->setStrokePatternTransform(patternScaleXS, patternScaleYS, patternOffsetXS, patternOffsetYS, patternRotationS, patternSkewXS, patternSkewYS);
@@ -1674,6 +1711,7 @@
 	bool patternMirrorXS;
 	bool patternMirrorYS;
 	QString gradNameS;
+	QString gradNameM;
 	int lowResType = 1;
 	int actualPageNumber = 0;
 	while(!reader.atEnd() && !reader.hasError())
@@ -1696,6 +1734,7 @@
 			actualPageNumber   = attrAsInt (attrs1, "Pagenumber", 0);
 			gradName           = attrAsString(attrs1, "GRNAME", "");
 			gradNameS          = attrAsString(attrs1, "GRNAMES", "");
+			gradNameM          = attrAsString(attrs1, "GRNAMEM", "");
 			StrokePattern = attrAsString(attrs, "patternS", "");
 			patternScaleXS   = attrAsDbl(attrs, "pScaleXS", 100.0);
 			patternScaleYS   = attrAsDbl(attrs, "pScaleYS", 100.0);
@@ -1804,6 +1843,14 @@
 			OB.GrColor   = "";
 			OB.GrColor2  = "";
 		}
+		if (tagName1 == "M_CSTOP" && reader.isStartElement())
+		{
+			QString name = attrs1.value("NAME").toString();
+			double ramp  = attrAsDbl(attrs1, "RAMP", 0.0);
+			int shade    = attrAsInt(attrs1, "SHADE", 100);
+			double opa   = attrAsDbl(attrs1, "TRANS", 1.0);
+			OB.mask_gradient.addStop(SetColor(doc, name, shade), ramp, 0.5, opa, name, shade);
+		}
 		if (tagName1=="Tabs" && reader.isStartElement())
 		{
 			ParagraphStyle::TabRecord tb;
@@ -1848,6 +1895,7 @@
 			Neu->doOverprint = doOverprint;
 			Neu->setGradient(gradName);
 			Neu->setStrokeGradient(gradNameS);
+			Neu->setGradientMask(gradNameM);
 			Neu->setStrokePattern(StrokePattern);
 			Neu->setStrokePatternTransform(patternScaleXS, patternScaleYS, patternOffsetXS, patternOffsetYS, patternRotationS, patternSkewXS, patternSkewYS);
 			Neu->setStrokePatternFlip(patternMirrorXS, patternMirrorYS);
@@ -2499,6 +2547,49 @@
 		writer.writeAttribute("pMirrorXS" , mirrorX);
 		writer.writeAttribute("pMirrorYS" , mirrorY);
 	}
+	if (item->GrMask > 0)
+	{
+		if (item->gradientMask().isEmpty())
+		{
+			QList<VColorStop*> cstops = item->mask_gradient.colorStops();
+			for (uint cst = 0; cst < item->mask_gradient.Stops(); ++cst)
+			{
+				writer.writeStartElement("M_CSTOP");
+				writer.writeAttribute("RAMP" , cstops.at(cst)->rampPoint);
+				writer.writeAttribute("NAME" , cstops.at(cst)->name);
+				writer.writeAttribute("SHADE", cstops.at(cst)->shade);
+				writer.writeAttribute("TRANS", cstops.at(cst)->opacity);
+				writer.writeEndElement();
+			}
+		}
+		else
+			writer.writeAttribute("GRNAMEM"  , item->gradientMask());
+		writer.writeAttribute("GRSTARTXM", item->GrMaskStartX);
+		writer.writeAttribute("GRSTARTYM", item->GrMaskStartY);
+		writer.writeAttribute("GRENDXM", item->GrMaskEndX);
+		writer.writeAttribute("GRENDYM", item->GrMaskEndY);
+		writer.writeAttribute("GRFOCALXM", item->GrMaskFocalX);
+		writer.writeAttribute("GRFOCALYM", item->GrMaskFocalY);
+		writer.writeAttribute("GRSCALEM" , item->GrMaskScale);
+		writer.writeAttribute("GRSKEWM" , item->GrMaskSkew);
+	}
+	if (!item->patternMask().isEmpty())
+	{
+		writer.writeAttribute("patternM", item->patternMask());
+		double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
+		item->maskTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
+		bool mirrorX, mirrorY;
+		item->maskFlip(mirrorX, mirrorY);
+		writer.writeAttribute("pScaleXM", patternScaleX);
+		writer.writeAttribute("pScaleYM", patternScaleY);
+		writer.writeAttribute("pOffsetXM", patternOffsetX);
+		writer.writeAttribute("pOffsetYM", patternOffsetY);
+		writer.writeAttribute("pRotationM", patternRotation);
+		writer.writeAttribute("pSkewXM"   , patternSkewX);
+		writer.writeAttribute("pSkewYM"   , patternSkewY);
+		writer.writeAttribute("pMirrorXM" , mirrorX);
+		writer.writeAttribute("pMirrorYM" , mirrorY);
+	}
 	if (item->asLatexFrame())
 	{
 		PageItem_LatexFrame *latexitem = item->asLatexFrame();
Index: scribus/pageitem.h
===================================================================
--- scribus/pageitem.h	(revision 14296)
+++ scribus/pageitem.h	(revision 14297)
@@ -605,6 +605,19 @@
 	void setStrokeGradientType(int val) { GrTypeStroke = val; }
 	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);
+
+	int maskType() const { return GrMask; }
+	void setMaskType(int val) { GrMask = val; }
+	void setGradientMask(const QString &newMask);
+	void setPatternMask(const QString &newMask);
+	QString gradientMask() const { return gradientMaskVal; }
+	QString patternMask() const { return patternMaskVal; }
+	void maskVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const;
+	void setMaskVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew);
+	void maskTransform(double &scaleX, double &scaleY, double &offsetX, double &offsetY, double &rotation, double &skewX, double &skewY) const;
+	void setMaskTransform(double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY);
+	void setMaskFlip(bool flipX, bool flipY);
+	void maskFlip(bool &flipX, bool &flipY);
 	// 
 	bool fillEvenOdd() const { return fillRule; }
 	void setFillEvenOdd(bool val) { fillRule = val; }
@@ -1386,6 +1399,31 @@
 	double GrStrokeScale;
 	double GrStrokeSkew;
 
+	/** 
+	* @brief Mask gradient variables
+	*/
+	int GrMask;
+	double GrMaskStartX;
+	double GrMaskStartY;
+	double GrMaskEndX;
+	double GrMaskEndY;
+	double GrMaskFocalX;
+	double GrMaskFocalY;
+	double GrMaskScale;
+	double GrMaskSkew;
+	double patternMaskScaleX;
+	double patternMaskScaleY;
+	double patternMaskOffsetX;
+	double patternMaskOffsetY;
+	double patternMaskRotation;
+	double patternMaskSkewX;
+	double patternMaskSkewY;
+	bool patternMaskMirrorX;
+	bool patternMaskMirrorY;
+	QString patternMaskVal;
+	QString gradientMaskVal;
+	VGradient mask_gradient;
+	
 	/** Inline Image */
 	bool isInlineImage;
 	QTemporaryFile *tempImageFile;
Index: scribus/scribusstructs.h
===================================================================
--- scribus/scribusstructs.h	(revision 14296)
+++ scribus/scribusstructs.h	(revision 14297)
@@ -103,6 +103,26 @@
 	double GrStrokeFocalY;
 	double GrStrokeScale;
 	double GrStrokeSkew;
+	int GrMask;
+	double GrMaskStartX;
+	double GrMaskStartY;
+	double GrMaskEndX;
+	double GrMaskEndY;
+	double GrMaskFocalX;
+	double GrMaskFocalY;
+	double GrMaskScale;
+	double GrMaskSkew;
+	double patternMaskScaleX;
+	double patternMaskScaleY;
+	double patternMaskOffsetX;
+	double patternMaskOffsetY;
+	double patternMaskRotation;
+	double patternMaskSkewX;
+	double patternMaskSkewY;
+	bool patternMaskMirrorX;
+	bool patternMaskMirrorY;
+	QString patternMaskVal;
+	VGradient mask_gradient;
 	QString TxtStroke;
 	QString TxtFill;
 	int ShTxtStroke;
Index: scribus/scpainter.cpp
===================================================================
--- scribus/scpainter.cpp	(revision 14296)
+++ scribus/scpainter.cpp	(revision 14297)
@@ -590,7 +590,7 @@
 			setupPolygon(&la.groupClip);
 			setClipPath();
 		}
-		painter.resetMatrix();
+		painter.resetTransform();
 		if ((m_blendMode > 0) && (m_blendMode < 12))
 		{
 			if (m_blendMode == 1)
@@ -822,6 +822,44 @@
 		gradientSkew = tan(M_PI / 180.0 * skew);
 }
 
+void ScPainter::setMaskMode(int mask)
+{
+	maskMode = mask;
+}
+
+void ScPainter::setGradientMask(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc, double scale, double skew)
+{
+	mask_gradient.setType(mode);
+	mask_gradient.setOrigin(orig);
+	mask_gradient.setVector(vec);
+	mask_gradient.setFocalPoint(foc);
+	mask_gradientScale = scale;
+	if (skew == 90)
+		mask_gradientSkew = 1;
+	else if (skew == 180)
+		mask_gradientSkew = 0;
+	else if (skew == 270)
+		mask_gradientSkew = -1;
+	else if (skew == 390)
+		mask_gradientSkew = 0;
+	else
+		mask_gradientSkew = tan(M_PI / 180.0 * skew);
+}
+
+void ScPainter::setPatternMask(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY)
+{
+	m_maskPattern = pattern;
+	mask_patternScaleX = scaleX / 100.0;
+	mask_patternScaleY = scaleY / 100.0;
+	mask_patternOffsetX = offsetX;
+	mask_patternOffsetY = offsetY;
+	mask_patternRotation = rotation;
+	mask_patternSkewX = skewX;
+	mask_patternSkewY = skewY;
+	mask_patternMirrorX = mirrorX;
+	mask_patternMirrorY = mirrorY;
+}
+
 void ScPainter::fillTextPath()
 {
 	drawVPath( 0 );
@@ -971,22 +1009,21 @@
 			double r, g, b;
 			m_fill.getRgbF(&r, &g, &b);
 /*
-	Experimental Code for testing gradient masks, sadly this feature
-	is only possible with cairo.
-			if (fill_trans != 1.0)
+	Experimental Code for testing gradient masks. */
+			if (maskMode == 1)
 			{
 				cairo_set_source_rgb( m_cr, r, g, b );
 				cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
 				cairo_pattern_t *pat;
-				double x1 = fill_gradient.origin().x();
-				double y1 = fill_gradient.origin().y();
-				double x2 = fill_gradient.vector().x();
-				double y2 = fill_gradient.vector().y();
-				if (fill_gradient.type() == VGradient::linear)
+				double x1 = mask_gradient.origin().x();
+				double y1 = mask_gradient.origin().y();
+				double x2 = mask_gradient.vector().x();
+				double y2 = mask_gradient.vector().y();
+				if (mask_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)));
-				QList<VColorStop*> colorStops = fill_gradient.colorStops();
+				QList<VColorStop*> colorStops = mask_gradient.colorStops();
 				QColor qStopColor;
 				for( int offset = 0 ; offset < colorStops.count() ; offset++ )
 				{
@@ -1002,17 +1039,37 @@
 					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 (mask_gradient.type() == VGradient::radial)
+				{
+					double rotEnd = xy2Deg(x2 - x1, y2 - y1);
+					qmatrix.translate(x1, y1);
+					qmatrix.rotate(rotEnd);
+					qmatrix.shear(mask_gradientSkew, 0);
+					qmatrix.translate(0, y1 * (1.0 - mask_gradientScale));
+					qmatrix.translate(-x1, -y1);
+					qmatrix.scale(1, mask_gradientScale);
+				}
+				else
+				{
+					qmatrix.translate(x1, y1);
+					qmatrix.shear(-mask_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_clip_preserve (m_cr);
 				cairo_mask(m_cr, pat);
 				cairo_pattern_destroy (pat);
 			}
 			else
 			{
-*/
-			cairo_set_source_rgba( m_cr, r, g, b, fill_trans );
-			cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
-			cairo_fill_preserve(m_cr);
-//			}
+				cairo_set_source_rgba( m_cr, r, g, b, fill_trans );
+				cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
+				cairo_fill_preserve(m_cr);
+			}
 //				cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
 //			else
 //				cairo_set_operator(m_cr, CAIRO_OPERATOR_SOURCE);
@@ -1070,7 +1127,59 @@
 			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);
+			if (maskMode == 1)
+			{
+				cairo_pattern_t *patM;
+				double x1 = mask_gradient.origin().x();
+				double y1 = mask_gradient.origin().y();
+				double x2 = mask_gradient.vector().x();
+				double y2 = mask_gradient.vector().y();
+				if (mask_gradient.type() == VGradient::linear)
+					patM = cairo_pattern_create_linear (x1, y1,  x2, y2);
+				else
+					patM = cairo_pattern_create_radial (x1, y1, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
+				QList<VColorStop*> colorStops = mask_gradient.colorStops();
+				QColor qStopColor;
+				for( int offset = 0 ; offset < colorStops.count() ; offset++ )
+				{
+					qStopColor = colorStops[ offset ]->color;
+					int h, s, v, sneu, vneu;
+					int shad = colorStops[offset]->shade;
+					qStopColor.getHsv(&h, &s, &v);
+					sneu = s * shad / 100;
+					vneu = 255 - ((255 - v) * shad / 100);
+					qStopColor.setHsv(h, sneu, vneu);
+					double a = colorStops[offset]->opacity;
+					double r, g, b;
+					qStopColor.getRgbF(&r, &g, &b);
+					cairo_pattern_add_color_stop_rgba (patM, colorStops[ offset ]->rampPoint, r, g, b, a);
+				}
+				cairo_matrix_t matrix;
+				QTransform qmatrix;
+				if (mask_gradient.type() == VGradient::radial)
+				{
+					double rotEnd = xy2Deg(x2 - x1, y2 - y1);
+					qmatrix.translate(x1, y1);
+					qmatrix.rotate(rotEnd);
+					qmatrix.shear(mask_gradientSkew, 0);
+					qmatrix.translate(0, y1 * (1.0 - mask_gradientScale));
+					qmatrix.translate(-x1, -y1);
+					qmatrix.scale(1, mask_gradientScale);
+				}
+				else
+				{
+					qmatrix.translate(x1, y1);
+					qmatrix.shear(-mask_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 (patM, &matrix);
+				cairo_mask(m_cr, patM);
+				cairo_pattern_destroy (patM);
+			}
+			else
+				cairo_paint_with_alpha (m_cr, fill_trans);
 			cairo_pattern_destroy (pat);
 		}
 		else if (fillMode == 3)
@@ -1096,7 +1205,59 @@
 			cairo_pattern_set_matrix (m_pat, &matrix);
 			cairo_set_source (m_cr, m_pat);
 			cairo_clip_preserve (m_cr);
-			cairo_paint_with_alpha (m_cr, fill_trans);
+			if (maskMode == 1)
+			{
+				cairo_pattern_t *patM;
+				double x1 = mask_gradient.origin().x();
+				double y1 = mask_gradient.origin().y();
+				double x2 = mask_gradient.vector().x();
+				double y2 = mask_gradient.vector().y();
+				if (mask_gradient.type() == VGradient::linear)
+					patM = cairo_pattern_create_linear (x1, y1,  x2, y2);
+				else
+					patM = cairo_pattern_create_radial (x1, y1, 0, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2)));
+				QList<VColorStop*> colorStops = mask_gradient.colorStops();
+				QColor qStopColor;
+				for( int offset = 0 ; offset < colorStops.count() ; offset++ )
+				{
+					qStopColor = colorStops[ offset ]->color;
+					int h, s, v, sneu, vneu;
+					int shad = colorStops[offset]->shade;
+					qStopColor.getHsv(&h, &s, &v);
+					sneu = s * shad / 100;
+					vneu = 255 - ((255 - v) * shad / 100);
+					qStopColor.setHsv(h, sneu, vneu);
+					double a = colorStops[offset]->opacity;
+					double r, g, b;
+					qStopColor.getRgbF(&r, &g, &b);
+					cairo_pattern_add_color_stop_rgba (patM, colorStops[ offset ]->rampPoint, r, g, b, a);
+				}
+				cairo_matrix_t matrix;
+				QTransform qmatrix;
+				if (mask_gradient.type() == VGradient::radial)
+				{
+					double rotEnd = xy2Deg(x2 - x1, y2 - y1);
+					qmatrix.translate(x1, y1);
+					qmatrix.rotate(rotEnd);
+					qmatrix.shear(mask_gradientSkew, 0);
+					qmatrix.translate(0, y1 * (1.0 - mask_gradientScale));
+					qmatrix.translate(-x1, -y1);
+					qmatrix.scale(1, mask_gradientScale);
+				}
+				else
+				{
+					qmatrix.translate(x1, y1);
+					qmatrix.shear(-mask_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 (patM, &matrix);
+				cairo_mask(m_cr, patM);
+				cairo_pattern_destroy (patM);
+			}
+			else
+				cairo_paint_with_alpha (m_cr, fill_trans);
 			cairo_pattern_destroy (m_pat);
 			cairo_surface_destroy (image2);
 			cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT);
@@ -1236,9 +1397,95 @@
 			m_path.setFillRule(Qt::WindingFill);
 		if (fillMode == 1)
 		{
-			QColor paint = m_fill;
-			paint.setAlphaF(fill_trans);
-			painter.fillPath(m_path, paint);
+/*		Experimental code for gradient masks */
+/*			if (fill_trans != 1.0)
+			{
+				QGradient pat;
+				double x1 = fill_gradient.origin().x();
+				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)), fx, fy);
+				QList<VColorStop*> colorStops = fill_gradient.colorStops();
+				QColor qStopColor;
+				for( int offset = 0 ; offset < colorStops.count() ; offset++ )
+				{
+					qStopColor = colorStops[ offset ]->color;
+					int h, s, v, sneu, vneu;
+					int shad = colorStops[offset]->shade;
+					qStopColor.getHsv(&h, &s, &v);
+					sneu = s * shad / 100;
+					vneu = 255 - ((255 - v) * shad / 100);
+					qStopColor.setHsv(h, sneu, vneu);
+					qStopColor.setAlphaF(colorStops[offset]->opacity);
+					pat.setColorAt(colorStops[ offset ]->rampPoint, qStopColor);
+				}
+				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);
+				}
+				QImage tmpImgM = QImage(m_image->width(), m_image->height(), QImage::Format_ARGB32);
+				QPainter painterM;
+				painterM.begin(&tmpImgM);
+				painterM.setWorldTransform(painter.worldTransform());
+				painterM.setRenderHint(QPainter::Antialiasing, true);
+				painterM.setRenderHint(QPainter::SmoothPixmapTransform, true);
+				QBrush brush = QBrush(pat);
+				brush.setTransform(qmatrix);
+				painterM.fillPath(m_path, brush);
+				painterM.end();
+				QImage tmpImgO = QImage(m_image->width(), m_image->height(), QImage::Format_ARGB32);
+				QPainter painterO;
+				painterO.begin(&tmpImgO);
+				painterO.setWorldTransform(painter.worldTransform());
+				painterO.setRenderHint(QPainter::Antialiasing, true);
+				painterO.setRenderHint(QPainter::SmoothPixmapTransform, true);
+				QColor paint = m_fill;
+				painterO.fillPath(m_path, paint);
+				painterO.end();
+				int h = tmpImgO.height();
+				int w = tmpImgO.width();
+				QRgb *s, *t;
+				for( int yi=0; yi < h; ++yi )
+				{
+					s = (QRgb*)(tmpImgM.scanLine( yi ));
+					t = (QRgb*)(tmpImgO.scanLine( yi ));
+					for( int xi=0; xi < w; ++xi )
+					{
+						*t = qRgba(qRed(*t), qGreen(*t), qBlue(*t), qAlpha(*s));
+						s++;
+						t++;
+					}
+				}
+				painter.save();
+				painter.resetTransform();
+				painter.drawImage(0, 0, tmpImgO);
+				painter.restore();
+			}
+			else
+			{ */
+				QColor paint = m_fill;
+				paint.setAlphaF(fill_trans);
+				painter.fillPath(m_path, paint);
+//			}
 		}
 		else if (fillMode == 2)
 		{
Index: scribus/pageitem.cpp
===================================================================
--- scribus/pageitem.cpp	(revision 14296)
+++ scribus/pageitem.cpp	(revision 14297)
@@ -269,7 +269,27 @@
 	GrStrokeFocalX(other.GrStrokeFocalX),
 	GrStrokeFocalY(other.GrStrokeFocalY),
 	GrStrokeScale(other.GrStrokeScale),
-	GrStrokeSkew(other.GrStrokeSkew)
+	GrStrokeSkew(other.GrStrokeSkew),
+	GrMask(other.GrMask),
+	GrMaskStartX(other.GrMaskStartX),
+	GrMaskStartY(other.GrMaskStartY),
+	GrMaskEndX(other.GrMaskEndX),
+	GrMaskEndY(other.GrMaskEndY),
+	GrMaskFocalX(other.GrMaskFocalX),
+	GrMaskFocalY(other.GrMaskFocalY),
+	GrMaskScale(other.GrMaskScale),
+	GrMaskSkew(other.GrMaskSkew),
+	patternMaskScaleX(other.patternMaskScaleX),
+	patternMaskScaleY(other.patternMaskScaleY),
+	patternMaskOffsetX(other.patternMaskOffsetX),
+	patternMaskOffsetY(other.patternMaskOffsetY),
+	patternMaskRotation(other.patternMaskRotation),
+	patternMaskSkewX(other.patternMaskSkewX),
+	patternMaskSkewY(other.patternMaskSkewY),
+	patternMaskMirrorX(other.patternMaskMirrorX),
+	patternMaskMirrorY(other.patternMaskMirrorY),
+	patternMaskVal(other.patternMaskVal),
+	mask_gradient(other.mask_gradient)
 {
 	QString tmp;
 	m_Doc->TotalItems++;
@@ -590,6 +610,32 @@
 			}
 		}
 	}
+	GrMask = 0;
+	GrMaskStartX = 0;
+	GrMaskStartY = 0;
+	GrMaskEndX = w;
+	GrMaskEndY = 0;
+	GrMaskFocalX = 0;
+	GrMaskFocalY = 0;
+	GrMaskScale = 1;
+	GrMaskSkew = 0;
+	patternMaskScaleX = 100;
+	patternMaskScaleY = 100;
+	patternMaskOffsetX = 0;
+	patternMaskOffsetY = 0;
+	patternMaskRotation = 0;
+	patternMaskSkewX = 0;
+	patternMaskSkewY = 0;
+	patternMaskMirrorX = false;
+	patternMaskMirrorY = false;
+	patternMaskVal = "";
+	gradientMaskVal = "";
+	mask_gradient = VGradient(VGradient::linear);
+	mask_gradient.clearStops();
+	const ScColor& col = m_Doc->PageColors["Black"];
+	QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
+	mask_gradient.addStop(qcol, 0.0, 0.5, 1.0, "Black", 100);
+	mask_gradient.addStop(qcol, 1.0, 0.5, 1.0, "Black", 100);
 	firstLineOffsetP = FLOPRealGlyphHeight;
 	Cols = m_Doc->itemToolPrefs.textColumns;
 	ColGap = m_Doc->itemToolPrefs.textColumnGap;
@@ -1112,100 +1158,111 @@
 	}
 	else
 	{
-	if (!isGroupControl)
-	{
-		if (fillBlendmode() != 0)
-			p->beginLayer(1.0 - fillTransparency(), fillBlendmode());
-
-		p->setLineWidth(m_lineWidth);
-		if (GrType != 0)
+		if (!isGroupControl)
 		{
-			if (GrType == 8)
+			if (fillBlendmode() != 0)
+				p->beginLayer(1.0 - fillTransparency(), fillBlendmode());
+	
+			p->setLineWidth(m_lineWidth);
+			if (GrType != 0)
 			{
-				if ((patternVal.isEmpty()) || (!m_Doc->docPatterns.contains(patternVal)))
+				if (GrType == 8)
 				{
-					p->fill_gradient = VGradient(VGradient::linear);
-					if (fillColor() != CommonStrings::None)
+					if ((patternVal.isEmpty()) || (!m_Doc->docPatterns.contains(patternVal)))
 					{
-						p->setBrush(fillQColor);
-						p->setFillMode(ScPainter::Solid);
+						p->fill_gradient = VGradient(VGradient::linear);
+						if (fillColor() != CommonStrings::None)
+						{
+							p->setBrush(fillQColor);
+							p->setFillMode(ScPainter::Solid);
+						}
+						else
+							p->setFillMode(ScPainter::None);
+						if ((!patternVal.isEmpty()) && (!m_Doc->docPatterns.contains(patternVal)))
+						{
+							GrType = 0;
+							patternVal = "";
+						}
 					}
 					else
-						p->setFillMode(ScPainter::None);
-					if ((!patternVal.isEmpty()) && (!m_Doc->docPatterns.contains(patternVal)))
 					{
-						GrType = 0;
-						patternVal = "";
+						p->setPattern(&m_Doc->docPatterns[patternVal], patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternMirrorX, patternMirrorY);
+						p->setFillMode(ScPainter::Pattern);
 					}
 				}
 				else
 				{
-					p->setPattern(&m_Doc->docPatterns[patternVal], patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternMirrorX, patternMirrorY);
-					p->setFillMode(ScPainter::Pattern);
+					if ((!gradientVal.isEmpty()) && (!m_Doc->docGradients.contains(gradientVal)))
+						gradientVal = "";
+					if (!(gradientVal.isEmpty()) && (m_Doc->docGradients.contains(gradientVal)))
+						fill_gradient = m_Doc->docGradients[gradientVal];
+					if (fill_gradient.Stops() < 2) // fall back to solid filling if there are not enough colorstops in the gradient.
+					{
+						if (fillColor() != CommonStrings::None)
+						{
+							p->setBrush(fillQColor);
+							p->setFillMode(ScPainter::Solid);
+						}
+						else
+							p->setFillMode(ScPainter::None);
+					}
+					else
+					{
+						p->setFillMode(ScPainter::Gradient);
+						p->fill_gradient = fill_gradient;
+						switch (GrType)
+						{
+							case 1:
+							case 2:
+							case 3:
+							case 4:
+							case 6:
+								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), GrScale, GrSkew);
+								break;
+						}
+					}
 				}
 			}
 			else
 			{
-				if ((!gradientVal.isEmpty()) && (!m_Doc->docGradients.contains(gradientVal)))
-					gradientVal = "";
-				if (!(gradientVal.isEmpty()) && (m_Doc->docGradients.contains(gradientVal)))
-					fill_gradient = m_Doc->docGradients[gradientVal];
-				if (fill_gradient.Stops() < 2) // fall back to solid filling if there are not enough colorstops in the gradient.
+				p->fill_gradient = VGradient(VGradient::linear);
+				if (fillColor() != CommonStrings::None)
 				{
-					if (fillColor() != CommonStrings::None)
-					{
-						p->setBrush(fillQColor);
-						p->setFillMode(ScPainter::Solid);
-					}
-					else
-						p->setFillMode(ScPainter::None);
+					p->setBrush(fillQColor);
+					p->setFillMode(ScPainter::Solid);
 				}
 				else
-				{
-					p->setFillMode(ScPainter::Gradient);
-					p->fill_gradient = fill_gradient;
-					switch (GrType)
-					{
-						case 1:
-						case 2:
-						case 3:
-						case 4:
-						case 6:
-							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), GrScale, GrSkew);
-							break;
-					}
-				}
+					p->setFillMode(ScPainter::None);
 			}
-		}
-		else
-		{
-			p->fill_gradient = VGradient(VGradient::linear);
-			if (fillColor() != CommonStrings::None)
+			if ((lineColor() != CommonStrings::None) || (!patternStrokeVal.isEmpty()) || (GrTypeStroke > 0))
 			{
-				p->setBrush(fillQColor);
-				p->setFillMode(ScPainter::Solid);
+				p->setPen(strokeQColor, m_lineWidth, PLineArt, PLineEnd, PLineJoin);
+				if (DashValues.count() != 0)
+					p->setDash(DashValues, DashOffset);
 			}
 			else
-				p->setFillMode(ScPainter::None);
+				p->setLineWidth(0);
+			if (fillBlendmode() == 0)
+				p->setBrushOpacity(1.0 - fillTransparency());
+			if (lineBlendmode() == 0)
+				p->setPenOpacity(1.0 - lineTransparency());
+			p->setFillRule(fillRule);
+			if (GrMask == 1)
+			{
+				p->setMaskMode(1);
+				p->mask_gradient = mask_gradient;
+				if (mask_gradient.type() == VGradient::linear)
+					p->setGradientMask(VGradient::linear, FPoint(GrMaskStartX, GrMaskStartY), FPoint(GrMaskEndX, GrMaskEndY), FPoint(GrMaskStartX, GrMaskStartY), GrMaskScale, GrMaskSkew);
+				else
+					p->setGradientMask(VGradient::radial, FPoint(GrMaskStartX, GrMaskStartY), FPoint(GrMaskEndX, GrMaskEndY), FPoint(GrMaskFocalX, GrMaskFocalY), GrMaskScale, GrMaskSkew);
+			}
+			else
+				p->setMaskMode(0);
 		}
-		if ((lineColor() != CommonStrings::None) || (!patternStrokeVal.isEmpty()) || (GrTypeStroke > 0))
-		{
-			p->setPen(strokeQColor, m_lineWidth, PLineArt, PLineEnd, PLineJoin);
-			if (DashValues.count() != 0)
-				p->setDash(DashValues, DashOffset);
-		}
-		else
-			p->setLineWidth(0);
-		if (fillBlendmode() == 0)
-			p->setBrushOpacity(1.0 - fillTransparency());
-		if (lineBlendmode() == 0)
-			p->setPenOpacity(1.0 - lineTransparency());
-		p->setFillRule(fillRule);
-		}
 	}
 }
 
@@ -2462,6 +2519,76 @@
 	flipY = patternMirrorY;
 }
 
+void PageItem::setGradientMask(const QString &newMask)
+{
+	if (gradientMaskVal != newMask)
+		gradientMaskVal = newMask;
+}
+
+void PageItem::setPatternMask(const QString &newMask)
+{
+	if (patternMaskVal != newMask)
+		patternMaskVal = newMask;
+}
+
+void PageItem::maskVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const
+{
+	startX = GrMaskStartX;
+	startY = GrMaskStartY;
+	endX   = GrMaskEndX;
+	endY   = GrMaskEndY;
+	focalX = GrMaskFocalX;
+	focalY = GrMaskFocalY;
+	scale  = GrMaskScale;
+	skew   = GrMaskSkew;
+}
+
+void PageItem::setMaskVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew)
+{
+	GrMaskStartX = startX;
+	GrMaskStartY = startY;
+	GrMaskEndX   = endX;
+	GrMaskEndY   = endY;
+	GrMaskFocalX = focalX;
+	GrMaskFocalY = focalY;
+	GrMaskScale  = scale;
+	GrMaskSkew   = skew;
+}
+
+void PageItem::maskTransform(double &scaleX, double &scaleY, double &offsetX, double &offsetY, double &rotation, double &skewX, double &skewY) const
+{
+	 scaleX = patternMaskScaleX;
+	 scaleY = patternMaskScaleY;
+	 offsetX = patternMaskOffsetX;
+	 offsetY = patternMaskOffsetY;
+	 rotation = patternMaskRotation;
+	 skewX = patternMaskSkewX;
+	 skewY = patternMaskSkewY;
+}
+
+void PageItem::setMaskTransform(double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY)
+{
+	patternMaskScaleX = scaleX;
+	patternMaskScaleY = scaleY;
+	patternMaskOffsetX = offsetX;
+	patternMaskOffsetY = offsetY;
+	patternMaskRotation = rotation;
+	patternMaskSkewX = skewX;
+	patternMaskSkewY = skewY;
+}
+
+void PageItem::setMaskFlip(bool flipX, bool flipY)
+{
+	patternMaskMirrorX = flipX;
+	patternMaskMirrorY = flipY;
+}
+
+void PageItem::maskFlip(bool &flipX, bool &flipY)
+{
+	flipX = patternMaskMirrorX;
+	flipY = patternMaskMirrorY;
+}
+
 void PageItem::setFillColor(const QString &newColor)
 {
 	QString tmp = newColor;
@@ -2505,7 +2632,7 @@
 		undoManager->action(this, ss);
 	}
 	fillColorVal = tmp;
-	if (GrType == 0)
+/*	if (GrType == 0)
 	{
 		fill_gradient = VGradient(VGradient::linear);
 		fill_gradient.clearStops();
@@ -2515,7 +2642,7 @@
 			fill_gradient.addStop(ScColorEngine::getRGBColor(col, m_Doc), 0.0, 0.5, 1.0, fillColorVal, 100);
 			fill_gradient.addStop(ScColorEngine::getRGBColor(col, m_Doc), 1.0, 0.5, 1.0, fillColorVal, 100);
 		}
-	}
+	} */
 	setFillQColor();
 //CB unused in 135	emit colors(lineColorVal, fillColorVal, lineShadeVal, fillShadeVal);
 }
@@ -4191,6 +4318,9 @@
 	it = newNames.patterns().find(strokePattern());
 	if (it != newNames.patterns().end())
 		setStrokePattern(*it);
+	it = newNames.patterns().find(patternMask());
+	if (it != newNames.patterns().end())
+		setPatternMask(*it);
 	
 	it = newNames.gradients().find(strokeGradient());
 	if (it != newNames.gradients().end())
@@ -4199,6 +4329,9 @@
 	it = newNames.gradients().find(gradient());
 	if (it != newNames.gradients().end())
 		setGradient(*it);
+	it = newNames.gradients().find(gradientMask());
+	if (it != newNames.gradients().end())
+		setGradientMask(*it);
 
 	it = newNames.lineStyles().find(customLineStyle());
 	if (it != newNames.lineStyles().end())
@@ -4231,6 +4364,14 @@
 			lists.collectColor(cstops.at(cst)->name);
 		}
 	}
+	if (GrMask == 1)
+	{
+		QList<VColorStop*> cstops = mask_gradient.colorStops();
+		for (uint cst = 0; cst < mask_gradient.Stops(); ++cst)
+		{
+			lists.collectColor(cstops.at(cst)->name);
+		}
+	}
 	if (effectsInUse.count() != 0)
 	{
 		for (int a = 0; a < effectsInUse.count(); ++a)
@@ -5798,6 +5939,17 @@
 				GrStrokeEndY = gr2.point(1).y();
 				GrStrokeFocalX = gr2.point(2).x();
 				GrStrokeFocalY = gr2.point(2).y();
+				FPointArray gr3;
+				gr3.addPoint(GrMaskStartX, GrMaskStartY);
+				gr3.addPoint(GrMaskEndX, GrMaskEndY);
+				gr3.addPoint(GrMaskFocalX, GrMaskFocalY);
+				gr3.map(ma);
+				GrMaskStartX = gr3.point(0).x();
+				GrMaskStartY = gr3.point(0).y();
+				GrMaskEndX = gr3.point(1).x();
+				GrMaskEndY = gr3.point(1).y();
+				GrMaskFocalX = gr3.point(2).x();
+				GrMaskFocalY = gr3.point(2).y();
 				ContourLine.map(ma);
 				if (FrameType > 2)
 				{
@@ -5864,6 +6016,17 @@
 			GrStrokeEndY = gr2.point(1).y();
 			GrStrokeFocalX = gr2.point(2).x();
 			GrStrokeFocalY = gr2.point(2).y();
+			FPointArray gr3;
+			gr3.addPoint(GrMaskStartX, GrMaskStartY);
+			gr3.addPoint(GrMaskEndX, GrMaskEndY);
+			gr3.addPoint(GrMaskFocalX, GrMaskFocalY);
+			gr3.map(ma);
+			GrMaskStartX = gr3.point(0).x();
+			GrMaskStartY = gr3.point(0).y();
+			GrMaskEndX = gr3.point(1).x();
+			GrMaskEndY = gr3.point(1).y();
+			GrMaskFocalX = gr3.point(2).x();
+			GrMaskFocalY = gr3.point(2).y();
 			PoLine.map(ma);
 			ContourLine.map(ma);
 			if (asPathText())
Index: scribus/scribusdoc.h
===================================================================
--- scribus/scribusdoc.h	(revision 14296)
+++ scribus/scribusdoc.h	(revision 14297)
@@ -1169,6 +1169,7 @@
 	void itemSelection_SetItemLineBlend(int t);
 	void itemSelection_SetLineGradient(VGradient& newGradient, Selection* customSelection=0);
 	void itemSelection_SetFillGradient(VGradient& newGradient, Selection* customSelection=0);
+	void itemSelection_SetMaskGradient(VGradient& newGradient, Selection* customSelection=0);
 	void itemSelection_SetOverprint(bool overprint, Selection* customSelection=0);
 	void itemSelection_ApplyImageEffects(ScImageEffectList& newEffectList, Selection* customSelection=0);
 	void itemSelection_FlipH();
Index: scribus/scribusview.cpp
===================================================================
--- scribus/scribusview.cpp	(revision 14296)
+++ scribus/scribusview.cpp	(revision 14297)
@@ -3868,7 +3868,6 @@
 			currItem->GrFocalY = Buffer->GrFocalY;
 			currItem->GrScale  = Buffer->GrScale;
 			currItem->GrSkew   = Buffer->GrSkew;
-			currItem->updateGradientVectors();
 		}
 	}
 	if (Buffer->GrTypeStroke >0)
@@ -3883,8 +3882,27 @@
 		currItem->GrStrokeFocalY = Buffer->GrStrokeFocalY;
 		currItem->GrStrokeScale  = Buffer->GrStrokeScale;
 		currItem->GrStrokeSkew   = Buffer->GrStrokeSkew;
-		currItem->updateGradientVectors();
 	}
+	currItem->GrMask = Buffer->GrMask;
+	if (currItem->GrMask == 1)
+	{
+		currItem->mask_gradient = Buffer->mask_gradient;
+		currItem->GrMaskStartX = Buffer->GrMaskStartX;
+		currItem->GrMaskStartY = Buffer->GrMaskStartY;
+		currItem->GrMaskEndX = Buffer->GrMaskEndX;
+		currItem->GrMaskEndY = Buffer->GrMaskEndY;
+		currItem->GrMaskFocalX = Buffer->GrMaskFocalX;
+		currItem->GrMaskFocalY = Buffer->GrMaskFocalY;
+		currItem->GrMaskScale  = Buffer->GrMaskScale;
+		currItem->GrMaskSkew   = Buffer->GrMaskSkew;
+	}
+	else if (currItem->GrMask == 2)
+	{
+		currItem->setPatternMask(Buffer->patternMaskVal);
+		currItem->setMaskTransform(Buffer->patternMaskScaleX, Buffer->patternMaskScaleY, Buffer->patternMaskOffsetX, Buffer->patternMaskOffsetY, Buffer->patternMaskRotation, Buffer->patternMaskSkewX, Buffer->patternMaskSkewY);
+		currItem->setMaskFlip(Buffer->patternMaskMirrorX, Buffer->patternMaskMirrorY);
+	}
+	currItem->updateGradientVectors();
 	currItem->setObjectAttributes(&(Buffer->pageItemAttributes));
 	if (resize)
 		Doc->setRedrawBounding(currItem);
Index: scribus/ui/hruler.cpp
===================================================================
--- scribus/ui/hruler.cpp	(revision 14296)
+++ scribus/ui/hruler.cpp	(revision 14297)
@@ -760,7 +760,7 @@
 		}
 #else
 		// draw slim marker
-		p.resetMatrix();
+		p.resetTransform();
 		p.translate(-currView->contentsX(), 0);
 		p.setPen(Qt::red);
 		p.setBrush(Qt::red);
Index: scribus/plugins/xarimplugin/importxar.cpp
===================================================================
--- scribus/plugins/xarimplugin/importxar.cpp	(revision 14296)
+++ scribus/plugins/xarimplugin/importxar.cpp	(revision 14297)
@@ -580,6 +580,8 @@
 		handleSimpleGradientSkewed(ts, dataLen);
 	else if (tag == 4122)
 		handleMultiGradientSkewed(ts);
+	else if (tag == 4123)
+		handleSimpleGradientTransparencySkewed(ts, dataLen);
 	else
 	{
 //		if (m_gc.count() > 3)
@@ -690,6 +692,7 @@
 	{
 		gc->FillOpacity = transVal / 255.0;
 		gc->FillBlend = convertBlendMode(transType);
+		gc->GradMask = 0;
 	}
 }
 
@@ -706,13 +709,49 @@
 		double p, p1;
 		ts >> p >> p1;
 	}
-	if (transType > 0)
+	if (linear)
+		gc->MaskGradient = VGradient(VGradient::linear);
+	else
+		gc->MaskGradient = VGradient(VGradient::radial);
+	gc->MaskGradient.clearStops();
+	gc->MaskGradient.addStop( ScColorEngine::getRGBColor(m_Doc->PageColors["Black"], m_Doc), 0.0, 0.5, 1.0 - transStart / 255.0, "Black", 100 );
+	gc->MaskGradient.addStop( ScColorEngine::getRGBColor(m_Doc->PageColors["Black"], m_Doc), 1.0, 0.5, 1.0 - transEnd / 255.0, "Black", 100 );
+	gc->GradMaskX1 = blx + baseX + m_Doc->currentPage()->xOffset();
+	gc->GradMaskY1 = (docHeight - bly) + baseY + m_Doc->currentPage()->yOffset();
+	gc->GradMaskX2 = brx + baseX + m_Doc->currentPage()->xOffset();
+	gc->GradMaskY2 = (docHeight - bry) + baseY + m_Doc->currentPage()->yOffset();
+	gc->GradMask = 1;
+}
+
+void XarPlug::handleSimpleGradientTransparencySkewed(QDataStream &ts, quint32 dataLen)
+{
+	XarStyle *gc = m_gc.top();
+	double blx, bly, brx, bry, tlx, tly;
+	quint8 transStart, transEnd, transType;
+	readCoords(ts, blx, bly);
+	readCoords(ts, brx, bry);
+	readCoords(ts, tlx, tly);
+	ts >> transStart >> transEnd >> transType;
+	if (dataLen == 43)
 	{
-		double s = transStart / 255.0;
-		double e = transEnd / 255.0;
-		gc->FillOpacity = (s + e) / 2.0;
-		gc->FillBlend = convertBlendMode(transType);
+		double p, p1;
+		ts >> p >> p1;
 	}
+	gc->MaskGradient = VGradient(VGradient::linear);
+	gc->MaskGradient.clearStops();
+	gc->MaskGradient.addStop( ScColorEngine::getRGBColor(m_Doc->PageColors["Black"], m_Doc), 0.0, 0.5, 1.0 - transStart / 255.0, "Black", 100 );
+	gc->MaskGradient.addStop( ScColorEngine::getRGBColor(m_Doc->PageColors["Black"], m_Doc), 1.0, 0.5, 1.0 - transEnd / 255.0, "Black", 100 );
+	double distX = distance(brx - blx, bry - bly);
+	double distY = distance(tlx - blx, tly - bly);
+	double rotB = xy2Deg(brx - blx, bry - bly);
+	double rotS = xy2Deg(tlx - blx, tly - bly);
+	gc->GradMaskScale = distY / distX;
+	gc->GradMaskSkew = rotS - 90 - rotB;
+	gc->GradMaskX1 = blx + baseX + m_Doc->currentPage()->xOffset();
+	gc->GradMaskY1 = (docHeight - bly) + baseY + m_Doc->currentPage()->yOffset();
+	gc->GradMaskX2 = brx + baseX + m_Doc->currentPage()->xOffset();
+	gc->GradMaskY2 = (docHeight - bry) + baseY + m_Doc->currentPage()->yOffset();
+	gc->GradMask = 1;
 }
 
 void XarPlug::handleEllipticalGradientTransparency(QDataStream &ts, quint32 dataLen)
@@ -729,13 +768,21 @@
 		double p, p1;
 		ts >> p >> p1;
 	}
-	if (transType > 0)
-	{
-		double s = transStart / 255.0;
-		double e = transEnd / 255.0;
-		gc->FillOpacity = (s + e) / 2.0;
-		gc->FillBlend = convertBlendMode(transType);
-	}
+	gc->MaskGradient = VGradient(VGradient::radial);
+	gc->MaskGradient.clearStops();
+	gc->MaskGradient.addStop( ScColorEngine::getRGBColor(m_Doc->PageColors["Black"], m_Doc), 0.0, 0.5, 1.0 - transStart / 255.0, "Black", 100 );
+	gc->MaskGradient.addStop( ScColorEngine::getRGBColor(m_Doc->PageColors["Black"], m_Doc), 1.0, 0.5, 1.0 - transEnd / 255.0, "Black", 100 );
+	double distX = distance(brx - blx, bry - bly);
+	double distY = distance(tlx - blx, tly - bly);
+	double rotB = xy2Deg(brx - blx, bry - bly);
+	double rotS = xy2Deg(tlx - blx, tly - bly);
+	gc->GradMaskScale = distY / distX;
+	gc->GradMaskSkew = rotS - 90 - rotB;
+	gc->GradMaskX1 = blx + baseX + m_Doc->currentPage()->xOffset();
+	gc->GradMaskY1 = (docHeight - bly) + baseY + m_Doc->currentPage()->yOffset();
+	gc->GradMaskX2 = brx + baseX + m_Doc->currentPage()->xOffset();
+	gc->GradMaskY2 = (docHeight - bry) + baseY + m_Doc->currentPage()->yOffset();
+	gc->GradMask = 1;
 }
 
 int XarPlug::convertBlendMode(int val)
@@ -1608,7 +1655,7 @@
 			PageItem *item = gc->Elements.at(a);
 			item->setFillColor(gc->FillCol);
 			item->setFillTransparency(gc->FillOpacity);
-			item->setFillBlendmode(gc->FillBlend);
+//			item->setFillBlendmode(gc->FillBlend);
 			item->setLineTransparency(gc->StrokeOpacity);
 			item->setLineWidth(gc->LWidth);
 			item->setLineColor(gc->StrokeCol);
@@ -1628,6 +1675,12 @@
 				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(), gc->GrScale, gc->GrSkew);
 			}
+			if (gc->GradMask == 1)
+			{
+				item->GrMask = 1;
+				item->mask_gradient = gc->MaskGradient;
+				item->setMaskVector(gc->GradMaskX1 - item->xPos(), gc->GradMaskY1 - item->yPos(), gc->GradMaskX2 - item->xPos(), gc->GradMaskY2 - item->yPos(), gc->GradMaskX1 - item->xPos(), gc->GradMaskY1 - item->yPos(), gc->GradMaskScale, gc->GradMaskSkew);
+			}
 		}
 	}
 	delete gc;
Index: scribus/plugins/xarimplugin/importxar.h
===================================================================
--- scribus/plugins/xarimplugin/importxar.h	(revision 14296)
+++ scribus/plugins/xarimplugin/importxar.h	(revision 14297)
@@ -41,6 +41,7 @@
 		fillRule(true),
 		FillGradient(VGradient::linear),
 		StrokeGradient(VGradient::linear),
+		MaskGradient(VGradient::linear),
 		FillGradientType(0),
 		StrokeGradientType(0),
 		GradFillX1(0),
@@ -53,6 +54,13 @@
 		GradStrokeX2(0),
 		GradStrokeY1(0),
 		GradStrokeY2(0),
+		GradMask(0),
+		GradMaskX1(0),
+		GradMaskX2(0),
+		GradMaskY1(0),
+		GradMaskY2(0),
+		GradMaskScale(1),
+		GradMaskSkew(0),
 		LWidth(0.5),
 		PLineArt(Qt::SolidLine),
 		PLineEnd(Qt::FlatCap),
@@ -85,6 +93,7 @@
 	bool fillRule;
 	VGradient FillGradient;
 	VGradient StrokeGradient;
+	VGradient MaskGradient;
 	int    FillGradientType;
 	int    StrokeGradientType;
 	double GradFillX1;
@@ -97,6 +106,13 @@
 	double GradStrokeX2;
 	double GradStrokeY1;
 	double GradStrokeY2;
+	int    GradMask;
+	double GradMaskX1;
+	double GradMaskX2;
+	double GradMaskY1;
+	double GradMaskY2;
+	double GradMaskScale;
+	double GradMaskSkew;
 	double LWidth;
 	Qt::PenStyle PLineArt;
 	Qt::PenCapStyle PLineEnd;
@@ -159,6 +175,7 @@
 	void handleQuickShapeSimple(QDataStream &ts, quint32 dataLen);
 	void handleFlatFillTransparency(QDataStream &ts);
 	void handleSimpleGradientTransparency(QDataStream &ts, quint32 dataLen, bool linear);
+	void handleSimpleGradientTransparencySkewed(QDataStream &ts, quint32 dataLen);
 	void handleEllipticalGradientTransparency(QDataStream &ts, quint32 dataLen);
 	int  convertBlendMode(int val);
 	void handleSimpleGradientElliptical(QDataStream &ts, quint32 dataLen);
Index: scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(revision 14296)
+++ scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(revision 14297)
@@ -1199,6 +1199,8 @@
 			docu.writeAttribute("GRNAME", item->gradient());
 		if (!item->strokeGradient().isEmpty())
 			docu.writeAttribute("GRNAMES", item->strokeGradient());
+		if (!item->gradientMask().isEmpty())
+			docu.writeAttribute("GRNAMEM", item->gradientMask());
 		if (item->GrTypeStroke > 0)
 		{
 			docu.writeAttribute("GRSTARTXS", item->GrStrokeStartX);
@@ -1227,6 +1229,35 @@
 			docu.writeAttribute("pMirrorXS" , mirrorX);
 			docu.writeAttribute("pMirrorYS" , mirrorY);
 		}
+		if (item->GrMask > 0)
+		{
+			docu.writeAttribute("GRTYPM", item->GrMask);
+			docu.writeAttribute("GRSTARTXM", item->GrMaskStartX);
+			docu.writeAttribute("GRSTARTYM", item->GrMaskStartY);
+			docu.writeAttribute("GRENDXM", item->GrMaskEndX);
+			docu.writeAttribute("GRENDYM", item->GrMaskEndY);
+			docu.writeAttribute("GRFOCALXM", item->GrMaskFocalX);
+			docu.writeAttribute("GRFOCALYM", item->GrMaskFocalY);
+			docu.writeAttribute("GRSCALEM" , item->GrMaskScale);
+			docu.writeAttribute("GRSKEWM" , item->GrMaskSkew);
+		}
+		if (!item->patternMask().isEmpty())
+		{
+			docu.writeAttribute("patternM", item->patternMask());
+			double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
+			item->maskTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
+			bool mirrorX, mirrorY;
+			item->maskFlip(mirrorX, mirrorY);
+			docu.writeAttribute("pScaleXM", patternScaleX);
+			docu.writeAttribute("pScaleYM", patternScaleY);
+			docu.writeAttribute("pOffsetXM", patternOffsetX);
+			docu.writeAttribute("pOffsetYM", patternOffsetY);
+			docu.writeAttribute("pRotationM", patternRotation);
+			docu.writeAttribute("pSkewXM", patternSkewX);
+			docu.writeAttribute("pSkewYM", patternSkewY);
+			docu.writeAttribute("pMirrorXM" , mirrorX);
+			docu.writeAttribute("pMirrorYM" , mirrorY);
+		}
 		if (item->itemText.defaultStyle().hasParent())
 			docu.writeAttribute("PSTYLE", item->itemText.defaultStyle().parent());
 		if (! item->itemText.defaultStyle().isInhAlignment())
@@ -1307,6 +1338,18 @@
 				docu.writeAttribute("TRANS", cstops.at(cst)->opacity);
 			}
 		}
+		if ((item->GrMask > 0) && (item->gradientMask().isEmpty()))
+		{
+			QList<VColorStop*> cstops = item->mask_gradient.colorStops();
+			for (uint cst = 0; cst < item->mask_gradient.Stops(); ++cst)
+			{
+				docu.writeEmptyElement("M_CSTOP");
+				docu.writeAttribute("RAMP", cstops.at(cst)->rampPoint);
+				docu.writeAttribute("NAME", cstops.at(cst)->name);
+				docu.writeAttribute("SHADE", cstops.at(cst)->shade);
+				docu.writeAttribute("TRANS", cstops.at(cst)->opacity);
+			}
+		}
 		
 		if (item->asLatexFrame())
 		{
Index: scribus/plugins/fileloader/scribus150format/scribus150format.cpp
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(revision 14296)
+++ scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(revision 14297)
@@ -1778,6 +1778,14 @@
 			double opa   = tAtt.valueAsDouble("TRANS", 1.0);
 			newItem->stroke_gradient.addStop(SetColor(doc, name, shade), ramp, 0.5, opa, name, shade);
 		}
+		if (tName == "M_CSTOP")
+		{
+			QString name = tAtt.valueAsString("NAME");
+			double ramp  = tAtt.valueAsDouble("RAMP", 0.0);
+			int shade    = tAtt.valueAsInt("SHADE", 100);
+			double opa   = tAtt.valueAsDouble("TRANS", 1.0);
+			newItem->mask_gradient.addStop(SetColor(doc, name, shade), ramp, 0.5, opa, name, shade);
+		}
 
 		if (tName == "ITEXT")
 			readItemText(newItem, tAtt, lastStyle);
@@ -2838,11 +2846,40 @@
 	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);
+	currItem->GrStrokeSkew  = attrs.valueAsDouble("GRSKEWS", 0.0);
 	QString GrNameS = "";
 	GrNameS = attrs.valueAsString("GRNAMES","");
 	if (!GrNameS.isEmpty())
 		currItem->setStrokeGradient(GrNameS);
+
+
+	currItem->setPatternMask( attrs.valueAsString("patternM", "") );
+	double patternScaleXm   = attrs.valueAsDouble("pScaleXM", 100.0);
+	double patternScaleYm   = attrs.valueAsDouble("pScaleYM", 100.0);
+	double patternOffsetXm  = attrs.valueAsDouble("pOffsetXM", 0.0);
+	double patternOffsetYm  = attrs.valueAsDouble("pOffsetYM", 0.0);
+	double patternRotationm = attrs.valueAsDouble("pRotationM", 0.0);
+	double patternSkewXm    = attrs.valueAsDouble("pSkewXM", 0.0);
+	double patternSkewYm    = attrs.valueAsDouble("pSkewYM", 0.0);
+	currItem->maskTransform(patternScaleXm, patternScaleYm, patternOffsetXm, patternOffsetYm, patternRotationm, patternSkewXm, patternSkewYm);
+	bool mirrorXm = attrs.valueAsBool("pMirrorXM", false);
+	bool mirrorYm = attrs.valueAsBool("pMirrorYM", false);
+	currItem->setMaskFlip(mirrorXm, mirrorYm);
+	currItem->mask_gradient.clearStops();
+	currItem->GrMask = attrs.valueAsInt("GRTYPM", 0);
+	currItem->GrMaskStartX = attrs.valueAsDouble("GRSTARTXM", 0.0);
+	currItem->GrMaskStartY = attrs.valueAsDouble("GRSTARTYM", 0.0);
+	currItem->GrMaskEndX   = attrs.valueAsDouble("GRENDXM", 0.0);
+	currItem->GrMaskEndY   = attrs.valueAsDouble("GRENDYM", 0.0);
+	currItem->GrMaskFocalX = attrs.valueAsDouble("GRFOCALXM", 0.0);
+	currItem->GrMaskFocalY = attrs.valueAsDouble("GRFOCALYM", 0.0);
+	currItem->GrMaskScale  = attrs.valueAsDouble("GRSCALEM", 1.0);
+	currItem->GrMaskSkew  = attrs.valueAsDouble("GRSKEWM", 0.0);
+	QString GrNameM = "";
+	GrNameM = attrs.valueAsString("GRNAMEM","");
+	if (!GrNameM.isEmpty())
+		currItem->setGradientMask(GrNameM);
+
 	//currItem->setRedrawBounding();
 	//currItem->OwnPage = view->OnPage(currItem);
 	UndoManager::instance()->setUndoEnabled(true);
Index: scribus/pageitem_desaxe.cpp
===================================================================
--- scribus/pageitem_desaxe.cpp	(revision 14296)
+++ scribus/pageitem_desaxe.cpp	(revision 14297)
@@ -261,32 +261,40 @@
 	{
 		Xml_attr patt;
 		patt.insert("patternS", strokePattern());
-//		double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
-//		strokePatternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
-//		bool mirrorX, mirrorY;
-//		strokePatternFlip(mirrorX, mirrorY);
-		patt.insert("pScaleXS", toXMLString(patternScaleX));
-		patt.insert("pScaleYS", toXMLString(patternScaleY));
-		patt.insert("pOffsetXS", toXMLString(patternOffsetX));
-		patt.insert("pOffsetYS", toXMLString(patternOffsetY));
-		patt.insert("pRotationS", toXMLString(patternRotation));
-		patt.insert("pSkewXS", toXMLString(patternSkewX));
-		patt.insert("pSkewYS", toXMLString(patternSkewY));
+		patt.insert("pScaleXS", toXMLString(patternStrokeScaleX));
+		patt.insert("pScaleYS", toXMLString(patternStrokeScaleY));
+		patt.insert("pOffsetXS", toXMLString(patternStrokeOffsetX));
+		patt.insert("pOffsetYS", toXMLString(patternStrokeOffsetY));
+		patt.insert("pRotationS", toXMLString(patternStrokeRotation));
+		patt.insert("pSkewXS", toXMLString(patternStrokeSkewX));
+		patt.insert("pSkewYS", toXMLString(patternStrokeSkewY));
 		patt.insert("pMirrorXS", toXMLString(patternStrokeMirrorX));
 		patt.insert("pMirrorYS", toXMLString(patternStrokeMirrorY));
 		handler.begin("PatternStroke", patt);
 		handler.end("PatternStroke");
 	}
+	if (!patternMask().isEmpty())
+	{
+		Xml_attr patt;
+		patt.insert("patternM", patternMask());
+		patt.insert("pScaleXM", toXMLString(patternMaskScaleX));
+		patt.insert("pScaleYM", toXMLString(patternMaskScaleY));
+		patt.insert("pOffsetXM", toXMLString(patternMaskOffsetX));
+		patt.insert("pOffsetYM", toXMLString(patternMaskOffsetY));
+		patt.insert("pRotationM", toXMLString(patternMaskRotation));
+		patt.insert("pSkewXM", toXMLString(patternMaskSkewX));
+		patt.insert("pSkewYM", toXMLString(patternMaskSkewY));
+		patt.insert("pMirrorXM", toXMLString(patternMaskMirrorX));
+		patt.insert("pMirrorYM", toXMLString(patternMaskMirrorY));
+		handler.begin("PatternMask", patt);
+		handler.end("PatternMask");
+	}
 	if (gradientType() != 0)
 	{
 		if (gradientType() == 8)
 		{
 			Xml_attr patt;
 			patt.insert("pattern", pattern());
-//			double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
-//			patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
-//			bool mirrorX, mirrorY;
-//			patternFlip(mirrorX, mirrorY);
 			patt.insert("pScaleX", toXMLString(patternScaleX));
 			patt.insert("pScaleY", toXMLString(patternScaleY));
 			patt.insert("pOffsetX", toXMLString(patternOffsetX));
@@ -326,34 +334,61 @@
 			}
 			handler.end("Gradient");
 		}
-		if (GrTypeStroke > 0)
+	}
+	if (GrTypeStroke > 0)
+	{
+		Xml_attr gradientV;
+		gradientV.insert("GRTYPES", toXMLString(GrTypeStroke));
+		gradientV.insert("GRSTARTXS", toXMLString(GrStrokeStartX));
+		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("GRSKEWS", toXMLString(GrStrokeSkew));
+		gradientV.insert("GRNAMES", toXMLString(strokeGradient()));
+		handler.begin("GradientS", gradientV);
+		QList<VColorStop*> cstops = fill_gradient.colorStops();
+		for (uint cst = 0; cst < const_cast<VGradient&>(fill_gradient).Stops(); ++cst) //FIXME make const
 		{
-			Xml_attr gradientV;
-			gradientV.insert("GRTYPES", toXMLString(GrTypeStroke));
-			gradientV.insert("GRSTARTXS", toXMLString(GrStrokeStartX));
-			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("GRSKEWS", toXMLString(GrStrokeSkew));
-			gradientV.insert("GRNAMES", toXMLString(strokeGradient()));
-			handler.begin("GradientS", gradientV);
-			QList<VColorStop*> cstops = fill_gradient.colorStops();
-			for (uint cst = 0; cst < const_cast<VGradient&>(fill_gradient).Stops(); ++cst) //FIXME make const
-			{
-				Xml_attr itcl;
-				itcl.insert("RAMP", toXMLString(cstops.at(cst)->rampPoint));
-				itcl.insert("NAME", cstops.at(cst)->name);
-				itcl.insert("SHADE", toXMLString(cstops.at(cst)->shade));
-				itcl.insert("TRANS", toXMLString(cstops.at(cst)->opacity));
-				handler.begin("S_CStop",itcl);
-				handler.end("S_CStop");
-			}
-			handler.end("GradientS");
+			Xml_attr itcl;
+			itcl.insert("RAMP", toXMLString(cstops.at(cst)->rampPoint));
+			itcl.insert("NAME", cstops.at(cst)->name);
+			itcl.insert("SHADE", toXMLString(cstops.at(cst)->shade));
+			itcl.insert("TRANS", toXMLString(cstops.at(cst)->opacity));
+			handler.begin("S_CStop",itcl);
+			handler.end("S_CStop");
 		}
+		handler.end("GradientS");
 	}
+	if (GrMask > 0)
+	{
+		Xml_attr gradientV;
+		gradientV.insert("GRTYPEM", toXMLString(GrMask));
+		gradientV.insert("GRSTARTXM", toXMLString(GrMaskStartX));
+		gradientV.insert("GRSTARTYM", toXMLString(GrMaskStartY));
+		gradientV.insert("GRENDXM", toXMLString(GrMaskEndX));
+		gradientV.insert("GRENDYM", toXMLString(GrMaskEndY));
+		gradientV.insert("GRFOCALXM", toXMLString(GrMaskFocalX));
+		gradientV.insert("GRFOCALYM", toXMLString(GrMaskFocalY));
+		gradientV.insert("GRSCALEM", toXMLString(GrMaskScale));
+		gradientV.insert("GRSKEWM", toXMLString(GrMaskSkew));
+		gradientV.insert("GRNAMEM", toXMLString(gradientMask()));
+		handler.begin("GradientM", gradientV);
+		QList<VColorStop*> cstops = mask_gradient.colorStops();
+		for (uint cst = 0; cst < const_cast<VGradient&>(mask_gradient).Stops(); ++cst) //FIXME make const
+		{
+			Xml_attr itcl;
+			itcl.insert("RAMP", toXMLString(cstops.at(cst)->rampPoint));
+			itcl.insert("NAME", cstops.at(cst)->name);
+			itcl.insert("SHADE", toXMLString(cstops.at(cst)->shade));
+			itcl.insert("TRANS", toXMLString(cstops.at(cst)->opacity));
+			handler.begin("M_CStop",itcl);
+			handler.end("M_CStop");
+		}
+		handler.end("GradientM");
+	}
 	
 	// TODO: PI attributes...
 	
@@ -562,17 +597,22 @@
 		}
 		if (tagName=="S_CStop")
 		{
-//			ScribusDoc* doc = this->dig->lookup<ScribusDoc>("<scribusdoc>");
 			PageItem* item = this->dig->top<PageItem>();
 			QString name = attr["NAME"];
 			double ramp = parseDouble(attr["RAMP"]);
 			int shade = parseInt(attr["SHADE"]);
 			double opa = parseDouble(attr["TRANS"]);
-			// Hack : at this stage, colors may still not exists in document and SetColor would create it, 
-			// so use the dummy brown and update manually gradient colors in Serializer
-			// item->fill_gradient.addStop(SetColor(doc, name, shade), ramp, 0.5, opa, name, shade);
 			item->stroke_gradient.addStop( QColor(150, 100, 50) , ramp, 0.5, opa, name, shade);
 		}
+		if (tagName=="M_CStop")
+		{
+			PageItem* item = this->dig->top<PageItem>();
+			QString name = attr["NAME"];
+			double ramp = parseDouble(attr["RAMP"]);
+			int shade = parseInt(attr["SHADE"]);
+			double opa = parseDouble(attr["TRANS"]);
+			item->mask_gradient.addStop( QColor(150, 100, 50) , ramp, 0.5, opa, name, shade);
+		}
 		if (tagName=="GradientS")
 		{
 			PageItem* item = this->dig->top<PageItem>();
@@ -584,10 +624,25 @@
 			item->GrStrokeFocalX = parseDouble(attr["GRFOCALXS"]);
 			item->GrStrokeFocalY = parseDouble(attr["GRFOCALYS"]);
 			item->GrStrokeScale = parseDouble(attr["GRSCALES"]);
-			item->GrStrokeSkew = parseDouble(attr["GRSKEwS"]);
+			item->GrStrokeSkew = parseDouble(attr["GRSKEWS"]);
 			item->setStrokeGradient(attr["GRNAMES"]);
 			item->stroke_gradient.clearStops();
 		}
+		if (tagName=="GradientM")
+		{
+			PageItem* item = this->dig->top<PageItem>();
+			item->GrMask = parseInt(attr["GRTYPEM"]);
+			item->GrMaskStartX = parseDouble(attr["GRSTARTXM"]);
+			item->GrMaskStartY = parseDouble(attr["GRSTARTYM"]);
+			item->GrMaskEndX = parseDouble(attr["GRENDXM"]);
+			item->GrMaskEndY = parseDouble(attr["GRENDYM"]);
+			item->GrMaskFocalX = parseDouble(attr["GRFOCALXM"]);
+			item->GrMaskFocalY = parseDouble(attr["GRFOCALYM"]);
+			item->GrMaskScale = parseDouble(attr["GRSCALEM"]);
+			item->GrMaskSkew = parseDouble(attr["GRSKEWM"]);
+			item->setGradientMask(attr["GRNAMEM"]);
+			item->mask_gradient.clearStops();
+		}
 		if (tagName=="Gradient")
 		{
 			PageItem* item = this->dig->top<PageItem>();
@@ -659,8 +714,32 @@
 class PatternStroke : public MakeAction<PatternStroke_body>
 {};
 
+class PatternMask_body : public Action_body
+{
+	void begin (const Xml_string& tagName, Xml_attr attr)
+	{
+		PageItem* item = this->dig->top<PageItem>();
+		
+		double patternScaleX = parseDouble(attr["pScaleXM"]);
+		double patternScaleY = parseDouble(attr["pScaleYM"]);
+		double patternOffsetX = parseDouble(attr["pOffsetXM"]);
+		double patternOffsetY = parseDouble(attr["pOffsetYM"]);
+		double patternRotation = parseDouble(attr["pRotationM"]);
+		double patternSkewX = parseDouble(attr["pSkewXM"]);
+		double patternSkewY = parseDouble(attr["pSkewYM"]);
+		bool mirrorX = parseBool(attr["pMirrorXM"]);
+		bool mirrorY = parseBool(attr["pMirrorYM"]);
+		item->setPatternMask(attr["patternM"]);
+		item->maskTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
+		item->setMaskFlip(mirrorX, mirrorY);
+	}
+};
 
+class PatternMask : public MakeAction<PatternMask_body>
+{};
 
+
+
 class ImageEffectsAndLayers_body : public Action_body
 {
 	void begin (const Xml_string& tagName, Xml_attr attr)
@@ -915,7 +994,8 @@
 	ruleset.addRule(itemPrefix, SetAttributeWithConversion<PageItem,bool>( & PageItem::setHasBottomLine, "BottomLine", &parseBool ));
 	
 	ruleset.addRule(Digester::concat(itemPrefix, "Pattern"), Pattern()); 
-	ruleset.addRule(Digester::concat(itemPrefix, "PatternStroke"), PatternStroke()); 
+	ruleset.addRule(Digester::concat(itemPrefix, "PatternStroke"), PatternStroke());
+	ruleset.addRule(Digester::concat(itemPrefix, "PatternMask"), PatternMask());
 	
 	Gradient gradient;
 	Xml_string gradientPrefix(Digester::concat(itemPrefix, "Gradient"));
@@ -925,6 +1005,10 @@
 	Xml_string gradientPrefixS(Digester::concat(itemPrefix, "GradientS"));
 	ruleset.addRule(gradientPrefixS, gradientS);
 	ruleset.addRule(Digester::concat(gradientPrefixS, "S_CStop"), gradientS);
+	Gradient gradientM;
+	Xml_string gradientPrefixM(Digester::concat(itemPrefix, "GradientM"));
+	ruleset.addRule(gradientPrefixM, gradientM);
+	ruleset.addRule(Digester::concat(gradientPrefixM, "M_CStop"), gradientM);
 		
 	ImageEffectsAndLayers effectsAndLayers;
 	ruleset.addRule(Digester::concat(itemPrefix, "ImageEffect"), effectsAndLayers);
Index: scribus/scpainter.h
===================================================================
--- scribus/scpainter.h	(revision 14296)
+++ scribus/scpainter.h	(revision 14297)
@@ -71,6 +71,11 @@
 	virtual void setStrokeMode( int stroke );
 	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 setMaskMode( int mask );
+	virtual void setGradientMask( VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc, double scale, double skew);
+	virtual void setPatternMask(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY);
+	
 	virtual void setClipPath();
 
 	virtual void drawImage( QImage *image );
@@ -104,6 +109,8 @@
 
 	VGradient fill_gradient;
 	VGradient stroke_gradient;
+	VGradient mask_gradient;
+	ScPattern *m_maskPattern;
 	ScPattern *m_pattern;
 
 private:
@@ -165,6 +172,18 @@
 	double stroke_trans;
 	double LineWidth;
 	int strokeMode;				// 0 = none, 1 = solid, 2 = gradient 3 = pattern
+	int maskMode;				// 0 = none, 1 = gradient 2 = pattern
+	double mask_patternScaleX;
+	double mask_patternScaleY;
+	double mask_patternOffsetX;
+	double mask_patternOffsetY;
+	double mask_patternRotation;
+	double mask_patternSkewX;
+	double mask_patternSkewY;
+	bool mask_patternMirrorX;
+	bool mask_patternMirrorY;
+	double mask_gradientScale;
+	double mask_gradientSkew;
 
 	/*! \brief Line End Style */
 	Qt::PenCapStyle PLineEnd;




More information about the scribus-commit mailing list