Skip to content

Commit ccfe557

Browse files
committed
Fix DPI scaling issue with paint effects and composer
1 parent d6e22af commit ccfe557

File tree

4 files changed

+48
-15
lines changed

4 files changed

+48
-15
lines changed

python/core/effects/qgspainteffect.sip

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ class QgsPaintEffect
230230
*/
231231
virtual QRectF boundingRect( const QRectF& rect, const QgsRenderContext& context ) const;
232232

233+
/** Applies a workaround to a QPainter to avoid an issue with incorrect scaling
234+
* when drawing QPictures. This may need to be called by derived classes prior
235+
* to rendering results onto a painter.
236+
* @param painter destination painter
237+
*/
238+
void fixQPictureDpi( QPainter* painter ) const;
239+
233240
};
234241

235242
/** \ingroup core

src/core/effects/qgseffectstack.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,11 @@ void QgsEffectStack::draw( QgsRenderContext &context )
100100
QPicture *resultPic = new QPicture();
101101
QPainter p( resultPic );
102102
context.setPainter( &p );
103+
//effect stack has it's own handling of the QPicture DPI issue, so
104+
//we disable QgsPaintEffect's internal workaround
105+
effect->requiresQPainterDpiFix = false;
103106
effect->render( *pic, context );
107+
effect->requiresQPainterDpiFix = true;
104108
p.end();
105109

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

115119
context.setPainter( destPainter );
116-
117120
//then, we render all the results in the opposite order
118121
for ( int i = 0; i < mEffectList.count(); ++i )
119122
{
@@ -125,7 +128,11 @@ void QgsEffectStack::draw( QgsRenderContext &context )
125128
QPicture* pic = results.takeLast();
126129
if ( mEffectList[i]->drawMode() != QgsPaintEffect::Modifier )
127130
{
131+
context.painter()->save();
132+
fixQPictureDpi( context.painter() );
128133
context.painter()->drawPicture( 0, 0, *pic );
134+
context.painter()->restore();
135+
129136
}
130137
delete pic;
131138
}

src/core/effects/qgspainteffect.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,10 @@
2323
Q_GUI_EXPORT extern int qt_defaultDpiX();
2424
Q_GUI_EXPORT extern int qt_defaultDpiY();
2525

26-
static void _fixQPictureDPI( QPainter* p )
27-
{
28-
// QPicture makes an assumption that we drawing to it with system DPI.
29-
// Then when being drawn, it scales the painter. The following call
30-
// negates the effect. There is no way of setting QPicture's DPI.
31-
// See QTBUG-20361
32-
p->scale(( double )qt_defaultDpiX() / p->device()->logicalDpiX(),
33-
( double )qt_defaultDpiY() / p->device()->logicalDpiY() );
34-
}
35-
3626
QgsPaintEffect::QgsPaintEffect()
3727
: mEnabled( true )
3828
, mDrawMode( ModifyAndRender )
29+
, requiresQPainterDpiFix( true )
3930
, mPicture( 0 )
4031
, mSourceImage( 0 )
4132
, mOwnsImage( false )
@@ -49,6 +40,7 @@ QgsPaintEffect::QgsPaintEffect()
4940
QgsPaintEffect::QgsPaintEffect( const QgsPaintEffect &other )
5041
: mEnabled( other.enabled() )
5142
, mDrawMode( other.drawMode() )
43+
, requiresQPainterDpiFix( true )
5244
, mPicture( 0 )
5345
, mSourceImage( 0 )
5446
, mOwnsImage( false )
@@ -180,10 +172,17 @@ void QgsPaintEffect::end( QgsRenderContext &context )
180172

181173
void QgsPaintEffect::drawSource( QPainter &painter )
182174
{
183-
painter.save();
184-
_fixQPictureDPI( &painter );
185-
painter.drawPicture( 0, 0, *mPicture );
186-
painter.restore();
175+
if ( requiresQPainterDpiFix )
176+
{
177+
painter.save();
178+
fixQPictureDpi( &painter );
179+
painter.drawPicture( 0, 0, *mPicture );
180+
painter.restore();
181+
}
182+
else
183+
{
184+
painter.drawPicture( 0, 0, *mPicture );
185+
}
187186
}
188187

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

224+
void QgsPaintEffect::fixQPictureDpi( QPainter *painter ) const
225+
{
226+
// QPicture makes an assumption that we drawing to it with system DPI.
227+
// Then when being drawn, it scales the painter. The following call
228+
// negates the effect. There is no way of setting QPicture's DPI.
229+
// See QTBUG-20361
230+
painter->scale(( double )qt_defaultDpiX() / painter->device()->logicalDpiX(),
231+
( double )qt_defaultDpiY() / painter->device()->logicalDpiY() );
232+
}
233+
225234
QRectF QgsPaintEffect::imageBoundingRect( const QgsRenderContext &context ) const
226235
{
227236
return boundingRect( mPicture->boundingRect(), context );

src/core/effects/qgspainteffect.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ class CORE_EXPORT QgsPaintEffect
161161

162162
bool mEnabled;
163163
DrawMode mDrawMode;
164+
bool requiresQPainterDpiFix;
164165

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

220+
/** Applies a workaround to a QPainter to avoid an issue with incorrect scaling
221+
* when drawing QPictures. This may need to be called by derived classes prior
222+
* to rendering results onto a painter.
223+
* @param painter destination painter
224+
*/
225+
void fixQPictureDpi( QPainter* painter ) const;
226+
219227
private:
220228

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

229237
QRectF imageBoundingRect( const QgsRenderContext& context ) const;
230238

239+
friend class QgsEffectStack;
240+
231241
};
232242

233243
/** \ingroup core

0 commit comments

Comments
 (0)