Skip to content

Commit

Permalink
Move QgsSymbolLayerUtils::createRenderContext to QgsRenderContext::fr…
Browse files Browse the repository at this point in the history
…omQPainter

This method is useful in many contexts outside of symbology
  • Loading branch information
nyalldawson committed Jan 16, 2017
1 parent f32d11b commit 8a722d2
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 32 deletions.
1 change: 1 addition & 0 deletions doc/api_break.dox
Expand Up @@ -1688,6 +1688,7 @@ QgsSymbolLayerUtils (renamed from QgsSymbolLayerUtilsV2) {#qgis_api_break
- encodeOutputUnit() and decodeOutputUnit() were removed. QgsUnitTypes::encodeUnit() and QgsUnitTypes::decodeRenderUnit() should be used instead.
- The signatures for wellKnownMarkerToSld() and wellKnownMarkerFromSld() were changed.
- The symbolPreviewPixmap() customContext is now the fourth parameter
- createRenderContext() was moved to QgsRenderContext::fromQPainter()


QgsSymbolSelectorWidget {#qgis_api_break_3_0_QgsSymbolSelectorWidget}
Expand Down
8 changes: 8 additions & 0 deletions python/core/qgsrendercontext.sip
Expand Up @@ -51,6 +51,14 @@ class QgsRenderContext
//! @note added in 2.4
static QgsRenderContext fromMapSettings( const QgsMapSettings& mapSettings );

/**
* Creates a default render context given a pixel based QPainter destination.
* If no painter is specified or the painter has no device, then a default
* DPI of 88 will be assumed.
* @note added in QGIS 3.0
*/
static QgsRenderContext fromQPainter( QPainter* painter );

//getters

QPainter* painter();
Expand Down
3 changes: 0 additions & 3 deletions python/core/symbology-ng/qgssymbollayerutils.sip
Expand Up @@ -430,9 +430,6 @@ class QgsSymbolLayerUtils
/** Returns scale factor painter units -> map units*/
static double mapUnitScaleFactor( const QgsRenderContext& c, QgsUnitTypes::RenderUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );

/** Creates a render context for a pixel based device*/
static QgsRenderContext createRenderContext( QPainter* p );

/** Multiplies opacity of image pixel values with a (global) transparency value*/
static void multiplyImageOpacity( QImage* image, qreal alpha );

Expand Down
16 changes: 16 additions & 0 deletions src/core/qgsrendercontext.cpp
Expand Up @@ -88,6 +88,22 @@ QgsRenderContext::~QgsRenderContext()
mFeatureFilterProvider = nullptr;
}

QgsRenderContext QgsRenderContext::fromQPainter( QPainter* painter )
{
QgsRenderContext context;
context.setPainter( painter );
context.setRasterScaleFactor( 1.0 );
if ( painter && painter->device() )
{
context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
}
else
{
context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
}
return context;
}

void QgsRenderContext::setFlags( QgsRenderContext::Flags flags )
{
mFlags = flags;
Expand Down
8 changes: 8 additions & 0 deletions src/core/qgsrendercontext.h
Expand Up @@ -93,6 +93,14 @@ class CORE_EXPORT QgsRenderContext
//! @note added in 2.4
static QgsRenderContext fromMapSettings( const QgsMapSettings& mapSettings );

/**
* Creates a default render context given a pixel based QPainter destination.
* If no painter is specified or the painter has no device, then a default
* DPI of 88 will be assumed.
* @note added in QGIS 3.0
*/
static QgsRenderContext fromQPainter( QPainter* painter );

//getters

QPainter* painter() {return mPainter;}
Expand Down
4 changes: 2 additions & 2 deletions src/core/symbology-ng/qgssymbol.cpp
Expand Up @@ -447,7 +447,7 @@ QColor QgsSymbol::color() const

void QgsSymbol::drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext )
{
QgsRenderContext context = customContext ? *customContext : QgsSymbolLayerUtils::createRenderContext( painter );
QgsRenderContext context = customContext ? *customContext : QgsRenderContext::fromQPainter( painter );
context.setForceVectorOutput( true );
QgsSymbolRenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, QgsFields(), mapUnitScale() );

Expand Down Expand Up @@ -526,7 +526,7 @@ QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext* expressionContext
p.drawLine( 50, 0, 50, 100 );
}

QgsRenderContext context = QgsSymbolLayerUtils::createRenderContext( &p );
QgsRenderContext context = QgsRenderContext::fromQPainter( &p );
if ( expressionContext )
context.setExpressionContext( *expressionContext );

Expand Down
20 changes: 2 additions & 18 deletions src/core/symbology-ng/qgssymbollayerutils.cpp
Expand Up @@ -626,7 +626,7 @@ QPicture QgsSymbolLayerUtils::symbolLayerPreviewPicture( QgsSymbolLayer* layer,
QPainter painter;
painter.begin( &picture );
painter.setRenderHint( QPainter::Antialiasing );
QgsRenderContext renderContext = createRenderContext( &painter );
QgsRenderContext renderContext = QgsRenderContext::fromQPainter( &painter );
renderContext.setForceVectorOutput( true );
QgsSymbolRenderContext symbolContext( renderContext, units, 1.0, false, 0, nullptr, QgsFields(), scale );
layer->drawPreviewIcon( symbolContext, size );
Expand All @@ -641,7 +641,7 @@ QIcon QgsSymbolLayerUtils::symbolLayerPreviewIcon( QgsSymbolLayer* layer, QgsUni
QPainter painter;
painter.begin( &pixmap );
painter.setRenderHint( QPainter::Antialiasing );
QgsRenderContext renderContext = createRenderContext( &painter );
QgsRenderContext renderContext = QgsRenderContext::fromQPainter( &painter );
QgsSymbolRenderContext symbolContext( renderContext, u, 1.0, false, 0, nullptr, QgsFields(), scale );
layer->drawPreviewIcon( symbolContext, size );
painter.end();
Expand Down Expand Up @@ -3468,22 +3468,6 @@ double QgsSymbolLayerUtils::mapUnitScaleFactor( const QgsRenderContext &c, QgsUn
return 1.0;
}

QgsRenderContext QgsSymbolLayerUtils::createRenderContext( QPainter* p )
{
QgsRenderContext context;
context.setPainter( p );
context.setRasterScaleFactor( 1.0 );
if ( p && p->device() )
{
context.setScaleFactor( p->device()->logicalDpiX() / 25.4 );
}
else
{
context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
}
return context;
}

void QgsSymbolLayerUtils::multiplyImageOpacity( QImage* image, qreal alpha )
{
if ( !image )
Expand Down
3 changes: 0 additions & 3 deletions src/core/symbology-ng/qgssymbollayerutils.h
Expand Up @@ -508,9 +508,6 @@ class CORE_EXPORT QgsSymbolLayerUtils
//! Returns scale factor painter units -> map units
static double mapUnitScaleFactor( const QgsRenderContext& c, QgsUnitTypes::RenderUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );

//! Creates a render context for a pixel based device
static QgsRenderContext createRenderContext( QPainter* p );

//! Multiplies opacity of image pixel values with a (global) transparency value
static void multiplyImageOpacity( QImage* image, qreal alpha );

Expand Down
2 changes: 1 addition & 1 deletion src/gui/effects/qgseffectstackpropertieswidget.cpp
Expand Up @@ -212,7 +212,7 @@ void QgsEffectStackPropertiesWidget::updatePreview()
previewImage.fill( Qt::transparent );
painter.begin( &previewImage );
painter.setRenderHint( QPainter::Antialiasing );
QgsRenderContext context = QgsSymbolLayerUtils::createRenderContext( &painter );
QgsRenderContext context = QgsRenderContext::fromQPainter( &painter );
if ( !mPreviewPicture )
{
QPicture previewPic;
Expand Down
10 changes: 5 additions & 5 deletions tests/src/core/testqgspainteffect.cpp
Expand Up @@ -336,7 +336,7 @@ void TestQgsPaintEffect::drawSource()

QPainter painter;
painter.begin( &image );
QgsRenderContext context = QgsSymbolLayerUtils::createRenderContext( &painter );
QgsRenderContext context = QgsRenderContext::fromQPainter( &painter );

effect = new QgsDrawSourceEffect();
effect->render( *mPicture, context );
Expand Down Expand Up @@ -410,7 +410,7 @@ void TestQgsPaintEffect::blur()
image.fill( Qt::transparent );
QPainter painter;
painter.begin( &image );
QgsRenderContext context = QgsSymbolLayerUtils::createRenderContext( &painter );
QgsRenderContext context = QgsRenderContext::fromQPainter( &painter );

effect = new QgsBlurEffect();
effect->render( *mPicture, context );
Expand Down Expand Up @@ -508,7 +508,7 @@ void TestQgsPaintEffect::dropShadow()
image.fill( Qt::transparent );
QPainter painter;
painter.begin( &image );
QgsRenderContext context = QgsSymbolLayerUtils::createRenderContext( &painter );
QgsRenderContext context = QgsRenderContext::fromQPainter( &painter );

effect = new QgsDropShadowEffect();
effect->render( *mPicture, context );
Expand Down Expand Up @@ -611,7 +611,7 @@ void TestQgsPaintEffect::glow()
image.fill( Qt::transparent );
QPainter painter;
painter.begin( &image );
QgsRenderContext context = QgsSymbolLayerUtils::createRenderContext( &painter );
QgsRenderContext context = QgsRenderContext::fromQPainter( &painter );

effect = new QgsOuterGlowEffect();
effect->setSpread( 20 );
Expand Down Expand Up @@ -673,7 +673,7 @@ void TestQgsPaintEffect::stack()
image.fill( Qt::transparent );
QPainter painter;
painter.begin( &image );
QgsRenderContext context = QgsSymbolLayerUtils::createRenderContext( &painter );
QgsRenderContext context = QgsRenderContext::fromQPainter( &painter );

effect = new QgsEffectStack();
QgsBlurEffect* blur = new QgsBlurEffect();
Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -87,6 +87,7 @@ ADD_PYTHON_TEST(PyQgsRasterColorRampShader test_qgsrastercolorrampshader.py)
ADD_PYTHON_TEST(PyQgsRectangle test_qgsrectangle.py)
ADD_PYTHON_TEST(PyQgsRelation test_qgsrelation.py)
ADD_PYTHON_TEST(PyQgsRelationManager test_qgsrelationmanager.py)
ADD_PYTHON_TEST(PyQgsRenderContext test_qgsrendercontext.py)
ADD_PYTHON_TEST(PyQgsRenderer test_qgsrenderer.py)
ADD_PYTHON_TEST(PyQgsRulebasedRenderer test_qgsrulebasedrenderer.py)
ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py)
Expand Down
50 changes: 50 additions & 0 deletions tests/src/python/test_qgsrendercontext.py
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsRenderContext.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '16/01/2017'
__copyright__ = 'Copyright 2017, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import qgis # NOQA

from qgis.core import QgsRenderContext
from qgis.PyQt.QtGui import QPainter, QImage
from qgis.testing import unittest


class TestQgsRenderContext(unittest.TestCase):

def testFromQPainter(self):
""" test QgsRenderContext.fromQPainter """

# no painter
c = QgsRenderContext.fromQPainter(None)
self.assertFalse(c.painter())
# assuming 88 dpi as fallback
self.assertAlmostEqual(c.scaleFactor(), 88 / 25.4, 3)

# no painter destination
p = QPainter()
c = QgsRenderContext.fromQPainter(p)
self.assertEqual(c.painter(), p)
self.assertAlmostEqual(c.scaleFactor(), 88 / 25.4, 3)

im = QImage(1000, 600, QImage.Format_RGB32)
dots_per_m = 300 / 25.4 * 1000 # 300 dpi to dots per m
im.setDotsPerMeterX(dots_per_m)
im.setDotsPerMeterY(dots_per_m)
p = QPainter(im)
c = QgsRenderContext.fromQPainter(p)
self.assertEqual(c.painter(), p)
self.assertAlmostEqual(c.scaleFactor(), dots_per_m / 1000, 3) # scaleFactor should be pixels/mm


if __name__ == '__main__':
unittest.main()

0 comments on commit 8a722d2

Please sign in to comment.