@ -1,16 +1,32 @@
/*
* 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 < http : //www.gnu.org/licenses/>.
*/
# include <QRegExp>
# include <QRegExp>
# include <QSvgGenerator>
# include <QSvgGenerator>
# include <QSvgRenderer>
# include <QSvgRenderer>
# include "UBCFFSubsetAdaptor.h"
# include "core/UBPersistenceManager.h"
# include "core/UBPersistenceManager.h"
# include "document/UBDocumentProxy.h"
# include "document/UBDocumentProxy.h"
# include "domain/UBItem.h"
# include "domain/UBItem.h"
# include "domain/UBGraphicsPolygonItem.h"
# include "domain/UBGraphicsPolygonItem.h"
# include "domain/UBGraphicsStroke.h"
# include "domain/UBGraphicsStroke.h"
# include "domain/UBGraphicsTextItem.h"
# include "domain/UBGraphicsSvgItem.h"
# include "UBCFFSubsetAdaptor.h"
# include "UBMetadataDcSubsetAdaptor.h"
# include "UBMetadataDcSubsetAdaptor.h"
# include "UBThumbnailAdaptor.h"
# include "UBThumbnailAdaptor.h"
# include "UBSvgSubsetAdaptor.h"
# include "UBSvgSubsetAdaptor.h"
@ -19,32 +35,42 @@
//tag names definition
//tag names definition
//use them everiwhere!
//use them everiwhere!
static char * tElement = " element " ;
static QString tElement = " element " ;
static char * tEllipse = " ellipse " ;
static QString tEllipse = " ellipse " ;
static char * tIwb = " iwb " ;
static QString tIwb = " iwb " ;
static char * tMeta = " meta " ;
static QString tMeta = " meta " ;
static char * tPage = " page " ;
static QString tPage = " page " ;
static char * tPageset = " pageset " ;
static QString tPageset = " pageset " ;
static char * tPolygon = " polygon " ;
static QString tPolygon = " polygon " ;
static char * tRect = " rect " ;
static QString tRect = " rect " ;
static char * tSvg = " svg " ;
static QString tSvg = " svg " ;
static char * tTextarea = " textarea " ;
static QString tText = " text " ;
static QString tTextarea = " textarea " ;
static QString tTspan = " tspan " ;
static QString tBreak = " tbreak " ;
//attribute names definition
//attribute names definition
static char * aFill = " fill " ;
static QString aFill = " fill " ;
static char * aFillopacity = " fill-opacity " ;
static QString aFillopacity = " fill-opacity " ;
static char * aX = " x " ;
static QString aX = " x " ;
static char * aY = " y " ;
static QString aY = " y " ;
static char * aWidth = " width " ;
static QString aWidth = " width " ;
static char * aHeight = " height " ;
static QString aHeight = " height " ;
static char * aStroke = " stroke " ;
static QString aStroke = " stroke " ;
static char * aStrokewidth = " stroke-width " ;
static QString aStrokewidth = " stroke-width " ;
static char * aCx = " cx " ;
static QString aCx = " cx " ;
static char * aCy = " cy " ;
static QString aCy = " cy " ;
static char * aRx = " rx " ;
static QString aRx = " rx " ;
static char * aRy = " ry " ;
static QString aRy = " ry " ;
static char * aTransform = " transform " ;
static QString aTransform = " transform " ;
static char * aViewbox = " viewbox " ;
static QString aViewbox = " viewbox " ;
static QString aFontSize = " font-size " ;
static QString aFontfamily = " font-family " ;
static QString aFontstretch = " font-stretch " ;
static QString aFontstyle = " font-style " ;
static QString aFontweight = " font-weight " ;
static QString aTextalign = " text-align " ;
UBCFFSubsetAdaptor : : UBCFFSubsetAdaptor ( )
UBCFFSubsetAdaptor : : UBCFFSubsetAdaptor ( )
{
{
@ -82,10 +108,8 @@ bool UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentP
UBCFFSubsetAdaptor : : UBCFFSubsetReader : : UBCFFSubsetReader ( UBDocumentProxy * proxy , QByteArray & content ) :
UBCFFSubsetAdaptor : : UBCFFSubsetReader : : UBCFFSubsetReader ( UBDocumentProxy * proxy , QByteArray & content ) :
mReader ( content ) , mProxy ( proxy ) , currentState ( NONE )
mReader ( content ) , mProxy ( proxy ) , currentState ( NONE )
{
{
//TODO parse
}
}
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : parse ( )
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : parse ( )
{
{
UBMetadataDcSubsetAdaptor : : persist ( mProxy ) ;
UBMetadataDcSubsetAdaptor : : persist ( mProxy ) ;
@ -187,6 +211,12 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseCurrentElementStart()
return false ;
return false ;
}
}
else
else
if ( elName = = tText )
{
if ( ! parseText ( ) )
return false ;
}
else
if ( elName = = tTextarea )
if ( elName = = tTextarea )
{
{
if ( ! parseTextArea ( ) )
if ( ! parseTextArea ( ) )
@ -300,6 +330,37 @@ 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 )
{
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 ) ;
}
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 ( ) ) ;
}
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : parseRect ( )
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : parseRect ( )
{
{
if ( currentState ! = SVG & & currentState ! = PAGE )
if ( currentState ! = SVG & & currentState ! = PAGE )
@ -312,11 +373,6 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseRect()
if ( currentState = = SVG & & mCurrentScene = = NULL )
if ( currentState = = SVG & & mCurrentScene = = NULL )
createNewScene ( ) ;
createNewScene ( ) ;
//fill and stroke color
QColor fillColor = colorFromString ( mReader . attributes ( ) . value ( aFill ) . toString ( ) ) ;
QColor strokeColor = colorFromString ( mReader . attributes ( ) . value ( aStroke ) . toString ( ) ) ;
int strokeWidth = mReader . attributes ( ) . value ( aStrokewidth ) . toString ( ) . toInt ( ) ;
//rect lef top corner coordinates
//rect lef top corner coordinates
qreal x1 = mReader . attributes ( ) . value ( aX ) . toString ( ) . toDouble ( ) ;
qreal x1 = mReader . attributes ( ) . value ( aX ) . toString ( ) . toDouble ( ) ;
qreal y1 = mReader . attributes ( ) . value ( aY ) . toString ( ) . toDouble ( ) ;
qreal y1 = mReader . attributes ( ) . value ( aY ) . toString ( ) . toDouble ( ) ;
@ -325,34 +381,41 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseRect()
qreal height = mReader . attributes ( ) . value ( aHeight ) . toString ( ) . toDouble ( ) ;
qreal height = mReader . attributes ( ) . value ( aHeight ) . toString ( ) . toDouble ( ) ;
//init svg generator with temp file
//init svg generator with temp file
QSvgGenerator * generator = createSvgGenerator ( ) ;
QSvgGenerator * generator = createSvgGenerator ( width + 10 , height + 10 ) ;
//init painter to paint to svg
//init painter to paint to svg
QPainter painter ;
QPainter painter ;
painter . begin ( generator ) ;
painter . begin ( generator ) ;
//check if rect is rotated
//fill rect
if ( mReader . attributes ( ) . hasAttribute ( aTransform ) )
if ( mReader . attributes ( ) . hasAttribute ( aFill ) )
{
{
QTransform transform = transformFromString ( mReader . attributes ( ) . value ( aTransform ) . toString ( ) ) ;
QColor fillColor = colorFromString ( mReader . attributes ( ) . value ( aFill ) . toString ( ) ) ;
painter . setTransform ( transform ) ;
painter . setBrush ( QBrush ( fillColor ) ) ;
//change left top coordinates to correspond to transformation
painter . fillRect ( 5 , 5 , width , height , fillColor ) ;
x1 - = transform . dx ( ) ;
y1 - = transform . dy ( ) ;
}
}
painter . setBrush ( QBrush ( fillColor ) ) ;
bool hasStrokeColor = mReader . attributes ( ) . hasAttribute ( aStroke ) ;
painter . fillRect ( x1 , y1 , width , height , fillColor ) ;
bool hasStrokeWidth = mReader . attributes ( ) . hasAttribute ( aStrokewidth ) ;
if ( hasStrokeColor | | hasStrokeWidth )
QPen pen ( strokeColor ) ;
{
pen . setWidth ( strokeWidth ) ;
QPen pen ;
painter . setPen ( pen ) ;
if ( hasStrokeColor )
painter . drawRect ( x1 , y1 , width , height ) ;
pen . setColor ( colorFromString ( mReader . attributes ( ) . value ( aStroke ) . toString ( ) ) ) ;
if ( hasStrokeWidth )
pen . setWidth ( mReader . attributes ( ) . value ( aStrokewidth ) . toString ( ) . toInt ( ) ) ;
painter . setPen ( pen ) ;
painter . drawRect ( 5 , 5 , width , height ) ;
}
painter . end ( ) ;
painter . end ( ) ;
//add resulting svg file to scene
//add resulting svg file to scene
mCurrentScene - > addSvg ( QUrl : : fromLocalFile ( generator - > fileName ( ) ) ) ;
UBGraphicsSvgItem * svgItem = mCurrentScene - > addSvg ( QUrl : : fromLocalFile ( generator - > fileName ( ) ) ) ;
QTransform transform ;
bool hastransform = getCurElementTransorm ( transform ) ;
repositionSvgItem ( svgItem , width + 10 , height + 10 , x1 - 5 , y1 - 5 , hastransform , transform ) ;
delete generator ;
delete generator ;
return true ;
return true ;
@ -370,7 +433,10 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseEllipse()
if ( currentState = = SVG & & mCurrentScene = = NULL )
if ( currentState = = SVG & & mCurrentScene = = NULL )
createNewScene ( ) ;
createNewScene ( ) ;
QSvgGenerator * generator = createSvgGenerator ( ) ;
//ellipse horisontal and vertical radius
qreal rx = mReader . attributes ( ) . value ( aRx ) . toString ( ) . toDouble ( ) ;
qreal ry = mReader . attributes ( ) . value ( aRy ) . toString ( ) . toDouble ( ) ;
QSvgGenerator * generator = createSvgGenerator ( rx * 2 + 10 , ry * 2 + 10 ) ;
//fill and stroke color
//fill and stroke color
QColor fillColor = colorFromString ( mReader . attributes ( ) . value ( aFill ) . toString ( ) ) ;
QColor fillColor = colorFromString ( mReader . attributes ( ) . value ( aFill ) . toString ( ) ) ;
@ -380,44 +446,33 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseEllipse()
//ellipse center coordinates
//ellipse center coordinates
qreal cx = mReader . attributes ( ) . value ( aCx ) . toString ( ) . toDouble ( ) ;
qreal cx = mReader . attributes ( ) . value ( aCx ) . toString ( ) . toDouble ( ) ;
qreal cy = mReader . attributes ( ) . value ( aCy ) . toString ( ) . toDouble ( ) ;
qreal cy = mReader . attributes ( ) . value ( aCy ) . toString ( ) . toDouble ( ) ;
//ellipse horisontal and vertical radius
qreal rx = mReader . attributes ( ) . value ( aRx ) . toString ( ) . toDouble ( ) ;
qreal ry = mReader . attributes ( ) . value ( aRy ) . toString ( ) . toDouble ( ) ;
//we should change cx and cy by rx and ry because qpainter
//draws ellipse by its rect coordinates
cx - = rx ;
cy - = ry ;
//init painter to paint to svg
//init painter to paint to svg
QPainter painter ;
QPainter painter ;
painter . begin ( generator ) ;
painter . begin ( generator ) ;
//check if ellipse is rotated
if ( mReader . attributes ( ) . hasAttribute ( aTransform ) )
{
QTransform transform = transformFromString ( mReader . attributes ( ) . value ( aTransform ) . toString ( ) ) ;
painter . setTransform ( transform ) ;
//change cx and cy to correspond to transformation
cx - = transform . dx ( ) ;
cy - = transform . dy ( ) ;
}
QPen pen ( strokeColor ) ;
QPen pen ( strokeColor ) ;
pen . setWidth ( strokeWidth ) ;
pen . setWidth ( strokeWidth ) ;
painter . setPen ( pen ) ;
painter . setPen ( pen ) ;
painter . setBrush ( QBrush ( fillColor ) ) ;
painter . setBrush ( QBrush ( fillColor ) ) ;
painter . drawEllipse ( cx , cy , rx * 2 , ry * 2 ) ;
painter . drawEllipse ( 5 , 5 , rx * 2 , ry * 2 ) ;
painter . end ( ) ;
painter . end ( ) ;
//add resulting svg file to scene
//add resulting svg file to scene
mCurrentScene - > addSvg ( QUrl : : fromLocalFile ( generator - > fileName ( ) ) ) ;
UBGraphicsSvgItem * svgItem = mCurrentScene - > addSvg ( QUrl : : fromLocalFile ( generator - > fileName ( ) ) ) ;
QTransform transform ;
bool hasTransform = getCurElementTransorm ( transform ) ;
repositionSvgItem ( svgItem , rx * 2 + 10 , ry * 2 + 10 , cx - rx - 5 , cy - ry - 5 , hasTransform , transform ) ;
delete generator ;
delete generator ;
return true ;
return true ;
}
}
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : parseTextArea ( )
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : parseTextArea ( )
{
{
@ -431,6 +486,254 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseTextArea()
if ( currentState = = SVG & & mCurrentScene = = NULL )
if ( currentState = = SVG & & mCurrentScene = = NULL )
createNewScene ( ) ;
createNewScene ( ) ;
//TODO textarea node
qreal x = mReader . attributes ( ) . value ( aX ) . toString ( ) . toDouble ( ) ;
qreal y = mReader . attributes ( ) . value ( aY ) . toString ( ) . toDouble ( ) ;
qreal width = mReader . attributes ( ) . value ( aWidth ) . toString ( ) . toDouble ( ) ;
qreal height = mReader . attributes ( ) . value ( aHeight ) . toString ( ) . toDouble ( ) ;
qWarning ( ) < < QString ( ) . sprintf ( " Text coordinates : %f,%f. Text size %f,%f " , x , y , width , height ) ;
qreal fontSize = 12.0 ;
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 ;
bool hasTransform = getCurElementTransorm ( transform ) ;
QRectF lastDrawnTextBoundingRect ;
//parse text area tags
while ( true )
{
mReader . readNext ( ) ;
QStringRef elementName = mReader . name ( ) ;
if ( mReader . isEndDocument ( ) )
break ;
if ( mReader . isEndElement ( ) & & elementName = = tBreak )
{
//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 ) ;
continue ;
}
if ( mReader . isEndElement ( ) & & elementName = = tTextarea )
break ;
if ( mReader . isStartElement ( ) & & elementName = = tTspan )
{
parseTextAttributes ( fontSize , fontColor , fontFamily , fontStretch , italic , fontWeight , textAlign , fontTransform ) ;
painter . setFont ( QFont ( fontFamily , fontSize , fontWeight , italic ) ) ;
painter . setPen ( fontColor ) ;
linespacing = QFontMetricsF ( painter . font ( ) ) . leading ( ) ;
continue ;
}
if ( mReader . isCharacters ( ) | | mReader . isCDATA ( ) )
{
QString text = mReader . text ( ) . toString ( ) . trimmed ( ) ;
//skip empty text
if ( text . length ( ) = = 0 )
continue ;
//get bounding rect to obtain desired text height
lastDrawnTextBoundingRect = painter . boundingRect ( QRectF ( curX , curY , width , height - curY ) , textAlign | Qt : : TextWordWrap , 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 ;
painter . drawText ( curX , curY , width , lastDrawnTextBoundingRect . height ( ) , textAlign | Qt : : TextWordWrap , text ) ;
curX + = lastDrawnTextBoundingRect . x ( ) + lastDrawnTextBoundingRect . width ( ) ;
continue ;
}
}
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 : : parseText ( )
{
if ( currentState ! = SVG & & currentState ! = PAGE )
{
qWarning ( ) < < " iwb content parse error, unexpected textarea tag at line " < < mReader . lineNumber ( ) ;
return false ;
}
//create new scene if it's not created yet (for one page document case)
if ( currentState = = SVG & & mCurrentScene = = NULL )
createNewScene ( ) ;
qreal x = mReader . attributes ( ) . value ( aX ) . toString ( ) . toDouble ( ) ;
qreal y = mReader . attributes ( ) . value ( aY ) . toString ( ) . 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 ( 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 ;
return true ;
}
}
@ -459,6 +762,8 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parsePage()
createNewScene ( ) ;
createNewScene ( ) ;
qWarning ( ) < < " Added page number " < < mProxy - > pageCount ( ) ;
return true ;
return true ;
}
}
@ -487,6 +792,7 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseIwbElementRef()
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : createNewScene ( )
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : createNewScene ( )
{
{
mCurrentScene = UBPersistenceManager : : persistenceManager ( ) - > createDocumentSceneAt ( mProxy , mProxy - > pageCount ( ) ) ;
mCurrentScene = UBPersistenceManager : : persistenceManager ( ) - > createDocumentSceneAt ( mProxy , mProxy - > pageCount ( ) ) ;
mCurrentSceneRect = mCurrentScene - > normalizedSceneRect ( ) ;
return true ;
return true ;
}
}
@ -530,10 +836,21 @@ QColor UBCFFSubsetAdaptor::UBCFFSubsetReader::colorFromString(const QString& clr
return QColor ( clrString ) ;
return QColor ( clrString ) ;
}
}
bool UBCFFSubsetAdaptor : : UBCFFSubsetReader : : getCurElementTransorm ( QTransform & transform )
{
if ( mReader . attributes ( ) . hasAttribute ( aTransform ) )
{
transform = transformFromString ( mReader . attributes ( ) . value ( aTransform ) . toString ( ) ) ;
return true ;
}
else
return false ;
}
QTransform UBCFFSubsetAdaptor : : UBCFFSubsetReader : : transformFromString ( const QString trString )
QTransform UBCFFSubsetAdaptor : : UBCFFSubsetReader : : transformFromString ( const QString trString )
{
{
//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 ) )
{
{
if ( regexp . capturedTexts ( ) . count ( ) = = 2 & & regexp . capturedTexts ( ) . at ( 0 ) . length ( ) = = trString . length ( ) )
if ( regexp . capturedTexts ( ) . count ( ) = = 2 & & regexp . capturedTexts ( ) . at ( 0 ) . length ( ) = = trString . length ( ) )
@ -544,7 +861,7 @@ QTransform UBCFFSubsetAdaptor::UBCFFSubsetReader::transformFromString(const QStr
}
}
//check pattern for strings like 'rotate(10,20,20)' or 'rotate(10.1,10.2,34.2)'
//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]*) \\ ) " ) ;
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 ) )
{
{
if ( regexp . capturedTexts ( ) . count ( ) = = 4 & & regexp . capturedTexts ( ) . at ( 0 ) . length ( ) = = trString . length ( ) )
if ( regexp . capturedTexts ( ) . count ( ) = = 4 & & regexp . capturedTexts ( ) . at ( 0 ) . length ( ) = = trString . length ( ) )
@ -569,20 +886,26 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getViewBoxDimenstions(const QString&
if ( capturesCount = = 5 & & regexp . capturedTexts ( ) . at ( 0 ) . length ( ) = = viewBox . length ( ) )
if ( capturesCount = = 5 & & regexp . capturedTexts ( ) . at ( 0 ) . length ( ) = = viewBox . length ( ) )
{
{
mViewBox = QRectF ( 0 , 0 , regexp . capturedTexts ( ) . at ( 3 ) . toDouble ( ) , regexp . capturedTexts ( ) . at ( 4 ) . toDouble ( ) ) ;
mViewBox = QRectF ( 0 , 0 , regexp . capturedTexts ( ) . at ( 3 ) . toDouble ( ) , regexp . capturedTexts ( ) . at ( 4 ) . toDouble ( ) ) ;
mViewBoxCenter . setX ( mViewBox . width ( ) / 2 ) ;
mViewBoxCenter . setY ( mViewBox . height ( ) / 2 ) ;
return true ;
return true ;
}
}
}
}
mViewBox = QRectF ( 0 , 0 , 1000 , 1000 ) ;
mViewBox = QRectF ( 0 , 0 , 1000 , 1000 ) ;
mViewBoxCenter = QPointF ( 500 , 500 ) ;
return false ;
return false ;
}
}
QSvgGenerator * UBCFFSubsetAdaptor : : UBCFFSubsetReader : : createSvgGenerator ( )
QSvgGenerator * UBCFFSubsetAdaptor : : UBCFFSubsetReader : : createSvgGenerator ( qreal width , qreal height )
{
{
QSvgGenerator * generator = new QSvgGenerator ( ) ;
QSvgGenerator * generator = new QSvgGenerator ( ) ;
qWarning ( ) < < QString ( " Making generator with file %1, size (%2, %3) and viewbox (%4 %5 %6 %7) " ) . arg ( mTempFilePath )
. arg ( width ) . arg ( height ) . arg ( 0.0 ) . arg ( 0.0 ) . arg ( width ) . arg ( width ) ;
generator - > setResolution ( QApplication : : desktop ( ) - > physicalDpiY ( ) ) ;
generator - > setFileName ( mTempFilePath ) ;
generator - > setFileName ( mTempFilePath ) ;
generator - > setSize ( mSize ) ;
generator - > setSize ( QSize ( width , height ) ) ;
generator - > setViewBox ( mViewBox ) ;
generator - > setViewBox ( QRectF ( 0 , 0 , width , height ) ) ;
return generator ;
return generator ;
}
}
@ -608,3 +931,62 @@ bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getTempFileName()
}
}
}
}
void UBCFFSubsetAdaptor : : UBCFFSubsetReader : : parseTextAttributes ( qreal & fontSize , QColor & fontColor ,
QString & fontFamily , QString & fontStretch , bool & italic ,
int & fontWeight , int & textAlign , QTransform & fontTransform )
{
if ( mReader . attributes ( ) . hasAttribute ( aFontSize ) )
{
//consider inch has 72 liens
//since svg font size is given in pixels, divide it by pixels per line
fontSize = mReader . attributes ( ) . value ( aFontSize ) . toString ( ) . toDouble ( ) * 72 / QApplication : : desktop ( ) - > physicalDpiY ( ) ;
}
if ( mReader . attributes ( ) . hasAttribute ( aFill ) )
fontColor = colorFromString ( mReader . attributes ( ) . value ( aFill ) . toString ( ) ) ;
if ( mReader . attributes ( ) . hasAttribute ( aFontfamily ) )
fontFamily = mReader . attributes ( ) . value ( aFontfamily ) . toString ( ) ;
if ( mReader . attributes ( ) . hasAttribute ( aFontstretch ) )
fontStretch = mReader . attributes ( ) . value ( aFontstretch ) . toString ( ) ;
if ( mReader . attributes ( ) . hasAttribute ( aFontstyle ) )
{
QStringRef fontStyle = mReader . attributes ( ) . value ( aFontstyle ) ;
italic = fontStyle = = " italic " ;
}
if ( mReader . attributes ( ) . hasAttribute ( aFontweight ) )
{
QStringRef weight = mReader . attributes ( ) . value ( aFontweight ) ;
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 ;
if ( weight = = " black " )
fontWeight = QFont : : Black ;
}
if ( mReader . attributes ( ) . hasAttribute ( aTextalign ) )
{
QString align = mReader . attributes ( ) . value ( aTextalign ) . toString ( ) ;
if ( align = = " middle " | | align = = " center " )
textAlign = Qt : : AlignHCenter ;
else
if ( align = = " start " )
textAlign = Qt : : AlignLeft ;
else
if ( align = = " end " )
textAlign = Qt : : AlignRight ;
}
if ( mReader . attributes ( ) . hasAttribute ( aTransform ) )
fontTransform = transformFromString ( mReader . attributes ( ) . value ( aTransform ) . toString ( ) ) ;
}