nextExtendedIwbElement(mExtendedElements);
+ while (nextExtendedIwbElement.hasNext()) {
+ writeQDomElementToXML(nextExtendedIwbElement.next());
+ //TODO write iwb extended element to mIWBContentWriter
+ }
+
+ return true;
+}
+
+// extended element options
+// editable, background, locked are supported for now
+
+QDomElement UBCFFAdaptor::UBToCFFConverter::parseGroupPageSection(const QDomElement &element)
+{
+// First sankore side implementation needed. TODO in Sankore 1.5
+ Q_UNUSED(element)
+ qDebug() << "parsing ubz group section";
+ return QDomElement();
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::getDstContentFolderName(const QString &elementType)
+{
+ QString sRet;
+ QString sDstContentFolderName;
+
+ // widgets must be saved as .png images.
+ if ((tIWBImage == elementType) || (tUBZForeignObject == elementType))
+ sDstContentFolderName = cfImages;
+ else
+ if (tIWBVideo == elementType)
+ sDstContentFolderName = cfVideos;
+ else
+ if (tIWBAudio == elementType)
+ sDstContentFolderName = cfAudios;
+
+ sRet = sDstContentFolderName;
+
+ return sRet;
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::getSrcContentFolderName(QString href)
+{
+ QString sRet;
+
+ QStringList ls = href.split("/");
+ for (int i = 0; i < ls.count()-1; i++)
+ {
+ QString sPart = ls.at(i);
+ if (ubzContentFolders.contains(sPart))
+ {
+ sRet = sPart;
+ }
+ }
+
+// if (0 < ls.count())
+// sRet = ls.at(ls.count()-1);
+//
+// sRet = href.remove(sRet);
+//
+// if (sRet.endsWith("/"))
+// sRet.remove("/");
+
+ return sRet;
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::getFileNameFromPath(const QString sPath)
+{
+ QString sRet;
+ QStringList sl = sPath.split("/",QString::SkipEmptyParts);
+
+ if (0 < sl.count())
+ {
+ QString name = sl.at(sl.count()-1);
+ QString extention = getExtentionFromFileName(name);
+
+ if (feWgt == extention)
+ {
+ name.remove("{");
+ name.remove("}");
+ }
+
+ name.remove(name.length()-extention.length(), extention.length());
+ name += convertExtention(extention);
+
+ sRet = name;
+ }
+ return sRet;
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::getExtentionFromFileName(const QString &filename)
+{
+ QStringList sl = filename.split("/",QString::SkipEmptyParts);
+
+ if (0 < sl.count())
+ {
+ QString name = sl.at(sl.count()-1);
+ QStringList tl = name.split(".");
+ return tl.at(tl.count()-1);
+ }
+ return QString();
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::convertExtention(const QString &ext)
+{
+ QString sRet;
+
+ if (feSvg == ext)
+ sRet = fePng;
+ else
+ if (feWgt == ext)
+ sRet = fePng;
+ else
+ sRet = ext;
+
+ return sRet;
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::getElementTypeFromUBZ(const QDomElement &element)
+{
+ QString sRet;
+ if (tUBZForeignObject == element.tagName())
+ {
+ QString sPath;
+ if (element.hasAttribute(aUBZType))
+ {
+ if (avUBZText == element.attribute(aUBZType))
+ sRet = tIWBTextArea;
+ else
+ sRet = element.attribute(aUBZType);
+ }
+ else
+ {
+ if (element.hasAttribute(aSrc))
+ sPath = element.attribute(aSrc);
+ else
+ if (element.hasAttribute(aUBZHref))
+ sPath = element.attribute(aUBZHref);
+
+ QStringList tsl = sPath.split(".", QString::SkipEmptyParts);
+ if (0 < tsl.count())
+ {
+ QString elementType = tsl.at(tsl.count()-1);
+ if (iwbElementImage.contains(elementType))
+ sRet = tIWBImage;
+ else
+ if (iwbElementAudio.contains(elementType))
+ sRet = tIWBAudio;
+ else
+ if (iwbElementVideo.contains(elementType))
+ sRet = tIWBVideo;
+ }
+ }
+ }
+ else
+ sRet = element.tagName();
+
+ return sRet;
+}
+
+int UBCFFAdaptor::UBToCFFConverter::getElementLayer(const QDomElement &element)
+{
+ int iRetLayer = 0;
+ if (element.hasAttribute(aZLayer))
+ iRetLayer = (int)element.attribute(aZLayer).toDouble();
+ else
+ iRetLayer = DEFAULT_LAYER;
+
+ return iRetLayer;
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::itIsSupportedFormat(const QString &format) const
+{
+ bool bRet;
+
+ QStringList tsl = format.split(".", QString::SkipEmptyParts);
+ if (0 < tsl.count())
+ bRet = cffSupportedFileFormats.contains(tsl.at(tsl.count()-1));
+ else
+ bRet = false;
+
+ return bRet;
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::itIsFormatToConvert(const QString &format) const
+{
+ foreach (QString f, ubzFormatsToConvert.split(","))
+ {
+ if (format == f)
+ return true;
+ }
+ return false;
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::itIsSVGElementAttribute(const QString ItemType, const QString &AttrName)
+{
+ QString allowedElementAttributes = iwbSVGItemsAttributes[ItemType];
+
+ allowedElementAttributes.remove("/t");
+ allowedElementAttributes.remove(" ");
+ foreach(QString attr, allowedElementAttributes.split(","))
+ {
+ if (AttrName == attr.trimmed())
+ return true;
+ }
+ return false;
+}
+
+
+bool UBCFFAdaptor::UBToCFFConverter::itIsIWBAttribute(const QString &attribute) const
+{
+ foreach (QString attr, iwbElementAttributes.split(","))
+ {
+ if (attribute == attr.trimmed())
+ return true;
+ }
+ return false;
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::itIsUBZAttributeToConvert(const QString &attribute) const
+{
+ foreach (QString attr, ubzElementAttributesToConvert.split(","))
+ {
+ if (attribute == attr.trimmed())
+ return true;
+ }
+ return false;
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::ibwAddLine(int x1, int y1, int x2, int y2, QString color, int width, bool isBackground)
+{
+ bool bRet = true;
+
+ QDomDocument doc;
+
+ QDomElement svgBackgroundCrossPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":line");
+ QDomElement iwbBackgroundCrossPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ QString sUUID = QUuid::createUuid().toString().remove("{").remove("}");
+
+ svgBackgroundCrossPart.setTagName(tIWBLine);
+
+ svgBackgroundCrossPart.setAttribute(aX+"1", x1);
+ svgBackgroundCrossPart.setAttribute(aY+"1", y1);
+ svgBackgroundCrossPart.setAttribute(aX+"2", x2);
+ svgBackgroundCrossPart.setAttribute(aY+"2", y2);
+
+ svgBackgroundCrossPart.setAttribute(aStroke, color);
+ svgBackgroundCrossPart.setAttribute(aStrokeWidth, width);
+
+ svgBackgroundCrossPart.setAttribute(aID, sUUID);
+
+ if (isBackground)
+ {
+ iwbBackgroundCrossPart.setAttribute(aRef, sUUID);
+ iwbBackgroundCrossPart.setAttribute(aLocked, avTrue);
+
+ addIWBElementToResultModel(iwbBackgroundCrossPart);
+ }
+
+ addSVGElementToResultModel(svgBackgroundCrossPart, mSvgElements, DEFAULT_BACKGROUND_CROSS_LAYER);
+
+ if (!bRet)
+ {
+ qDebug() << "|error at creating crosses on background";
+ errorStr = "CreatingCrossedBackgroundParsingError.";
+ }
+
+ return bRet;
+}
+
+QTransform UBCFFAdaptor::UBToCFFConverter::getTransformFromUBZ(const QDomElement &ubzElement)
+{
+ QTransform trRet;
+
+ QStringList transformParameters;
+
+ QString ubzTransform = ubzElement.attribute(aTransform);
+ ubzTransform.remove("matrix");
+ ubzTransform.remove("(");
+ ubzTransform.remove(")");
+
+ transformParameters = ubzTransform.split(",", QString::SkipEmptyParts);
+
+ if (6 <= transformParameters.count())
+ {
+ QTransform *tr = NULL;
+ tr = new QTransform(transformParameters.at(0).toDouble(),
+ transformParameters.at(1).toDouble(),
+ transformParameters.at(2).toDouble(),
+ transformParameters.at(3).toDouble(),
+ transformParameters.at(4).toDouble(),
+ transformParameters.at(5).toDouble());
+
+ trRet = *tr;
+
+ delete tr;
+ }
+
+ if (6 <= transformParameters.count())
+ {
+ QTransform *tr = NULL;
+ tr = new QTransform(transformParameters.at(0).toDouble(),
+ transformParameters.at(1).toDouble(),
+ transformParameters.at(2).toDouble(),
+ transformParameters.at(3).toDouble(),
+ transformParameters.at(4).toDouble(),
+ transformParameters.at(5).toDouble());
+
+ trRet = *tr;
+
+ delete tr;
+ }
+ return trRet;
+}
+
+qreal UBCFFAdaptor::UBToCFFConverter::getAngleFromTransform(const QTransform &tr)
+{
+ qreal angle = -(atan(tr.m21()/tr.m11())*180/PI);
+ if (tr.m21() > 0 && tr.m11() < 0)
+ angle += 180;
+ else
+ if (tr.m21() < 0 && tr.m11() < 0)
+ angle += 180;
+ return angle;
+}
+
+void UBCFFAdaptor::UBToCFFConverter::setGeometryFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement)
+{
+ setCoordinatesFromUBZ(ubzElement,iwbElement);
+
+
+
+}
+
+void UBCFFAdaptor::UBToCFFConverter::setCoordinatesFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement)
+{
+ QTransform tr;
+
+ if (QString() != ubzElement.attribute(aTransform))
+ tr = getTransformFromUBZ(ubzElement);
+
+ qreal x = ubzElement.attribute(aX).toDouble();
+ qreal y = ubzElement.attribute(aY).toDouble();
+ qreal height = ubzElement.attribute(aHeight).toDouble();
+ qreal width = ubzElement.attribute(aWidth).toDouble();
+
+ qreal alpha = getAngleFromTransform(tr);
+
+ QRectF itemRect;
+ QGraphicsRectItem item;
+
+ item.setRect(0,0, width, height);
+ item.setTransform(tr);
+
+ item.setTransformOriginPoint(item.boundingRect().center());
+ item.setRotation(-alpha);
+ QMatrix sceneMatrix = item.sceneMatrix();
+
+ iwbElement.setAttribute(aX, x);
+ iwbElement.setAttribute(aY, y);
+ iwbElement.setAttribute(aHeight, height*sceneMatrix.m22());
+ iwbElement.setAttribute(aWidth, width*sceneMatrix.m11());
+ iwbElement.setAttribute(aTransform, QString("rotate(%1) translate(%2,%3)").arg(alpha)
+ .arg(sceneMatrix.dx())
+ .arg(sceneMatrix.dy()));
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::setContentFromUBZ(const QDomElement &ubzElement, QDomElement &svgElement)
+{
+ bool bRet = true;
+
+ QString srcPath;
+ if (tUBZForeignObject != ubzElement.tagName())
+ srcPath = ubzElement.attribute(aUBZHref);
+ else
+ srcPath = ubzElement.attribute(aSrc);
+
+ QString sSrcContentFolder = getSrcContentFolderName(srcPath);
+ QString sSrcFileName = sourcePath + "/" + srcPath ;
+ QString fileExtention = getExtentionFromFileName(sSrcFileName);
+ QString sDstContentFolder = getDstContentFolderName(ubzElement.tagName());
+ QString sDstFileName(QString(QUuid::createUuid().toString()+"."+convertExtention(fileExtention)).remove("{").remove("}"));
+
+
+ if (itIsSupportedFormat(fileExtention)) // format is supported and we can copy src. files without changing.
+ {
+ sSrcFileName = sourcePath + "/" + sSrcContentFolder + "/" + getFileNameFromPath(srcPath); // some elements must be exported as images, so we take hes existing thumbnails.
+
+ QFile srcFile;
+ srcFile.setFileName(sSrcFileName);
+
+ QDir dstDocFolder(destinationPath);
+
+ if (!dstDocFolder.exists(sDstContentFolder))
+ bRet &= dstDocFolder.mkdir(sDstContentFolder);
+
+ if (bRet)
+ {
+ QString dstFilePath = destinationPath+"/"+sDstContentFolder+"/"+sDstFileName;
+ bRet &= srcFile.copy(dstFilePath);
+ }
+
+ if (bRet)
+ {
+ svgElement.setAttribute(aSVGHref, sDstContentFolder+"/"+sDstFileName);
+ svgElement.setAttribute(aSVGRequiredExtension, svgRequiredExtensionPrefix+convertExtention(fileExtention));
+ }
+ }
+ else
+ if (itIsFormatToConvert(fileExtention)) // we cannot copy that source files. We need to create dst. file from src. file without copy.
+ {
+ if (feSvg == fileExtention)
+ {
+ QDir dstDocFolder(destinationPath);
+
+ if (!dstDocFolder.exists(sDstContentFolder))
+ bRet &= dstDocFolder.mkdir(sDstContentFolder);
+
+ if (bRet)
+ {
+ if (feSvg == fileExtention) // svg images must be converted to PNG.
+ {
+ QString dstFilePath = destinationPath+"/"+sDstContentFolder+"/"+sDstFileName;
+ bRet &= createPngFromSvg(sSrcFileName, dstFilePath, getTransformFromUBZ(ubzElement));
+ }
+ else
+ bRet = false;
+ }
+
+ if (bRet)
+ {
+ svgElement.setAttribute(aSVGHref, sDstContentFolder+"/"+sDstFileName);
+ svgElement.setAttribute(aSVGRequiredExtension, svgRequiredExtensionPrefix+fePng);
+ }
+ }
+ }
+
+ if (!bRet)
+ {
+ qDebug() << "format is not supported by CFF";
+ }
+
+ return bRet;
+}
+
+void UBCFFAdaptor::UBToCFFConverter::setCFFTextFromHTMLTextNode(const QDomElement htmlTextNode, QDomElement &iwbElement)
+{
+
+ QDomDocument textDoc;
+
+ QDomElement textParentElement = iwbElement;
+
+ QString textString;
+ QDomNode htmlPNode = htmlTextNode.firstChild();
+ bool bTbreak = false;
+
+ // reads HTML text strings - each string placed in separate section
+ while(!htmlPNode.isNull())
+ {
+ // add for split strings
+ if (bTbreak)
+ {
+ bTbreak = false;
+
+ QDomElement tbreakNode = textDoc.createElementNS(svgIWBNS, svgIWBNSPrefix+":"+tIWBTbreak);
+ textParentElement.appendChild(tbreakNode.cloneNode(true));
+ }
+
+ QDomNode spanNode = htmlPNode.firstChild();
+
+
+ while (!spanNode.isNull())
+ {
+ if (spanNode.isText())
+ {
+ QDomText nodeText = textDoc.createTextNode(spanNode.nodeValue());
+ textParentElement.appendChild(nodeText.cloneNode(true));
+ }
+ else
+ if (spanNode.isElement())
+ {
+ QDomElement spanElement = textDoc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBTspan);
+ if (spanNode.hasAttributes())
+ {
+ int attrCount = spanNode.attributes().count();
+ if (0 < attrCount)
+ {
+ for (int i = 0; i < attrCount; i++)
+ {
+ // html attributes like: style="font-size:40pt; color:"red";".
+ QStringList cffAttributes = spanNode.attributes().item(i).nodeValue().split(";", QString::SkipEmptyParts);
+ {
+ for (int i = 0; i < cffAttributes.count(); i++)
+ {
+ QString attr = cffAttributes.at(i).trimmed();
+ QStringList AttrVal = attr.split(":", QString::SkipEmptyParts);
+ if(1 < AttrVal.count())
+ {
+ QString sAttr = ubzAttrNameToCFFAttrName(AttrVal.at(0));
+ if (itIsSVGElementAttribute(spanElement.tagName(), sAttr))
+ spanElement.setAttribute(sAttr, ubzAttrValueToCFFAttrName(AttrVal.at(1)));
+ }
+ }
+ }
+ }
+ }
+ }
+ QDomText nodeText = textDoc.createTextNode(spanNode.firstChild().nodeValue());
+ spanElement.appendChild(nodeText);
+ textParentElement.appendChild(spanElement.cloneNode(true));
+ }
+ spanNode = spanNode.nextSibling();
+ }
+
+ bTbreak = true;
+ htmlPNode = htmlPNode.nextSibling();
+ }
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::ubzAttrNameToCFFAttrName(QString cffAttrName)
+{
+ QString sRet = cffAttrName;
+ if (QString("color") == cffAttrName)
+ sRet = QString("fill");
+
+ return sRet;
+}
+QString UBCFFAdaptor::UBToCFFConverter::ubzAttrValueToCFFAttrName(QString cffValue)
+{
+ QString sRet = cffValue;
+ if (QString("text") == cffValue)
+ sRet = QString("normal");
+
+ return sRet;
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::setCFFAttribute(const QString &attributeName, const QString &attributeValue, const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement)
+{
+ bool bRet = true;
+ bool bNeedsIWBSection = false;
+
+ if (itIsIWBAttribute(attributeName))
+ {
+ if (!((aBackground == attributeName) && (avFalse == attributeValue)))
+ {
+ iwbElement.setAttribute(attributeName, attributeValue);
+ bNeedsIWBSection = true;
+ }
+ }
+ else
+ if (itIsUBZAttributeToConvert(attributeName))
+ {
+ if (aTransform == attributeName)
+ {
+ setGeometryFromUBZ(ubzElement, svgElement);
+ }
+ else
+ if (attributeName.contains(aUBZHref)||attributeName.contains(aSrc))
+ {
+ bRet &= setContentFromUBZ(ubzElement, svgElement);
+ bNeedsIWBSection = bRet||bNeedsIWBSection;
+ }
+ }
+ else
+ if (itIsSVGElementAttribute(svgElement.tagName(),attributeName))
+ {
+ svgElement.setAttribute(attributeName, attributeValue);
+ }
+
+ if (bNeedsIWBSection)
+ {
+ if (0 < iwbElement.attributes().count())
+ {
+
+ QStringList tl = ubzElement.attribute(aSVGHref).split("/");
+ QString id = tl.at(tl.count()-1);
+ // if element already have an ID, we use it. Else we create new id for element.
+ if (QString() == id)
+ id = QUuid::createUuid().toString().remove("{").remove("}");
+
+ svgElement.setAttribute(aID, id);
+ iwbElement.setAttribute(aRef, id);
+ }
+ }
+
+ return bRet;
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::setCommonAttributesFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement)
+{
+ bool bRet = true;
+
+ for (int i = 0; i < ubzElement.attributes().count(); i++)
+ {
+ QDomNode attribute = ubzElement.attributes().item(i);
+ QString attributeName = ubzAttrNameToCFFAttrName(attribute.nodeName().remove("ub:"));
+
+ bRet &= setCFFAttribute(attributeName, ubzAttrValueToCFFAttrName(attribute.nodeValue()), ubzElement, iwbElement, svgElement);
+ if (!bRet) break;
+ }
+ return bRet;
+}
+
+void UBCFFAdaptor::UBToCFFConverter::setViewBox(QRect viewbox)
+{
+ mViewbox |= viewbox;
+}
+
+QDomNode UBCFFAdaptor::UBToCFFConverter::findTextNode(const QDomNode &node)
+{
+ QDomNode iterNode = node;
+
+ while (!iterNode.isNull())
+ {
+ if (iterNode.isText())
+ {
+ if (!iterNode.isNull())
+ return iterNode;
+ }
+ else
+ {
+ if (!iterNode.firstChild().isNull())
+ {
+ QDomNode foundNode = findTextNode(iterNode.firstChild());
+ if (!foundNode.isNull())
+ if (foundNode.isText())
+ return foundNode;
+ }
+ }
+ if (!iterNode.nextSibling().isNull())
+ iterNode = iterNode.nextSibling();
+ else
+ break;
+ }
+ return iterNode;
+}
+
+QDomNode UBCFFAdaptor::UBToCFFConverter::findNodeByTagName(const QDomNode &node, QString tagName)
+{
+ QDomNode iterNode = node;
+
+ while (!iterNode.isNull())
+ {
+ QString t = iterNode.toElement().tagName();
+ if (tagName == t)
+ return iterNode;
+ else
+ {
+ if (!iterNode.firstChildElement().isNull())
+ {
+ QDomNode foundNode = findNodeByTagName(iterNode.firstChildElement(), tagName);
+ if (!foundNode.isNull())
+ if (foundNode.isElement())
+ {
+ if (tagName == foundNode.toElement().tagName())
+ return foundNode;
+ }
+ else
+ break;
+ }
+ }
+
+ if (!iterNode.nextSibling().isNull())
+ iterNode = iterNode.nextSibling();
+ else
+ break;
+ }
+ return QDomNode();
+
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::createBackground(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "|creating element background";
+
+
+ QDomDocument doc;
+
+ //QDomElement svgBackgroundElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tUBZImage);
+ QDomElement svgBackgroundElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBRect);
+ QDomElement iwbBackgroundElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+
+ QRect bckRect(mViewbox);
+
+ if (0 <= mViewbox.topLeft().x())
+ bckRect.topLeft().setX(0);
+
+ if (0 <= mViewbox.topLeft().y())
+ bckRect.topLeft().setY(0);
+
+// QString backgroundImagePath = createBackgroundImage(element, QSize(bckRect.width(), bckRect.height()));
+// if (QString() != backgroundImagePath)
+ if (QRect() != bckRect)
+ {
+ QString sElementID = QUuid::createUuid().toString().remove("{").remove("}");
+
+ bool darkBackground = (avTrue == element.attribute(aDarkBackground));
+ svgBackgroundElementPart.setAttribute(aFill, darkBackground ? "black" : "white");
+ svgBackgroundElementPart.setAttribute(aID, sElementID);
+ svgBackgroundElementPart.setAttribute(aX, bckRect.x());
+ svgBackgroundElementPart.setAttribute(aY, bckRect.y());
+ svgBackgroundElementPart.setAttribute(aHeight, bckRect.height());
+ svgBackgroundElementPart.setAttribute(aWidth, bckRect.width());
+
+ //svgBackgroundElementPart.setAttribute(aSVGHref, backgroundImagePath);
+
+ iwbBackgroundElementPart.setAttribute(aRef, sElementID);
+ iwbBackgroundElementPart.setAttribute(aBackground, avTrue);
+ //iwbBackgroundElementPart.setAttribute(aLocked, avTrue);
+
+ addSVGElementToResultModel(svgBackgroundElementPart, dstSvgList, DEFAULT_BACKGROUND_LAYER);
+ addIWBElementToResultModel(iwbBackgroundElementPart);
+ return true;
+ }
+ else
+ {
+ qDebug() << "|error at creating element background";
+ errorStr = "CreatingElementBackgroundParsingError.";
+ return false;
+ }
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::createBackgroundImage(const QDomElement &element, QSize size)
+{
+ QString sRet;
+
+ QString sDstFileName(fIWBBackground);
+
+ bool bDirExists = true;
+ QDir dstDocFolder(destinationPath);
+
+ if (!dstDocFolder.exists(cfImages))
+ bDirExists &= dstDocFolder.mkdir(cfImages);
+
+ QString dstFilePath;
+ if (bDirExists)
+ dstFilePath = destinationPath+"/"+cfImages+"/"+sDstFileName;
+
+ if (!QFile().exists(dstFilePath))
+ {
+ QRect rect(0,0, size.width(), size.height());
+
+ QImage *bckImage = new QImage(size, QImage::Format_RGB888);
+
+ QPainter *painter = new QPainter(bckImage);
+
+ bool darkBackground = (avTrue == element.attribute(aDarkBackground));
+
+ QColor bCrossColor;
+
+ bCrossColor = darkBackground?QColor(Qt::white):QColor(Qt::blue);
+ int penAlpha = (int)(255/2); // default Sankore value for transform.m11 < 1
+ bCrossColor.setAlpha(penAlpha);
+ painter->setPen(bCrossColor);
+ painter->setBrush(darkBackground?QColor(Qt::black):QColor(Qt::white));
+
+ painter->drawRect(rect);
+
+ if (avTrue == element.attribute(aCrossedBackground))
+ {
+ qreal firstY = ((int) (rect.y () / iCrossSize)) * iCrossSize;
+
+ for (qreal yPos = firstY; yPos <= rect.y () + rect.height (); yPos += iCrossSize)
+ {
+ painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos);
+ }
+
+ qreal firstX = ((int) (rect.x () / iCrossSize)) * iCrossSize;
+
+ for (qreal xPos = firstX; xPos <= rect.x () + rect.width (); xPos += iCrossSize)
+ {
+ painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ());
+ }
+ }
+
+ painter->end();
+ painter->save();
+
+ if (QString() != dstFilePath)
+ if (bckImage->save(dstFilePath))
+ sRet = cfImages+"/"+sDstFileName;
+
+ delete bckImage;
+ delete painter;
+ }
+ else
+ sRet = cfImages+"/"+sDstFileName;
+
+ return sRet;
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::createPngFromSvg(QString &svgPath, QString &dstPath, QTransform transformation, QSize size)
+{
+ if (QFile().exists(svgPath))
+ {
+ QImage i(svgPath);
+
+ QSize iSize = (QSize() == size)?QSize(i.size().width()*transformation.m11(), i.size().height()*transformation.m22()):size;
+
+ QImage image(iSize, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter imagePainter(&image);
+ QSvgRenderer renderer(svgPath);
+ renderer.render(&imagePainter);
+
+ return image.save(dstPath);
+
+ }
+ else
+ return false;
+}
+
+
+bool UBCFFAdaptor::UBToCFFConverter::parseSVGGGroup(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "|parsing g section";
+ QDomElement nextElement = element.firstChildElement();
+ if (nextElement.isNull()) {
+ qDebug() << "Empty g element";
+ errorStr = "EmptyGSection";
+ return false;
+ }
+
+ QMultiMap svgElements;
+
+ QDomDocument doc;
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBG);
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ // Elements can know about its layer, so it must add result QDomElements to ordrered list.
+ while (!nextElement.isNull()) {
+ QString tagName = nextElement.tagName();
+ if (tagName == tUBZLine) parseUBZLine(nextElement, svgElements);
+ else if (tagName == tUBZPolygon) parseUBZPolygon(nextElement, svgElements);
+ else if (tagName == tUBZPolyline) parseUBZPolyline(nextElement, svgElements);
+
+ nextElement = nextElement.nextSiblingElement();
+ }
+
+ QList layers;
+ QMapIterator nextSVGElement(svgElements);
+ while (nextSVGElement.hasNext())
+ layers << nextSVGElement.next().key();
+
+ qSort(layers);
+ int layer = layers.at(0);
+
+ nextSVGElement.toFront();
+ while (nextSVGElement.hasNext())
+ svgElementPart.appendChild(nextSVGElement.next().value());
+
+ addSVGElementToResultModel(svgElementPart, dstSvgList, layer);
+
+ return true;
+}
+bool UBCFFAdaptor::UBToCFFConverter::parseUBZImage(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "|parsing image";
+
+ QDomDocument doc;
+
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
+ {
+ addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
+
+ if (0 < iwbElementPart.attributes().count())
+ addIWBElementToResultModel(iwbElementPart);
+ return true;
+ }
+ else
+ {
+ qDebug() << "|error at image parsing";
+ errorStr = "ImageParsingError";
+ return false;
+
+ }
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::parseUBZVideo(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "|parsing video";
+
+ QDomDocument doc;
+
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
+ {
+ QDomElement svgSwitchSection = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBSwitch);
+ svgSwitchSection.appendChild(svgElementPart);
+
+ // if viewer cannot open that content - it must use that:
+ QDomElement svgText = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBTextArea);
+ svgText.setAttribute(aX, svgElementPart.attribute(aX));
+ svgText.setAttribute(aY, svgElementPart.attribute(aY));
+ svgText.setAttribute(aWidth, svgElementPart.attribute(aWidth));
+ svgText.setAttribute(aHeight, svgElementPart.attribute(aHeight));
+ svgText.setAttribute(aTransform, svgElementPart.attribute(aTransform));
+
+ QDomText text = doc.createTextNode("Cannot Open Content");
+ svgText.appendChild(text);
+
+ svgSwitchSection.appendChild(svgText);
+
+ addSVGElementToResultModel(svgSwitchSection, dstSvgList, getElementLayer(element));
+
+ if (0 < iwbElementPart.attributes().count())
+ addIWBElementToResultModel(iwbElementPart);
+ return true;
+ }
+ else
+ {
+ qDebug() << "|error at video parsing";
+ errorStr = "VideoParsingError";
+ return false;
+ }
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::parseUBZAudio(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "|parsing audio";
+
+ // audio file must be linked to cff item excluding video.
+ // to do:
+ // 1 add image for audio element.
+ // 2 set id for this element
+ // 3 add section with xlink:href to audio file
+ // 4 add shild to a section with id of the image
+
+ QDomDocument doc;
+
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
+ {
+ //we must create image-containers for audio files
+ int audioImageDimention = qMin(svgElementPart.attribute(aWidth).toInt(), svgElementPart.attribute(aHeight).toInt());
+ QString srcAudioImageFile(sAudioElementImage);
+ QString elementId = QString(QUuid::createUuid().toString()).remove("{").remove("}");
+ QString sDstAudioImageFileName = elementId+"."+fePng;
+ QString dstAudioImageFilePath = destinationPath+"/"+cfImages+"/"+sDstAudioImageFileName;
+ QString dstAudioImageRelativePath = cfImages+"/"+sDstAudioImageFileName;
+
+ QFile srcFile(srcAudioImageFile);
+
+ //creating folder for audioImage
+ QDir dstDocFolder(destinationPath);
+ bool bRes = true;
+ if (!dstDocFolder.exists(cfImages))
+ bRes &= dstDocFolder.mkdir(cfImages);
+
+ // CFF cannot show SVG images, so we need to convert it to png.
+ if (bRes && createPngFromSvg(srcAudioImageFile, dstAudioImageFilePath, getTransformFromUBZ(element), QSize(audioImageDimention, audioImageDimention)))
+ {
+ QDomElement svgSwitchSection = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBSwitch);
+
+ // first we place content
+ QDomElement svgASection = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBA);
+ svgASection.setAttribute(aSVGHref, svgElementPart.attribute(aSVGHref));
+
+ svgElementPart.setTagName(tIWBImage);
+ svgElementPart.setAttribute(aSVGHref, dstAudioImageRelativePath);
+ svgElementPart.setAttribute(aHeight, audioImageDimention);
+ svgElementPart.setAttribute(aWidth, audioImageDimention);
+
+ svgASection.appendChild(svgElementPart);
+
+ svgSwitchSection.appendChild(svgASection);
+
+ // if viewer cannot open that content - it must use that:
+ QDomElement svgText = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBTextArea);
+ svgText.setAttribute(aX, svgElementPart.attribute(aX));
+ svgText.setAttribute(aY, svgElementPart.attribute(aY));
+ svgText.setAttribute(aWidth, svgElementPart.attribute(aWidth));
+ svgText.setAttribute(aHeight, svgElementPart.attribute(aHeight));
+ svgText.setAttribute(aTransform, svgElementPart.attribute(aTransform));
+
+ QDomText text = doc.createTextNode("Cannot Open Content");
+ svgText.appendChild(text);
+
+ svgSwitchSection.appendChild(svgText);
+
+ addSVGElementToResultModel(svgSwitchSection, dstSvgList, getElementLayer(element));
+
+ if (0 < iwbElementPart.attributes().count())
+ addIWBElementToResultModel(iwbElementPart);
+ return true;
+ }
+ return false;
+ }
+ else
+ {
+ qDebug() << "|error at audio parsing";
+ errorStr = "AudioParsingError";
+ return false;
+ }
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::parseForeignObject(const QDomElement &element, QMultiMap &dstSvgList)
+{
+
+ if (element.attribute(aUBZType) == avUBZText) {
+ return parseUBZText(element, dstSvgList);
+ }
+
+ qDebug() << "|parsing foreign object";
+
+ QDomDocument doc;
+
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
+ {
+ addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
+ if (0 < iwbElementPart.attributes().count())
+ addIWBElementToResultModel(iwbElementPart);
+ return true;
+ }
+ else
+ {
+ qDebug() << "|error at parsing foreign object";
+ errorStr = "ForeignObjectParsingError";
+ return false;
+ }
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::parseUBZText(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "|parsing text";
+
+ QDomDocument doc;
+
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ if (element.hasChildNodes())
+ {
+ QDomDocument htmlDoc;
+ htmlDoc.setContent(findTextNode(element).nodeValue());
+ QDomNode bodyNode = findNodeByTagName(htmlDoc.firstChildElement(), "body");
+
+ setCFFTextFromHTMLTextNode(bodyNode.toElement(), svgElementPart);
+
+ if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
+ {
+ QString commonParams;
+ for (int i = 0; i < bodyNode.attributes().count(); i++)
+ {
+ commonParams += " " + bodyNode.attributes().item(i).nodeValue();
+ }
+ commonParams.remove(" ");
+ commonParams.remove("'");
+
+ QStringList commonAttributes = commonParams.split(";", QString::SkipEmptyParts);
+ for (int i = 0; i < commonAttributes.count(); i++)
+ {
+ QStringList AttrVal = commonAttributes.at(i).split(":", QString::SkipEmptyParts);
+ if (1 < AttrVal.count())
+ {
+ QString sAttr = ubzAttrNameToCFFAttrName(AttrVal.at(0));
+ QString sVal = ubzAttrValueToCFFAttrName(AttrVal.at(1));
+
+ setCFFAttribute(sAttr, sVal, element, iwbElementPart, svgElementPart);
+ }
+ }
+ addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
+ if (0 < iwbElementPart.attributes().count())
+ addIWBElementToResultModel(iwbElementPart);
+ return true;
+ }
+ return false;
+ }
+ else
+ {
+ qDebug() << "|error at text parsing";
+ errorStr = "TextParsingError";
+ return false;
+ }
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::parseUBZPolygon(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "||parsing polygon";
+
+ QDomDocument doc;
+
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
+ {
+ addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
+
+ if (0 < iwbElementPart.attributes().count())
+ {
+ QString id = QUuid::createUuid().toString().remove("{").remove("}");
+ svgElementPart.setAttribute(aID, id);
+ iwbElementPart.setAttribute(aRef, id);
+
+ addIWBElementToResultModel(iwbElementPart);
+ }
+ return true;
+ }
+ else
+ {
+ qDebug() << "||error at parsing polygon";
+ errorStr = "PolygonParsingError";
+ return false;
+ }
+
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::parseUBZPolyline(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "||parsing polyline";
+ QDomElement resElement;
+
+ QDomDocument doc;
+
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
+ {
+ addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
+
+ if (0 < iwbElementPart.attributes().count())
+ {
+ QString id = QUuid::createUuid().toString().remove("{").remove("}");
+ svgElementPart.setAttribute(aID, id);
+ iwbElementPart.setAttribute(aRef, id);
+
+ addIWBElementToResultModel(iwbElementPart);
+ }
+ return true;
+ }
+ else
+ {
+ qDebug() << "||error at parsing polygon";
+ errorStr = "PolylineParsingError";
+ return false;
+ }
+
+}
+
+bool UBCFFAdaptor::UBToCFFConverter::parseUBZLine(const QDomElement &element, QMultiMap &dstSvgList)
+{
+ qDebug() << "||parsing line";
+ QDomElement resElement;
+ QDomDocument doc;
+
+ QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
+ QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
+
+ if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
+ {
+ addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
+
+ if (0 < iwbElementPart.attributes().count())
+ {
+ QString id = QUuid::createUuid().toString().remove("{").remove("}");
+ svgElementPart.setAttribute(aID, id);
+ iwbElementPart.setAttribute(aRef, id);
+
+ addIWBElementToResultModel(iwbElementPart);
+ }
+ }
+ else
+ {
+ qDebug() << "||error at parsing polygon";
+ errorStr = "LineParsingError";
+ return false;
+ }
+ return true;
+}
+
+void UBCFFAdaptor::UBToCFFConverter::addSVGElementToResultModel(const QDomElement &element, QMultiMap &dstList, int layer)
+{
+ int elementLayer = (DEFAULT_LAYER == layer) ? DEFAULT_LAYER : layer;
+ dstList.setInsertInOrder(true);
+ QDomElement rootElement = element.cloneNode(true).toElement();
+ mDocumentToWrite->firstChildElement().appendChild(rootElement);
+ dstList.insert(elementLayer, rootElement);
+}
+
+void UBCFFAdaptor::UBToCFFConverter::addIWBElementToResultModel(const QDomElement &element)
+{
+ QDomElement rootElement = element.cloneNode(true).toElement();
+ mDocumentToWrite->firstChildElement().appendChild(rootElement);
+ mExtendedElements.append(rootElement);
+}
+
+UBCFFAdaptor::UBToCFFConverter::~UBToCFFConverter()
+{
+ if (mDataModel)
+ delete mDataModel;
+ if (mIWBContentWriter)
+ delete mIWBContentWriter;
+}
+bool UBCFFAdaptor::UBToCFFConverter::isValid() const
+{
+ bool result = QFileInfo(sourcePath).exists()
+ && QFileInfo(sourcePath).isDir()
+ && errorStr == noErrorMsg;
+
+ if (!result) {
+ qDebug() << "specified data is not valid";
+ errorStr = "ValidateDataError";
+ }
+
+ return result;
+}
+
+void UBCFFAdaptor::UBToCFFConverter::fillNamespaces()
+{
+ mIWBContentWriter->writeDefaultNamespace(svgUBZNS);
+ mIWBContentWriter->writeNamespace(iwbNS, iwbNsPrefix);
+ mIWBContentWriter->writeNamespace(svgIWBNS, svgIWBNSPrefix);
+ mIWBContentWriter->writeNamespace(xlinkNS, xlinkNSPrefix);
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::digitFileFormat(int digit) const
+{
+ return QString("%1").arg(digit, 3, 10, QLatin1Char('0'));
+}
+QString UBCFFAdaptor::UBToCFFConverter::contentIWBFileName() const
+{
+ return destinationPath + "/" + fIWBContent;
+}
+
+//setting SVG dimenitons
+QSize UBCFFAdaptor::UBToCFFConverter::getSVGDimentions(const QString &element)
+{
+
+ QStringList dimList;
+
+ dimList = element.split(dimensionsDelimiter1, QString::KeepEmptyParts);
+ if (dimList.count() != 2) // row unlike 0x0
+ return QSize();
+
+ bool ok;
+
+ int width = dimList.takeFirst().toInt(&ok);
+ if (!ok || !width)
+ return QSize();
+
+ int height = dimList.takeFirst().toInt(&ok);
+ if (!ok || !height)
+ return QSize();
+
+ return QSize(width, height);
+}
+
+//Setting viewbox rectangle
+QRect UBCFFAdaptor::UBToCFFConverter::getViewboxRect(const QString &element) const
+{
+ QStringList dimList;
+
+ dimList = element.split(dimensionsDelimiter2, QString::KeepEmptyParts);
+ if (dimList.count() != 4) // row unlike 0 0 0 0
+ return QRect();
+
+ bool ok = false;
+
+ int x = dimList.takeFirst().toInt(&ok);
+ if (!ok || !x)
+ return QRect();
+
+ int y = dimList.takeFirst().toInt(&ok);
+ if (!ok || !y)
+ return QRect();
+
+ int width = dimList.takeFirst().toInt(&ok);
+ if (!ok || !width)
+ return QRect();
+
+ int height = dimList.takeFirst().toInt(&ok);
+ if (!ok || !height)
+ return QRect();
+
+ return QRect(x, y, width, height);
+}
+
+QString UBCFFAdaptor::UBToCFFConverter::rectToIWBAttr(const QRect &rect) const
+{
+ if (rect.isNull()) return QString();
+
+ return QString("%1 %2 %3 %4").arg(rect.topLeft().x())
+ .arg(rect.topLeft().y())
+ .arg(rect.width())
+ .arg(rect.height());
+}
+
+UBCFFAdaptor::UBToUBZConverter::UBToUBZConverter()
+{
+
+}
diff --git a/plugins/cffadaptor/src/UBCFFAdaptor.h b/plugins/cffadaptor/src/UBCFFAdaptor.h
new file mode 100644
index 00000000..385df3cc
--- /dev/null
+++ b/plugins/cffadaptor/src/UBCFFAdaptor.h
@@ -0,0 +1,146 @@
+#ifndef UBCFFADAPTOR_H
+#define UBCFFADAPTOR_H
+
+#include "UBCFFAdaptor_global.h"
+
+#include
+
+class QTransform;
+class QDomDocument;
+class QDomElement;
+class QDomNode;
+class QuaZipFile;
+
+class UBCFFADAPTORSHARED_EXPORT UBCFFAdaptor {
+ class UBToCFFConverter;
+
+public:
+ UBCFFAdaptor();
+ ~UBCFFAdaptor();
+
+ bool convertUBZToIWB(const QString &from, const QString &to);
+ bool deleteDir(const QString& pDirPath) const;
+
+private:
+ QString uncompressZip(const QString &zipFile);
+ bool compressZip(const QString &source, const QString &destination);
+ bool compressDir(const QString &dirName, const QString &parentDir, QuaZipFile *outZip);
+ bool compressFile(const QString &fileName, const QString &parentDir, QuaZipFile *outZip);
+
+ QString createNewTmpDir();
+ bool freeDir(const QString &dir);
+ void freeTmpDirs();
+
+private:
+ QStringList tmpDirs;
+
+private:
+
+ class UBToCFFConverter {
+
+ static const int DEFAULT_LAYER = -100000;
+
+ public:
+ UBToCFFConverter(const QString &source, const QString &destination);
+ ~UBToCFFConverter();
+ bool isValid() const;
+ QString lastErrStr() const {return errorStr;}
+ bool parse();
+
+ private:
+ void fillNamespaces();
+
+ bool parseMetadata();
+ bool parseContent();
+ QDomElement parsePageset(const QStringList &pageFileNames);
+ QDomElement parsePage(const QString &pageFileName);
+ QDomElement parseSvgPageSection(const QDomElement &element);
+ void writeQDomElementToXML(const QDomNode &node);
+ bool writeExtendedIwbSection();
+ QDomElement parseGroupPageSection(const QDomElement &element);
+
+ bool createBackground(const QDomElement &element, QMultiMap &dstSvgList);
+ QString createBackgroundImage(const QDomElement &element, QSize size);
+ bool createPngFromSvg(QString &svgPath, QString &dstPath, QTransform transformation, QSize size = QSize());
+
+ bool parseSVGGGroup(const QDomElement &element, QMultiMap &dstSvgList);
+ bool parseUBZImage(const QDomElement &element, QMultiMap &dstSvgList);
+ bool parseUBZVideo(const QDomElement &element, QMultiMap &dstSvgList);
+ bool parseUBZAudio(const QDomElement &element, QMultiMap &dstSvgList);
+ bool parseForeignObject(const QDomElement &element, QMultiMap &dstSvgList);
+ bool parseUBZText(const QDomElement &element, QMultiMap &dstSvgList);
+
+ bool parseUBZPolygon(const QDomElement &element, QMultiMap &dstSvgList);
+ bool parseUBZPolyline(const QDomElement &element, QMultiMap &dstSvgList);
+ bool parseUBZLine(const QDomElement &element, QMultiMap &dstSvgList);
+ void addSVGElementToResultModel(const QDomElement &element, QMultiMap &dstList, int layer = DEFAULT_LAYER);
+ void addIWBElementToResultModel(const QDomElement &element);
+
+ qreal getAngleFromTransform(const QTransform &tr);
+ QString getDstContentFolderName(const QString &elementType);
+ QString getSrcContentFolderName(QString href);
+ QString getFileNameFromPath(QString sPath);
+ QString getExtentionFromFileName(const QString &filename);
+ QString convertExtention(const QString &ext);
+ QString getElementTypeFromUBZ(const QDomElement &element);
+
+ int getElementLayer(const QDomElement &element);
+
+ bool itIsSupportedFormat(const QString &format) const;
+ bool itIsFormatToConvert(const QString &format) const;
+ bool itIsSVGElementAttribute(const QString ItemType, const QString &AttrName);
+ bool itIsIWBAttribute(const QString &attribute) const;
+ bool itIsUBZAttributeToConvert(const QString &attribute) const;
+
+ bool ibwAddLine(int x1, int y1, int x2, int y2, QString color=QString(), int width=1, bool isBackground=false);
+
+ QTransform getTransformFromUBZ(const QDomElement &ubzElement);
+ void setGeometryFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement);
+ void setCoordinatesFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement);
+ bool setContentFromUBZ(const QDomElement &ubzElement, QDomElement &svgElement);
+ void setCFFTextFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement);
+ void setCFFTextFromHTMLTextNode(const QDomElement htmlTextNode, QDomElement &iwbElement);
+ QString ubzAttrNameToCFFAttrName(QString cffAttrName);
+ QString ubzAttrValueToCFFAttrName(QString cffAttrValue);
+
+ bool setCFFAttribute(const QString &attributeName, const QString &attributeValue, const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement);
+ bool setCommonAttributesFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement);
+ void setViewBox(QRect viewbox);
+
+ QDomNode findTextNode(const QDomNode &node);
+ QDomNode findNodeByTagName(const QDomNode &node, QString tagName);
+
+ QSize getSVGDimentions(const QString &element);
+
+ inline QRect getViewboxRect(const QString &element) const;
+ inline QString rectToIWBAttr(const QRect &rect) const;
+ inline QString digitFileFormat(int num) const;
+ inline bool strToBool(const QString &in) const {return in == "true";}
+ QString contentIWBFileName() const;
+
+ private:
+ QMap iwbSVGItemsAttributes;
+ QDomDocument *mDataModel; //model for reading indata
+ QXmlStreamWriter *mIWBContentWriter; //stream to write outdata
+ QSize mSVGSize; //svg page size
+ QRect mViewbox; //Main viewbox parameter for CFF
+ QString sourcePath; // dir with unpacked source data (ubz)
+ QString destinationPath; //dir with unpacked destination data (iwb)
+ QDomDocument *mDocumentToWrite; //document for saved QDomElements from mSvgElements and mExtendedElements
+ QMultiMap mSvgElements; //Saving svg elements to have a sorted by z order list of elements to write;
+ QList mExtendedElements; //Saving extended options of elements to be able to add them to the end of result iwb document;
+ mutable QString errorStr; // last error string message
+
+ public:
+ operator bool() const {return isValid();}
+ };
+
+ class UBToUBZConverter {
+ public:
+ UBToUBZConverter();
+ };
+
+
+};
+
+#endif // UBCFFADAPTOR_H
diff --git a/plugins/cffadaptor/src/UBCFFAdaptor_global.h b/plugins/cffadaptor/src/UBCFFAdaptor_global.h
new file mode 100644
index 00000000..2fbf871f
--- /dev/null
+++ b/plugins/cffadaptor/src/UBCFFAdaptor_global.h
@@ -0,0 +1,12 @@
+#ifndef UBCFFADAPTOR_GLOBAL_H
+#define UBCFFADAPTOR_GLOBAL_H
+
+#include
+
+#if defined(UBCFFADAPTOR_LIBRARY)
+# define UBCFFADAPTORSHARED_EXPORT Q_DECL_EXPORT
+#else
+# define UBCFFADAPTORSHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // UBCFFADAPTOR_GLOBAL_H
diff --git a/plugins/cffadaptor/src/UBCFFConstants.h b/plugins/cffadaptor/src/UBCFFConstants.h
new file mode 100644
index 00000000..9d7707ee
--- /dev/null
+++ b/plugins/cffadaptor/src/UBCFFConstants.h
@@ -0,0 +1,378 @@
+#ifndef UBCFFCONSTANTS_H
+#define UBCFFCONSTANTS_H
+
+#define PI 3.1415926535
+
+const int DEFAULT_BACKGROUND_LAYER = -20000002;
+const int DEFAULT_BACKGROUND_CROSS_LAYER = -20000001;
+
+// Constant names. Use only them instead const char* in each function
+
+// Constant fileNames;
+const QString fMetadata = "metadata.rdf";
+const QString fIWBContent = "content.xml";
+const QString fIWBBackground = "background.png";
+const QString sAudioElementImage = ":images/soundOn.svg";
+
+// Constant messages;
+const QString noErrorMsg = "NoError";
+
+// Tag names
+const QString tDescription = "Description";
+const QString tIWBRoot = "iwb";
+const QString tIWBMeta = "meta";
+const QString tUBZSize = "size";
+const QString tSvg = "svg";
+const QString tIWBPage = "page";
+const QString tIWBPageSet = "pageset";
+const QString tId = "id";
+const QString tElement = "element";
+const QString tUBZGroup = "group";
+const QString tUBZG = "g";
+const QString tUBZPolygon = "polygon";
+const QString tUBZPolyline = "polyline";
+const QString tUBZLine = "line";
+const QString tUBZAudio = "audio";
+const QString tUBZVideo = "video";
+const QString tUBZImage = "image";
+const QString tUBZForeignObject = "foreignObject";
+const QString tUBZTextContent = "itemTextContent";
+
+const QString tIWBA = "a";
+const QString tIWBG = "g";
+const QString tIWBSwitch = "switch";
+const QString tIWBImage = "image";
+const QString tIWBVideo = "video";
+const QString tIWBAudio = "audio";
+const QString tIWBText = "text";
+const QString tIWBTextArea = "textarea";
+const QString tIWBPolyLine = "polyline";
+const QString tIWBPolygon = "polygon";
+const QString tIWBFlash = "video";
+const QString tIWBRect = "rect";
+const QString tIWBLine = "line";
+const QString tIWBTbreak = "tbreak";
+const QString tIWBTspan = "tspan";
+
+// Attributes names
+const QString aIWBVersion = "version";
+const QString aOwner = "owner";
+const QString aDescription = "description";
+const QString aCreator = "creator";
+const QString aAbout = "about";
+const QString aIWBViewBox = "viewbox";
+const QString aUBZViewBox = "viewBox";
+const QString aDarkBackground = "dark-background";
+const QString aBackground = "background";
+const QString aCrossedBackground = "crossed-background";
+const QString aUBZType = "type";
+const QString aUBZUuid = "uuid";
+const QString aFill = "fill"; // IWB attribute contans color to fill
+
+const QString aID = "id"; // ID of any svg element can be placed in to iwb section
+const QString aRef = "ref"; // as reference for applying additional attributes
+const QString aSVGHref = "xlink:href"; // reference to file
+const QString aIWBHref = "ref"; // reference to element ID
+const QString aUBZHref = "href";
+const QString aSrc = "src";
+const QString aSVGRequiredExtension = "requiredExtensions";
+
+const QString aX = "x";
+const QString aY = "y";
+const QString aWidth = "width";
+const QString aHeight = "height";
+const QString aStroke = "stroke";
+const QString aStrokeWidth = "stroke-width";
+const QString aPoints = "points";
+const QString aZLayer = "z-value";
+const QString aLayer = "layer";
+const QString aTransform = "transform";
+const QString aLocked = "locked";
+const QString aIWBName = "name";
+const QString aIWBContent = "content";
+
+
+// Attribute values
+const QString avIWBVersionNo = "1.0";
+const QString avUBZText = "text";
+const QString avFalse = "false";
+const QString avTrue = "true";
+
+// Namespaces and prefixes
+const QString svgRequiredExtensionPrefix = "http://www.imsglobal.org/iwb/";
+const QString dcNS = "http://purl.org/dc/elements/1.1/";
+const QString ubNS = "http://uniboard.mnemis.com/document";
+const QString svgUBZNS = "http://www.imsglobal.org/xsd/iwb_v1p0";
+const QString svgIWBNS = "http://www.w3.org/2000/svg";
+const QString xlinkNS = "http://www.w3.org/1999/xlink";
+const QString iwbNS = "http://www.becta.org.uk/iwb";
+const QString xsiNS = "http://www.w3.org/2001/XMLSchema-instance";
+const QString xsiShemaLocation = "\
+http://www.imsglobal.org/xsd/iwb_v1p0 \
+http://www.imsglobal.org/profile/iwb/iwbv1p0_v1p0.xsd \
+http://www.w3.org/2000/svg http://www.imsglobal.org/profile/iwb/svgsubsetv1p0_v1p0.xsd \
+http://www.w3.org/1999/xlink http://www.imsglobal.org/xsd/w3/1999/xlink.xsd";
+const QString dcNSPrefix = "dc";
+const QString ubNSPrefix = "ub";
+const QString svgIWBNSPrefix = "svg";
+const QString xlinkNSPrefix = "xlink";
+const QString iwbNsPrefix = "iwb";
+const QString xsiPrefix = "xsi";
+const QString xsiSchemaLocationPrefix = "schemaLocation";
+
+const QString avOwner = "";
+const QString avCreator = "";
+const QString avDescription = "";
+
+//constant symbols and words etc
+const QString dimensionsDelimiter1 = "x";
+const QString dimensionsDelimiter2 = " ";
+const QString pageAlias = "page";
+const QString pageFileExtentionUBZ = "svg";
+
+//content folder names
+const QString cfImages = "images";
+const QString cfVideos = "video";
+const QString cfAudios = "audio";
+const QString cfFlash = "flash";
+
+//known file extentions
+const QString feSvg = "svg";
+const QString feWgt = "wgt";
+const QString fePng = "png";
+
+const int iCrossSize = 32;
+const int iCrossWidth = 1;
+
+// Image formats supported by CFF exclude wgt. Wgt is Sankore widget, which is considered as a .png preview.
+const QString iwbElementImage(" \
+wgt, \
+jpeg, \
+jpg, \
+bmp, \
+gif, \
+wmf, \
+emf, \
+png, \
+tif, \
+tiff \
+");
+
+// Video formats supported by CFF
+const QString iwbElementVideo(" \
+mpg, \
+mpeg, \
+swf, \
+");
+
+// Audio formats supported by CFF
+const QString iwbElementAudio(" \
+mp3, \
+wav \
+");
+
+const QString cffSupportedFileFormats(iwbElementImage + iwbElementVideo + iwbElementAudio);
+const QString ubzFormatsToConvert("svg");
+
+
+const QString iwbSVGImageAttributes(" \
+id, \
+xlink:href, \
+x, \
+y, \
+height, \
+width, \
+fill-opacity, \
+requiredExtentions, \
+transform \
+");
+
+
+const QString iwbSVGAudioAttributes(" \
+id, \
+xlink:href, \
+x, \
+y, \
+height, \
+width, \
+fill-opacity, \
+requiredExtentions, \
+transform \
+");
+
+const QString iwbSVGVideoAttributes(" \
+id, \
+xlink:href, \
+x, \
+y, \
+height, \
+width, \
+fill-opacity, \
+requiredExtentions, \
+transform \
+");
+
+const QString iwbSVGRectAttributes(" \
+id, \
+x, \
+y, \
+height, \
+width, \
+fill, \
+fill-opacity, \
+stroke, \
+stroke-dasharray, \
+stroke-linecap, \
+stroke-linejoin, \
+stroke-opacity, \
+stroke-width, \
+transform \
+");
+
+
+
+const QString iwbSVGTextAttributes(" \
+id, \
+x, \
+y, \
+fill, \
+font-family, \
+font-size, \
+font-style, \
+font-weight, \
+font-stretch, \
+transform \
+");
+
+const QString iwbSVGTextAreaAttributes(" \
+id, \
+x, \
+y, \
+height, \
+width, \
+fill, \
+font-family, \
+font-size, \
+font-style, \
+font-weight, \
+font-stretch, \
+text-align, \
+transform \
+");
+
+const QString iwbSVGTspanAttributes(" \
+id, \
+fill, \
+font-family, \
+font-size, \
+font-style, \
+font-weight, \
+font-stretch, \
+text-align, \
+");
+
+const QString iwbSVGLineAttributes(" \
+id, \
+x1, \
+y1, \
+x2, \
+y2, \
+stroke, \
+stroke-dasharray, \
+stroke-width, \
+stroke-opacity, \
+stroke-linecap, \
+transform \
+");
+
+const QString iwbSVGPolyLineAttributes(" \
+id, \
+points, \
+stroke, \
+stroke-width, \
+stroke-dasharray, \
+stroke-opacity, \
+stroke-linecap, \
+transform \
+");
+
+const QString iwbSVGPolygonAttributes(" \
+id, \
+points, \
+fill, \
+fill-opacity, \
+stroke, \
+stroke-dasharray, \
+stroke-width, \
+stroke-linecap, \
+stroke-linejoin, \
+stroke-opacity, \
+stroke-width, \
+transform \
+");
+
+// 1 to 1 copy to SVG section
+const QString iwbElementAttributes(" \
+background, \
+background-fill, \
+background-posture, \
+flip, \
+freehand, \
+highlight, \
+highlight-fill, \
+list-style-type, \
+list-style-type-fill, \
+locked, \
+replicate, \
+revealer, \
+stroke-lineshape-start, \
+stroke-lineshape-end \
+");
+
+// cannot be copied 1 to 1 to SVG section
+const QString ubzElementAttributesToConvert(" \
+xlink:href, \
+src, \
+transform \
+");
+
+// additional attributes. Have references in SVG section.
+const QString svgElementAttributes(" \
+points, \
+fill, \
+fill-opacity, \
+stroke, \
+stroke-dasharray, \
+stroke-linecap, \
+stroke-opacity, \
+stroke-width, \
+stroke_linejoin, \
+requiredExtensions, \
+viewbox, \
+x, \
+y, \
+x1, \
+y1, \
+x2, \
+y2, \
+height, \
+width, \
+font-family, \
+font-size, \
+font-style, \
+font-weight, \
+font-stretch, \
+text-align \
+");
+
+const QString ubzContentFolders("audios,videos,images,widgets");
+
+struct UBItemLayerType
+{
+ enum Enum
+ {
+ FixedBackground = -2000, Object = -1000, Graphic = 0, Tool = 1000, Control = 2000
+ };
+};
+
+#endif // UBCFFCONSTANTS_H
\ No newline at end of file
diff --git a/plugins/cffadaptor/src/UBGlobals.h b/plugins/cffadaptor/src/UBGlobals.h
new file mode 100644
index 00000000..adfc677d
--- /dev/null
+++ b/plugins/cffadaptor/src/UBGlobals.h
@@ -0,0 +1,47 @@
+#ifndef UBGLOBALS_H
+#define UBGLOBALS_H
+
+#define DELETEPTR(ptr) if(NULL != ptr){ \
+ delete ptr; \
+ ptr = NULL; \
+ }
+
+#ifdef Q_WS_WIN
+
+#define WARNINGS_DISABLE __pragma(warning(push, 0));
+#define WARNINGS_ENABLE __pragma(warning(pop));
+
+#ifdef NO_THIRD_PARTY_WARNINGS
+// disabling warning level to 0 and save old state
+#define THIRD_PARTY_WARNINGS_DISABLE WARNINGS_DISABLE
+#else
+// just save old state (needs for not empty define)
+#define THIRD_PARTY_WARNINGS_DISABLE __pragma(warning(push));
+#endif //#ifdef NO_THIRD_PARTY_WARNINGS
+// anyway on WIN
+#define THIRD_PARTY_WARNINGS_ENABLE WARNINGS_ENABLE
+
+#else //#ifdef Q_WS_WIN
+
+#define WARNINGS_DISABLE _Pragma("GCC diagnostic push"); \
+_Pragma("GCC diagnostic ignored \"-Wunused-parameter\""); \
+_Pragma("GCC diagnostic ignored \"-Wunused-variable\""); \
+_Pragma("GCC diagnostic ignored \"-Wsign-compare\"");
+
+#define WARNINGS_ENABLE _Pragma("GCC diagnostic pop");
+
+#ifdef NO_THIRD_PARTY_WARNINGS
+//disabling some warnings
+#define THIRD_PARTY_WARNINGS_DISABLE WARNINGS_DISABLE
+
+#define THIRD_PARTY_WARNINGS_ENABLE WARNINGS_ENABLE
+#else
+// just save old state (needs for not empty define)
+#define THIRD_PARTY_WARNINGS_ENABLE WARNINGS_ENABLE
+
+#endif //#ifdef NO_THIRD_PARTY_WARNINGS
+
+#endif //#ifdef Q_WS_WIN
+
+#endif // UBGLOBALS_H
+
diff --git a/src/adaptors/UBExportCFF.cpp b/src/adaptors/UBExportCFF.cpp
new file mode 100644
index 00000000..741eb871
--- /dev/null
+++ b/src/adaptors/UBExportCFF.cpp
@@ -0,0 +1,60 @@
+#include "UBExportCFF.h"
+#include "UBCFFAdaptor.h"
+#include "document/UBDocumentProxy.h"
+#include "core/UBDocumentManager.h"
+#include "core/UBApplication.h"
+
+
+UBExportCFF::UBExportCFF(QObject *parent)
+: UBExportAdaptor(parent)
+{
+
+}
+
+UBExportCFF::~UBExportCFF()
+{
+
+}
+QString UBExportCFF::exportName()
+{
+ return tr("Export to IWB");
+}
+
+QString UBExportCFF::exportExtention()
+{
+ return QString(".iwb");
+}
+
+void UBExportCFF::persist(UBDocumentProxy* pDocument)
+{
+ QString src = pDocument->persistencePath();
+
+ if (!pDocument)
+ return;
+
+ QString filename = askForFileName(pDocument, tr("Export as IWB File"));
+
+ if (filename.length() > 0)
+ {
+ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+
+ if (mIsVerbose)
+ UBApplication::showMessage(tr("Exporting document..."));
+
+ UBCFFAdaptor toIWBExporter;
+ if (toIWBExporter.convertUBZToIWB(src, filename))
+ {
+ if (mIsVerbose)
+ UBApplication::showMessage(tr("Export successful."));
+ }
+ else
+ if (mIsVerbose)
+ UBApplication::showMessage(tr("Export failed."));
+
+
+ QApplication::restoreOverrideCursor();
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/adaptors/UBExportCFF.h b/src/adaptors/UBExportCFF.h
new file mode 100644
index 00000000..6c7012d6
--- /dev/null
+++ b/src/adaptors/UBExportCFF.h
@@ -0,0 +1,39 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifndef UBExportCFF_H_
+#define UBExportCFF_H_
+
+#include
+
+#include "UBExportAdaptor.h"
+
+#include "frameworks/UBFileSystemUtils.h"
+
+class UBDocumentProxy;
+
+class UBExportCFF : public UBExportAdaptor
+{
+ Q_OBJECT;
+
+public:
+ UBExportCFF(QObject *parent = 0);
+ virtual ~UBExportCFF();
+
+ virtual QString exportName();
+ virtual QString exportExtention();
+ virtual void persist(UBDocumentProxy* pDocument);
+};
+
+#endif /* UBExportCFF_H_ */
\ No newline at end of file
diff --git a/src/adaptors/adaptors.pri b/src/adaptors/adaptors.pri
index b69d434f..4fc92ce9 100644
--- a/src/adaptors/adaptors.pri
+++ b/src/adaptors/adaptors.pri
@@ -14,6 +14,7 @@ HEADERS += src/adaptors/UBExportAdaptor.h\
src/adaptors/UBExportWeb.h \
src/adaptors/UBWebPublisher.h \
src/adaptors/UBImportCFF.h \
+ src/adaptors/UBExportCFF.h \
src/adaptors/UBCFFSubsetAdaptor.h
HEADERS += src/adaptors/publishing/UBDocumentPublisher.h \
@@ -36,6 +37,7 @@ SOURCES += src/adaptors/UBExportAdaptor.cpp\
src/adaptors/UBExportWeb.cpp \
src/adaptors/UBWebPublisher.cpp \
src/adaptors/UBImportCFF.cpp \
+ src/adaptors/UBExportCFF.cpp \
src/adaptors/UBCFFSubsetAdaptor.cpp \
src/adaptors/publishing/UBDocumentPublisher.cpp
diff --git a/src/core/UBDocumentManager.cpp b/src/core/UBDocumentManager.cpp
index 48dd0352..fbe315e2 100644
--- a/src/core/UBDocumentManager.cpp
+++ b/src/core/UBDocumentManager.cpp
@@ -21,6 +21,7 @@
#include "adaptors/UBExportFullPDF.h"
#include "adaptors/UBExportDocument.h"
#include "adaptors/UBExportWeb.h"
+#include "adaptors/UBExportCFF.h"
#include "adaptors/UBWebPublisher.h"
#include "adaptors/UBImportDocument.h"
#include "adaptors/UBImportPDF.h"
@@ -62,6 +63,8 @@ UBDocumentManager::UBDocumentManager(QObject *parent)
QString dummyObjects = tr("objects");
QString dummyWidgets = tr("widgets");
+ UBExportCFF* cffExporter = new UBExportCFF(this);
+ mExportAdaptors.append(cffExporter);
UBExportFullPDF* exportFullPdf = new UBExportFullPDF(this);
mExportAdaptors.append(exportFullPdf);
UBExportDocument* exportDocument = new UBExportDocument(this);