From 2caf0e0cbc6b8c0c230b9ca658d345fda932244d Mon Sep 17 00:00:00 2001 From: nyalldawson Date: Fri, 10 May 2013 15:20:11 +1000 Subject: [PATCH] Disable blend modes when printing or pdf exporting as vector, prevents missing composer items in output --- src/app/composer/qgscomposer.cpp | 34 ++++++++++++++ src/core/composer/qgscomposeritem.cpp | 10 ++++- src/core/composer/qgscomposeritem.h | 11 ++++- src/core/composer/qgscomposermap.cpp | 3 ++ src/core/composer/qgscomposition.cpp | 64 +++++++++++++++++++++++---- src/core/composer/qgscomposition.h | 10 +++++ src/core/qgsmaprenderer.cpp | 13 +++--- src/core/qgspallabeling.cpp | 25 ++++++++--- src/core/qgsrendercontext.cpp | 1 + src/core/qgsrendercontext.h | 10 +++++ 10 files changed, 161 insertions(+), 20 deletions(-) diff --git a/src/app/composer/qgscomposer.cpp b/src/app/composer/qgscomposer.cpp index fe97d90a4b9b..1557db152675 100644 --- a/src/app/composer/qgscomposer.cpp +++ b/src/app/composer/qgscomposer.cpp @@ -637,6 +637,18 @@ void QgsComposer::on_mActionExportAsPDF_triggered() showBlendModePrintingWarning(); } + // If we are not printing as raster, temporarily disable advanced effects + // as QPrinter does not support composition modes and can result + // in items missing from the output + if ( mComposition->printAsRaster() ) + { + mComposition->setUseAdvancedEffects( true ); + } + else + { + mComposition->setUseAdvancedEffects( false ); + } + bool hasAnAtlas = mComposition->atlasComposition().enabled(); bool atlasOnASingleFile = hasAnAtlas && mComposition->atlasComposition().singleFile(); QgsAtlasComposition* atlasMap = &mComposition->atlasComposition(); @@ -795,6 +807,11 @@ void QgsComposer::on_mActionExportAsPDF_triggered() mComposition->exportAsPDF( outputFileName ); } + if ( ! mComposition->useAdvancedEffects() ) + { + //Switch advanced effects back on + mComposition->setUseAdvancedEffects( true ); + } mView->setPaintingEnabled( true ); QApplication::restoreOverrideCursor(); } @@ -816,6 +833,18 @@ void QgsComposer::on_mActionPrint_triggered() showBlendModePrintingWarning(); } + // If we are not printing as raster, temporarily disable advanced effects + // as QPrinter does not support composition modes and can result + // in items missing from the output + if ( mComposition->printAsRaster() ) + { + mComposition->setUseAdvancedEffects( true ); + } + else + { + mComposition->setUseAdvancedEffects( false ); + } + //orientation and page size are already set to QPrinter in the page setup dialog QPrintDialog printDialog( &mPrinter, 0 ); if ( printDialog.exec() != QDialog::Accepted ) @@ -887,6 +916,11 @@ void QgsComposer::on_mActionPrint_triggered() painter.end(); } + if ( ! mComposition->useAdvancedEffects() ) + { + //Switch advanced effects back on + mComposition->setUseAdvancedEffects( true ); + } mView->setPaintingEnabled( true ); QApplication::restoreOverrideCursor(); } diff --git a/src/core/composer/qgscomposeritem.cpp b/src/core/composer/qgscomposeritem.cpp index 8bc05128a085..69ae741691a2 100644 --- a/src/core/composer/qgscomposeritem.cpp +++ b/src/core/composer/qgscomposeritem.cpp @@ -56,6 +56,7 @@ QgsComposerItem::QgsComposerItem( QgsComposition* composition, bool manageZValue , mLastValidViewScaleFactor( -1 ) , mRotation( 0 ) , mBlendMode( QPainter::CompositionMode_SourceOver ) + , mEffectsEnabled( true ) , mTransparency( 0 ) , mLastUsedPositionMode( UpperLeft ) , mId( "" ) @@ -78,6 +79,7 @@ QgsComposerItem::QgsComposerItem( qreal x, qreal y, qreal width, qreal height, Q , mLastValidViewScaleFactor( -1 ) , mRotation( 0 ) , mBlendMode( QPainter::CompositionMode_SourceOver ) + , mEffectsEnabled( true ) , mTransparency( 0 ) , mLastUsedPositionMode( UpperLeft ) , mId( "" ) @@ -107,7 +109,6 @@ void QgsComposerItem::init( bool manageZValue ) // Setup composer effect mEffect = new QgsComposerEffect(); setGraphicsEffect( mEffect ); - } QgsComposerItem::~QgsComposerItem() @@ -906,6 +907,13 @@ void QgsComposerItem::setTransparency( int transparency ) setOpacity( 1. - ( transparency / 100. ) ); } +void QgsComposerItem::setEffectsEnabled( bool effectsEnabled ) +{ + //enable or disable the QgsComposerEffect applied to this item + mEffectsEnabled = effectsEnabled; + mEffect->setEnabled( effectsEnabled ); +} + void QgsComposerItem::hoverMoveEvent( QGraphicsSceneHoverEvent * event ) { if ( isSelected() ) diff --git a/src/core/composer/qgscomposeritem.h b/src/core/composer/qgscomposeritem.h index 40b34840a29d..0d384041b1ca 100644 --- a/src/core/composer/qgscomposeritem.h +++ b/src/core/composer/qgscomposeritem.h @@ -221,6 +221,15 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem /** Sets the item's transparency */ void setTransparency( int transparency ); + /** Returns true if effects (eg blend modes) are enabled for the item + * @note introduced in 2.0 + */ + bool effectsEnabled() const {return mEffectsEnabled;} + /** Sets whether effects (eg blend modes) are enabled for the item + * @note introduced in 2.0 + */ + void setEffectsEnabled( bool effectsEnabled ); + /**Composite operations for item groups do nothing per default*/ virtual void addItem( QgsComposerItem* item ) { Q_UNUSED( item ); } virtual void removeItems() {} @@ -337,7 +346,7 @@ class CORE_EXPORT QgsComposerItem: public QObject, public QGraphicsRectItem /**Composition blend mode for item*/ QPainter::CompositionMode mBlendMode; - + bool mEffectsEnabled; QgsComposerEffect *mEffect; /**Item transparency*/ diff --git a/src/core/composer/qgscomposermap.cpp b/src/core/composer/qgscomposermap.cpp index 813ff724f179..0551b0c08024 100644 --- a/src/core/composer/qgscomposermap.cpp +++ b/src/core/composer/qgscomposermap.cpp @@ -168,6 +168,9 @@ void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, const // force vector output (no caching of marker images etc.) theRendererContext->setForceVectorOutput( true ); + // make the renderer respect the composition's useAdvancedEffects flag + theRendererContext->setUseAdvancedEffects( mComposition->useAdvancedEffects() ); + //force composer map scale for scale dependent visibility double bk_scale = theMapRenderer.scale(); theMapRenderer.setScale( scale() ); diff --git a/src/core/composer/qgscomposition.cpp b/src/core/composer/qgscomposition.cpp index 3e88743a385f..bd6ddefde480 100644 --- a/src/core/composer/qgscomposition.cpp +++ b/src/core/composer/qgscomposition.cpp @@ -47,10 +47,25 @@ #include -QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer ) : - QGraphicsScene( 0 ), mMapRenderer( mapRenderer ), mPlotStyle( QgsComposition::Preview ), mPageWidth( 297 ), mPageHeight( 210 ), mSpaceBetweenPages( 10 ), mPrintAsRaster( false ), mSelectionTolerance( 0.0 ), - mSnapToGrid( false ), mSnapGridResolution( 10.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mAlignmentSnap( true ), mAlignmentSnapTolerance( 2 ), - mActiveItemCommand( 0 ), mActiveMultiFrameCommand( 0 ), mAtlasComposition( this ) +QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer ) + : QGraphicsScene( 0 ), + mMapRenderer( mapRenderer ), + mPlotStyle( QgsComposition::Preview ), + mPageWidth( 297 ), + mPageHeight( 210 ), + mSpaceBetweenPages( 10 ), + mPrintAsRaster( false ), + mUseAdvancedEffects( true ), + mSelectionTolerance( 0.0 ), + mSnapToGrid( false ), + mSnapGridResolution( 10.0 ), + mSnapGridOffsetX( 0.0 ), + mSnapGridOffsetY( 0.0 ), + mAlignmentSnap( true ), + mAlignmentSnapTolerance( 2 ), + mActiveItemCommand( 0 ), + mActiveMultiFrameCommand( 0 ), + mAtlasComposition( this ) { setBackgroundBrush( Qt::gray ); addPaperItem(); @@ -59,10 +74,25 @@ QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer ) : loadSettings(); } -QgsComposition::QgsComposition(): - QGraphicsScene( 0 ), mMapRenderer( 0 ), mPlotStyle( QgsComposition::Preview ), mPageWidth( 297 ), mPageHeight( 210 ), mSpaceBetweenPages( 10 ), mPrintAsRaster( false ), - mSelectionTolerance( 0.0 ), mSnapToGrid( false ), mSnapGridResolution( 10.0 ), mSnapGridOffsetX( 0.0 ), mSnapGridOffsetY( 0.0 ), mAlignmentSnap( true ), - mAlignmentSnapTolerance( 2 ), mActiveItemCommand( 0 ), mActiveMultiFrameCommand( 0 ), mAtlasComposition( this ) +QgsComposition::QgsComposition() + : QGraphicsScene( 0 ), + mMapRenderer( 0 ), + mPlotStyle( QgsComposition::Preview ), + mPageWidth( 297 ), + mPageHeight( 210 ), + mSpaceBetweenPages( 10 ), + mPrintAsRaster( false ), + mUseAdvancedEffects( true ), + mSelectionTolerance( 0.0 ), + mSnapToGrid( false ), + mSnapGridResolution( 10.0 ), + mSnapGridOffsetX( 0.0 ), + mSnapGridOffsetY( 0.0 ), + mAlignmentSnap( true ), + mAlignmentSnapTolerance( 2 ), + mActiveItemCommand( 0 ), + mActiveMultiFrameCommand( 0 ), + mAtlasComposition( this ) { loadSettings(); @@ -318,6 +348,24 @@ const QgsComposerItem* QgsComposition::getComposerItemByUuid( QString theUuid ) return 0; } + +void QgsComposition::setUseAdvancedEffects( bool effectsEnabled ) +{ + mUseAdvancedEffects = effectsEnabled; + + //toggle effects for all composer items + QList itemList = items(); + QList::const_iterator itemIt = itemList.constBegin(); + for ( ; itemIt != itemList.constEnd(); ++itemIt ) + { + QgsComposerItem* composerItem = dynamic_cast( *itemIt ); + if ( composerItem ) + { + composerItem->setEffectsEnabled( effectsEnabled ); + } + } +} + int QgsComposition::pixelFontSize( double pointSize ) const { //in QgsComposition, one unit = one mm diff --git a/src/core/composer/qgscomposition.h b/src/core/composer/qgscomposition.h index afa064e8648f..282fc471c151 100644 --- a/src/core/composer/qgscomposition.h +++ b/src/core/composer/qgscomposition.h @@ -182,6 +182,13 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene bool printAsRaster() const {return mPrintAsRaster;} void setPrintAsRaster( bool enabled ) { mPrintAsRaster = enabled; } + /**Returns true if a composition should use advanced effects such as blend modes + @note added in 1.9*/ + bool useAdvancedEffects() const {return mUseAdvancedEffects;} + /**Used to enable or disable advanced effects such as blend modes in a composition + @note: added in version 1.9*/ + void setUseAdvancedEffects( bool effectsEnabled ); + double selectionTolerance() const { return mSelectionTolerance; } void setSelectionTolerance( double tol ); @@ -375,6 +382,9 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene /**Flag if map should be printed as a raster (via QImage). False by default*/ bool mPrintAsRaster; + /**Flag if advanced visual effects such as blend modes should be used. True by default*/ + bool mUseAdvancedEffects; + /**Distance tolerance for item selection (in mm)*/ double mSelectionTolerance; diff --git a/src/core/qgsmaprenderer.cpp b/src/core/qgsmaprenderer.cpp index 58d482639c13..683a4cddf973 100644 --- a/src/core/qgsmaprenderer.cpp +++ b/src/core/qgsmaprenderer.cpp @@ -397,9 +397,12 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale ) .arg( ml->blendMode() ) ); - // Set the QPainter composition mode so that this layer is rendered using - // the desired blending mode - mypContextPainter->setCompositionMode( ml->blendMode() ); + if ( mRenderContext.useAdvancedEffects() ) + { + // Set the QPainter composition mode so that this layer is rendered using + // the desired blending mode + mypContextPainter->setCompositionMode( ml->blendMode() ); + } if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview ) { @@ -515,7 +518,7 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale ) // before compositing this on the map. This effectively flattens the layer and prevents // blending occuring between objects on the layer // (this is not required for raster layers or when layer caching is enabled, since that has the same effect) - if (( ml->blendMode() != QPainter::CompositionMode_SourceOver ) && + if (( mRenderContext.useAdvancedEffects() ) && ( ml->blendMode() != QPainter::CompositionMode_SourceOver ) && ( ml->type() != QgsMapLayer::RasterLayer ) && ( split || !mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) ) { @@ -581,7 +584,7 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale ) } // If we flattened this layer for alternate blend modes, composite it now - if (( ml->blendMode() != QPainter::CompositionMode_SourceOver ) && + if (( mRenderContext.useAdvancedEffects() ) && ( ml->blendMode() != QPainter::CompositionMode_SourceOver ) && ( ml->type() != QgsMapLayer::RasterLayer ) && ( split || !mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) ) { diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp index e19f82b26bdd..8b4a8845cb62 100644 --- a/src/core/qgspallabeling.cpp +++ b/src/core/qgspallabeling.cpp @@ -2286,7 +2286,10 @@ void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext& con } // paint the text - painter->setCompositionMode( tmpLyr.blendMode ); + if ( context.useAdvancedEffects() ) + { + painter->setCompositionMode( tmpLyr.blendMode ); + } // painter->setPen( Qt::NoPen ); // painter->setBrush( tmpLyr.textColor ); // painter->drawPath( path ); @@ -2350,7 +2353,10 @@ void QgsPalLabeling::drawLabelBuffer( QgsRenderContext& context, } p->save(); - p->setCompositionMode( tmpLyr.bufferBlendMode ); + if ( context.useAdvancedEffects() ) + { + p->setCompositionMode( tmpLyr.bufferBlendMode ); + } // p->setPen( pen ); // p->setBrush( tmpColor ); // p->drawPath( path ); @@ -2512,7 +2518,10 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, ( 100.0 - ( double )( tmpLyr.shapeTransparency ) ) / 100.0 ); p->save(); - p->setCompositionMode( tmpLyr.shapeBlendMode ); + if ( context.useAdvancedEffects() ) + { + p->setCompositionMode( tmpLyr.shapeBlendMode ); + } p->translate( component.center().x(), component.center().y() ); p->rotate( component.rotation() ); double xoff = tmpLyr.scaleToPixelContext( tmpLyr.shapeOffset.x(), context, tmpLyr.shapeOffsetUnits ); @@ -2642,7 +2651,10 @@ void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context, } p->setOpacity(( 100.0 - ( double )( tmpLyr.shapeTransparency ) ) / 100.0 ); - p->setCompositionMode( tmpLyr.shapeBlendMode ); + if ( context.useAdvancedEffects() ) + { + p->setCompositionMode( tmpLyr.shapeBlendMode ); + } // scale for any print output or image saving @ specific dpi p->scale( component.dpiRatio(), component.dpiRatio() ); @@ -2744,7 +2756,10 @@ void QgsPalLabeling::drawLabelShadow( QgsRenderContext& context, p->save(); p->setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform ); - p->setCompositionMode( tmpLyr.shadowBlendMode ); + if ( context.useAdvancedEffects() ) + { + p->setCompositionMode( tmpLyr.shadowBlendMode ); + } p->setOpacity(( 100.0 - ( double )( tmpLyr.shadowTransparency ) ) / 100.0 ); double scale = ( double )tmpLyr.shadowScale / 100.0; diff --git a/src/core/qgsrendercontext.cpp b/src/core/qgsrendercontext.cpp index d6eb5c41e3b1..288481497340 100644 --- a/src/core/qgsrendercontext.cpp +++ b/src/core/qgsrendercontext.cpp @@ -23,6 +23,7 @@ QgsRenderContext::QgsRenderContext() mCoordTransform( 0 ), mDrawEditingInformation( true ), mForceVectorOutput( false ), + mUseAdvancedEffects( true ), mRenderingStopped( false ), mScaleFactor( 1.0 ), mRasterScaleFactor( 1.0 ), diff --git a/src/core/qgsrendercontext.h b/src/core/qgsrendercontext.h index 18b908031fda..f047d9bed990 100644 --- a/src/core/qgsrendercontext.h +++ b/src/core/qgsrendercontext.h @@ -59,6 +59,13 @@ class CORE_EXPORT QgsRenderContext bool forceVectorOutput() const {return mForceVectorOutput;} + /**Returns true if advanced effects such as blend modes such be used + @note added in 1.9*/ + bool useAdvancedEffects() const {return mUseAdvancedEffects;} + /**Used to enable or disable advanced effects such as blend modes + @note: added in version 1.9*/ + void setUseAdvancedEffects( bool enabled ) { mUseAdvancedEffects = enabled; } + bool drawEditingInformation() const {return mDrawEditingInformation;} double rendererScale() const {return mRendererScale;} @@ -104,6 +111,9 @@ class CORE_EXPORT QgsRenderContext /**If true then no rendered vector elements should be cached as image*/ bool mForceVectorOutput; + /**Flag if advanced visual effects such as blend modes should be used. True by default*/ + bool mUseAdvancedEffects; + QgsMapToPixel mMapToPixel; /**True if the rendering has been canceled*/