Skip to content

Commit

Permalink
Merge pull request #5497 from nyalldawson/svg_crash
Browse files Browse the repository at this point in the history
Fix crashes and issues with SVG rendering
  • Loading branch information
nyalldawson committed Oct 31, 2017
2 parents 8b7fd54 + 0b2de85 commit 48d43d3
Show file tree
Hide file tree
Showing 14 changed files with 488 additions and 178 deletions.
3 changes: 3 additions & 0 deletions doc/api_break.dox
Expand Up @@ -319,6 +319,7 @@ should now call QgsCoordinateReferenceSystem::invalidateCache() and QgsCoordinat
- QgsEditorWidgetConfig was removed. Use QVariantMap instead.
- QgsScaleExpression. Use QgsProperty with a QgsSizeScalePropertyTransformer instead.
- QgsSvgAnnotationItem. Use QgsSvgAnnotation instead.
- QgsSvgCacheEntry. This is an internal class and is no longer exposed to public API.
- QgsSymbologyV2Conversion was removed. Reading of renderers from pre-1.0 versions is not supported anymore.
- QgsTextAnnotationItem. Use QgsTextAnnotation instead.
- QgsTransectSample. This class was unused and unmaintained.
Expand Down Expand Up @@ -2317,6 +2318,8 @@ QgsSvgCache {#qgis_api_break_3_0_QgsSvgCache}
- containsParamsV2() was removed. Use containsParamsV3() instead.
- The rasterScaleFactor parameter was removed from all methods
- svgAsImage(), svgAsPicture(), svgViewboxSize(), svgContent(), insertSvg(), cacheEntry() only accept absolute path to SVG file (relative paths will not be resolved).
- The protected member insertSvg() was made private. QgsSvgCache is not intended to be subclassed.


QgsSvgCacheEntry {#qgis_api_break_3_0_QgsSvgCacheEntry}
----------------
Expand Down
96 changes: 0 additions & 96 deletions python/core/symbology/qgssvgcache.sip
Expand Up @@ -11,69 +11,6 @@



class QgsSvgCacheEntry
{

%TypeHeaderCode
#include "qgssvgcache.h"
%End
public:

QgsSvgCacheEntry();

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).
\param size
\param strokeWidth width of stroke
\param widthScaleFactor width scale factor
\param fill color of fill
\param stroke color of stroke
\param fixedAspectRatio fixed aspect ratio (optional)
%End
~QgsSvgCacheEntry();


QString path;
%Docstring
Absolute path to SVG file
%End
double size;
double strokeWidth;
double widthScaleFactor;

double fixedAspectRatio;
%Docstring
Fixed aspect ratio
%End

QSizeF viewboxSize;
%Docstring
SVG viewbox size.
.. versionadded:: 2.14
%End

QColor fill;
QColor stroke;
QImage *image;
QPicture *picture;
QByteArray svgContent;

QgsSvgCacheEntry *nextEntry;
QgsSvgCacheEntry *previousEntry;

bool operator==( const QgsSvgCacheEntry &other ) const;
int dataSize() const;
%Docstring
Return memory usage in bytes
:rtype: int
%End

private:
QgsSvgCacheEntry( const QgsSvgCacheEntry &rh );
};

class QgsSvgCache : QObject
{
Expand Down Expand Up @@ -200,39 +137,6 @@ Get SVG content
Emit a signal to be caught by qgisapp and display a msg on status bar
%End

protected:

QgsSvgCacheEntry *insertSvg( const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth,
double widthScaleFactor, double fixedAspectRatio = 0 );
%Docstring
Creates new cache entry and returns pointer to it
\param path Absolute path to SVG file
\param size size of cached image
\param fill color of fill
\param stroke color of stroke
\param strokeWidth width of stroke
\param widthScaleFactor width scale factor
\param fixedAspectRatio fixed aspect ratio (optional)
:rtype: QgsSvgCacheEntry
%End

void replaceParamsAndCacheSvg( QgsSvgCacheEntry *entry );
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 fixedAspectRatio = 0 );
%Docstring
Returns entry from cache or creates a new entry if it does not exist already
:rtype: QgsSvgCacheEntry
%End

void trimToMaximumSize();
%Docstring
Removes the least used items until the maximum size is under the limit
%End

void takeEntryFromList( QgsSvgCacheEntry *entry );

};

/************************************************************************
Expand Down
2 changes: 1 addition & 1 deletion src/app/composer/qgscomposerpicturewidget.cpp
Expand Up @@ -448,7 +448,7 @@ QIcon QgsComposerPictureWidget::svgToIcon( const QString &filePath ) const
strokeWidth = 0.6;

bool fitsInCache; // should always fit in cache at these sizes (i.e. under 559 px ^ 2, or half cache size)
const QImage &img = QgsApplication::svgCache()->svgAsImage( filePath, 30.0, fill, stroke, strokeWidth, 3.5 /*appr. 88 dpi*/, fitsInCache );
QImage img = QgsApplication::svgCache()->svgAsImage( filePath, 30.0, fill, stroke, strokeWidth, 3.5 /*appr. 88 dpi*/, fitsInCache );

return QIcon( QPixmap::fromImage( img ) );
}
Expand Down
8 changes: 4 additions & 4 deletions src/core/symbology/qgsfillsymbollayer.cpp
Expand Up @@ -1930,12 +1930,12 @@ void QgsSVGFillSymbolLayer::applyPattern( QBrush &brush, const QString &svgFileP
{
bool fitsInCache = true;
double strokeWidth = context.renderContext().convertToPainterUnits( svgStrokeWidth, svgStrokeWidthUnit, svgStrokeWidthMapUnitScale );
const QImage &patternImage = QgsApplication::svgCache()->svgAsImage( svgFilePath, size, svgFillColor, svgStrokeColor, strokeWidth,
context.renderContext().scaleFactor(), fitsInCache );
QImage patternImage = QgsApplication::svgCache()->svgAsImage( svgFilePath, size, svgFillColor, svgStrokeColor, strokeWidth,
context.renderContext().scaleFactor(), fitsInCache );
if ( !fitsInCache )
{
const QPicture &patternPict = QgsApplication::svgCache()->svgAsPicture( svgFilePath, size, svgFillColor, svgStrokeColor, strokeWidth,
context.renderContext().scaleFactor() );
QPicture patternPict = QgsApplication::svgCache()->svgAsPicture( svgFilePath, size, svgFillColor, svgStrokeColor, strokeWidth,
context.renderContext().scaleFactor() );
double hwRatio = 1.0;
if ( patternPict.width() > 0 )
{
Expand Down
9 changes: 4 additions & 5 deletions src/core/symbology/qgsmarkersymbollayer.cpp
Expand Up @@ -2009,8 +2009,8 @@ void QgsSvgMarkerSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext
if ( !context.renderContext().forceVectorOutput() && !rotated )
{
usePict = false;
const QImage &img = QgsApplication::svgCache()->svgAsImage( path, size, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor(), fitsInCache, aspectRatio );
QImage img = QgsApplication::svgCache()->svgAsImage( path, size, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor(), fitsInCache, aspectRatio );
if ( fitsInCache && img.width() > 1 )
{
//consider transparency
Expand All @@ -2032,9 +2032,8 @@ void QgsSvgMarkerSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext
if ( usePict || !fitsInCache )
{
p->setOpacity( context.opacity() );
const QPicture &pct = QgsApplication::svgCache()->svgAsPicture( path, size, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor(), context.renderContext().forceVectorOutput(), aspectRatio );

QPicture pct = QgsApplication::svgCache()->svgAsPicture( path, size, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor(), context.renderContext().forceVectorOutput(), aspectRatio );
if ( pct.width() > 1 )
{
p->save();
Expand Down

0 comments on commit 48d43d3

Please sign in to comment.