images for CFF implementation

preferencesAboutTextFull
Ivan Ilin 13 years ago
parent 023fddb607
commit 6f205698d9
  1. 843
      src/adaptors/UBCFFSubsetAdaptor.cpp
  2. 37
      src/adaptors/UBCFFSubsetAdaptor.h
  3. 0
      src/board/UBBoardPaletteManager.cpp

@ -25,6 +25,7 @@
#include "domain/UBGraphicsStroke.h" #include "domain/UBGraphicsStroke.h"
#include "domain/UBGraphicsTextItem.h" #include "domain/UBGraphicsTextItem.h"
#include "domain/UBGraphicsSvgItem.h" #include "domain/UBGraphicsSvgItem.h"
#include "domain/UBGraphicsPixmapItem.h"
#include "UBCFFSubsetAdaptor.h" #include "UBCFFSubsetAdaptor.h"
#include "UBMetadataDcSubsetAdaptor.h" #include "UBMetadataDcSubsetAdaptor.h"
@ -55,6 +56,7 @@ static QString tText = "text";
static QString tTextarea = "textarea"; static QString tTextarea = "textarea";
static QString tTspan = "tspan"; static QString tTspan = "tspan";
static QString tBreak = "tbreak"; static QString tBreak = "tbreak";
static QString tImage = "image";
//attribute names definition //attribute names definition
static QString aFill = "fill"; static QString aFill = "fill";
@ -81,56 +83,57 @@ static QString aPoints = "points";
static QString svgNS = "http://www.w3.org/2000/svg"; static QString svgNS = "http://www.w3.org/2000/svg";
static QString iwbNS = "http://www.becta.org.uk/iwb"; static QString iwbNS = "http://www.becta.org.uk/iwb";
static QString aId = "id"; static QString aId = "id";
static QString aRef = "ref";
static QString aHref = "href";
//attributes part names
static QString apRotate = "rotate";
static QString apTranslate = "translate";
UBCFFSubsetAdaptor::UBCFFSubsetAdaptor() UBCFFSubsetAdaptor::UBCFFSubsetAdaptor()
{ {
} }
void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSiblingIwbElements(QDomElement *parent, QDomElement *topGroup) { void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSiblingIwbElements(QDomElement *parent, QDomElement *topGroup) {
QDomElement curExt = parent->firstChildElement(tElement); QDomElement curExt = parent->firstChildElement(tElement);
while (!curExt.isNull()) { while (!curExt.isNull()) {
QDomElement n = curExt;
if (curExt.namespaceURI() != iwbNS) if (curExt.namespaceURI() != iwbNS)
continue; continue;
QHash<QString, IwbExt>::iterator iSvgElement = extProperties.find(curExt.attribute("ref")); QHash<QString, IwbExt>::iterator iSvgElement = iwbExtProperties.find(curExt.attribute(aRef));
if (iSvgElement != extProperties.end()) { if (iSvgElement != iwbExtProperties.end()) {
IwbExt &svgElement = *iSvgElement; IwbExt &svgElement = *iSvgElement;
svgElement.extAttr.push_back(curExt); svgElement.extAttr.push_back(curExt);
if (topGroup) if (topGroup)
qDebug() << "made"; svgElement.group = *topGroup;
} }
curExt = curExt.nextSiblingElement(tElement); curExt = curExt.nextSiblingElement(tElement);
} }
} }
void UBCFFSubsetAdaptor::UBCFFSubsetReader::addExtentionsToHash(QDomElement *parent) void UBCFFSubsetAdaptor::UBCFFSubsetReader::addExtentionsToHash(QDomElement *parent, QDomElement *topGroup)
{ {
//add top level elements //add top level elements
if(*parent == mDOMdoc.documentElement()) {
hashSiblingIwbElements(parent);
} else
hashSiblingIwbElements(parent, topGroup);
//add iwb groups if needed
QDomElement curGroup = parent->firstChildElement(tGroup); QDomElement curGroup = parent->firstChildElement(tGroup);
QDomElement topGroup;
while (!curGroup.isNull()) { while (!curGroup.isNull()) {
if (curGroup.namespaceURI() != iwbNS) if (curGroup.namespaceURI() != iwbNS)
continue; continue;
if(*parent == mDOMdoc.documentElement()) {
// if (parent == mDOMdoc.documentElement()) topGroup = &curGroup;
// topGroup = curGroup; }
// QHash<QString, IwbExt>::iterator iSvgElement = extProperties.find(curExt.attribute("ref"));
// if (iSvgElement != extProperties.end()) {
// IwbExt &svgElement = *iSvgElement;
// svgElement.group = curGroup;
// qDebug() << "made";
// }
hashSiblingIwbElements(&curGroup, &topGroup);
if (curGroup.hasChildNodes()) { if (curGroup.hasChildNodes()) {
addExtentionsToHash(&curGroup); addExtentionsToHash(&curGroup, topGroup);
} }
curGroup = curGroup.nextSiblingElement(tGroup); curGroup = curGroup.nextSiblingElement(tGroup);
} }
//add groups
} }
void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSvg(QDomNode *parent, QString prefix) void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSvg(QDomNode *parent, QString prefix)
@ -140,7 +143,7 @@ void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSvg(QDomNode *parent, QString pr
QDomElement e = n.toElement(); QDomElement e = n.toElement();
QString id = e.attribute(aId); QString id = e.attribute(aId);
if(!id.isNull()) { if(!id.isNull()) {
extProperties.insert(id, IwbExt(e)); iwbExtProperties.insert(id, IwbExt(e));
qDebug() << prefix + e.prefix() + ":" + e.tagName(); qDebug() << prefix + e.prefix() + ":" + e.tagName();
} }
if (n.hasChildNodes()) { if (n.hasChildNodes()) {
@ -152,36 +155,51 @@ void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSvg(QDomNode *parent, QString pr
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::hashElements() bool UBCFFSubsetAdaptor::UBCFFSubsetReader::hashElements()
{ {
QDomElement svgSection = mDOMdoc.elementsByTagNameNS(svgNS, tSvg).at(0).toElement(); bool result = true;
Q_ASSERT(!svgSection.isNull());
QDomElement svgSection = mDOMdoc.elementsByTagNameNS(svgNS, tSvg).at(0).toElement();
if (svgSection.isNull()) {
qDebug("\"svg:svg\" section not found maybe invalid document");
result = false;
}
hashSvg(&svgSection); hashSvg(&svgSection);
QDomElement parElement = mDOMdoc.documentElement(); QDomElement parElement = mDOMdoc.documentElement();
Q_ASSERT(!parElement.isNull()); if (parElement.isNull()) {
qDebug("invalid pass paramentr maybe invalid document");
addExtentionsToHash(&parElement); result = false;
// qDebug() << "ext properties count " << extProperties.count();
// qDebug() << extProperties.value("link1").element.toElement().tagName();
foreach (IwbExt cur, extProperties) {
qDebug() << (cur.extAttr.count() ? cur.extAttr.first().toElement().tagName() : "count < 0") ;
} }
// for (int i = 0; i < extProperties.count(); i++) {
// Adding iwb extentions to hash table crossing elements and groups using recursive descent
addExtentionsToHash(&parElement, 0);
// int i = 0;
// foreach (IwbExt cur, iwbExtProperties) {
// QString elem = cur.element.toElement().attribute(aId);
// QString tagName = cur.element.toElement().tagName();
// QString gr = !cur.group.isNull()
// ? i++, " is group\n-------------\n" + QString::number(i)
// + cur.group.toElement().tagName()
// + (cur.group.toElement().hasChildNodes() ? "true" : "false")
// : "";
//// QString attr = !cur.extAttr.isEmpty() ? cur.extAttr.first().toElement().attribute(aRef) : "";
//// if (cur.group) {
//// *(cur.group);
//// }
// qDebug() << "element" + elem + "tag" + tagName + gr;
// if (!gr.isNull()) {
// mDOMdoc.documentElement().removeChild(cur.group);
// }
// }
// QDomNode n = mDOMdoc.documentElement().firstChild();
// while (!n.isNull()) {
// qDebug() << "new dom tags"<< n.toElement().tagName();
// n = n.nextSibling();
// } // }
// QDomNode n = docElem.firstChild();
// int i = 0; return result;
// while(!n.isNull()) {
// QDomElement e = n.toElement(); // try to convert the node to an element.
// if(!e.isNull()) {
// qDebug() << e.prefix() << ":" << e.tagName() ; // the node really is an element.
// i++;
// }
// n = n.nextSibling();
// }
return false;
} }
bool UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentProxy* pDocument) bool UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentProxy* pDocument)
@ -198,25 +216,14 @@ bool UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentP
return false; return false;
} }
// QTextStream out(&file); UBCFFSubsetReader cffReader(pDocument, &file);
// out.setCodec("UTF-8");
// QString dta = out.readAll();
QByteArray data = file.readAll();
if (data.length() == 0)
{
qWarning() << "Either content file " << cffSourceFile << " is empty or failed to read from file";
file.close();
return false;
}
UBCFFSubsetReader cffReader(pDocument, data);
bool result = cffReader.parse(); bool result = cffReader.parse();
file.close(); file.close();
return result; return result;
} }
UBCFFSubsetAdaptor::UBCFFSubsetReader::UBCFFSubsetReader(UBDocumentProxy *proxy, QByteArray &content): UBCFFSubsetAdaptor::UBCFFSubsetReader::UBCFFSubsetReader(UBDocumentProxy *proxy, QFile *content):
mReader(content), mProxy(proxy), currentState(NONE) mReader(content), mProxy(proxy), currentState(NONE)
{ {
int errorLine, errorColumn; int errorLine, errorColumn;
@ -226,6 +233,7 @@ UBCFFSubsetAdaptor::UBCFFSubsetReader::UBCFFSubsetReader(UBDocumentProxy *proxy,
<< "column" << errorColumn << ":" << errorStr; << "column" << errorColumn << ":" << errorStr;
} else { } else {
qDebug() << "well parsed to DOM"; qDebug() << "well parsed to DOM";
pwdContent = QFileInfo(content->fileName()).dir().absolutePath();
} }
// QFile tfile("/home/ilia/Documents/tmp/2/out.xml"); // QFile tfile("/home/ilia/Documents/tmp/2/out.xml");
// tfile.open(QIODevice::ReadWr ite | QIODevice::Text); // tfile.open(QIODevice::ReadWr ite | QIODevice::Text);
@ -272,8 +280,633 @@ void UBCFFSubsetAdaptor::UBCFFSubsetReader::PushState(int state)
currentState = state; currentState = state;
} }
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgRect(const QDomElement &element)
{
qreal x1 = element.attribute(aX).toDouble();
qreal y1 = element.attribute(aY).toDouble();
//rect dimensions
qreal width = element.attribute(aWidth).toDouble();
qreal height = element.attribute(aHeight).toDouble();
QString textFillColor = element.attribute(aFill);
QString textStrokeColor = element.attribute(aStroke);
QString textStrokeWidth = element.attribute(aStrokewidth);
QColor fillColor = !textFillColor.isNull() ? colorFromString(textFillColor) : QColor();
QColor strokeColor = !textStrokeColor.isNull() ? colorFromString(textStrokeColor) : QColor();
int strokeWidth = !textStrokeWidth.isNull() ? textStrokeWidth.toInt() : 0;
//init svg generator with temp file
QSvgGenerator *generator = createSvgGenerator(width + 10, height + 10);
//init painter to paint to svg
QPainter painter;
painter.begin(generator);
//fill rect
if (fillColor.isValid()) {
painter.setBrush(QBrush(fillColor));
painter.fillRect(5, 5, width, height, fillColor);
}
QPen pen;
if (strokeColor.isValid()) {
pen.setColor(strokeColor);
}
if (strokeWidth)
pen.setWidth(strokeWidth);
painter.setPen(pen);
painter.drawRect(5, 5, width, height);
painter.end();
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QTransform transform;
QString textTransform = element.attribute(aTransform);
bool hastransform = false;
if (!textTransform.isNull()) {
transform = transformFromString(textTransform);
hastransform = true;
}
repositionSvgItem(svgItem, width + 10, height + 10, x1 - 5, y1 - 5, hastransform, transform);
delete generator;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgEllipse(const QDomElement &element)
{
//ellipse horisontal and vertical radius
qreal rx = element.attribute(aRx).toDouble();
qreal ry = element.attribute(aRy).toDouble();
QSvgGenerator *generator = createSvgGenerator(rx * 2 + 10, ry * 2 + 10);
//fill and stroke color
QColor fillColor = colorFromString(element.attribute(aFill));
QColor strokeColor = colorFromString(element.attribute(aStroke));
int strokeWidth = element.attribute(aStrokewidth).toInt();
//ellipse center coordinates
qreal cx = element.attribute(aCx).toDouble();
qreal cy = element.attribute(aCy).toDouble();
//init painter to paint to svg
QPainter painter;
painter.begin(generator);
QPen pen(strokeColor);
pen.setWidth(strokeWidth);
painter.setPen(pen);
painter.setBrush(QBrush(fillColor));
painter.drawEllipse(5, 5, rx * 2, ry * 2);
painter.end();
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QTransform transform;
QString textTransform = element.attribute(aTransform);
bool hastransform = false;
if (!textTransform.isNull()) {
transform = transformFromString(textTransform);
hastransform = true;
}
repositionSvgItem(svgItem, rx * 2 + 10, ry * 2 + 10, cx - rx - 5, cy - ry -5, hastransform, transform);
delete generator;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgPolygon(const QDomElement &element)
{
QString svgPoints = element.attribute(aPoints);
QPolygonF polygon;
if (!svgPoints.isNull()) {
QStringList ts = svgPoints.split(QLatin1Char(' '), QString::SkipEmptyParts);
foreach(const QString sPoint, ts) {
QStringList sCoord = sPoint.split(QLatin1Char(','), QString::SkipEmptyParts);
if (sCoord.size() == 2) {
QPointF point;
point.setX(sCoord.at(0).toFloat());
point.setY(sCoord.at(1).toFloat());
polygon << point;
}
else {
qWarning() << "cannot make sense of a 'point' value" << sCoord;
}
}
}
//bounding rect lef top corner coordinates
qreal x1 = polygon.boundingRect().topLeft().x();
qreal y1 = polygon.boundingRect().topLeft().y();
//bounding rect dimensions
qreal width = polygon.boundingRect().width();
qreal height = polygon.boundingRect().height();
QString strokeColorText = element.attribute(aStroke);
QString fillColorText = element.attribute(aFill);
QString strokeWidthText = element.attribute(aStrokewidth);
QColor strokeColor = !strokeColorText.isEmpty() ? colorFromString(strokeColorText) : QColor();
QColor fillColor = !fillColorText.isEmpty() ? colorFromString(fillColorText) : QColor();
int strokeWidth = strokeWidthText.toInt() > 0 ? strokeWidthText.toInt() : 0;
QPen pen;
pen.setColor(strokeColor);
pen.setWidth(strokeWidth);
QBrush brush;
brush.setColor(fillColor);
brush.setStyle(Qt::SolidPattern);
QSvgGenerator *generator = createSvgGenerator(width + pen.width(), height + pen.width());
QPainter painter;
painter.begin(generator); //drawing to svg tmp file
painter.translate(pen.widthF() / 2 - x1, pen.widthF() / 2 - y1);
painter.setBrush(brush);
painter.setPen(pen);
painter.drawPolygon(polygon);
painter.end();
//add resulting svg file to scene
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QTransform transform;
QString textTransform = element.attribute(aTransform);
bool hastransform = false;
if (!textTransform.isNull()) {
transform = transformFromString(textTransform);
hastransform = true;
}
repositionSvgItem(svgItem, width + 10, height + 10, x1 - 5, y1 - 5, hastransform, transform);
delete generator;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgPolyline(const QDomElement &element)
{
QString svgPoints = element.attribute(aPoints);
QPolygonF polygon;
if (!svgPoints.isNull()) {
QStringList ts = svgPoints.split(QLatin1Char(' '),
QString::SkipEmptyParts);
foreach(const QString sPoint, ts) {
QStringList sCoord = sPoint.split(QLatin1Char(','), QString::SkipEmptyParts);
if (sCoord.size() == 2) {
QPointF point;
point.setX(sCoord.at(0).toFloat());
point.setY(sCoord.at(1).toFloat());
polygon << point;
}
else {
qWarning() << "cannot make sense of a 'point' value" << sCoord;
}
}
}
//bounding rect lef top corner coordinates
qreal x1 = polygon.boundingRect().topLeft().x();
qreal y1 = polygon.boundingRect().topLeft().y();
//bounding rect dimensions
qreal width = polygon.boundingRect().width();
qreal height = polygon.boundingRect().height();
QString strokeColorText = element.attribute(aStroke);
QString strokeWidthText = element.attribute(aStrokewidth);
QColor strokeColor = !strokeColorText.isEmpty() ? colorFromString(strokeColorText) : QColor();
int strokeWidth = strokeWidthText.toInt() > 0 ? strokeWidthText.toInt() : 0;
QPen pen;
pen.setColor(strokeColor);
pen.setWidth(strokeWidth);
QSvgGenerator *generator = createSvgGenerator(width + pen.width(), height + pen.width());
QPainter painter;
painter.begin(generator); //drawing to svg tmp file
painter.translate(pen.widthF() / 2 - x1, pen.widthF() / 2 - y1);
painter.setPen(pen);
painter.drawPolyline(polygon);
painter.end();
//add resulting svg file to scene
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QTransform transform;
QString textTransform = element.attribute(aTransform);
bool hastransform = false;
if (!textTransform.isNull()) {
transform = transformFromString(textTransform);
hastransform = true;
}
repositionSvgItem(svgItem, width + 10, height + 10, x1 - 5, y1 - 5, hastransform, transform);
delete generator;
return true;
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::parseTextAttributes(const QDomElement &element,
qreal &fontSize, QColor &fontColor, QString &fontFamily,
QString &fontStretch, bool &italic, int &fontWeight,
int &textAlign, QTransform &fontTransform)
{
//consider inch has 72 liens
//since svg font size is given in pixels, divide it by pixels per line
QString fontSz = element.attribute(aFontSize);
if (!fontSz.isNull()) fontSize = fontSz.toDouble() * 72 / QApplication::desktop()->physicalDpiY();
QString fontColorText = element.attribute(aFill);
if (!fontColorText.isNull()) fontColor = colorFromString(fontColorText);
QString fontFamilyText = element.attribute(aFontfamily);
if (!fontFamilyText.isNull()) fontFamily = fontFamilyText;
QString fontStretchText = element.attribute(aFontstretch);
if (!fontStretchText.isNull()) fontStretch = fontStretchText;
if (!element.attribute(aFontstyle).isNull())
italic = (element.attribute(aFontstyle) == "italic");
QString weight = element.attribute(aFontweight);
if (!weight.isNull()) {
if (weight == "normal") fontWeight = QFont::Normal;
else if (weight == "light") fontWeight = QFont::Light;
else if (weight == "demibold") fontWeight = QFont::DemiBold;
else if (weight == "bold") fontWeight = QFont::Bold;
else if (weight == "black") fontWeight = QFont::Black;
}
QString align = element.attribute(aTextalign);
if (!align.isNull()) {
if (align == "middle" || align == "center") textAlign = Qt::AlignHCenter;
else if (align == "start") textAlign = Qt::AlignLeft;
else if (align == "end") textAlign = Qt::AlignRight;
}
if (!element.attribute(aTransform).isNull())
fontTransform = transformFromString(element.attribute(aTransform));
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgText(const QDomElement &element)
{
// qreal x = element.attribute(aX).toDouble();
// qreal y = element.attribute(aY).toDouble();;
// qreal width = 0;
// qreal height = 0;
// QList<QRectF> textRects;
// QList<QFont> textFonts;
// QList<QString> textLines;
// QList<int> textAligns;
// QList<QColor> textColors;
// qWarning() << QString().sprintf("Text coordinates : %f,%f. Text size %f,%f", x, y, width, height);
// qreal fontSize = 12.0;
// QFont textFont;
// QColor fontColor;
// QString fontFamily = "Arial";
// QString fontStretch = "normal";
// bool italic = false;
// int fontWeight = QFont::Normal;
// int textAlign = Qt::AlignLeft;
// QTransform fontTransform;
// parseTextAttributes(element, fontSize, fontColor, fontFamily, fontStretch, italic, fontWeight, textAlign, fontTransform);
// textFont = QFont(fontFamily, fontSize, fontWeight, italic);
// QFontMetricsF metrics = QFontMetricsF(textFont);
// qreal curHeight = metrics.height();
// qreal curY = 0.0;
// qreal curX = 0.0;
// qreal linespacing = QFontMetrics(textFont).leading();
// //remember if text area has transform
// QTransform transform;
//// bool hasTransform = getCurElementTransorm(transform);
// QRectF lastDrawnTextBoundingRect;
// QStack<QFont> fontStack;
// QStack<QColor> colorStack;
// QStack<int> alignStack;
// // first extimate desired text area size
// // to do that, parse text area tags
// while(true)
// {
// mReader.readNext();
// QStringRef elementName = mReader.name();
// if (mReader.isEndDocument())
// break;
// if (mReader.isEndElement())
// {
// if (elementName == tBreak)
// {
// //when tbreak appers, move down by the drawn rect height
// //TODO: line spacing is not calculated yet, probably additional code is required
// curY += lastDrawnTextBoundingRect.height() + linespacing;
// curX = 0.0;
// height += lastDrawnTextBoundingRect.height();
// lastDrawnTextBoundingRect = QRectF(0,0,0,0);
// continue;
// }
// if (elementName == tTspan)
// {
// textFont = fontStack.pop();
// fontColor = colorStack.pop();
// textAlign = alignStack.pop();
// continue;
// }
// }
// if (mReader.isEndElement() && elementName == tText)
// break;
// if (mReader.isStartElement() && elementName == tTspan)
// {
// fontStack.push(textFont);
// colorStack.push(fontColor);
// alignStack.push(textAlign);
// parseTextAttributes(fontSize, fontColor, fontFamily, fontStretch, italic, fontWeight, textAlign, fontTransform);
// textFont = QFont(fontFamily, fontSize, fontWeight, italic);
// metrics = QFontMetricsF(textFont);
// curHeight = metrics.height();
// linespacing = QFontMetricsF(textFont).leading();
// continue;
// }
// if (mReader.isCharacters() || mReader.isCDATA())
// {
// QString text = mReader.text().toString();
// //skip empty text
// if (text.trimmed().length() == 0)
// continue;
// //get bounding rect to obtain desired text height
// lastDrawnTextBoundingRect = metrics.boundingRect(QRectF(), textAlign, text);
// QString log = QString().sprintf(" at rect %f, %f, %f, %f. Bounding rect is %f, %f, %f, %f", 0.0, curY, width, height - curY, lastDrawnTextBoundingRect.x(), lastDrawnTextBoundingRect.y(), lastDrawnTextBoundingRect.width(), lastDrawnTextBoundingRect.height());
// qWarning() << "Text " << text << log;
// textFonts.append(textFont);
// textRects.append(QRectF(curX, curY, lastDrawnTextBoundingRect.width(), lastDrawnTextBoundingRect.height()));
// textLines.append(text);
// textAligns.append(textAlign);
// textColors.append(fontColor);
// curX += lastDrawnTextBoundingRect.width();
// if (width < curX)
// width = curX;
// if (height == 0)
// height = curHeight;
// continue;
// }
// }
// QSvgGenerator *generator = createSvgGenerator(width, height);
// QPainter painter;
// painter.begin(generator);
// if (textRects.count() != 0)
// {
// QListIterator<QRectF> textRectsIter(textRects);
// QListIterator<QFont> textFontsIter(textFonts);
// QListIterator<QString> textLinesIter(textLines);
// QListIterator<int> textAlignsIter(textAligns);
// QListIterator<QColor> textColorsIter(textColors);
// while (textRectsIter.hasNext())
// {
// QRectF rt = textRectsIter.next();
// QFont font = textFontsIter.next();
// QString line = textLinesIter.next();
// int align = textAlignsIter.next();
// QColor color = textColorsIter.next();
// painter.setFont(font);
// painter.setPen(color);
// painter.drawText(rt.x(), rt.y(), rt.width(), rt.height(), align, line);
// }
// }
// painter.end();
// //add resulting svg file to scene
// UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
// repositionSvgItem(svgItem, width, height, x, y, hasTransform, transform);
// delete generator;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgTextarea(const QDomElement &element)
{
//TODO textarea node
qreal x = element.attribute(aX).toDouble();
qreal y = element.attribute(aY).toDouble();
qreal width = element.attribute(aWidth).toDouble();
qreal height = element.attribute(aHeight).toDouble();
qreal fontSize = 12;
QColor fontColor;
QString fontFamily = "Arial";
QString fontStretch = "normal";
bool italic = false;
int fontWeight = QFont::Normal;
int textAlign = Qt::AlignLeft;
QTransform fontTransform;
parseTextAttributes(fontSize, fontColor, fontFamily, fontStretch, italic, fontWeight, textAlign, fontTransform);
QSvgGenerator *generator = createSvgGenerator(width, height);
QPainter painter;
painter.begin(generator);
painter.setFont(QFont(fontFamily, fontSize, fontWeight, italic));
qreal curY = 0.0;
qreal curX = 0.0;
qreal linespacing = QFontMetricsF(painter.font()).leading();
// remember if text area has transform
// QString transformString;
QTransform transform = fontTransform;
bool hasTransform = !fontTransform.isIdentity();
QRectF lastDrawnTextBoundingRect;
//parse text area tags
QDomElement curTextElement = element.firstChildElement();
while (!curTextElement.isNull()) {
QString tagName = curTextElement.tagName();
if (tagName == tTspan) {
parseTextAttributes(curTextElement, fontSize, fontColor, fontFamily, fontStretch, italic, fontWeight, textAlign, fontTransform);
painter.setFont(QFont(fontFamily, fontSize, fontWeight, italic));
painter.setPen(fontColor);
linespacing = QFontMetricsF(painter.font()).leading();
QDomNode tspanNode = curTextElement.firstChild();
while (!tspanNode.isNull()) {
if (tspanNode.nodeType() == QDomNode::CharacterDataNode
|| tspanNode.nodeType() == QDomNode::CDATASectionNode) {
QDomCharacterData textData = tspanNode.toCharacterData();
QString text = textData.data().trimmed();
//get bounding rect to obtain desired text height
lastDrawnTextBoundingRect = painter.boundingRect(QRectF(curX, curY, width, height - curY), textAlign|Qt::TextWordWrap, text);
painter.drawText(curX, curY, width, lastDrawnTextBoundingRect.height(), textAlign|Qt::TextWordWrap, text);
curX += lastDrawnTextBoundingRect.x() + lastDrawnTextBoundingRect.width();
} else if (tspanNode.nodeType() == QDomNode::ElementNode) {
//when tbreak appers, move down by the drawn rect height
//TODO: line spacing is not calculated yet, additional code is required
curY += lastDrawnTextBoundingRect.height() + linespacing;
curX = 0.0;
lastDrawnTextBoundingRect = QRectF(0,0,0,0);
}
tspanNode = tspanNode.nextSibling();
}
} else if (tagName == tBreak) {
}
curTextElement = curTextElement.nextSiblingElement();
}
painter.end();
//add resulting svg file to scene
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
repositionSvgItem(svgItem, width, height, x, y, hasTransform, transform);
delete generator;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgImage(const QDomElement &element)
{
qreal x = element.attribute(aX).toDouble();
qreal y = element.attribute(aY).toDouble();
qreal width = element.attribute(aWidth).toDouble();
qreal height = element.attribute(aHeight).toDouble();
QString itemRefPath = element.attribute(aHref);
QPixmap pix;
if (!itemRefPath.isNull()) {
QString imagePath = pwdContent + "/" + itemRefPath;
if (!QFile::exists(imagePath)) {
qDebug() << "can't load file" << pwdContent + "/" + itemRefPath << "maybe file corrupted";
return false;
}
pix.load(imagePath);
if (pix.isNull()) {
qDebug() << "can't create pixmap for file" << pwdContent + "/" + itemRefPath << "maybe format does not supported";
}
}
UBGraphicsPixmapItem *pixItem = mCurrentScene->addPixmap(pix);
QTransform transform;
QString textTransform = element.attribute(aTransform);
bool hastransform = false;
if (!textTransform.isNull()) {
transform = transformFromString(textTransform);
hastransform = true;
}
// repositionSvgItem(svgItem, rx * 2 + 10, ry * 2 + 10, cx - rx - 5, cy - ry -5, hastransform, transform);
repositionPixmapItem(pixItem, width, height, x, y, hastransform, transform);
return true;
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgSectionAttr(const QDomElement &svgSection)
{
getViewBoxDimenstions(svgSection.attribute(aViewbox));
mSize = QSize(svgSection.attribute(aWidth).toInt(),
svgSection.attribute(aHeight).toInt());
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseIwbGroup(QDomNode *group)
{
QDomElement curGroupPtr = group->firstChildElement();
while (!curGroupPtr.isNull()) {
if (curGroupPtr.namespaceURI() != iwbNS)
continue;
if (curGroupPtr.hasChildNodes() && curGroupPtr.toElement().tagName() == tGroup) {
parseIwbGroup(&curGroupPtr);
} else if (curGroupPtr.toElement().tagName() == tElement) {
QHash<QString, IwbExt>::iterator iSvgElementExt = iwbExtProperties.find(curGroupPtr.attribute(aRef));
if (iSvgElementExt != iwbExtProperties.end()) {
IwbExt &svgElementExt = *iSvgElementExt;
QDomNode &svgElement = svgElementExt.element;
svgElement.parentNode().removeChild(svgElement);
}
}
curGroupPtr = curGroupPtr.nextSiblingElement(tElement);
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgElement(const QDomElement &parent)
{
QString tagName = parent.tagName();
if (parent.namespaceURI() != svgNS) {
qDebug() << "Incorrect namespace, error at content file, line number" << parent.lineNumber();
return false;
}
if (tagName == tRect && !parseSvgRect(parent)) return false;
else if (tagName == tEllipse && !parseSvgEllipse(parent)) return false;
else if (tagName == tPolygon && !parseSvgPolygon(parent)) return false;
else if (tagName == tPolyline && !parseSvgPolyline(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;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgPage(const QDomElement &parent)
{
createNewScene();
QDomElement currentSvgElement = parent.firstChildElement();
while (!currentSvgElement.isNull()) {
if (!parseSvgElement(currentSvgElement))
return false;
currentSvgElement = currentSvgElement.nextSiblingElement();
}
persistCurrentScene();
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgPageset(const QDomElement &parent)
{
QDomElement currentPage = parent.firstChildElement(tPage);
while (!currentPage.isNull()) {
if (!parseSvgPage(currentPage))
return false;
currentPage = currentPage.nextSiblingElement(tPage);
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseDoc() bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseDoc()
{ {
if (!hashElements()) return false; //hashing all elements having id attribute
QDomElement svgSection = mDOMdoc.elementsByTagNameNS(svgNS, tSvg).at(0).toElement();
parseSvgSectionAttr(svgSection);
QDomElement currentSvg = svgSection.firstChildElement();
if (currentSvg.tagName() != tPageset) {
parseSvgPage(svgSection);
} else if (currentSvg.tagName() == tPageset){
parseSvgPageset(currentSvg);
}
// while (!mReader.atEnd()) // while (!mReader.atEnd())
// { // {
// mReader.readNext(); // mReader.readNext();
@ -297,7 +930,6 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseDoc()
// } // }
// if (!mReader.error() == QXmlStreamReader::NoError) // if (!mReader.error() == QXmlStreamReader::NoError)
// UBApplication::showMessage(mReader.errorString()); // UBApplication::showMessage(mReader.errorString());
if (!hashElements()) return false;
return true; return true;
} }
@ -305,8 +937,8 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseDoc()
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseCurrentElementStart() bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseCurrentElementStart()
{ {
QStringRef elName = mReader.name(); QStringRef elName = mReader.name();
QString log = QString("%1<%2>").arg(mIndent).arg(elName.toString()); // QString log = QString("%1<%2>").arg(mIndent).arg(elName.toString());
qDebug() << log; // qDebug() << log;
mIndent += " "; mIndent += " ";
if ( elName == tIwb) if ( elName == tIwb)
{ {
@ -467,10 +1099,12 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvg()
return true; return true;
} }
void UBCFFSubsetAdaptor::UBCFFSubsetReader::repositionSvgItem(UBGraphicsSvgItem *item, qreal width, qreal height, qreal x, qreal y, bool useTransform, QTransform &transform) void UBCFFSubsetAdaptor::UBCFFSubsetReader::repositionSvgItem(UBGraphicsSvgItem *item, qreal width, qreal height,
qreal x, qreal y,
bool useTransform, QTransform &transform)
{ {
QTransform curTrans = item->transform(); QTransform curTrans = item->transform();
qWarning() << QString().sprintf("Item current transform = %f 0 0 %f %f %f, position %f, %f", curTrans.m11(), curTrans.m22(), curTrans.dx(), curTrans.dy(), item->x(), item->y()); // qWarning() << QString().sprintf("Item current transform = %f 0 0 %f %f %f, position %f, %f", curTrans.m11(), curTrans.m22(), curTrans.dx(), curTrans.dy(), item->x(), item->y());
//check if rect is rotated //check if rect is rotated
//rotate svg item itself //rotate svg item itself
QRectF itemBounds = item->boundingRect(); QRectF itemBounds = item->boundingRect();
@ -495,7 +1129,49 @@ void UBCFFSubsetAdaptor::UBCFFSubsetReader::repositionSvgItem(UBGraphicsSvgItem
} }
QTransform newTrans = item->transform(); QTransform newTrans = item->transform();
qWarning() << QString("Item new transform = %3 0 0 %4 %1 %2, position %5, %6").arg(newTrans.dx()).arg(newTrans.dy()).arg(newTrans.m11()).arg(newTrans.m22()).arg(item->x()).arg(item->y()); // qWarning() << QString("Item new transform = %3 0 0 %4 %1 %2, position %5, %6").arg(newTrans.dx()).arg(newTrans.dy()).arg(newTrans.m11()).arg(newTrans.m22()).arg(item->x()).arg(item->y());
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::repositionPixmapItem(UBGraphicsPixmapItem *item, qreal width, qreal height,
qreal x, qreal y,
bool useTransform, QTransform &transform)
{
//if element is to transform
// if (!transform.isIdentity()) {
// QTransform curTransform = item->transform();
// qreal hScale = item->boundingRect().width() / width * curTransform.m11();
// qreal vScale = item->boundingRect().height() / height * curTransform.m22();
// curTransform = curTransform.translate(x - mViewBoxCenter.x(), y - mViewBoxCenter.y()).scale(hScale, vScale);
// curTransform = curTransform * transform;
// item->setTransform(curTransform);
QTransform curTrans = item->transform();
// qWarning() << QString().sprintf("Item current transform = %f 0 0 %f %f %f, position %f, %f", curTrans.m11(), curTrans.m22(), curTrans.dx(), curTrans.dy(), item->x(), item->y());
//check if rect is rotated
//rotate svg item itself
QRectF itemBounds = item->boundingRect();
//first, svg is mapped to svg item bound
//second, svg item is mapped to scene
//so, get svg to svg item scale and multiple by scene scale
qreal hScale = itemBounds.width() / width * curTrans.m11();
qreal vScale = itemBounds.height() / height * curTrans.m22();
if (useTransform)
{
QPointF oldVector((x - transform.dx()), (y - transform.dy()));
QTransform rTransform(transform.m11(), transform.m12(), transform.m21(), transform.m22(), 0, 0);
QPointF newVector = rTransform.map(oldVector);
rTransform.scale(curTrans.m11(), curTrans.m22());
item->setTransform(QTransform(rTransform.m11(), rTransform.m12(), rTransform.m21(), rTransform.m22(), 0, 0));
item->setPos((x - mViewBoxCenter.x() + (newVector - oldVector).x()) * hScale, (y - mViewBoxCenter.y() + (newVector - oldVector).y()) * vScale );
}
else
{
item->setPos((x - mViewBoxCenter.x()) * hScale, (y - mViewBoxCenter.y()) * vScale);
}
} }
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseRect() bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseRect()
@ -995,8 +1671,6 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parsePolyline()
if (mReader.attributes().hasAttribute(aStrokewidth)) if (mReader.attributes().hasAttribute(aStrokewidth))
pen.setWidth(mReader.attributes().value(aStrokewidth).toString().toInt()); pen.setWidth(mReader.attributes().value(aStrokewidth).toString().toInt());
pen.setColor(Qt::yellow);
QSvgGenerator *generator = createSvgGenerator(width + pen.width(), height + pen.width()); QSvgGenerator *generator = createSvgGenerator(width + pen.width(), height + pen.width());
QPainter painter; QPainter painter;
@ -1025,11 +1699,8 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parsePage()
qWarning() << "iwb content parse error, unexpected page tag at line" << mReader.lineNumber(); qWarning() << "iwb content parse error, unexpected page tag at line" << mReader.lineNumber();
return false; return false;
} }
createNewScene(); createNewScene();
qWarning() << "Added page number" << mProxy->pageCount(); qWarning() << "Added page number" << mProxy->pageCount();
return true; return true;
} }
@ -1115,31 +1786,31 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getCurElementTransorm(QTransform &tr
QTransform UBCFFSubsetAdaptor::UBCFFSubsetReader::transformFromString(const QString trString) QTransform UBCFFSubsetAdaptor::UBCFFSubsetReader::transformFromString(const QString trString)
{ {
qreal dx = 0.0;
qreal dy = 0.0;
qreal angle = 0.0;
//check pattern for strings like 'rotate(10)' //check pattern for strings like 'rotate(10)'
QRegExp regexp("rotate\\( *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *\\)"); QRegExp regexp("rotate\\( *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *\\)");
if (regexp.exactMatch(trString)) if (regexp.exactMatch(trString)) {
{ angle = regexp.capturedTexts().at(1).toDouble();
if (regexp.capturedTexts().count() == 2 && regexp.capturedTexts().at(0).length() == trString.length()) } else {
{ //check pattern for strings like 'rotate(10,20,20)' or 'rotate(10.1,10.2,34.2)'
qreal angle = regexp.capturedTexts().at(1).toDouble(); regexp.setPattern("rotate\\( *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *, *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *, *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *\\)");
return QTransform().rotate(angle); if (regexp.exactMatch(trString)) {
angle = regexp.capturedTexts().at(1).toDouble();
dx = regexp.capturedTexts().at(2).toDouble();
dy = regexp.capturedTexts().at(3).toDouble();
} }
} }
//check pattern for strings like 'translate(11.0, 12.34)'
//check pattern for strings like 'rotate(10,20,20)' or 'rotate(10.1,10.2,34.2)' regexp.setPattern("translate\\( *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *,*([-+]{0,1}[0-9]*\\.{0,1}[0-9]*)*\\)");
regexp.setPattern("rotate\\( *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *, *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *, *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *\\)"); if (regexp.exactMatch(trString)) {
if (regexp.exactMatch(trString)) dx = regexp.capturedTexts().at(1).toDouble();
{ dy = regexp.capturedTexts().at(2).toDouble();
if (regexp.capturedTexts().count() == 4 && regexp.capturedTexts().at(0).length() == trString.length())
{
qreal angle = regexp.capturedTexts().at(1).toDouble();
qreal dx = regexp.capturedTexts().at(2).toDouble();
qreal dy = regexp.capturedTexts().at(3).toDouble();
return QTransform().translate(dx, dy).rotate(angle);
}
} }
return QTransform(); return QTransform().translate(dx, dy).rotate(angle);
} }
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getViewBoxDimenstions(const QString& viewBox) bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getViewBoxDimenstions(const QString& viewBox)

@ -26,7 +26,9 @@ class UBDocumentProxy;
class UBGraphicsScene; class UBGraphicsScene;
class QSvgGenerator; class QSvgGenerator;
class UBGraphicsSvgItem; class UBGraphicsSvgItem;
class UBGraphicsPixmapItem;
class QTransform; class QTransform;
class QPainter;
struct IwbExt { struct IwbExt {
IwbExt() {;} IwbExt() {;}
@ -36,7 +38,7 @@ struct IwbExt {
QDomNode element; QDomNode element;
QVector<QDomNode> extAttr; QVector<QDomNode> extAttr;
QHash<QString, QString> textAttributes; QHash<QString, QString> textAttributes;
operator bool() const {return group.isNull() || !element.isNull();} operator bool() const {return !group.isNull() || !element.isNull();}
}; };
class UBCFFSubsetAdaptor class UBCFFSubsetAdaptor
@ -62,10 +64,11 @@ private:
}; };
public: public:
UBCFFSubsetReader(UBDocumentProxy *proxy, QByteArray &content); UBCFFSubsetReader(UBDocumentProxy *proxy, QFile *content);
QXmlStreamReader mReader; QXmlStreamReader mReader;
UBDocumentProxy *mProxy; UBDocumentProxy *mProxy;
QString pwdContent;
bool parse(); bool parse();
@ -79,14 +82,38 @@ private:
QSize mSize; QSize mSize;
private: private:
// to kill
QDomDocument mDOMdoc; QDomDocument mDOMdoc;
QHash<QString, IwbExt> extProperties; QDomNode mCurrentDOMElement;
QHash<QString, IwbExt> iwbExtProperties;
bool hashElements(); bool hashElements();
void addExtentionsToHash(QDomElement *parent); void addExtentionsToHash(QDomElement *parent, QDomElement *topGroup);
void hashSvg(QDomNode *parent, QString prefix = ""); void hashSvg(QDomNode *parent, QString prefix = "");
void hashSiblingIwbElements(QDomElement *parent, QDomElement *topGroup = 0); void hashSiblingIwbElements(QDomElement *parent, QDomElement *topGroup = 0);
inline void parseSvgSectionAttr(const QDomElement &);
bool parseSvgPage(const QDomElement &parent);
bool parseSvgPageset(const QDomElement &parent);
bool parseSvgElement(const QDomElement &parent);
inline bool parseSvgRect(const QDomElement &element);
inline bool parseSvgEllipse(const QDomElement &element);
inline bool parseSvgPolygon(const QDomElement &element);
inline bool parseSvgPolyline(const QDomElement &element);
inline bool parseSvgText(const QDomElement &element);
inline bool parseSvgTextarea(const QDomElement &element);
inline bool parseSvgImage(const QDomElement &element);
// inline bool parseSvgTSpan(const QDomElement)
bool parseIwbGroup(QDomNode *element);
// to kill
void parseTextAttributes(const QDomElement &element, qreal &fontSize, QColor &fontColor,
QString &fontFamily, QString &fontStretch, bool &italic,
int &fontWeight, int &textAlign, QTransform &fontTransform);
//methods to store current xml parse state //methods to store current xml parse state
int PopState(); int PopState();
@ -123,6 +150,8 @@ private:
//helper methods //helper methods
bool getCurElementTransorm(QTransform &transform); bool getCurElementTransorm(QTransform &transform);
void repositionSvgItem(UBGraphicsSvgItem *item, qreal width, qreal height, qreal x, qreal y, bool useTransform, QTransform &transform); void repositionSvgItem(UBGraphicsSvgItem *item, qreal width, qreal height, qreal x, qreal y, bool useTransform, QTransform &transform);
void repositionPixmapItem(UBGraphicsPixmapItem *item, qreal width, qreal height, qreal x, qreal y
, bool useTransform, QTransform &transform);
QColor colorFromString(const QString& clrString); QColor colorFromString(const QString& clrString);
QTransform transformFromString(const QString trString); QTransform transformFromString(const QString trString);
bool getViewBoxDimenstions(const QString& viewBox); bool getViewBoxDimenstions(const QString& viewBox);

Loading…
Cancel
Save