Skip to content
Permalink
Browse files

Configure and use fixedAspectRatio in QgsSvgSymbolLayerWidget and Qgs…

…SvgSymbolLayer
  • Loading branch information
rldhont committed Sep 28, 2017
1 parent 740ccbe commit 60cf7bdaf7bcda842583b63707ecb38e4e8f8599
@@ -526,6 +526,20 @@ Constructs SVG marker symbol layer with picture from given absolute path to a SV
%End
void setPath( const QString &path );

double defaultAspectRatio() const;
%Docstring
:rtype: float
%End
double updateDefaultAspectRatio();
%Docstring
:rtype: float
%End
double fixedAspectRatio() const;
%Docstring
:rtype: float
%End
void setFixedAspectRatio( double far );

virtual QColor fillColor() const;
virtual void setFillColor( const QColor &color );

@@ -576,6 +590,19 @@ Constructs SVG marker symbol layer with picture from given absolute path to a SV

protected:

double calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const;
%Docstring
Calculates the marker aspect ratio between width and height.
\param context symbol render context
\param scaledSize size of symbol to render
\param hasDataDefinedAspectRatio will be set to true if marker has data defined aspectRatio
.. note::

not available in Python bindings
:rtype: float
%End



};

@@ -185,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 fixedAspectRatio = 0);
double widthScaleFactor, double fixedAspectRatio = 0 );
%Docstring
Get SVG content
:rtype: QByteArray
@@ -92,6 +92,7 @@ class QgsSymbolLayer
PropertyCharacter,
PropertyWidth,
PropertyHeight,
PropertyPreserveAspectRatio,
PropertyFillStyle,
PropertyJoinStyle,
PropertySecondaryColor,
@@ -364,7 +364,9 @@ class QgsSvgMarkerSymbolLayerWidget : QgsSymbolLayerWidget
public slots:
void setName( const QModelIndex &idx );
void populateIcons( const QModelIndex &idx );
void setSize();
void setWidth();
void setHeight();
void stateChangedAspectRatio();
void setAngle();
void setOffset();
void on_mFileToolButton_clicked();
@@ -1700,6 +1700,7 @@ QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer( const QString &path, double si
mStrokeWidthUnit = QgsUnitTypes::RenderMillimeters;
mColor = QColor( Qt::black );
mStrokeColor = QColor( Qt::black );
updateDefaultAspectRatio();
}


@@ -1766,6 +1767,8 @@ QgsSymbolLayer *QgsSvgMarkerSymbolLayer::create( const QgsStringMap &props )
m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
if ( props.contains( QStringLiteral( "fixedAspectRatio" ) ) )
m->setFixedAspectRatio( props[QStringLiteral( "fixedAspectRatio" )].toDouble() );
if ( props.contains( QStringLiteral( "offset" ) ) )
m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
if ( props.contains( QStringLiteral( "offset_unit" ) ) )
@@ -1831,6 +1834,8 @@ QgsSymbolLayer *QgsSvgMarkerSymbolLayer::create( const QgsStringMap &props )

m->restoreOldDataDefinedProperties( props );

m->updateDefaultAspectRatio();

return m;
}

@@ -1888,6 +1893,37 @@ void QgsSvgMarkerSymbolLayer::setPath( const QString &path )
c.setAlphaF( strokeOpacity );
setStrokeColor( c );
}

updateDefaultAspectRatio();
}

double QgsSvgMarkerSymbolLayer::updateDefaultAspectRatio()
{
if ( mDefaultAspectRatio == 0.0 )
{
//size
double size = mSize;
//assume 88 dpi as standard value
double widthScaleFactor = 3.465;
QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( mPath, size, mColor, mStrokeColor, mStrokeWidth, widthScaleFactor );
// set default aspect ratio
mDefaultAspectRatio = svgViewbox.isValid() ? svgViewbox.height() / svgViewbox.width() : 0.0;
}
return mDefaultAspectRatio;
}

bool QgsSvgMarkerSymbolLayer::setPreservedAspectRatio( bool par )
{
bool aPreservedAspectRatio = preservedAspectRatio();
if ( aPreservedAspectRatio && !par )
{
mFixedAspectRatio = mDefaultAspectRatio;
}
else if ( !aPreservedAspectRatio && par )
{
mFixedAspectRatio = 0.0;
}
return preservedAspectRatio();
}


@@ -1925,6 +1961,9 @@ void QgsSvgMarkerSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext

p->save();

bool hasDataDefinedAspectRatio = false;
double aspectRatio = calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );

QPointF outputOffset;
double angle = 0.0;
calculateOffsetAndRotation( context, scaledSize, outputOffset, angle );
@@ -1971,7 +2010,7 @@ void QgsSvgMarkerSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext
{
usePict = false;
const QImage &img = QgsApplication::svgCache()->svgAsImage( path, size, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor(), fitsInCache );
context.renderContext().scaleFactor(), fitsInCache, aspectRatio );
if ( fitsInCache && img.width() > 1 )
{
//consider transparency
@@ -1994,7 +2033,7 @@ void QgsSvgMarkerSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext
{
p->setOpacity( context.opacity() );
const QPicture &pct = QgsApplication::svgCache()->svgAsPicture( path, size, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor(), context.renderContext().forceVectorOutput() );
context.renderContext().scaleFactor(), context.renderContext().forceVectorOutput(), aspectRatio );

if ( pct.width() > 1 )
{
@@ -2045,6 +2084,15 @@ double QgsSvgMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context,
context.setOriginalValueVariable( mSize );
scaledSize = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertySize, context.renderContext().expressionContext(), mSize, &ok );
}
else
{
hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyWidth );
if ( hasDataDefinedSize )
{
context.setOriginalValueVariable( mSize );
scaledSize = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyWidth, context.renderContext().expressionContext(), mSize, &ok );
}
}

if ( hasDataDefinedSize && ok )
{
@@ -2061,6 +2109,48 @@ double QgsSvgMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context,
return scaledSize;
}

double QgsSvgMarkerSymbolLayer::calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const
{
hasDataDefinedAspectRatio = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyWidth ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyPreserveAspectRatio ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHeight );
if ( !hasDataDefinedAspectRatio )
return mFixedAspectRatio;

context.setOriginalValueVariable( mFixedAspectRatio <= 0.0 );
if ( mDataDefinedProperties.valueAsBool( QgsSymbolLayer::PropertyPreserveAspectRatio, context.renderContext().expressionContext(), mFixedAspectRatio <= 0.0 ) )
return 0.0;

double scaledAspectRatio = mDefaultAspectRatio;
if ( mFixedAspectRatio > 0.0 )
scaledAspectRatio = mFixedAspectRatio;

double defaultHeight = mSize * scaledAspectRatio;
scaledAspectRatio = defaultHeight / scaledSize;

bool ok = true;
double scaledHeight = scaledSize * scaledAspectRatio;
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHeight ) )
{
context.setOriginalValueVariable( defaultHeight );
scaledHeight = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), defaultHeight, &ok );
}

if ( hasDataDefinedAspectRatio && ok )
{
switch ( mScaleMethod )
{
case QgsSymbol::ScaleArea:
scaledHeight = sqrt( scaledHeight );
break;
case QgsSymbol::ScaleDiameter:
break;
}
}

scaledAspectRatio = scaledHeight / scaledSize;

return scaledAspectRatio;
}

void QgsSvgMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledSize, QPointF &offset, double &angle ) const
{
//offset
@@ -2107,6 +2197,7 @@ QgsStringMap QgsSvgMarkerSymbolLayer::properties() const
map[QStringLiteral( "size" )] = QString::number( mSize );
map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
map[QStringLiteral( "fixedAspectRatio" )] = QString::number( mFixedAspectRatio );
map[QStringLiteral( "angle" )] = QString::number( mAngle );
map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
@@ -2125,6 +2216,7 @@ QgsStringMap QgsSvgMarkerSymbolLayer::properties() const
QgsSvgMarkerSymbolLayer *QgsSvgMarkerSymbolLayer::clone() const
{
QgsSvgMarkerSymbolLayer *m = new QgsSvgMarkerSymbolLayer( mPath, mSize, mAngle );
m->setFixedAspectRatio( mFixedAspectRatio );
m->setColor( mColor );
m->setStrokeColor( mStrokeColor );
m->setStrokeWidth( mStrokeWidth );
@@ -2344,7 +2436,7 @@ bool QgsSvgMarkerSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFa
}

const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, size, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor() );
context.renderContext().scaleFactor(), mFixedAspectRatio );

//if current entry image is 0: cache image for entry
// checks to see if image will fit into cache
@@ -2421,7 +2513,7 @@ QRectF QgsSvgMarkerSymbolLayer::bounds( QPointF point, QgsSymbolRenderContext &c
}

QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( path, scaledSize, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor() );
context.renderContext().scaleFactor(), mFixedAspectRatio );

double scaledHeight = svgViewbox.isValid() ? scaledSize * svgViewbox.height() / svgViewbox.width() : scaledSize;

@@ -481,9 +481,53 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayer : public QgsMarkerSymbolLayer

void writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const override;

/** Returns the marker SVG path.
* \see setPath()
*/
QString path() const { return mPath; }

/** Set the marker SVG path.
* \param path SVG path
* \see path()
*/
void setPath( const QString &path );

/** Returns the default marker aspect ratio between width and height, 0 if not yet calculated.
* \see updateDefaultAspectRatio()
*/
double defaultAspectRatio() const { return mDefaultAspectRatio; }

/** Calculates the default marker aspect ratio between width and height.
* \returns the default aspect ratio value
* \see defaultAspectRatio()
*/
double updateDefaultAspectRatio();

/** Returns the preserved aspect ratio value, true if fixed aspect ratio has been lower or equal to 0.
* \see setPreservedAspectRatio()
*/
bool preservedAspectRatio() const { return mFixedAspectRatio <= 0.0; }

/** Set preserved the marker aspect ratio between width and height.
* \param par Preserved Aspect Ratio
* \returns the preserved aspect ratio value, true if fixed aspect ratio has been lower or equal to 0
* \see preservedAspectRatio()
*/
bool setPreservedAspectRatio( bool par );

/** Returns the marker aspect ratio between width and height to be used in rendering,
* if the value set is lower or equal to 0 the aspect ratio will be preserved in rendering
* \see setFixedAspectRatio() QgsSvgCache
*/
double fixedAspectRatio() const { return mFixedAspectRatio; }

/** Set the marker aspect ratio between width and height to be used in rendering,
* if the value set is lower or equal to 0 the aspect ratio will be preserved in rendering
* \param ratio Fixed Aspect Ratio
* \see fixedAspectRatio() QgsSvgCache
*/
void setFixedAspectRatio( double ratio ) { mFixedAspectRatio = ratio; }

QColor fillColor() const override { return color(); }
void setFillColor( const QColor &color ) override { setColor( color ); }

@@ -518,8 +562,21 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayer : public QgsMarkerSymbolLayer
QRectF bounds( QPointF point, QgsSymbolRenderContext &context ) override;

protected:

/** Calculates the marker aspect ratio between width and height.
* \param context symbol render context
* \param scaledSize size of symbol to render
* \param hasDataDefinedAspectRatio will be set to true if marker has data defined aspectRatio
* \note not available in Python bindings
*/
double calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const;

QString mPath;

//! The marker default aspect ratio
double mDefaultAspectRatio = 0.0;
//! The marker fixed aspect ratio
double mFixedAspectRatio = 0.0;
//param(fill), param(stroke), param(stroke-width) are going
//to be replaced in memory
QColor mStrokeColor;
@@ -110,7 +110,7 @@ QImage QgsSvgCache::svgAsImage( const QString &file, double size, const QColor &
double hwRatio = 1.0;
if ( r.viewBoxF().width() > 0 )
{
if( currentEntry->fixedAspectRatio > 0 )
if ( currentEntry->fixedAspectRatio > 0 )
{
hwRatio = currentEntry->fixedAspectRatio;
}
@@ -485,7 +485,7 @@ void QgsSvgCache::cacheImage( QgsSvgCacheEntry *entry )
double hwRatio = 1.0;
if ( r.viewBoxF().width() > 0 )
{
if( isFixedAR )
if ( isFixedAR )
{
hwRatio = entry->fixedAspectRatio;
}
@@ -547,14 +547,14 @@ void QgsSvgCache::cachePicture( QgsSvgCacheEntry *entry, bool forceVectorOutput
double hwRatio = 1.0;
if ( r.viewBoxF().width() > 0 )
{
if( isFixedAR )
{
hwRatio = entry->fixedAspectRatio;
}
else
{
hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
}
if ( isFixedAR )
{
hwRatio = entry->fixedAspectRatio;
}
else
{
hwRatio = r.viewBoxF().height() / r.viewBoxF().width();
}
}

double wSize = entry->size;
@@ -583,7 +583,7 @@ 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->fixedAspectRatio, fixedAspectRatio ))
qgsDoubleNear( cacheEntry->fixedAspectRatio, fixedAspectRatio ) )
{
currentEntry = cacheEntry;
break;
@@ -594,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, fixedAspectRatio);
currentEntry = insertSvg( path, size, fill, stroke, strokeWidth, widthScaleFactor, fixedAspectRatio );
}
else
{

0 comments on commit 60cf7bd

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