r17315 by fschmid - Tables: implemented SVG export

scribus-commit scribus-commit at lists.scribus.net
Sat Feb 18 20:59:38 UTC 2012


Author: fschmid
Date: Sat Feb 18 20:59:38 2012
New Revision: 17315

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=17315
Log:
Tables: implemented SVG export

Modified:
    trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.cpp
    trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.h

Modified: trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=17315&path=/trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.cpp
==============================================================================
--- trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.cpp (original)
+++ trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.cpp Sat Feb 18 20:59:38 2012
@@ -37,6 +37,7 @@
 #include "cmsettings.h"
 #include "commonstrings.h"
 #include "pageitem_pathtext.h"
+#include "pageitem_table.h"
 #include "prefsmanager.h"
 #include "prefsfile.h"
 #include "prefscontext.h"
@@ -45,6 +46,7 @@
 #include "scpattern.h"
 #include "scribuscore.h"
 #include "sctextstruct.h"
+#include "tableutils.h"
 #include "util.h"
 #include "ui/customfdialog.h"
 #include "ui/guidemanager.h"
@@ -71,6 +73,8 @@
 	Q_ASSERT(plug);
 	delete plug;
 }
+
+using namespace TableUtils;
 
 SVGExportPlugin::SVGExportPlugin() : ScActionPlugin()
 {
@@ -442,6 +446,208 @@
 				}
 			}
 			break;
+		case PageItem::Table:
+			ob = docu.createElement("g");
+			ob.setAttribute("transform", trans + QString("translate(%1, %2)").arg(Item->asTable()->gridOffset().x()).arg(Item->asTable()->gridOffset().y()));
+			// Paint table fill.
+			if (Item->asTable()->fillColor() != CommonStrings::None)
+			{
+				int lastCol = Item->asTable()->columns() - 1;
+				int lastRow = Item->asTable()->rows() - 1;
+				double x = Item->asTable()->columnPosition(0);
+				double y = Item->asTable()->rowPosition(0);
+				double width = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol) - x;
+				double height = Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow) - y;
+				QDomElement cl = docu.createElement("rect");
+				cl.setAttribute("fill", SetColor(Item->asTable()->fillColor(), Item->asTable()->fillShade()));
+				cl.setAttribute("x", "0");
+				cl.setAttribute("y", "0");
+				cl.setAttribute("width", FToStr(width));
+				cl.setAttribute("height", FToStr(height));
+				ob.appendChild(cl);
+			}
+			// Pass 1: Paint cell fills.
+			for (int row = 0; row < Item->asTable()->rows(); ++row)
+			{
+				int colSpan = 0;
+				for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
+				{
+					TableCell cell = Item->asTable()->cellAt(row, col);
+					if (row == cell.row())
+					{
+						QString colorName = cell.fillColor();
+						if (colorName != CommonStrings::None)
+						{
+							int row = cell.row();
+							int col = cell.column();
+							int lastRow = row + cell.rowSpan() - 1;
+							int lastCol = col + cell.columnSpan() - 1;
+							double x = Item->asTable()->columnPosition(col);
+							double y = Item->asTable()->rowPosition(row);
+							double width = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol) - x;
+							double height = Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow) - y;
+							QDomElement cl = docu.createElement("rect");
+							cl.setAttribute("fill", SetColor(colorName, cell.fillShade()));
+							cl.setAttribute("x", FToStr(x));
+							cl.setAttribute("y", FToStr(y));
+							cl.setAttribute("width", FToStr(width));
+							cl.setAttribute("height", FToStr(height));
+							ob.appendChild(cl);
+						}
+					}
+					colSpan = cell.columnSpan();
+				}
+			}
+			// Pass 2: Paint vertical borders.
+			for (int row = 0; row < Item->asTable()->rows(); ++row)
+			{
+				int colSpan = 0;
+				for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
+				{
+					TableCell cell = Item->asTable()->cellAt(row, col);
+					if (row == cell.row())
+					{
+						const int lastRow = cell.row() + cell.rowSpan() - 1;
+						const int lastCol = cell.column() + cell.columnSpan() - 1;
+						const double borderX = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol);
+						QPointF start(borderX, 0.0);
+						QPointF end(borderX, 0.0);
+						QPointF startOffsetFactors, endOffsetFactors;
+						int startRow, endRow;
+						for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1)
+						{
+							TableCell rightCell = Item->asTable()->cellAt(row, lastCol + 1);
+							startRow = qMax(cell.row(), rightCell.row());
+							endRow = qMin(lastRow, rightCell.isValid() ? rightCell.row() + rightCell.rowSpan() - 1 : lastRow);
+							TableCell topLeftCell = Item->asTable()->cellAt(startRow - 1, lastCol);
+							TableCell topRightCell = Item->asTable()->cellAt(startRow - 1, lastCol + 1);
+							TableCell bottomRightCell = Item->asTable()->cellAt(endRow + 1, lastCol + 1);
+							TableCell bottomLeftCell = Item->asTable()->cellAt(endRow + 1, lastCol);
+							TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight;
+							resolveBordersVertical(topLeftCell, topRightCell, cell, rightCell, bottomLeftCell, bottomRightCell,
+												   &topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, Item->asTable());
+							if (border.isNull())
+								continue; // Quit early if the border to paint is null.
+							start.setY(Item->asTable()->rowPosition(startRow));
+							end.setY((Item->asTable()->rowPosition(endRow) + Item->asTable()->rowHeight(endRow)));
+							joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
+							paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
+						}
+						if (col == 0)
+						{
+							const int lastRow = cell.row() + cell.rowSpan() - 1;
+							const int firstCol = cell.column();
+							const double borderX = Item->asTable()->columnPosition(firstCol);
+							QPointF start(borderX, 0.0);
+							QPointF end(borderX, 0.0);
+							QPointF startOffsetFactors, endOffsetFactors;
+							int startRow, endRow;
+							for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1)
+							{
+								TableCell leftCell = Item->asTable()->cellAt(row, firstCol - 1);
+								startRow = qMax(cell.row(), leftCell.row());
+								endRow = qMin(lastRow, leftCell.isValid() ? leftCell.row() + leftCell.rowSpan() - 1 : lastRow);
+								TableCell topLeftCell = Item->asTable()->cellAt(startRow - 1, firstCol - 1);
+								TableCell topRightCell = Item->asTable()->cellAt(startRow - 1, firstCol);
+								TableCell bottomRightCell = Item->asTable()->cellAt(lastRow + 1, firstCol);
+								TableCell bottomLeftCell = Item->asTable()->cellAt(lastRow + 1, firstCol - 1);
+								TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight;
+								resolveBordersVertical(topLeftCell, topRightCell, leftCell, cell, bottomLeftCell, bottomRightCell,
+													   &topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, Item->asTable());
+								if (border.isNull())
+									continue; // Quit early if the border to paint is null.
+								start.setY(Item->asTable()->rowPosition(startRow));
+								end.setY((Item->asTable()->rowPosition(endRow) + Item->asTable()->rowHeight(endRow)));
+								joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
+								paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
+							}
+						}
+					}
+					colSpan = cell.columnSpan();
+				}
+			}
+			// Pass 3: Paint horizontal borders.
+			for (int row = 0; row < Item->asTable()->rows(); ++row)
+			{
+				int colSpan = 0;
+				for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
+				{
+					TableCell cell = Item->asTable()->cellAt(row, col);
+					if (row == cell.row())
+					{
+						const int lastRow = cell.row() + cell.rowSpan() - 1;
+						const int lastCol = cell.column() + cell.columnSpan() - 1;
+						const double borderY = (Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow));
+						QPointF start(0.0, borderY);
+						QPointF end(0.0, borderY);
+						QPointF startOffsetFactors, endOffsetFactors;
+						int startCol, endCol;
+						for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1)
+						{
+							TableCell bottomCell = Item->asTable()->cellAt(lastRow + 1, col);
+							startCol = qMax(cell.column(), bottomCell.column());
+							endCol = qMin(lastCol, bottomCell.isValid() ? bottomCell.column() + bottomCell.columnSpan() - 1 : lastCol);
+							TableCell topLeftCell = Item->asTable()->cellAt(lastRow, startCol - 1);
+							TableCell topRightCell = Item->asTable()->cellAt(lastRow, endCol + 1);
+							TableCell bottomRightCell = Item->asTable()->cellAt(lastRow + 1, endCol + 1);
+							TableCell bottomLeftCell = Item->asTable()->cellAt(lastRow + 1, startCol - 1);
+							TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight;
+							resolveBordersHorizontal(topLeftCell, cell, topRightCell, bottomLeftCell, bottomCell,
+													 bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, Item->asTable());
+							if (border.isNull())
+								continue; // Quit early if the border is null.
+							start.setX(Item->asTable()->columnPosition(startCol));
+							end.setX(Item->asTable()->columnPosition(endCol) + Item->asTable()->columnWidth(endCol));
+							joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
+							paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
+						}
+						if (row == 0)
+						{
+							const int firstRow = cell.row();
+							const int lastCol = cell.column() + cell.columnSpan() - 1;
+							const double borderY = Item->asTable()->rowPosition(firstRow);
+							QPointF start(0.0, borderY);
+							QPointF end(0.0, borderY);
+							QPointF startOffsetFactors, endOffsetFactors;
+							int startCol, endCol;
+							for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1)
+							{
+								TableCell topCell = Item->asTable()->cellAt(firstRow - 1, col);
+								startCol = qMax(cell.column(), topCell.column());
+								endCol = qMin(lastCol, topCell.isValid() ? topCell.column() + topCell.columnSpan() - 1 : lastCol);
+								TableCell topLeftCell = Item->asTable()->cellAt(firstRow - 1, startCol - 1);
+								TableCell topRightCell = Item->asTable()->cellAt(firstRow - 1, endCol + 1);
+								TableCell bottomRightCell = Item->asTable()->cellAt(firstRow, endCol + 1);
+								TableCell bottomLeftCell = Item->asTable()->cellAt(firstRow, startCol - 1);
+								TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight;
+								resolveBordersHorizontal(topLeftCell, topCell, topRightCell, bottomLeftCell, cell,
+														 bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, Item->asTable());
+								if (border.isNull())
+									continue; // Quit early if the border is null.
+								start.setX(Item->asTable()->columnPosition(startCol));
+								end.setX(Item->asTable()->columnPosition(endCol) + Item->asTable()->columnWidth(endCol));
+								joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
+								paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
+							}
+						}
+					}
+					colSpan = cell.columnSpan();
+				}
+			}
+			// Pass 4: Paint cell content.
+			for (int row = 0; row < Item->asTable()->rows(); ++row)
+			{
+				for (int col = 0; col < Item->asTable()->columns(); col ++)
+				{
+					TableCell cell = Item->asTable()->cellAt(row, col);
+					if (cell.row() == row && cell.column() == col)
+					{
+						PageItem* textFrame = cell.textFrame();
+						ProcessItemOnPage(cell.contentRect().x(), cell.contentRect().y(), textFrame, &ob);
+					}
+				}
+			}
+			break;
 		default:
 			break;
 	}
@@ -450,6 +656,42 @@
 	if (!Item->AutoName)
 		ob.setAttribute("id", Item->itemName());
 	parentElem->appendChild(ob);
+}
+
+void SVGExPlug::paintBorder(const TableBorder& border, const QPointF& start, const QPointF& end, const QPointF& startOffsetFactors, const QPointF& endOffsetFactors, QDomElement &ob)
+{
+	QPointF lineStart, lineEnd;
+	foreach (const TableBorderLine& line, border.borderLines())
+	{
+		lineStart.setX(start.x() + line.width() * startOffsetFactors.x());
+		lineStart.setY(start.y() + line.width() * startOffsetFactors.y());
+		lineEnd.setX(end.x() + line.width() * endOffsetFactors.x());
+		lineEnd.setY(end.y() + line.width() * endOffsetFactors.y());
+		QDomElement cl = docu.createElement("path");
+		cl.setAttribute("d", "M "+FToStr(lineStart.x())+" "+FToStr(lineStart.y())+" L "+FToStr(lineEnd.x())+" "+FToStr(lineEnd.y()));
+		QString stroke = "";
+		if (line.color() != CommonStrings::None)
+			cl.setAttribute("stroke", SetColor(line.color(), line.shade()));
+		if (line.width() != 0.0)
+			stroke = "stroke-width:"+FToStr(line.width())+";";
+		else
+			stroke = "stroke-width:1px;";
+		stroke += " stroke-linecap:butt;";
+		stroke += " stroke-linejoin:miter;";
+		stroke += " stroke-dasharray:";
+		if (line.style() == Qt::SolidLine)
+			stroke += "none;";
+		else
+		{
+			QString Da = getDashString(line.style(), qMax(line.width(), 1.0));
+			if (Da.isEmpty())
+				stroke += "none;";
+			else
+				stroke += Da.replace(" ", ", ")+";";
+		}
+		cl.setAttribute("style", stroke);
+		ob.appendChild(cl);
+	}
 }
 
 QDomElement SVGExPlug::processSymbolStroke(PageItem *Item, QString trans)

Modified: trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=17315&path=/trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.h
==============================================================================
--- trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.h (original)
+++ trunk/Scribus/scribus/plugins/svgexplugin/svgexplugin.h Sat Feb 18 20:59:38 2012
@@ -11,6 +11,7 @@
 #include <QDomElement>
 #include "pluginapi.h"
 #include "loadsaveplugin.h"
+#include "tableborder.h"
 
 class QString;
 class ScLayer;
@@ -80,6 +81,7 @@
 	*/
 	void ProcessPageLayer(ScPage *page, ScLayer& layer);
 	void ProcessItemOnPage(double xOffset, double yOffset, PageItem *Item, QDomElement *parentElem);
+	void paintBorder(const TableBorder& border, const QPointF& start, const QPointF& end, const QPointF& startOffsetFactors, const QPointF& endOffsetFactors, QDomElement &ob);
 	QDomElement processSymbolStroke(PageItem *Item, QString trans);
 	QDomElement processSymbolItem(PageItem *Item, QString trans);
 	QDomElement processPolyItem(PageItem *Item, QString trans, QString fill, QString stroke);




More information about the scribus-commit mailing list