Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE] Add option to force a vector layer to render as a raster
(under the layer properties, rendering tab)

So why would you want this? Well, extremely detailed layers (eg
polygon layers with a huge number of nodes) can cause composer
exports in PDF/SVG format to be huge as all nodes are included in
the exported file. This can also make the resultant file very slow
to work with/open in other programs (*cough* Inkscape *cough*).

Now, these you can force these layers to be rasterised so that the
exported files won't have to include all the nodes contained in these
layers. (Before you could also do this by forcing the composer to
export as a raster, but that was an all-or-nothing solution).

The ideal solution would be a simplification option for composer
exports which would simplify the layers by removing redundant points
at the export DPI, but this is an easy workaround for now.
  • Loading branch information
nyalldawson committed Jul 9, 2015
1 parent a9e9f86 commit cfee456
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 20 deletions.
15 changes: 15 additions & 0 deletions python/core/symbology-ng/qgsrendererv2.sip
Expand Up @@ -211,6 +211,21 @@ class QgsFeatureRendererV2
*/
void setPaintEffect( QgsPaintEffect* effect /Transfer/);

/** Returns whether the renderer must render as a raster.
* @note added in QGIS 2.12
* @see setForceRasterRender
*/
bool forceRasterRender() const;

/** Sets whether the renderer should be rendered to a raster destination.
* @param forceRaster set to true if renderer must be drawn on a raster surface.
* This may be desirable for highly detailed layers where rendering as a vector
* would result in a large, complex vector output.
* @see forceRasterRender
* @note added in QGIS 2.12
*/
void setForceRasterRender( bool forceRaster );

protected:
QgsFeatureRendererV2( QString type );

Expand Down
8 changes: 7 additions & 1 deletion src/app/qgsvectorlayerproperties.cpp
Expand Up @@ -49,6 +49,7 @@
#include "qgsvectordataprovider.h"
#include "qgsquerybuilder.h"
#include "qgsdatasourceuri.h"
#include "qgsrendererv2.h"

#include <QMessageBox>
#include <QDir>
Expand Down Expand Up @@ -435,15 +436,17 @@ void QgsVectorLayerProperties::syncToLayer( void )
// disable simplification for point layers, now it is not implemented
if ( layer->geometryType() == QGis::Point )
{
mOptionsStackedWidget->removeWidget( mOptsPage_Rendering );
mSimplifyDrawingGroupBox->setChecked( false );
mSimplifyDrawingGroupBox->setEnabled( false );
}

QStringList myScalesList = PROJECT_SCALES.split( "," );
myScalesList.append( "1:1" );
mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
mSimplifyMaximumScaleComboBox->setScale( 1.0 / simplifyMethod.maximumScale() );

mForceRasterCheckBox->setChecked( layer->rendererV2() && layer->rendererV2()->forceRasterRender() );

// load appropriate symbology page (V1 or V2)
updateSymbologyPage();

Expand Down Expand Up @@ -602,6 +605,9 @@ void QgsVectorLayerProperties::apply()
simplifyMethod.setMaximumScale( 1.0 / mSimplifyMaximumScaleComboBox->scale() );
layer->setSimplifyMethod( simplifyMethod );

if ( layer->rendererV2() )
layer->rendererV2()->setForceRasterRender( mForceRasterCheckBox->isChecked() );

mOldJoins = layer->vectorJoins();

// update symbology
Expand Down
18 changes: 14 additions & 4 deletions src/core/qgsmaprenderercustompainterjob.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgsmaplayerrenderer.h"
#include "qgspallabeling.h"
#include "qgsvectorlayer.h"
#include "qgsrendererv2.h"

QgsMapRendererCustomPainterJob::QgsMapRendererCustomPainterJob( const QgsMapSettings& settings, QPainter* painter )
: QgsMapRendererJob( settings )
Expand Down Expand Up @@ -338,13 +339,22 @@ void QgsMapRendererJob::updateLayerGeometryCaches()

bool QgsMapRendererJob::needTemporaryImage( QgsMapLayer* ml )
{
if ( mSettings.testFlag( QgsMapSettings::UseAdvancedEffects ) && ml->type() == QgsMapLayer::VectorLayer )
if ( ml->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
if ((( vl->blendMode() != QPainter::CompositionMode_SourceOver )
|| ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
|| ( vl->layerTransparency() != 0 ) ) )
if ( vl->rendererV2()->forceRasterRender() )
{
//raster rendering is forced for this layer
return true;
}
if ( mSettings.testFlag( QgsMapSettings::UseAdvancedEffects ) &&
(( vl->blendMode() != QPainter::CompositionMode_SourceOver )
|| ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
|| ( vl->layerTransparency() != 0 ) ) )
{
//layer properties require rasterisation
return true;
}
}

return false;
Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
Expand Up @@ -626,6 +626,7 @@ QDomElement QgsCategorizedSymbolRendererV2::save( QDomDocument& doc )
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
rendererElem.setAttribute( "type", "categorizedSymbol" );
rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) );
rendererElem.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );
rendererElem.setAttribute( "attr", mAttrName );

// categories
Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
Expand Up @@ -1071,6 +1071,7 @@ QDomElement QgsGraduatedSymbolRendererV2::save( QDomDocument& doc )
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
rendererElem.setAttribute( "type", "graduatedSymbol" );
rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) );
rendererElem.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );
rendererElem.setAttribute( "attr", mAttrName );
rendererElem.setAttribute( "graduatedMethod", graduatedMethodStr( mGraduatedMethod ) );

Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgsinvertedpolygonrenderer.cpp
Expand Up @@ -360,6 +360,7 @@ QDomElement QgsInvertedPolygonRenderer::save( QDomDocument& doc )
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
rendererElem.setAttribute( "type", "invertedPolygonRenderer" );
rendererElem.setAttribute( "preprocessing", preprocessingEnabled() ? "1" : "0" );
rendererElem.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );

if ( mSubRenderer )
{
Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgspointdisplacementrenderer.cpp
Expand Up @@ -370,6 +370,7 @@ QgsFeatureRendererV2* QgsPointDisplacementRenderer::create( QDomElement& symbolo
QDomElement QgsPointDisplacementRenderer::save( QDomDocument& doc )
{
QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
rendererElement.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );
rendererElement.setAttribute( "type", "pointDisplacement" );
rendererElement.setAttribute( "labelAttributeName", mLabelAttributeName );
rendererElement.appendChild( QgsFontUtils::toXmlElement( mLabelFont, doc, "labelFontProperties" ) );
Expand Down
3 changes: 3 additions & 0 deletions src/core/symbology-ng/qgsrendererv2.cpp
Expand Up @@ -209,6 +209,7 @@ QgsFeatureRendererV2::QgsFeatureRendererV2( QString type )
, mCurrentVertexMarkerType( QgsVectorLayer::Cross )
, mCurrentVertexMarkerSize( 3 )
, mPaintEffect( 0 )
, mForceRaster( false )
{
mPaintEffect = QgsPaintEffectRegistry::defaultStack();
mPaintEffect->setEnabled( false );
Expand Down Expand Up @@ -423,6 +424,7 @@ QgsFeatureRendererV2* QgsFeatureRendererV2::load( QDomElement& element )
if ( r )
{
r->setUsingSymbolLevels( element.attribute( "symbollevels", "0" ).toInt() );
r->setForceRasterRender( element.attribute( "forceraster", "0" ).toInt() );

//restore layer effect
QDomElement effectElem = element.firstChildElement( "effect" );
Expand All @@ -438,6 +440,7 @@ QDomElement QgsFeatureRendererV2::save( QDomDocument& doc )
{
// create empty renderer element
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
rendererElem.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );

if ( mPaintEffect )
mPaintEffect->saveProperties( doc, rendererElem );
Expand Down
27 changes: 22 additions & 5 deletions src/core/symbology-ng/qgsrendererv2.h
Expand Up @@ -81,7 +81,7 @@ class CORE_EXPORT QgsFeatureRendererV2

QString type() const { return mType; }

/** to be overridden
/** To be overridden
* @param feature feature
* @return returns pointer to symbol or 0 if symbol was not found
*/
Expand Down Expand Up @@ -144,7 +144,7 @@ class CORE_EXPORT QgsFeatureRendererV2
//! @note added in 2.8
virtual QDomElement writeSld( QDomDocument& doc, const QString& styleName ) const;

/** create a new renderer according to the information contained in
/** Create a new renderer according to the information contained in
* the UserStyle element of a SLD style document
* @param node the node in the SLD document whose the UserStyle element
* is a child
Expand Down Expand Up @@ -211,7 +211,7 @@ class CORE_EXPORT QgsFeatureRendererV2
//! @note added in 2.6
virtual QgsSymbolV2List originalSymbolsForFeature( QgsFeature& feat );

/**Allows for a renderer to modify the extent of a feature request prior to rendering
/** Allows for a renderer to modify the extent of a feature request prior to rendering
* @param extent reference to request's filter extent. Modify extent to change the
* extent of feature request
* @param context render context
Expand All @@ -233,6 +233,21 @@ class CORE_EXPORT QgsFeatureRendererV2
*/
void setPaintEffect( QgsPaintEffect* effect );

/** Returns whether the renderer must render as a raster.
* @note added in QGIS 2.12
* @see setForceRasterRender
*/
bool forceRasterRender() const { return mForceRaster; }

/** Sets whether the renderer should be rendered to a raster destination.
* @param forceRaster set to true if renderer must be drawn on a raster surface.
* This may be desirable for highly detailed layers where rendering as a vector
* would result in a large, complex vector output.
* @see forceRasterRender
* @note added in QGIS 2.12
*/
void setForceRasterRender( bool forceRaster ) { mForceRaster = forceRaster; }

protected:
QgsFeatureRendererV2( QString type );

Expand Down Expand Up @@ -272,11 +287,13 @@ class CORE_EXPORT QgsFeatureRendererV2

QgsPaintEffect* mPaintEffect;

/**@note this function is used to convert old sizeScale expresssions to symbol
bool mForceRaster;

/** @note this function is used to convert old sizeScale expresssions to symbol
* level DataDefined size
*/
static void convertSymbolSizeScale( QgsSymbolV2 * symbol, QgsSymbolV2::ScaleMethod method, const QString & field );
/**@note this function is used to convert old rotations expresssions to symbol
/** @note this function is used to convert old rotations expresssions to symbol
* level DataDefined angle
*/
static void convertSymbolRotation( QgsSymbolV2 * symbol, const QString & field );
Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgsrulebasedrendererv2.cpp
Expand Up @@ -885,6 +885,7 @@ QDomElement QgsRuleBasedRendererV2::save( QDomDocument& doc )
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
rendererElem.setAttribute( "type", "RuleRenderer" );
rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) );
rendererElem.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );

QgsSymbolV2Map symbols;

Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgssinglesymbolrendererv2.cpp
Expand Up @@ -344,6 +344,7 @@ QDomElement QgsSingleSymbolRendererV2::save( QDomDocument& doc )
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
rendererElem.setAttribute( "type", "singleSymbol" );
rendererElem.setAttribute( "symbollevels", ( mUsingSymbolLevels ? "1" : "0" ) );
rendererElem.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );

QgsSymbolV2Map symbols;
symbols["0"] = mSymbol.data();
Expand Down
27 changes: 17 additions & 10 deletions src/ui/qgsvectorlayerpropertiesbase.ui
Expand Up @@ -692,8 +692,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>123</width>
<height>38</height>
<width>730</width>
<height>537</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_28">
Expand Down Expand Up @@ -774,8 +774,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
<width>730</width>
<height>537</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_20">
Expand Down Expand Up @@ -834,8 +834,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>721</width>
<height>171</height>
<width>730</width>
<height>537</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_32">
Expand Down Expand Up @@ -940,6 +940,13 @@
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mForceRasterCheckBox">
<property name="text">
<string>Force layer to render as a raster (may result in smaller export file sizes)</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
Expand Down Expand Up @@ -1400,7 +1407,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>393</width>
<width>714</width>
<height>608</height>
</rect>
</property>
Expand Down Expand Up @@ -1801,7 +1808,6 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>buttonBox</tabstop>
<tabstop>mOptionsListWidget</tabstop>
<tabstop>scrollArea</tabstop>
<tabstop>mLayerOrigNameLineEdit</tabstop>
Expand All @@ -1823,7 +1829,7 @@
<tabstop>mSimplifyDrawingSpinBox</tabstop>
<tabstop>mSimplifyDrawingAtProvider</tabstop>
<tabstop>mSimplifyMaximumScaleComboBox</tabstop>
<tabstop>scrollArea_10</tabstop>
<tabstop>mForceRasterCheckBox</tabstop>
<tabstop>fieldComboRadio</tabstop>
<tabstop>displayFieldComboBox</tabstop>
<tabstop>htmlRadio</tabstop>
Expand All @@ -1836,7 +1842,6 @@
<tabstop>scrollArea_7</tabstop>
<tabstop>mButtonAddJoin</tabstop>
<tabstop>mButtonRemoveJoin</tabstop>
<tabstop>mDiagramFrame</tabstop>
<tabstop>scrollArea_2</tabstop>
<tabstop>mLayerTitleLineEdit</tabstop>
<tabstop>mLayerAbstractTextEdit</tabstop>
Expand All @@ -1851,6 +1856,8 @@
<tabstop>mLayerLegendUrlLineEdit</tabstop>
<tabstop>mLayerLegendUrlFormatComboBox</tabstop>
<tabstop>teMetadata</tabstop>
<tabstop>mButtonEditJoin</tabstop>
<tabstop>scrollArea_10</tabstop>
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
Expand Down

3 comments on commit cfee456

@nirvn
Copy link
Contributor

@nirvn nirvn commented on cfee456 Jul 9, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouhou. Thanks

@andremano
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@jonnyforestGIS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice Nyall! Regards

Please sign in to comment.