Skip to content

Commit

Permalink
Print svg item in qgis server. Developed for Faunalia (http://www.fau…
Browse files Browse the repository at this point in the history
…nalia.it) with funding from Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
  • Loading branch information
mhugent committed Nov 6, 2012
1 parent cca386f commit 716d619
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 25 deletions.
116 changes: 93 additions & 23 deletions src/mapserver/qgsprojectparser.cpp
Expand Up @@ -38,6 +38,7 @@
#include "qgscomposershape.h"

#include "QFileInfo"
#include <QSvgRenderer>
#include <QTextDocument>
#include "QTextStream"

Expand Down Expand Up @@ -75,6 +76,7 @@ QgsProjectParser::QgsProjectParser( QDomDocument* xmlDoc, const QString& filePat

mRestrictedLayers = restrictedLayers();
createTextAnnotationItems();
createSvgAnnotationItems();
}
}

Expand All @@ -86,6 +88,7 @@ QgsProjectParser::~QgsProjectParser()
{
delete mXMLDoc;
cleanupTextAnnotationItems();
cleanupSvgAnnotationItems();
}

int QgsProjectParser::numberOfLayers() const
Expand Down Expand Up @@ -2451,16 +2454,60 @@ void QgsProjectParser::drawOverlays( QPainter* p, int dpi, int width, int height

//calculate item position
double xPos, yPos;
if ( !annotationPosition( annotationElem, scaleFactor, prjExtent, width, height, itemWidth, itemHeight, xPos, yPos ) )
if ( !annotationPosition( annotationElem, scaleFactor, xPos, yPos ) )
{
continue;
}

drawAnnotationRectangle( p, annotationElem, scaleFactor, xPos, yPos, itemWidth, itemHeight );

//draw annotation contents
p->translate( xPos / scaleFactor, yPos / scaleFactor );
textIt->first->drawContents( p, QRectF( 0, 0, itemWidth, itemHeight ) );
p->translate( xPos, yPos );
p->scale( scaleFactor, scaleFactor );
textIt->first->drawContents( p, QRectF( 0, 0, itemWidth / scaleFactor, itemHeight / scaleFactor ) );
p->restore();
}

//svg annotations
QList< QPair< QSvgRenderer*, QDomElement > >::const_iterator svgIt = mSvgAnnotationElems.constBegin();
QDomElement annotationElem;
for ( ; svgIt != mSvgAnnotationElems.constEnd(); ++svgIt )
{
annotationElem = svgIt->second;
int itemWidth = annotationElem.attribute( "frameWidth", "0" ).toInt() * scaleFactor;
int itemHeight = annotationElem.attribute( "frameHeight", "0" ).toInt() * scaleFactor;

//calculate item position
double xPos, yPos;
if ( !annotationPosition( annotationElem, scaleFactor, xPos, yPos ) )
{
continue;
}

drawAnnotationRectangle( p, annotationElem, scaleFactor, xPos, yPos, itemWidth, itemHeight );

//keep width/height ratio of svg
QRect viewBox = svgIt->first->viewBox();
if ( viewBox.isValid() )
{
double widthRatio = ( double )( itemWidth ) / ( double )( viewBox.width() );
double heightRatio = ( double )( itemHeight ) / ( double )( viewBox.height() );
double renderWidth = 0;
double renderHeight = 0;
if ( widthRatio <= heightRatio )
{
renderWidth = itemWidth;
renderHeight = viewBox.height() * itemWidth / viewBox.width() ;
}
else
{
renderHeight = itemHeight;
renderWidth = viewBox.width() * itemHeight / viewBox.height() ;
}

svgIt->first->render( p, QRectF( xPos, yPos, renderWidth,
renderHeight ) );
}
}
}

Expand Down Expand Up @@ -2491,6 +2538,44 @@ void QgsProjectParser::createTextAnnotationItems()
}
}

void QgsProjectParser::createSvgAnnotationItems()
{
mSvgAnnotationElems.clear();
if ( !mXMLDoc )
{
return;
}

QDomElement qgisElem = mXMLDoc->documentElement();
QDomNodeList svgAnnotationList = qgisElem.elementsByTagName( "SVGAnnotationItem" );
QDomElement svgAnnotationElem;
QDomElement annotationElem;
for ( int i = 0; i < svgAnnotationList.size(); ++i )
{
svgAnnotationElem = svgAnnotationList.at( i ).toElement();
annotationElem = svgAnnotationElem.firstChildElement( "AnnotationItem" );
QSvgRenderer* svg = new QSvgRenderer();
if ( svg->load( convertToAbsolutePath( svgAnnotationElem.attribute( "file" ) ) ) )
{
mSvgAnnotationElems.push_back( qMakePair( svg, annotationElem ) );
}
else
{
delete svg;
}
}
}

void QgsProjectParser::cleanupSvgAnnotationItems()
{
QList< QPair< QSvgRenderer*, QDomElement > >::const_iterator it = mSvgAnnotationElems.constBegin();
for ( ; it != mSvgAnnotationElems.constEnd(); ++it )
{
delete it->first;
}
mSvgAnnotationElems.clear();
}

void QgsProjectParser::cleanupTextAnnotationItems()
{
QList< QPair< QTextDocument*, QDomElement > >::const_iterator it = mTextAnnotationItems.constBegin();
Expand All @@ -2501,23 +2586,11 @@ void QgsProjectParser::cleanupTextAnnotationItems()
mTextAnnotationItems.clear();
}

bool QgsProjectParser::annotationPosition( const QDomElement& elem, double scaleFactor, const QgsRectangle& projectExtent, int width, int height,
int itemWidth, int itemHeight, double& xPos, double& yPos )
bool QgsProjectParser::annotationPosition( const QDomElement& elem, double scaleFactor,
double& xPos, double& yPos )
{
if ( projectExtent.isEmpty() )
{
return false;
}

double itemMapPosX = elem.attribute( "mapPosX" ).toDouble();
double itemCanvasPosX = elem.attribute( "canvasPosX" ).toDouble();
int maxCanvasX = itemCanvasPosX / ( itemMapPosX - projectExtent.xMinimum() ) * projectExtent.width();
xPos = width - ( maxCanvasX - itemCanvasPosX ) * scaleFactor - itemWidth / 2.0 + 100;

double itemMapPosY = elem.attribute( "mapPosY" ).toDouble();
double itemCanvasPosY = elem.attribute( "canvasPosY" ).toDouble();
int maxCanvasY = itemCanvasPosY / ( projectExtent.yMaximum() - itemMapPosY ) * projectExtent.height();
yPos = height - ( maxCanvasY - itemCanvasPosY ) * scaleFactor - itemHeight + 100;
xPos = elem.attribute( "canvasPosX" ).toDouble() / scaleFactor;
yPos = elem.attribute( "canvasPosY" ).toDouble() / scaleFactor;
return true;
}

Expand All @@ -2535,8 +2608,5 @@ void QgsProjectParser::drawAnnotationRectangle( QPainter* p, const QDomElement&
framePen.setWidth( elem.attribute( "frameBorderWidth", "1" ).toInt() );
p->setPen( framePen );

p->save();
p->scale( scaleFactor, scaleFactor );
p->drawRect( QRectF( xPos / scaleFactor, yPos / scaleFactor, itemWidth, itemHeight ) );
p->restore();
p->drawRect( QRectF( xPos, yPos, itemWidth, itemHeight ) );
}
10 changes: 8 additions & 2 deletions src/mapserver/qgsprojectparser.h
Expand Up @@ -23,6 +23,7 @@
#include <QList>
#include <QPair>

class QSvgRenderer;
class QTextDocument;

//Information about relationship between groups and layers
Expand Down Expand Up @@ -151,6 +152,8 @@ class QgsProjectParser: public QgsConfigParser
QSet<QString> mRestrictedLayers;
/**Watermark text items*/
QList< QPair< QTextDocument*, QDomElement > > mTextAnnotationItems;
/**Watermark items (content cached in QgsSVGCache)*/
QList< QPair< QSvgRenderer*, QDomElement > > mSvgAnnotationElems;

/**Creates a maplayer object from <maplayer> element. The layer cash owns the maplayer, so don't delete it
@return the maplayer or 0 in case of error*/
Expand Down Expand Up @@ -217,16 +220,19 @@ class QgsProjectParser: public QgsConfigParser
QgsRectangle projectExtent() const;

void createTextAnnotationItems();
void createSvgAnnotationItems();

void cleanupSvgAnnotationItems();
void cleanupTextAnnotationItems();

/**Calculates annotation position to provide the same distance to the lower right corner as in the QGIS project file
@param width output image pixel width
@param height output image pixel height
@param itemWidth item width in pixels in the QGIS project (screen pixels)
@param itemHeight item height in pixels in the QGIS project (screen pixels)
@param xPos out: x-coordinate of the item in the output image
@param yPos out: y-coordinate of the item in the output image*/
static bool annotationPosition( const QDomElement& elem, double scaleFactor, const QgsRectangle& projectExtent, int width, int height,
int itemWidth, int itemHeight, double& xPos, double& yPos );
static bool annotationPosition( const QDomElement& elem, double scaleFactor, double& xPos, double& yPos );

/**Draws background rectangle and frame for an annotation
@param elem <Annotation> xml element
Expand Down

0 comments on commit 716d619

Please sign in to comment.