Skip to content
Permalink
Browse files

Add fixedAspectRatio in QgsSvgCacheEntry and compute image size accor…

…dingly
  • Loading branch information
dmarteau authored and rldhont committed Sep 28, 2017
1 parent f9f5aaf commit 740ccbe9385069c1191a5e7ac3263b3ebea64398
Showing with 74 additions and 32 deletions.
  1. +15 −7 python/core/symbology/qgssvgcache.sip
  2. +46 −18 src/core/symbology/qgssvgcache.cpp
  3. +13 −7 src/core/symbology/qgssvgcache.h
@@ -18,9 +18,11 @@ class QgsSvgCacheEntry
#include "qgssvgcache.h"
%End
public:

QgsSvgCacheEntry();

QgsSvgCacheEntry( const QString &path, double size, double strokeWidth, double widthScaleFactor, const QColor &fill, const QColor &stroke );
QgsSvgCacheEntry( const QString &path, double size, double strokeWidth, double widthScaleFactor, const QColor &fill, const QColor &stroke,
double fixedAspectRatio = 0 ) ;
%Docstring
Constructor.
\param path Absolute path to SVG file (relative paths are not resolved).
@@ -29,6 +31,7 @@ class QgsSvgCacheEntry
\param widthScaleFactor width scale factor
\param fill color of fill
\param stroke color of stroke
\param fixedAspectRatio fixed aspect ratio (optional)
%End
~QgsSvgCacheEntry();

@@ -41,6 +44,11 @@ Absolute path to SVG file
double strokeWidth;
double widthScaleFactor;

double fixedAspectRatio;
%Docstring
Fixed aspect ratio
%End

QSizeF viewboxSize;
%Docstring
SVG viewbox size.
@@ -91,7 +99,7 @@ the parameters 'fill-color', 'pen-color', 'outline-width', 'stroke-width'. E.g.
~QgsSvgCache();

QImage svgAsImage( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor, bool &fitsInCache );
double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio = 0 );
%Docstring
Get SVG as QImage.
\param path Absolute path to SVG file.
@@ -105,7 +113,7 @@ the parameters 'fill-color', 'pen-color', 'outline-width', 'stroke-width'. E.g.
%End

QPicture svgAsPicture( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor, bool forceVectorOutput = false );
double widthScaleFactor, bool forceVectorOutput = false, double fixedAspectRatio = 0 );
%Docstring
Get SVG as QPicture&.
\param path Absolute path to SVG file.
@@ -119,7 +127,7 @@ the parameters 'fill-color', 'pen-color', 'outline-width', 'stroke-width'. E.g.
%End

QSizeF svgViewboxSize( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor );
double widthScaleFactor, double fixedAspectRatio = 0 );
%Docstring
Calculates the viewbox size of a (possibly cached) SVG file.
\param path Absolute path to SVG file.
@@ -177,7 +185,7 @@ Get image data
%End

QByteArray svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor );
double widthScaleFactor, double fixedAspectRatio = 0);
%Docstring
Get SVG content
:rtype: QByteArray
@@ -192,7 +200,7 @@ Emit a signal to be caught by qgisapp and display a msg on status bar
protected:

QgsSvgCacheEntry *insertSvg( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor );
double widthScaleFactor, double fixedAspectRatio = 0 );
%Docstring
Creates new cache entry and returns pointer to it
\param path Absolute path to SVG file
@@ -208,7 +216,7 @@ Emit a signal to be caught by qgisapp and display a msg on status bar
void cacheImage( QgsSvgCacheEntry *entry );
void cachePicture( QgsSvgCacheEntry *entry, bool forceVectorOutput = false );
QgsSvgCacheEntry *cacheEntry( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor );
double widthScaleFactor, double fixedAspectRatio = 0 );
%Docstring
Returns entry from cache or creates a new entry if it does not exist already
:rtype: QgsSvgCacheEntry
@@ -43,11 +43,12 @@ QgsSvgCacheEntry::QgsSvgCacheEntry()
{
}

QgsSvgCacheEntry::QgsSvgCacheEntry( const QString &p, double s, double ow, double wsf, const QColor &fi, const QColor &ou )
QgsSvgCacheEntry::QgsSvgCacheEntry( const QString &p, double s, double ow, double wsf, const QColor &fi, const QColor &ou, double far )
: path( p )
, size( s )
, strokeWidth( ow )
, widthScaleFactor( wsf )
, fixedAspectRatio( far )
, fill( fi )
, stroke( ou )
{
@@ -93,12 +94,12 @@ QgsSvgCache::~QgsSvgCache()


QImage QgsSvgCache::svgAsImage( const QString &file, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor, bool &fitsInCache )
double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio )
{
QMutexLocker locker( &mMutex );

fitsInCache = true;
QgsSvgCacheEntry *currentEntry = cacheEntry( file, size, fill, stroke, strokeWidth, widthScaleFactor );
QgsSvgCacheEntry *currentEntry = cacheEntry( file, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );

//if current entry image is 0: cache image for entry
// checks to see if image will fit into cache
@@ -109,7 +110,14 @@ QImage QgsSvgCache::svgAsImage( const QString &file, double size, const QColor &
double hwRatio = 1.0;
if ( r.viewBoxF().width() > 0 )
{
hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
if( currentEntry->fixedAspectRatio > 0 )
{
hwRatio = currentEntry->fixedAspectRatio;
}
else
{
hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
}
}
long cachedDataSize = 0;
cachedDataSize += currentEntry->svgContent.size();
@@ -138,11 +146,11 @@ QImage QgsSvgCache::svgAsImage( const QString &file, double size, const QColor &
}

QPicture QgsSvgCache::svgAsPicture( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor, bool forceVectorOutput )
double widthScaleFactor, bool forceVectorOutput, double fixedAspectRatio )
{
QMutexLocker locker( &mMutex );

QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor );
QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );

//if current entry picture is 0: cache picture for entry
//update stats for memory usage
@@ -156,28 +164,28 @@ QPicture QgsSvgCache::svgAsPicture( const QString &path, double size, const QCol
}

QByteArray QgsSvgCache::svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor )
double widthScaleFactor, double fixedAspectRatio )
{
QMutexLocker locker( &mMutex );

QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor );
QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );

return currentEntry->svgContent;
}

QSizeF QgsSvgCache::svgViewboxSize( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor )
QSizeF QgsSvgCache::svgViewboxSize( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio )
{
QMutexLocker locker( &mMutex );

QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor );
QgsSvgCacheEntry *currentEntry = cacheEntry( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );

return currentEntry->viewboxSize;
}

QgsSvgCacheEntry *QgsSvgCache::insertSvg( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor )
double widthScaleFactor, double fixedAspectRatio )
{
QgsSvgCacheEntry *entry = new QgsSvgCacheEntry( path, size, strokeWidth, widthScaleFactor, fill, stroke );
QgsSvgCacheEntry *entry = new QgsSvgCacheEntry( path, size, strokeWidth, widthScaleFactor, fill, stroke, fixedAspectRatio );

replaceParamsAndCacheSvg( entry );

@@ -471,11 +479,20 @@ void QgsSvgCache::cacheImage( QgsSvgCacheEntry *entry )
delete entry->image;
entry->image = nullptr;

bool isFixedAR = entry->fixedAspectRatio > 0;

QSvgRenderer r( entry->svgContent );
double hwRatio = 1.0;
if ( r.viewBoxF().width() > 0 )
{
hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
if( isFixedAR )
{
hwRatio = entry->fixedAspectRatio;
}
else
{
hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
}
}
double wSize = entry->size;
int wImgSize = static_cast< int >( wSize );
@@ -521,20 +538,30 @@ void QgsSvgCache::cachePicture( QgsSvgCacheEntry *entry, bool forceVectorOutput
delete entry->picture;
entry->picture = nullptr;

bool isFixedAR = entry->fixedAspectRatio > 0;

//correct QPictures dpi correction
QPicture *picture = new QPicture();
QRectF rect;
QSvgRenderer r( entry->svgContent );
double hwRatio = 1.0;
if ( r.viewBoxF().width() > 0 )
{
hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
if( isFixedAR )
{
hwRatio = entry->fixedAspectRatio;
}
else
{
hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
}
}

double wSize = entry->size;
double hSize = wSize * hwRatio;

QSizeF s( r.viewBoxF().size() );
s.scale( wSize, hSize, Qt::KeepAspectRatio );
s.scale( wSize, hSize, isFixedAR ? Qt::IgnoreAspectRatio : Qt::KeepAspectRatio );
rect = QRectF( -s.width() / 2.0, -s.height() / 2.0, s.width(), s.height() );

QPainter p( picture );
@@ -544,7 +571,7 @@ void QgsSvgCache::cachePicture( QgsSvgCacheEntry *entry, bool forceVectorOutput
}

QgsSvgCacheEntry *QgsSvgCache::cacheEntry( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor )
double widthScaleFactor, double fixedAspectRatio )
{
//search entries in mEntryLookup
QgsSvgCacheEntry *currentEntry = nullptr;
@@ -555,7 +582,8 @@ QgsSvgCacheEntry *QgsSvgCache::cacheEntry( const QString &path, double size, con
{
QgsSvgCacheEntry *cacheEntry = *entryIt;
if ( qgsDoubleNear( cacheEntry->size, size ) && cacheEntry->fill == fill && cacheEntry->stroke == stroke &&
qgsDoubleNear( cacheEntry->strokeWidth, strokeWidth ) && qgsDoubleNear( cacheEntry->widthScaleFactor, widthScaleFactor ) )
qgsDoubleNear( cacheEntry->strokeWidth, strokeWidth ) && qgsDoubleNear( cacheEntry->widthScaleFactor, widthScaleFactor ) &&
qgsDoubleNear( cacheEntry->fixedAspectRatio, fixedAspectRatio ))
{
currentEntry = cacheEntry;
break;
@@ -566,7 +594,7 @@ QgsSvgCacheEntry *QgsSvgCache::cacheEntry( const QString &path, double size, con
//cache and replace params in svg content
if ( !currentEntry )
{
currentEntry = insertSvg( path, size, fill, stroke, strokeWidth, widthScaleFactor );
currentEntry = insertSvg( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio);
}
else
{
@@ -40,6 +40,7 @@ class QPicture;
class CORE_EXPORT QgsSvgCacheEntry
{
public:

QgsSvgCacheEntry();

/** Constructor.
@@ -49,8 +50,10 @@ class CORE_EXPORT QgsSvgCacheEntry
* \param widthScaleFactor width scale factor
* \param fill color of fill
* \param stroke color of stroke
* \param fixedAspectRatio fixed aspect ratio (optional)
*/
QgsSvgCacheEntry( const QString &path, double size, double strokeWidth, double widthScaleFactor, const QColor &fill, const QColor &stroke );
QgsSvgCacheEntry( const QString &path, double size, double strokeWidth, double widthScaleFactor, const QColor &fill, const QColor &stroke,
double fixedAspectRatio = 0 ) ;
~QgsSvgCacheEntry();

//! QgsSvgCacheEntry cannot be copied.
@@ -64,6 +67,9 @@ class CORE_EXPORT QgsSvgCacheEntry
double strokeWidth = 0;
double widthScaleFactor = 1.0;

//! Fixed aspect ratio
double fixedAspectRatio = 0;

/** SVG viewbox size.
* \since QGIS 2.14
*/
@@ -123,7 +129,7 @@ class CORE_EXPORT QgsSvgCache : public QObject
* \param fitsInCache
*/
QImage svgAsImage( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor, bool &fitsInCache );
double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio = 0 );

/** Get SVG as QPicture&.
* \param path Absolute path to SVG file.
@@ -135,7 +141,7 @@ class CORE_EXPORT QgsSvgCache : public QObject
* \param forceVectorOutput
*/
QPicture svgAsPicture( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor, bool forceVectorOutput = false );
double widthScaleFactor, bool forceVectorOutput = false, double fixedAspectRatio = 0 );

/** Calculates the viewbox size of a (possibly cached) SVG file.
* \param path Absolute path to SVG file.
@@ -148,7 +154,7 @@ class CORE_EXPORT QgsSvgCache : public QObject
* \since QGIS 2.14
*/
QSizeF svgViewboxSize( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor );
double widthScaleFactor, double fixedAspectRatio = 0 );

/** Tests if an svg file contains parameters for fill, stroke color, stroke width. If yes, possible default values are returned. If there are several
default values in the svg file, only the first one is considered*/
@@ -187,7 +193,7 @@ class CORE_EXPORT QgsSvgCache : public QObject

//! Get SVG content
QByteArray svgContent( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor );
double widthScaleFactor, double fixedAspectRatio = 0);

signals:
//! Emit a signal to be caught by qgisapp and display a msg on status bar
@@ -204,14 +210,14 @@ class CORE_EXPORT QgsSvgCache : public QObject
* \param widthScaleFactor width scale factor
*/
QgsSvgCacheEntry *insertSvg( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor );
double widthScaleFactor, double fixedAspectRatio = 0 );

void replaceParamsAndCacheSvg( QgsSvgCacheEntry *entry );
void cacheImage( QgsSvgCacheEntry *entry );
void cachePicture( QgsSvgCacheEntry *entry, bool forceVectorOutput = false );
//! Returns entry from cache or creates a new entry if it does not exist already
QgsSvgCacheEntry *cacheEntry( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor );
double widthScaleFactor, double fixedAspectRatio = 0 );

//! Removes the least used items until the maximum size is under the limit
void trimToMaximumSize();

0 comments on commit 740ccbe

Please sign in to comment.
You can’t perform that action at this time.