Skip to content

Commit

Permalink
Add caching, experimental test with QPicture for svg marker
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Jun 23, 2011
1 parent 48aa535 commit aa2ad45
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 24 deletions.
7 changes: 6 additions & 1 deletion src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsproject.h"
#include "qgssvgcache.h"

#include <QPainter>
#include <QSvgRenderer>
Expand Down Expand Up @@ -533,9 +534,13 @@ void QgsSvgMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2Re
if ( mAngle != 0 )
p->rotate( mAngle );

QPicture &pct = context.selected() ? mSelPicture : mPicture;
const QPicture& pct = QgsSvgCache::instance()->svgAsPicture( mPath, mSize, QColor( Qt::black )/*const QColor& fill*/, QColor( Qt::black ) /*const QColor& outline*/,
1.0 /*outline width*/, context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor() );
p->drawPicture( 0, 0, pct );

/*QPicture &pct = context.selected() ? mSelPicture : mPicture;
p->drawPicture( 0, 0, pct );*/

p->restore();
}

Expand Down
108 changes: 85 additions & 23 deletions src/core/symbology-ng/qgssvgcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
#include <QDomDocument>
#include <QFile>
#include <QImage>
#include <QPainter>
#include <QPicture>
#include <QSvgRenderer>

QgsSvgCacheEntry::QgsSvgCacheEntry(): file( QString() ), size( 0 ), outlineWidth( 0 ), widthScaleFactor( 1.0 ), rasterScaleFactor( 1.0 ), fill( Qt::black ),
outline( Qt::black ), image( 0 ), picture( 0 )
Expand Down Expand Up @@ -69,41 +71,35 @@ QgsSvgCache::QgsSvgCache()

QgsSvgCache::~QgsSvgCache()
{
QMap< QDateTime, QgsSvgCacheEntry* >::iterator it = mEntries.begin();
for(; it != mEntries.end(); ++it )
{
delete it.value();
}
}


const QImage& QgsSvgCache::svgAsImage( const QString& file, double size, const QColor& fill, const QColor& outline, double outlineWidth,
double widthScaleFactor, double rasterScaleFactor )
{
QgsSvgCacheEntry* currentEntry = this->cacheEntry( file, size, fill, outline, outlineWidth, widthScaleFactor, rasterScaleFactor );

//if current entry image is 0: cache image for entry
//update stats for memory usage
if( !currentEntry->image )
{
cacheImage( currentEntry );
}

//update lastUsed with current date time

return *( currentEntry->image );
}

const QPicture& QgsSvgCache::svgAsPicture( const QString& file, double size, const QColor& fill, const QColor& outline, double outlineWidth,
double widthScaleFactor, double rasterScaleFactor )
{
//search entries in mEntryLookup
QgsSvgCacheEntry* currentEntry = 0;
QList<QgsSvgCacheEntry*> entries = mEntryLookup.values( file );

QList<QgsSvgCacheEntry*>::iterator entryIt = entries.begin();
for(; entryIt != entries.end(); ++entryIt )
{
QgsSvgCacheEntry* cacheEntry = *entryIt;
if( cacheEntry->file == file && cacheEntry->size == size && cacheEntry->fill == fill && cacheEntry->outline == outline &&
cacheEntry->outlineWidth == outlineWidth && cacheEntry->widthScaleFactor == widthScaleFactor && cacheEntry->rasterScaleFactor == rasterScaleFactor)
{
currentEntry = cacheEntry;
break;
}
}


//if not found: create new entry
//cache and replace params in svg content
if( !currentEntry )
{
currentEntry = insertSVG( file, size, fill, outline, outlineWidth, widthScaleFactor, rasterScaleFactor );
}
QgsSvgCacheEntry* currentEntry = this->cacheEntry( file, size, fill, outline, outlineWidth, widthScaleFactor, rasterScaleFactor );

//if current entry image is 0: cache image for entry
//update stats for memory usage
Expand Down Expand Up @@ -156,9 +152,75 @@ void QgsSvgCache::replaceParamsAndCacheSvg( QgsSvgCacheEntry* entry )

void QgsSvgCache::cacheImage( QgsSvgCacheEntry* entry )
{
if( !entry )
{
return;
}

delete entry->image;
entry->image = 0;

double imageSize = entry->size * entry->widthScaleFactor * entry->rasterScaleFactor;
QImage* image = new QImage( imageSize, imageSize, QImage::Format_ARGB32_Premultiplied );
image->fill( 0 ); // transparent background

//rasterise byte array to image
QPainter p( image );
QSvgRenderer r( entry->svgContent );
r.render( &p );

entry->image = image;
}

void QgsSvgCache::cachePicture( QgsSvgCacheEntry *entry )
{
if( !entry )
{
return;
}

delete entry->picture;
entry->picture = 0;

//correct QPictures dpi correction
QPicture* picture = new QPicture();
double dpi = entry->widthScaleFactor * 25.4 * entry->rasterScaleFactor;
double pictureSize = entry->size * entry->widthScaleFactor / dpi * picture->logicalDpiX();
QRectF rect( QPointF( -pictureSize / 2.0, -pictureSize / 2.0 ), QSizeF( pictureSize, pictureSize ) );


QSvgRenderer renderer( entry->svgContent );
QPainter painter( picture );
renderer.render( &painter, rect );
entry->picture = picture;
}

QgsSvgCacheEntry* QgsSvgCache::cacheEntry( const QString& file, double size, const QColor& fill, const QColor& outline, double outlineWidth,
double widthScaleFactor, double rasterScaleFactor )
{
//search entries in mEntryLookup
QgsSvgCacheEntry* currentEntry = 0;
QList<QgsSvgCacheEntry*> entries = mEntryLookup.values( file );

QList<QgsSvgCacheEntry*>::iterator entryIt = entries.begin();
for(; entryIt != entries.end(); ++entryIt )
{
QgsSvgCacheEntry* cacheEntry = *entryIt;
if( cacheEntry->file == file && cacheEntry->size == size && cacheEntry->fill == fill && cacheEntry->outline == outline &&
cacheEntry->outlineWidth == outlineWidth && cacheEntry->widthScaleFactor == widthScaleFactor && cacheEntry->rasterScaleFactor == rasterScaleFactor)
{
currentEntry = cacheEntry;
break;
}
}


//if not found: create new entry
//cache and replace params in svg content
if( !currentEntry )
{
currentEntry = insertSVG( file, size, fill, outline, outlineWidth, widthScaleFactor, rasterScaleFactor );
}
return currentEntry;
}

3 changes: 3 additions & 0 deletions src/core/symbology-ng/qgssvgcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ class QgsSvgCache
void replaceParamsAndCacheSvg( QgsSvgCacheEntry* entry );
void cacheImage( QgsSvgCacheEntry* entry );
void cachePicture( QgsSvgCacheEntry* entry );
/**Returns entry from cache or creates a new entry if it does not exist already*/
QgsSvgCacheEntry* cacheEntry( const QString& file, double size, const QColor& fill, const QColor& outline, double outlineWidth,
double widthScaleFactor, double rasterScaleFactor );

private:
static QgsSvgCache* mInstance;
Expand Down

0 comments on commit aa2ad45

Please sign in to comment.