Skip to content
Permalink
Browse files
Fix DPI scaling issue with paint effects and composer
  • Loading branch information
nyalldawson committed Apr 7, 2015
1 parent d6e22af commit ccfe557cbec57ffdd5dee468fcb7edb938a3f469
@@ -230,6 +230,13 @@ class QgsPaintEffect
*/
virtual QRectF boundingRect( const QRectF& rect, const QgsRenderContext& context ) const;

/** Applies a workaround to a QPainter to avoid an issue with incorrect scaling
* when drawing QPictures. This may need to be called by derived classes prior
* to rendering results onto a painter.
* @param painter destination painter
*/
void fixQPictureDpi( QPainter* painter ) const;

};

/** \ingroup core
@@ -100,7 +100,11 @@ void QgsEffectStack::draw( QgsRenderContext &context )
QPicture *resultPic = new QPicture();
QPainter p( resultPic );
context.setPainter( &p );
//effect stack has it's own handling of the QPicture DPI issue, so
//we disable QgsPaintEffect's internal workaround
effect->requiresQPainterDpiFix = false;
effect->render( *pic, context );
effect->requiresQPainterDpiFix = true;
p.end();

results << resultPic;
@@ -113,7 +117,6 @@ void QgsEffectStack::draw( QgsRenderContext &context )
sourcePic = 0;

context.setPainter( destPainter );

//then, we render all the results in the opposite order
for ( int i = 0; i < mEffectList.count(); ++i )
{
@@ -125,7 +128,11 @@ void QgsEffectStack::draw( QgsRenderContext &context )
QPicture* pic = results.takeLast();
if ( mEffectList[i]->drawMode() != QgsPaintEffect::Modifier )
{
context.painter()->save();
fixQPictureDpi( context.painter() );
context.painter()->drawPicture( 0, 0, *pic );
context.painter()->restore();

}
delete pic;
}
@@ -23,19 +23,10 @@
Q_GUI_EXPORT extern int qt_defaultDpiX();
Q_GUI_EXPORT extern int qt_defaultDpiY();

static void _fixQPictureDPI( QPainter* p )
{
// QPicture makes an assumption that we drawing to it with system DPI.
// Then when being drawn, it scales the painter. The following call
// negates the effect. There is no way of setting QPicture's DPI.
// See QTBUG-20361
p->scale(( double )qt_defaultDpiX() / p->device()->logicalDpiX(),
( double )qt_defaultDpiY() / p->device()->logicalDpiY() );
}

QgsPaintEffect::QgsPaintEffect()
: mEnabled( true )
, mDrawMode( ModifyAndRender )
, requiresQPainterDpiFix( true )
, mPicture( 0 )
, mSourceImage( 0 )
, mOwnsImage( false )
@@ -49,6 +40,7 @@ QgsPaintEffect::QgsPaintEffect()
QgsPaintEffect::QgsPaintEffect( const QgsPaintEffect &other )
: mEnabled( other.enabled() )
, mDrawMode( other.drawMode() )
, requiresQPainterDpiFix( true )
, mPicture( 0 )
, mSourceImage( 0 )
, mOwnsImage( false )
@@ -180,10 +172,17 @@ void QgsPaintEffect::end( QgsRenderContext &context )

void QgsPaintEffect::drawSource( QPainter &painter )
{
painter.save();
_fixQPictureDPI( &painter );
painter.drawPicture( 0, 0, *mPicture );
painter.restore();
if ( requiresQPainterDpiFix )
{
painter.save();
fixQPictureDpi( &painter );
painter.drawPicture( 0, 0, *mPicture );
painter.restore();
}
else
{
painter.drawPicture( 0, 0, *mPicture );
}
}

QImage* QgsPaintEffect::sourceAsImage( QgsRenderContext &context )
@@ -222,6 +221,16 @@ QRectF QgsPaintEffect::boundingRect( const QRectF &rect, const QgsRenderContext
return rect;
}

void QgsPaintEffect::fixQPictureDpi( QPainter *painter ) const
{
// QPicture makes an assumption that we drawing to it with system DPI.
// Then when being drawn, it scales the painter. The following call
// negates the effect. There is no way of setting QPicture's DPI.
// See QTBUG-20361
painter->scale(( double )qt_defaultDpiX() / painter->device()->logicalDpiX(),
( double )qt_defaultDpiY() / painter->device()->logicalDpiY() );
}

QRectF QgsPaintEffect::imageBoundingRect( const QgsRenderContext &context ) const
{
return boundingRect( mPicture->boundingRect(), context );
@@ -161,6 +161,7 @@ class CORE_EXPORT QgsPaintEffect

bool mEnabled;
DrawMode mDrawMode;
bool requiresQPainterDpiFix;

/** Handles drawing of the effect's result on to the specified render context.
* Derived classes must reimplement this method to apply any transformations to
@@ -216,6 +217,13 @@ class CORE_EXPORT QgsPaintEffect
*/
virtual QRectF boundingRect( const QRectF& rect, const QgsRenderContext& context ) const;

/** Applies a workaround to a QPainter to avoid an issue with incorrect scaling
* when drawing QPictures. This may need to be called by derived classes prior
* to rendering results onto a painter.
* @param painter destination painter
*/
void fixQPictureDpi( QPainter* painter ) const;

private:

const QPicture* mPicture;
@@ -228,6 +236,8 @@ class CORE_EXPORT QgsPaintEffect

QRectF imageBoundingRect( const QgsRenderContext& context ) const;

friend class QgsEffectStack;

};

/** \ingroup core

0 comments on commit ccfe557

Please sign in to comment.