diff --git a/src/adaptors/UBCFFSubsetAdaptor.cpp b/src/adaptors/UBCFFSubsetAdaptor.cpp index 3769fd1c..068aed9b 100644 --- a/src/adaptors/UBCFFSubsetAdaptor.cpp +++ b/src/adaptors/UBCFFSubsetAdaptor.cpp @@ -39,6 +39,7 @@ #include "domain/UBItem.h" #include "domain/UBGraphicsPolygonItem.h" #include "domain/UBGraphicsLineItem.h" +#include "domain/UBGraphicsVectorItem.h" #include "domain/UBGraphicsStroke.h" #include "domain/UBGraphicsTextItem.h" #include "domain/UBGraphicsSvgItem.h" @@ -76,6 +77,7 @@ static QString tSwitch = "switch"; static QString tPolygon = "polygon"; static QString tPolyline = "polyline"; static QString tLine = "line"; +static QString tVector = "vector"; static QString tRect = "rect"; static QString tSvg = "svg"; static QString tText = "text"; @@ -120,6 +122,7 @@ static QString aBackground = "background"; static QString aLocked = "locked"; static QString aEditable = "editable"; static QString aLinestyle = "line-style"; +static QString aVectorstyle = "vector-style"; //attributes part names static QString apRotate = "rotate"; @@ -688,6 +691,96 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgLine(const QDomElement &elem return true; } +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgVector(const QDomElement &element) +{ + QString svgPoints = element.attribute(aPoints); + QLineF line; + + qreal x1 = element.attribute(aX).toDouble(); + qreal y1 = element.attribute(aY).toDouble(); + qreal x2 = element.attribute(aX2).toDouble(); + qreal y2 = element.attribute(aY2).toDouble(); + qreal width = element.attribute(aWidth).toDouble(); + qreal height = element.attribute(aHeight).toDouble(); + QString textStrokeColor = element.attribute(aStroke); + QString textStrokeWidth = element.attribute(aStrokewidth); + qreal style = element.attribute(aVectorstyle).toDouble(); + + QColor strokeColor = !textStrokeColor.isNull() ? colorFromString(textStrokeColor) : QColor(); + int strokeWidth = textStrokeWidth.toInt(); + + width += strokeWidth; + height += strokeWidth; + + QPen pen; + if (strokeColor.isValid()) { + pen.setColor(strokeColor); + } + if (strokeWidth) + pen.setWidth(strokeWidth); + + QUuid itemUuid(element.attribute(aId).right(QUuid().toString().length())); + QUuid itemGroupUuid(element.attribute(aId).left(QUuid().toString().length()-1)); + if (!itemUuid.isNull() && (itemGroupUuid!=itemUuid)) // reimported from UBZ + { + UBGraphicsVectorItem *graphicsVector = new UBGraphicsVectorItem(line); + + graphicsVector->setPen(pen); + QTransform transform; + QString textTransform = element.attribute(aTransform); + + //graphicsVector->setStyle(style); + + graphicsVector->resetTransform(); + if (!textTransform.isNull()) { + transform = transformFromString(textTransform, graphicsVector); + } + mCurrentScene->addItem(graphicsVector); + + graphicsVector->setUuid(itemUuid); + mRefToUuidMap.insert(element.attribute(aId), itemUuid.toString()); + + } + else // simple CFF + { + QSvgGenerator *generator = createSvgGenerator(width + pen.width(), height + pen.width()); + QPainter painter; + + painter.begin(generator); + painter.setPen(pen); + painter.drawLine(x1, y1, x2, y2); + painter.end(); + + + //add resulting svg file to scene + UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName())); + + QString uuid = QUuid::createUuid().toString(); + mRefToUuidMap.insert(element.attribute(aId), uuid); + svgItem->setUuid(QUuid(uuid)); + + QTransform transform; + QString textTransform = element.attribute(aTransform); + + svgItem->resetTransform(); + if (!textTransform.isNull()) { + transform = transformFromString(textTransform, svgItem); + } + repositionSvgItem(svgItem, width +strokeWidth, height + strokeWidth, x1 - strokeWidth/2 + transform.m31(), y1 + strokeWidth/2 + transform.m32(), transform); + hashSceneItem(element, svgItem); + + if (mGSectionContainer) + { + addItemToGSection(svgItem); + } + + delete generator; + } + + + return true; +} + void UBCFFSubsetAdaptor::UBCFFSubsetReader::parseTextAttributes(const QDomElement &element, qreal &fontSize, QColor &fontColor, QString &fontFamily, QString &fontStretch, bool &italic, int &fontWeight, @@ -1209,6 +1302,7 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgElement(const QDomElement &p else if (tagName == tPolygon && !parseSvgPolygon(parent)) return false; else if (tagName == tPolyline && !parseSvgPolyline(parent)) return false; else if (tagName == tLine && !parseSvgLine(parent)) return false; + else if (tagName == tVector && !parseSvgVector(parent)) return false; else if (tagName == tText && !parseSvgText(parent)) return false; else if (tagName == tTextarea && !parseSvgTextarea(parent)) return false; else if (tagName == tImage && !parseSvgImage(parent)) return false; diff --git a/src/adaptors/UBCFFSubsetAdaptor.h b/src/adaptors/UBCFFSubsetAdaptor.h index 96573fe3..ca0b4bc5 100644 --- a/src/adaptors/UBCFFSubsetAdaptor.h +++ b/src/adaptors/UBCFFSubsetAdaptor.h @@ -111,6 +111,7 @@ private: inline bool parseSvgPolygon(const QDomElement &element); inline bool parseSvgPolyline(const QDomElement &element); inline bool parseSvgLine(const QDomElement &element); + inline bool parseSvgVector(const QDomElement &element); inline bool parseSvgText(const QDomElement &element); inline bool parseSvgTextarea(const QDomElement &element); inline bool parseSvgImage(const QDomElement &element); diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 6966b051..6f840c9a 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -41,6 +41,7 @@ #include "domain/UBGraphicsProxyWidget.h" #include "domain/UBGraphicsPolygonItem.h" #include "domain/UBGraphicsLineItem.h" +#include "domain/UBGraphicsVectorItem.h" #include "domain/UBGraphicsMediaItem.h" #include "domain/UBGraphicsWidgetItem.h" #include "domain/UBGraphicsPDFItem.h" @@ -659,6 +660,45 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx group->addToGroup(lineItem); } } + else if (mXmlReader.name() == "vector") + { + UBGraphicsVectorItem* vectorItem = 0; + + QString parentId = mXmlReader.attributes().value(mNamespaceUri, "parent").toString(); + + vectorItem = vectorItemFromVectorSvg(mScene->isDarkBackground() ? Qt::white : Qt::black); + + if(parentId.isEmpty() && strokesGroup) + parentId = strokesGroup->uuid().toString(); + + if(parentId.isEmpty()) + parentId = QUuid::createUuid().toString(); + if (vectorItem) + { + vectorItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Graphic)); + + UBGraphicsStrokesGroup* group; + if(!mStrokesList.contains(parentId)){ + group = new UBGraphicsStrokesGroup(); + mStrokesList.insert(parentId,group); + group->setTransform(vectorItem->transform()); + UBGraphicsItem::assignZValue(group, vectorItem->zValue()); + } + else + group = mStrokesList.value(parentId); + + if (!currentStroke) + currentStroke = new UBGraphicsStroke(); + + if(vectorItem->transform().isIdentity()) + vectorItem->setTransform(group->transform()); + + group->addToGroup(vectorItem); + + vectorItem->show(); + group->addToGroup(vectorItem); + } + } else if (mXmlReader.name() == "polyline") { QList polygonItems = polygonItemsFromPolylineSvg(mScene->isDarkBackground() ? Qt::white : Qt::black); @@ -1384,6 +1424,48 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(UBDocumentProxy* proxy, continue; } + // Is the item a vector? + UBGraphicsVectorItem *vectorItem = qgraphicsitem_cast (item); + if (vectorItem && vectorItem->isVisible()) + { + mXmlWriter.writeStartElement("g"); + + QColor colorOnDarkBackground = vectorItem->colorOnDarkBackground(); + QColor colorOnLightBackground = vectorItem->colorOnLightBackground(); + if (colorOnDarkBackground.isValid() && colorOnLightBackground.isValid()) + { + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "z-value" + , QString("%1").arg(vectorItem->zValue())); + + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri + , "fill-on-dark-background", colorOnDarkBackground.name()); + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri + , "fill-on-light-background", colorOnLightBackground.name()); + + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "uuid", UBStringUtils::toCanonicalUuid(vectorItem->uuid())); + + QVariant locked = vectorItem->data(UBGraphicsItemData::ItemLocked); + + if (!locked.isNull() && locked.toBool()) + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "locked", xmlTrue); + + QVariant layer = vectorItem->data(UBGraphicsItemData::ItemLayerType); + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "layer", QString("%1").arg(layer.toInt())); + + QMatrix matrix = vectorItem->sceneMatrix(); + if (!matrix.isIdentity()) + mXmlWriter.writeAttribute("transform", toSvgTransform(matrix)); + + qDebug() << "Attributes written"; + + groupHoldsInfo = true; + } + + vectorItemToSvgVector(vectorItem, groupHoldsInfo); + + continue; + } + if (openStroke) { mXmlWriter.writeEndElement(); //g @@ -1687,6 +1769,55 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::lineItemToSvgLine(UBGraphicsLineItem } +void UBSvgSubsetAdaptor::UBSvgSubsetWriter::vectorItemToSvgVector(UBGraphicsVectorItem* vectorItem, bool groupHoldsInfo) +{ + mXmlWriter.writeStartElement("vector"); + + QLineF line = vectorItem->originalLine(); + + mXmlWriter.writeAttribute("x1", QString::number(line.p1().x(), 'f', 2)); + mXmlWriter.writeAttribute("y1", QString::number(line.p1().y(), 'f', 2)); + + // SVG renderers (Chrome) do not like line where (x1, y1) == (x2, y2) + qreal x2 = line.p2().x(); + if (line.p1() == line.p2()) + x2 += 0.01; + + mXmlWriter.writeAttribute("x2", QString::number(x2, 'f', 2)); + mXmlWriter.writeAttribute("y2", QString::number(line.p2().y(), 'f', 2)); + + mXmlWriter.writeAttribute("stroke-width", QString::number(vectorItem->originalWidth(), 'f', -1)); + mXmlWriter.writeAttribute("stroke", vectorItem->pen().color().name()); + + qreal alpha = vectorItem->pen().color().alphaF(); + if (alpha < 1.0) + mXmlWriter.writeAttribute("stroke-opacity", QString::number(alpha, 'f', 2)); + mXmlWriter.writeAttribute("stroke-linecap", "round"); + + /* VectorStyle + switch (vectorItem->style()) + { + case Qt::PenStyle::DotLine: + mXmlWriter.writeAttribute("line-style", "2"); + break; + case Qt::PenStyle::DashLine: + mXmlWriter.writeAttribute("line-style", "1"); + break; + default: + mXmlWriter.writeAttribute("line-style", "0"); + }*/ + + if (!groupHoldsInfo) + { + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "z-value", QString("%1").arg(vectorItem->zValue())); + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "fill-on-dark-background", vectorItem->colorOnDarkBackground().name()); + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "fill-on-light-background", vectorItem->colorOnLightBackground().name()); + } + + mXmlWriter.writeEndElement(); + +} + void UBSvgSubsetAdaptor::UBSvgSubsetWriter::strokeToSvgPolyline(UBGraphicsStroke* stroke, bool groupHoldsInfo) { QList pols = stroke->polygons(); @@ -2140,6 +2271,116 @@ UBGraphicsLineItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::lineItemFromLineSvg(c return lineItem; } +UBGraphicsVectorItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::vectorItemFromVectorSvg(const QColor& pDefaultColor) +{ + QStringRef svgX1 = mXmlReader.attributes().value("x1"); + QStringRef svgY1 = mXmlReader.attributes().value("y1"); + QStringRef svgX2 = mXmlReader.attributes().value("x2"); + QStringRef svgY2 = mXmlReader.attributes().value("y2"); + + qreal style = mXmlReader.attributes().value("vector-style").toDouble(); + + QLineF line; + + if (!svgX1.isNull() && !svgY1.isNull() && !svgX2.isNull() && !svgY2.isNull()) + { + qreal x1 = svgX1.toString().toFloat(); + qreal y1 = svgY1.toString().toFloat(); + qreal x2 = svgX2.toString().toFloat(); + qreal y2 = svgY2.toString().toFloat(); + + line.setLine(x1, y1, x2, y2); + } + else + { + qWarning() << "cannot make sense of 'line' value"; + return 0; + } + + QStringRef strokeWidth = mXmlReader.attributes().value("stroke-width"); + + qreal lineWidth = 1.; + + if (!strokeWidth.isNull()) + { + lineWidth = strokeWidth.toString().toFloat(); + } + + UBGraphicsVectorItem* vectorItem = new UBGraphicsVectorItem(line, lineWidth); + graphicsItemFromSvg(vectorItem); + + QStringRef svgStroke = mXmlReader.attributes().value("stroke"); + + QColor penColor = pDefaultColor; + + if (!svgStroke.isNull()) + { + penColor.setNamedColor(svgStroke.toString()); + + } + + QStringRef svgStrokeOpacity = mXmlReader.attributes().value("stroke-opacity"); + qreal opacity = 1.0; + + if (!svgStrokeOpacity.isNull()) + { + opacity = svgStrokeOpacity.toString().toFloat(); + penColor.setAlphaF(opacity); + } + + vectorItem->setColor(penColor); + /* VectorStyle + if (style == 2) + { + vectorItem->setStyle(Qt::PenStyle::DotLine); + } else if (style == 1) + { + lineItem->setStyle(Qt::PenStyle::DashLine); + } else + { + lineItem->setStyle(Qt::PenStyle::SolidLine); + }*/ + + QStringRef ubFillOnDarkBackground = mXmlReader.attributes().value(mNamespaceUri, "fill-on-dark-background"); + + if (!ubFillOnDarkBackground.isNull()) + { + QColor color; + color.setNamedColor(ubFillOnDarkBackground.toString()); + if (!color.isValid()) + color = Qt::white; + + color.setAlphaF(opacity); + vectorItem->setColorOnDarkBackground(color); + } + else + { + QColor color = mGroupDarkBackgroundColor; + color.setAlphaF(opacity); + vectorItem->setColorOnDarkBackground(color); + } + + QStringRef ubFillOnLightBackground = mXmlReader.attributes().value(mNamespaceUri, "fill-on-light-background"); + + if (!ubFillOnLightBackground.isNull()) + { + QColor color; + color.setNamedColor(ubFillOnLightBackground.toString()); + if (!color.isValid()) + color = Qt::black; + color.setAlphaF(opacity); + vectorItem->setColorOnLightBackground(color); + } + else + { + QColor color = mGroupLightBackgroundColor; + color.setAlphaF(opacity); + vectorItem->setColorOnLightBackground(color); + } + + return vectorItem; +} + QList UBSvgSubsetAdaptor::UBSvgSubsetReader::polygonItemsFromPolylineSvg(const QColor& pDefaultColor) { QStringRef strokeWidth = mXmlReader.attributes().value("stroke-width"); diff --git a/src/adaptors/UBSvgSubsetAdaptor.h b/src/adaptors/UBSvgSubsetAdaptor.h index 3e025d86..bdf3796c 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.h +++ b/src/adaptors/UBSvgSubsetAdaptor.h @@ -39,6 +39,7 @@ class UBGraphicsSvgItem; class UBGraphicsPolygonItem; class UBGraphicsLineItem; +class UBGraphicsVectorItem; class UBGraphicsPixmapItem; class UBGraphicsPDFItem; class UBGraphicsWidgetItem; @@ -128,6 +129,8 @@ class UBSvgSubsetAdaptor UBGraphicsLineItem* lineItemFromLineSvg(const QColor& pDefaultPenColor); + UBGraphicsVectorItem* vectorItemFromVectorSvg(const QColor& pDefaultPenColor); + UBGraphicsPixmapItem* pixmapItemFromSvg(); UBGraphicsSvgItem* svgItemFromSvg(); @@ -199,6 +202,7 @@ class UBSvgSubsetAdaptor void polygonItemToSvgPolygon(UBGraphicsPolygonItem* polygonItem, bool groupHoldsInfo); void polygonItemToSvgLine(UBGraphicsPolygonItem* polygonItem, bool groupHoldsInfo); void lineItemToSvgLine(UBGraphicsLineItem* lineItem, bool groupHoldsInfo); + void vectorItemToSvgVector(UBGraphicsVectorItem* vectorItem, bool groupHoldsInfo); void strokeToSvgPolyline(UBGraphicsStroke* stroke, bool groupHoldsInfo); void strokeToSvgPolygon(UBGraphicsStroke* stroke, bool groupHoldsInfo);