QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgstransformeffect.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgstransformeffect.cpp
3 ----------------------
4 begin : March 2015
5 copyright : (C) 2015 Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgstransformeffect.h"
19#include "qgssymbollayerutils.h"
20#include "qgsunittypes.h"
21#include <QPicture>
22#include <QTransform>
23
25{
26 QgsTransformEffect *newEffect = new QgsTransformEffect();
27 newEffect->readProperties( map );
28 return newEffect;
29}
30
32{
33 if ( !source() || !enabled() || !context.painter() )
34 return;
35
36 QPainter *painter = context.painter();
37
38 //apply transformations
39 const QgsScopedQPainterState painterState( painter );
40
41 const QTransform t = createTransform( context );
42 painter->setTransform( t, true );
43 drawSource( *painter );
44}
45
47{
48 QVariantMap props;
49 props.insert( QStringLiteral( "reflect_x" ), mReflectX ? "1" : "0" );
50 props.insert( QStringLiteral( "reflect_y" ), mReflectY ? "1" : "0" );
51 props.insert( QStringLiteral( "scale_x" ), QString::number( mScaleX ) );
52 props.insert( QStringLiteral( "scale_y" ), QString::number( mScaleY ) );
53 props.insert( QStringLiteral( "rotation" ), QString::number( mRotation ) );
54 props.insert( QStringLiteral( "shear_x" ), QString::number( mShearX ) );
55 props.insert( QStringLiteral( "shear_y" ), QString::number( mShearY ) );
56 props.insert( QStringLiteral( "translate_x" ), QString::number( mTranslateX ) );
57 props.insert( QStringLiteral( "translate_y" ), QString::number( mTranslateY ) );
58 props.insert( QStringLiteral( "translate_unit" ), QgsUnitTypes::encodeUnit( mTranslateUnit ) );
59 props.insert( QStringLiteral( "translate_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mTranslateMapUnitScale ) );
60 props.insert( QStringLiteral( "enabled" ), mEnabled ? "1" : "0" );
61 props.insert( QStringLiteral( "draw_mode" ), QString::number( int( mDrawMode ) ) );
62 return props;
63}
64
65void QgsTransformEffect::readProperties( const QVariantMap &props )
66{
67 mEnabled = props.value( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt();
68 mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( QStringLiteral( "draw_mode" ), QStringLiteral( "2" ) ).toInt() );
69 mReflectX = props.value( QStringLiteral( "reflect_x" ), QStringLiteral( "0" ) ).toInt();
70 mReflectY = props.value( QStringLiteral( "reflect_y" ), QStringLiteral( "0" ) ).toInt();
71 mScaleX = props.value( QStringLiteral( "scale_x" ), QStringLiteral( "1.0" ) ).toDouble();
72 mScaleY = props.value( QStringLiteral( "scale_y" ), QStringLiteral( "1.0" ) ).toDouble();
73 mRotation = props.value( QStringLiteral( "rotation" ), QStringLiteral( "0.0" ) ).toDouble();
74 mShearX = props.value( QStringLiteral( "shear_x" ), QStringLiteral( "0.0" ) ).toDouble();
75 mShearY = props.value( QStringLiteral( "shear_y" ), QStringLiteral( "0.0" ) ).toDouble();
76 mTranslateX = props.value( QStringLiteral( "translate_x" ), QStringLiteral( "0.0" ) ).toDouble();
77 mTranslateY = props.value( QStringLiteral( "translate_y" ), QStringLiteral( "0.0" ) ).toDouble();
78 mTranslateUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "translate_unit" ) ).toString() );
79 mTranslateMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "translate_unit_scale" ) ).toString() );
80}
81
83{
84 QgsTransformEffect *newEffect = new QgsTransformEffect( *this );
85 return newEffect;
86}
87
88QRectF QgsTransformEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
89{
90 const QTransform t = createTransform( context );
91 return t.mapRect( rect );
92}
93
94QTransform QgsTransformEffect::createTransform( const QgsRenderContext &context ) const
95{
96 QTransform t;
97
98 if ( !source() )
99 return t;
100
101 const int width = source()->boundingRect().width();
102 const int height = source()->boundingRect().height();
103 const int top = source()->boundingRect().top();
104 const int left = source()->boundingRect().left();
105
106 //remember that the below operations are effectively performed in the opposite order
107 //so, first the reflection applies, then scale, shear, rotate and lastly translation
108
109 const double translateX = context.convertToPainterUnits( mTranslateX, mTranslateUnit, mTranslateMapUnitScale );
110 const double translateY = context.convertToPainterUnits( mTranslateY, mTranslateUnit, mTranslateMapUnitScale );
111
112 t.translate( translateX + left + width / 2.0,
113 translateY + top + height / 2.0 );
114
115 t.rotate( mRotation );
116 t.shear( mShearX, mShearY );
117 t.scale( mScaleX, mScaleY );
118
119 if ( mReflectX || mReflectY )
120 {
121 t.scale( mReflectX ? -1 : 1, mReflectY ? -1 : 1 );
122 }
123
124 t.translate( -left - width / 2.0,
125 -top - height / 2.0 );
126
127 return t;
128}
Base class for visual effects which can be applied to QPicture drawings.
DrawMode mDrawMode
void drawSource(QPainter &painter)
Draws the source QPicture onto the specified painter.
const QPicture * source() const
Returns the source QPicture.
bool enabled() const
Returns whether the effect is enabled.
DrawMode
Drawing modes for effects.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Scoped object for saving and restoring a QPainter object's state.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
A paint effect which applies transformations (such as move, scale and rotate) to a picture.
double translateX() const
Returns the transform x translation.
QgsTransformEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
QgsTransformEffect()=default
Constructor for QgsTransformEffect.
static QgsPaintEffect * create(const QVariantMap &map)
Creates a new QgsTransformEffect effect from a properties string map.
double translateY() const
Returns the transform y translation.
void draw(QgsRenderContext &context) override
Handles drawing of the effect's result on to the specified render context.
QRectF boundingRect(const QRectF &rect, const QgsRenderContext &context) const override
Returns the bounding rect required for drawing the effect.
void readProperties(const QVariantMap &props) override
Reads a string map of an effect's properties and restores the effect to the state described by the pr...
QVariantMap properties() const override
Returns the properties describing the paint effect encoded in a string format.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.