QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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  painter->save();
40 
41  QTransform t = createTransform( context );
42  painter->setTransform( t, true );
43  drawSource( *painter );
44 
45  painter->restore();
46 }
47 
49 {
50  QgsStringMap props;
51  props.insert( QStringLiteral( "reflect_x" ), mReflectX ? "1" : "0" );
52  props.insert( QStringLiteral( "reflect_y" ), mReflectY ? "1" : "0" );
53  props.insert( QStringLiteral( "scale_x" ), QString::number( mScaleX ) );
54  props.insert( QStringLiteral( "scale_y" ), QString::number( mScaleY ) );
55  props.insert( QStringLiteral( "rotation" ), QString::number( mRotation ) );
56  props.insert( QStringLiteral( "shear_x" ), QString::number( mShearX ) );
57  props.insert( QStringLiteral( "shear_y" ), QString::number( mShearY ) );
58  props.insert( QStringLiteral( "translate_x" ), QString::number( mTranslateX ) );
59  props.insert( QStringLiteral( "translate_y" ), QString::number( mTranslateY ) );
60  props.insert( QStringLiteral( "translate_unit" ), QgsUnitTypes::encodeUnit( mTranslateUnit ) );
61  props.insert( QStringLiteral( "translate_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mTranslateMapUnitScale ) );
62  props.insert( QStringLiteral( "enabled" ), mEnabled ? "1" : "0" );
63  props.insert( QStringLiteral( "draw_mode" ), QString::number( int( mDrawMode ) ) );
64  return props;
65 }
66 
68 {
69  mEnabled = props.value( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt();
70  mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( QStringLiteral( "draw_mode" ), QStringLiteral( "2" ) ).toInt() );
71  mReflectX = props.value( QStringLiteral( "reflect_x" ), QStringLiteral( "0" ) ).toInt();
72  mReflectY = props.value( QStringLiteral( "reflect_y" ), QStringLiteral( "0" ) ).toInt();
73  mScaleX = props.value( QStringLiteral( "scale_x" ), QStringLiteral( "1.0" ) ).toDouble();
74  mScaleY = props.value( QStringLiteral( "scale_y" ), QStringLiteral( "1.0" ) ).toDouble();
75  mRotation = props.value( QStringLiteral( "rotation" ), QStringLiteral( "0.0" ) ).toDouble();
76  mShearX = props.value( QStringLiteral( "shear_x" ), QStringLiteral( "0.0" ) ).toDouble();
77  mShearY = props.value( QStringLiteral( "shear_y" ), QStringLiteral( "0.0" ) ).toDouble();
78  mTranslateX = props.value( QStringLiteral( "translate_x" ), QStringLiteral( "0.0" ) ).toDouble();
79  mTranslateY = props.value( QStringLiteral( "translate_y" ), QStringLiteral( "0.0" ) ).toDouble();
80  mTranslateUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "translate_unit" ) ) );
81  mTranslateMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "translate_unit_scale" ) ) );
82 }
83 
85 {
86  QgsTransformEffect *newEffect = new QgsTransformEffect( *this );
87  return newEffect;
88 }
89 
90 QRectF QgsTransformEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
91 {
92  QTransform t = createTransform( context );
93  return t.mapRect( rect );
94 }
95 
96 QTransform QgsTransformEffect::createTransform( const QgsRenderContext &context ) const
97 {
98  QTransform t;
99 
100  if ( !source() )
101  return t;
102 
103  int width = source()->boundingRect().width();
104  int height = source()->boundingRect().height();
105  int top = source()->boundingRect().top();
106  int left = source()->boundingRect().left();
107 
108  //remember that the below operations are effectively performed in the opposite order
109  //so, first the reflection applies, then scale, shear, rotate and lastly translation
110 
111  double translateX = context.convertToPainterUnits( mTranslateX, mTranslateUnit, mTranslateMapUnitScale );
112  double translateY = context.convertToPainterUnits( mTranslateY, mTranslateUnit, mTranslateMapUnitScale );
113 
114  t.translate( translateX + left + width / 2.0,
115  translateY + top + height / 2.0 );
116 
117  t.rotate( mRotation );
118  t.shear( mShearX, mShearY );
119  t.scale( mScaleX, mScaleY );
120 
121  if ( mReflectX || mReflectY )
122  {
123  t.scale( mReflectX ? -1 : 1, mReflectY ? -1 : 1 );
124  }
125 
126  t.translate( -left - width / 2.0,
127  -top - height / 2.0 );
128 
129  return t;
130 }
DrawMode mDrawMode
void readProperties(const QgsStringMap &props) override
Reads a string map of an effect&#39;s properties and restores the effect to the state described by the pr...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
void draw(QgsRenderContext &context) override
Handles drawing of the effect&#39;s result on to the specified render context.
bool enabled() const
Returns whether the effect is enabled.
Base class for visual effects which can be applied to QPicture drawings.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
double translateY() const
Returns the transform y translation.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:577
double translateX() const
Returns the transform x translation.
static QgsPaintEffect * create(const QgsStringMap &map)
Creates a new QgsTransformEffect effect from a properties string map.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
DrawMode
Drawing modes for effects.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
A paint effect which applies transformations (such as move, scale and rotate) to a picture...
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsStringMap properties() const override
Returns the properties describing the paint effect encoded in a string format.
QgsTransformEffect()=default
Constructor for QgsTransformEffect.
void drawSource(QPainter &painter)
Draws the source QPicture onto the specified painter.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
const QPicture * source() const
Returns the source QPicture.
QRectF boundingRect(const QRectF &rect, const QgsRenderContext &context) const override
Returns the bounding rect required for drawing the effect.
QgsTransformEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.