@ -25,6 +25,7 @@
# include "domain/UBGraphicsStroke.h"
# include "domain/UBGraphicsTextItem.h"
# include "domain/UBGraphicsSvgItem.h"
# include "domain/UBGraphicsPixmapItem.h"
# include "UBCFFSubsetAdaptor.h"
# include "UBMetadataDcSubsetAdaptor.h"
@ -55,6 +56,7 @@ static QString tText = "text";
static QString tTextarea = " textarea " ;
static QString tTspan = " tspan " ;
static QString tBreak = " tbreak " ;
static QString tImage = " image " ;
//attribute names definition
static QString aFill = " fill " ;
@ -81,56 +83,57 @@ static QString aPoints = "points";
static QString svgNS = " http://www.w3.org/2000/svg " ;
static QString iwbNS = " http://www.becta.org.uk/iwb " ;
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 ( )
{
}
void UBCFFSubsetAdaptor : : UBCFFSubsetReader : : hashSiblingIwbElements ( QDomElement * parent , QDomElement * topGroup ) {
QDomElement curExt = parent - > firstChildElement ( tElement ) ;
while ( ! curExt . isNull ( ) ) {
QDomElement n = curExt ;
if ( curExt . namespaceURI ( ) ! = iwbNS )
continue ;
QHash < QString , IwbExt > : : iterator iSvgElement = e xtProperties. find ( curExt . attribute ( " ref " ) ) ;
if ( iSvgElement ! = e xtProperties. end ( ) ) {
QHash < QString , IwbExt > : : iterator iSvgElement = iwbE xtProperties. find ( curExt . attribute ( aRef ) ) ;
if ( iSvgElement ! = iwbE xtProperties. end ( ) ) {
IwbExt & svgElement = * iSvgElement ;
svgElement . extAttr . push_back ( curExt ) ;
if ( topGroup )
qDebug ( ) < < " made " ;
svgElement . group = * topGroup ;
}
curExt = curExt . nextSiblingElement ( tElement ) ;
}
}
void UBCFFSubsetAdaptor : : UBCFFSubsetReader : : addExtentionsToHash ( QDomElement * parent )
void UBCFFSubsetAdaptor : : UBCFFSubsetReader : : addExtentionsToHash ( QDomElement * parent , QDomElement * topGroup )
{
//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 topGroup ;
while ( ! curGroup . isNull ( ) ) {
if ( curGroup . namespaceURI ( ) ! = iwbNS )
continue ;
// if (parent == mDOMdoc.documentElement())
// 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 ( * parent = = mDOMdoc . documentElement ( ) ) {
topGroup = & curGroup ;
}
if ( curGroup . hasChildNodes ( ) ) {
addExtentionsToHash ( & curGroup ) ;
addExtentionsToHash ( & curGroup , topGroup ) ;
}
curGroup = curGroup . nextSiblingElement ( tGroup ) ;
}
//add groups
}
void UBCFFSubsetAdaptor : : UBCFFSubsetReader : : hashSvg ( QDomNode * parent , QString prefix )
@ -140,7 +143,7 @@ void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSvg(QDomNode *parent, QString pr
QDomElement e = n . toElement ( ) ;
QString id = e . attribute ( aId ) ;
if ( ! id . isNull ( ) ) {
e xtProperties. insert ( id , IwbExt ( e ) ) ;
iwbE xtProperties. insert ( id , IwbExt ( e ) ) ;
qDebug ( ) < < prefix + e . prefix ( ) + " : " + e . tagName ( ) ;
}
if ( n . hasChildNodes ( ) ) {
@ -152,36 +155,51 @@ void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSvg(QDomNode *parent, QString pr
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : hashElements ( )
{
QDomElement svgSection = mDOMdoc . elementsByTagNameNS ( svgNS , tSvg ) . at ( 0 ) . toElement ( ) ;
Q_ASSERT ( ! svgSection . isNull ( ) ) ;
bool result = true ;
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 ) ;
QDomElement parElement = mDOMdoc . documentElement ( ) ;
Q_ASSERT ( ! parElement . isNull ( ) ) ;
addExtentionsToHash ( & parElement ) ;
// 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 " ) ;
if ( parElement . isNull ( ) ) {
qDebug ( " invalid pass paramentr maybe invalid document " ) ;
result = false ;
}
// for (int i = 0; i < extProperties.count(); i++) {
// }
// Adding iwb extentions to hash table crossing elements and groups using recursive descent
addExtentionsToHash ( & parElement , 0 ) ;
// QDomNode n = docElem.firstChild();
// int i = 0;
// 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++;
// 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();
// }
return false ;
return result ;
}
bool UBCFFSubsetAdaptor : : ConvertCFFFileToUbz ( QString & cffSourceFile , UBDocumentProxy * pDocument )
@ -198,25 +216,14 @@ bool UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentP
return false ;
}
// QTextStream out(&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 ) ;
UBCFFSubsetReader cffReader ( pDocument , & file ) ;
bool result = cffReader . parse ( ) ;
file . close ( ) ;
return result ;
}
UBCFFSubsetAdaptor : : UBCFFSubsetReader : : UBCFFSubsetReader ( UBDocumentProxy * proxy , QByteArray & content ) :
UBCFFSubsetAdaptor : : UBCFFSubsetReader : : UBCFFSubsetReader ( UBDocumentProxy * proxy , QFile * content ) :
mReader ( content ) , mProxy ( proxy ) , currentState ( NONE )
{
int errorLine , errorColumn ;
@ -226,6 +233,7 @@ UBCFFSubsetAdaptor::UBCFFSubsetReader::UBCFFSubsetReader(UBDocumentProxy *proxy,
< < " column " < < errorColumn < < " : " < < errorStr ;
} else {
qDebug ( ) < < " well parsed to DOM " ;
pwdContent = QFileInfo ( content - > fileName ( ) ) . dir ( ) . absolutePath ( ) ;
}
// QFile tfile("/home/ilia/Documents/tmp/2/out.xml");
// tfile.open(QIODevice::ReadWr ite | QIODevice::Text);
@ -272,8 +280,633 @@ void UBCFFSubsetAdaptor::UBCFFSubsetReader::PushState(int 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 ( )
{
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())
// {
// mReader.readNext();
@ -297,7 +930,6 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseDoc()
// }
// if (!mReader.error() == QXmlStreamReader::NoError)
// UBApplication::showMessage(mReader.errorString());
if ( ! hashElements ( ) ) return false ;
return true ;
}
@ -305,8 +937,8 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseDoc()
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : parseCurrentElementStart ( )
{
QStringRef elName = mReader . name ( ) ;
QString log = QString ( " %1<%2> " ) . arg ( mIndent ) . arg ( elName . toString ( ) ) ;
qDebug ( ) < < log ;
// QString log = QString("%1<%2>").arg(mIndent).arg(elName.toString());
// qDebug() << log;
mIndent + = " " ;
if ( elName = = tIwb )
{
@ -467,10 +1099,12 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvg()
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 ( ) ;
qWarning ( ) < < QString ( ) . sprintf ( " Item current transform = %f 0 0 %f %f %f, position %f, %f " , c urTrans . m11 ( ) , c urTrans . m22 ( ) , c urTrans . dx ( ) , c urTrans . dy ( ) , item - > x ( ) , item - > y ( ) ) ;
// qWarning() << QString().sprintf(" Item current transform = %f 0 0 %f %f %f, position %f, %f", c urTrans.m11(), c urTrans.m22(), c urTrans.dx(), c urTrans.dy(), item->x(), item->y());
//check if rect is rotated
//rotate svg item itself
QRectF itemBounds = item - > boundingRect ( ) ;
@ -495,7 +1129,49 @@ void UBCFFSubsetAdaptor::UBCFFSubsetReader::repositionSvgItem(UBGraphicsSvgItem
}
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 ( )
@ -995,8 +1671,6 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parsePolyline()
if ( mReader . attributes ( ) . hasAttribute ( aStrokewidth ) )
pen . setWidth ( mReader . attributes ( ) . value ( aStrokewidth ) . toString ( ) . toInt ( ) ) ;
pen . setColor ( Qt : : yellow ) ;
QSvgGenerator * generator = createSvgGenerator ( width + pen . width ( ) , height + pen . width ( ) ) ;
QPainter painter ;
@ -1025,11 +1699,8 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parsePage()
qWarning ( ) < < " iwb content parse error, unexpected page tag at line " < < mReader . lineNumber ( ) ;
return false ;
}
createNewScene ( ) ;
qWarning ( ) < < " Added page number " < < mProxy - > pageCount ( ) ;
return true ;
}
@ -1115,31 +1786,31 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getCurElementTransorm(QTransform &tr
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)'
QRegExp regexp ( " rotate \\ ( *([-+]{0,1}[0-9]* \\ .{0,1}[0-9]*) * \ \ ) " ) ;
if ( regexp . exactMatch ( trString ) )
{
if ( regexp . capturedTexts ( ) . count ( ) = = 2 & & regexp . capturedTexts ( ) . at ( 0 ) . length ( ) = = trString . length ( ) )
{
qreal angle = regexp . capturedTexts ( ) . at ( 1 ) . toDouble ( ) ;
return QTransform ( ) . rotate ( angle ) ;
}
}
if ( regexp . exactMatch ( trString ) ) {
angle = regexp . capturedTexts ( ) . at ( 1 ) . toDouble ( ) ;
} else {
//check pattern for strings like 'rotate(10,20,20)' or 'rotate(10.1,10.2,34.2)'
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 . 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 ) ;
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)'
regexp . setPattern ( " translate \\ ( *([-+]{0,1}[0-9]* \\ .{0,1}[0-9]*) *,*([-+]{0,1}[0-9]* \\ .{0,1}[0-9]*)* \\ ) " ) ;
if ( regexp . exactMatch ( trString ) ) {
dx = regexp . capturedTexts ( ) . at ( 1 ) . toDouble ( ) ;
dy = regexp . capturedTexts ( ) . at ( 2 ) . toDouble ( ) ;
}
return QTransform ( ) ;
return QTransform ( ) . translate ( dx , dy ) . rotate ( angle ) ;
}
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : getViewBoxDimenstions ( const QString & viewBox )