r15077 by fschmid - SVG Export: added Symbol support.

scribus-commit scribus-commit at lists.scribus.net
Sun May 16 13:40:34 CEST 2010


Revision: 15077
Author: fschmid
Date: 2010-05-16T11:31:53.987373Z
Commit message: SVG Export: added Symbol support.

Changeset: 
M  /trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.h
M  /trunk/Scribus/scribus/scribusdoc.cpp
M  /trunk/Scribus/scribus/scribusdoc.h
M  /trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.cpp

Diffs:
Index: scribus/scribusdoc.cpp
===================================================================
--- scribus/scribusdoc.cpp	(revision 15076)
+++ scribus/scribusdoc.cpp	(revision 15077)
@@ -2799,7 +2799,6 @@
 	} */
 }
 
-
 QStringList ScribusDoc::getUsedPatterns()
 {
 	QStringList results;
@@ -2892,7 +2891,6 @@
 		return QStringList();
 }
 
-
 QStringList ScribusDoc::getUsedPatternsHelper(QString pattern, QStringList &results)
 {
 	ScPattern *pat = &docPatterns[pattern];
@@ -2923,6 +2921,74 @@
 	return pats;
 }
 
+QStringList ScribusDoc::getUsedSymbols()
+{
+	QStringList results;
+	for (int c = 0; c < MasterItems.count(); ++c)
+	{
+		if ((!results.contains(MasterItems.at(c)->pattern())) && (MasterItems.at(c)->itemType() == PageItem::Symbol) && (!MasterItems.at(c)->pattern().isEmpty()))
+			results.append(MasterItems.at(c)->pattern());
+		if ((!MasterItems.at(c)->strokePattern().isEmpty()) && (MasterItems.at(c)->patternStrokePath))
+		{
+			if (!results.contains(MasterItems.at(c)->strokePattern()))
+				results.append(MasterItems.at(c)->strokePattern());
+		}
+		if ((!results.contains(MasterItems.at(c)->strokePattern())) && ((!MasterItems.at(c)->strokePattern().isEmpty()) && (MasterItems.at(c)->patternStrokePath)))
+			results.append(MasterItems.at(c)->pattern());
+	}
+	for (int c = 0; c < DocItems.count(); ++c)
+	{
+		if ((!results.contains(DocItems.at(c)->pattern())) && (DocItems.at(c)->itemType() == PageItem::Symbol) && (!DocItems.at(c)->pattern().isEmpty()))
+			results.append(DocItems.at(c)->pattern());
+		if ((!DocItems.at(c)->strokePattern().isEmpty()) && (DocItems.at(c)->patternStrokePath))
+		{
+			if (!results.contains(DocItems.at(c)->strokePattern()))
+				results.append(DocItems.at(c)->strokePattern());
+		}
+	}
+	for (int c = 0; c < FrameItems.count(); ++c)
+	{
+		if ((!results.contains(FrameItems.at(c)->pattern())) && (FrameItems.at(c)->itemType() == PageItem::Symbol) && (!FrameItems.at(c)->pattern().isEmpty()))
+			results.append(FrameItems.at(c)->pattern());
+		if ((!FrameItems.at(c)->strokePattern().isEmpty()) && (FrameItems.at(c)->patternStrokePath))
+		{
+			if (!results.contains(FrameItems.at(c)->strokePattern()))
+				results.append(FrameItems.at(c)->strokePattern());
+		}
+	}
+	for (int c = 0; c < results.count(); ++c)
+	{
+		QStringList pats = getUsedSymbolsHelper(results[c], results);
+		if (!pats.isEmpty())
+			results += pats;
+	}
+	return results;
+}
+
+QStringList ScribusDoc::getUsedSymbolsHelper(QString pattern, QStringList &results)
+{
+	ScPattern *pat = &docPatterns[pattern];
+	QStringList pats;
+	pats.clear();
+	for (int c = 0; c < pat->items.count(); ++c)
+	{
+		if (pat->items.at(c)->itemType() == PageItem::Symbol)
+		{
+			const QString& patName = pat->items.at(c)->pattern();
+			if (!patName.isEmpty() && !results.contains(patName))
+				pats.append(patName);
+		}
+	}
+	if (!pats.isEmpty())
+	{
+		for (int c = 0; c < pats.count(); ++c)
+		{
+			getUsedSymbolsHelper(pats[c], results);
+		}
+	}
+	return pats;
+}
+
 QMap<QString,int> ScribusDoc::reorganiseFonts()
 {
 //	QTime t;
Index: scribus/scribusdoc.h
===================================================================
--- scribus/scribusdoc.h	(revision 15076)
+++ scribus/scribusdoc.h	(revision 15077)
@@ -614,6 +614,11 @@
 	QStringList getUsedPatterns();
 	QStringList getUsedPatternsSelection(Selection* customSelection);
 	QStringList getUsedPatternsHelper(QString pattern, QStringList &results);
+	/*!
+	* @brief Builds a QStringList of the symbols used within the document
+	*/
+	QStringList getUsedSymbols();
+	QStringList getUsedSymbolsHelper(QString pattern, QStringList &results);
 	/**
 	 * @brief Set and get the document's unit index
 	 */
Index: scribus/plugins/svgexplugin/svgexplugin.h
===================================================================
--- scribus/plugins/svgexplugin/svgexplugin.h	(revision 15076)
+++ scribus/plugins/svgexplugin/svgexplugin.h	(revision 15077)
@@ -80,6 +80,8 @@
 	*/
 	void ProcessPageLayer(Page *page, ScLayer& layer);
 	void ProcessItemOnPage(double xOffset, double yOffset, PageItem *Item, QDomElement *parentElem);
+	QDomElement processSymbolStroke(PageItem *Item, QString trans);
+	QDomElement processSymbolItem(PageItem *Item, QString trans);
 	QDomElement processPolyItem(PageItem *Item, QString trans, QString fill, QString stroke);
 	QDomElement processLineItem(PageItem *Item, QString trans, QString stroke);
 	QDomElement processImageItem(PageItem *Item, QString trans, QString fill, QString stroke);
@@ -92,6 +94,7 @@
 	QString getFillStyle(PageItem *Item);
 	QString getStrokeStyle(PageItem *Item);
 	void writeBasePatterns();
+	void writeBaseSymbols();
 	/*!
 	\author Franz Schmid
 	\param ite PageItem *
Index: scribus/plugins/svgexplugin/svgexplugin.cpp
===================================================================
--- scribus/plugins/svgexplugin/svgexplugin.cpp	(revision 15076)
+++ scribus/plugins/svgexplugin/svgexplugin.cpp	(revision 15077)
@@ -230,6 +230,7 @@
 	}
 	globalDefs = docu.createElement("defs");
 	writeBasePatterns();
+	writeBaseSymbols();
 	docElement.appendChild(globalDefs);
 	if (Options.exportPageBackground)
 	{
@@ -441,6 +442,9 @@
 		case PageItem::PathText:
 			ob = processPathTextItem(Item, trans, stroke);
 			break;
+		case PageItem::Symbol:
+			ob = processSymbolItem(Item, trans);
+			break;
 		default:
 			break;
 	}
@@ -451,6 +455,74 @@
 	parentElem->appendChild(ob);
 }
 
+QDomElement SVGExPlug::processSymbolStroke(PageItem *Item, QString trans)
+{
+	QDomElement ob;
+	ob = docu.createElement("g");
+	ob.setAttribute("transform", trans);
+	QPainterPath path = Item->PoLine.toQPainterPath(false);
+	ScPattern pat = m_Doc->docPatterns[Item->strokePattern()];
+	double pLen = path.length() - ((pat.width / 2.0) * (Item->patternStrokeScaleX / 100.0));
+	double adv = pat.width * Item->patternStrokeScaleX / 100.0 * Item->patternStrokeSpace;
+	double xpos = Item->patternStrokeOffsetX * Item->patternStrokeScaleX / 100.0;
+	while (xpos < pLen)
+	{
+		double currPerc = path.percentAtLength(xpos);
+		double currAngle = path.angleAtPercent(currPerc);
+#if QT_VERSION  >= 0x040400
+		if (currAngle <= 180.0)
+			currAngle *= -1.0;
+		else
+			currAngle = 360.0 - currAngle;
+#endif
+		QPointF currPoint = path.pointAtPercent(currPerc);
+		QTransform trans;
+		trans.translate(currPoint.x(), currPoint.y());
+		trans.rotate(-currAngle);
+		trans.translate(0.0, Item->patternStrokeOffsetY);
+		trans.rotate(-Item->patternStrokeRotation);
+		trans.shear(Item->patternStrokeSkewX, -Item->patternStrokeSkewY);
+		trans.scale(Item->patternStrokeScaleX / 100.0, Item->patternStrokeScaleY / 100.0);
+		trans.translate(-pat.width / 2.0, -pat.height / 2.0);
+		QDomElement obS;
+		obS = docu.createElement("use");
+		obS.setAttribute("transform", MatrixToStr(trans));
+		if (Item->patternStrokeMirrorX)
+		{
+			trans.translate(pat.width, 0);
+			trans.scale(-1, 1);
+		}
+		if (Item->patternStrokeMirrorY)
+		{
+			trans.translate(0, pat.height);
+			trans.scale(1, -1);
+		}
+		obS.setAttribute("x", "0");
+		obS.setAttribute("y", "0");
+		obS.setAttribute("width", FToStr(pat.width));
+		obS.setAttribute("height", FToStr(pat.height));
+		obS.setAttribute("xlink:href", "#S"+Item->strokePattern());
+		ob.appendChild(obS);
+		xpos += adv;
+	}
+	return ob;
+}
+
+QDomElement SVGExPlug::processSymbolItem(PageItem *Item, QString trans)
+{
+	QDomElement ob;
+	ob = docu.createElement("use");
+	ob.setAttribute("x", "0");
+	ob.setAttribute("y", "0");
+	ob.setAttribute("width", FToStr(Item->width()));
+	ob.setAttribute("height", FToStr(Item->height()));
+	ob.setAttribute("xlink:href", "#S"+Item->pattern());
+	ScPattern pat = m_Doc->docPatterns[Item->pattern()];
+	QString tr = trans + QString(" scale(%1, %2)").arg(Item->width() / pat.width).arg(Item->height() / pat.height);
+	ob.setAttribute("transform", tr);
+	return ob;
+}
+
 QDomElement SVGExPlug::processPolyItem(PageItem *Item, QString trans, QString fill, QString stroke)
 {
 	bool closedPath;
@@ -461,10 +533,23 @@
 		closedPath = false;
 	if (Item->NamedLStyle.isEmpty())
 	{
-		ob = docu.createElement("path");
-		ob.setAttribute("d", SetClipPath(&Item->PoLine, closedPath));
-		ob.setAttribute("transform", trans);
-		ob.setAttribute("style", fill + stroke);
+		if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
+		{
+			ob = docu.createElement("g");
+			QDomElement ob2 = docu.createElement("path");
+			ob2.setAttribute("d", SetClipPath(&Item->PoLine, closedPath));
+			ob2.setAttribute("transform", trans);
+			ob2.setAttribute("style", fill);
+			ob.appendChild(ob2);
+			ob.appendChild(processSymbolStroke(Item, trans));
+		}
+		else
+		{
+			ob = docu.createElement("path");
+			ob.setAttribute("d", SetClipPath(&Item->PoLine, closedPath));
+			ob.setAttribute("transform", trans);
+			ob.setAttribute("style", fill + stroke);
+		}
 	}
 	else
 	{
@@ -595,10 +680,24 @@
 	}
 	if (Item->NamedLStyle.isEmpty())
 	{
-		QDomElement ob4 = docu.createElement("path");
-		ob4.setAttribute("d", SetClipPath(&Item->PoLine, true));
-		ob4.setAttribute("style", "fill:none; "+stroke);
-		ob.appendChild(ob4);
+		if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
+		{
+			QDomElement ob4 = docu.createElement("g");
+			QDomElement ob2 = docu.createElement("path");
+			ob2.setAttribute("d", SetClipPath(&Item->PoLine, true));
+			ob2.setAttribute("transform", trans);
+			ob2.setAttribute("style", fill);
+			ob4.appendChild(ob2);
+			ob4.appendChild(processSymbolStroke(Item, trans));
+			ob.appendChild(ob4);
+		}
+		else
+		{
+			QDomElement ob4 = docu.createElement("path");
+			ob4.setAttribute("d", SetClipPath(&Item->PoLine, true));
+			ob4.setAttribute("style", "fill:none; "+stroke);
+			ob.appendChild(ob4);
+		}
 	}
 	else
 	{
@@ -829,6 +928,8 @@
 		QDomElement ob4 = docu.createElement("path");
 		ob4.setAttribute("d", SetClipPath(&Item->PoLine, true));
 		ob4.setAttribute("style", "fill:none; "+stroke);
+		if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
+			ob4.appendChild(processSymbolStroke(Item, trans));
 		ob.appendChild(ob4);
 	}
 	else
@@ -1159,6 +1260,9 @@
 			case PageItem::PathText:
 				obE = processPathTextItem(embedded, trans, stroke);
 				break;
+			case PageItem::Symbol:
+				obE = processSymbolItem(embedded, trans);
+				break;
 			default:
 				break;
 		}
@@ -1896,6 +2000,87 @@
 	}
 }
 
+void SVGExPlug::writeBaseSymbols()
+{
+	QStringList patterns = m_Doc->getUsedSymbols();
+	for (int c = 0; c < patterns.count(); ++c)
+	{
+		QStack<PageItem*> groupStack;
+		QStack<QDomElement> groupStack2;
+		ScPattern pa = m_Doc->docPatterns[patterns[c]];
+		QDomElement patt = docu.createElement("symbol");
+		patt.setAttribute("id", "S"+patterns[c]);
+		patt.setAttribute("viewbox", "0 0 "+ FToStr(pa.height) + " " + FToStr(pa.width));
+		for (int em = 0; em < pa.items.count(); ++em)
+		{
+			PageItem* Item = pa.items.at(em);
+			if (Item->isGroupControl)
+			{
+				groupStack.push(Item->groupsLastItem);
+				groupStack2.push(patt);
+				patt = docu.createElement("g");
+				if (Item->fillTransparency() != 0)
+					patt.setAttribute("opacity", FToStr(1.0 - Item->fillTransparency()));
+				QDomElement ob = docu.createElement("clipPath");
+				ob.setAttribute("id", "Clip"+IToStr(ClipCount));
+				QDomElement cl = docu.createElement("path");
+				cl.setAttribute("d", SetClipPath(&Item->PoLine, true));
+				QString trans = "translate("+FToStr(Item->gXpos)+", "+FToStr(Item->gYpos)+")";
+				if (Item->rotation() != 0)
+					trans += " rotate("+FToStr(Item->rotation())+")";
+				cl.setAttribute("transform", trans);
+				ob.appendChild(cl);
+				globalDefs.appendChild(ob);
+				patt.setAttribute("clip-path", "url(#Clip"+IToStr(ClipCount)+")");
+				ClipCount++;
+				continue;
+			}
+			ProcessItemOnPage(Item->gXpos, Item->gYpos, Item, &patt);
+			if (groupStack.count() != 0)
+			{
+				while (Item == groupStack.top())
+				{
+					groupStack.pop();
+					groupStack2.top().appendChild(patt);
+					patt = groupStack2.pop();
+					if (groupStack.count() == 0)
+						break;
+				}
+			}
+		}
+		for (int em = 0; em < pa.items.count(); ++em)
+		{
+			PageItem* embedded = pa.items.at(em);
+			QString trans = "translate("+FToStr(embedded->gXpos)+", "+FToStr(embedded->gYpos)+")";
+			if (embedded->rotation() != 0)
+				trans += " rotate("+FToStr(embedded->rotation())+")";
+			if (!embedded->isTableItem)
+				continue;
+			if ((embedded->lineColor() == CommonStrings::None) || (embedded->lineWidth() == 0.0))
+				continue;
+			if ((embedded->TopLine) || (embedded->RightLine) || (embedded->BottomLine) || (embedded->LeftLine))
+			{
+				QString stroke = getStrokeStyle(embedded);
+				QDomElement obL = docu.createElement("path");
+				obL.setAttribute("transform", trans);
+				obL.setAttribute("style", "fill:none; " + stroke);
+				QString pathAttr = "";
+				if (embedded->TopLine)
+					pathAttr += "M 0 0 L "+FToStr(embedded->width())+" 0";
+				if (embedded->RightLine)
+					pathAttr += " M " + FToStr(embedded->width()) + "0 L "+FToStr(embedded->width())+" "+FToStr(embedded->height());
+				if (embedded->BottomLine)
+					pathAttr += " M 0 " + FToStr(embedded->height()) + " L "+FToStr(embedded->width())+" "+FToStr(embedded->height());
+				if (embedded->LeftLine)
+					pathAttr += " M 0 0 L 0 "+FToStr(embedded->height());
+				obL.setAttribute("d", pathAttr);
+				patt.appendChild(obL);
+			}
+		}
+		globalDefs.appendChild(patt);
+	}
+}
+
 QString SVGExPlug::getStrokeStyle(PageItem *Item)
 {
 	QString stroke = "";
@@ -1960,7 +2145,7 @@
 				stroke += Da.replace(" ", ", ")+";";
 		}
 	}
-	if (!Item->strokePattern().isEmpty())
+	if ((!Item->strokePattern().isEmpty()) && (!Item->patternStrokePath))
 	{
 		QString pattID = Item->strokePattern()+IToStr(PattCount);
 		PattCount++;




More information about the scribus-commit mailing list