QGIS API Documentation  2.14.0-Essen
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 "qgssymbollayerv2utils.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  : QgsPaintEffect()
33  , mTranslateX( 0.0 )
34  , mTranslateY( 0.0 )
35  , mTranslateUnit( QgsSymbolV2::MM )
36  , mScaleX( 1.0 )
37  , mScaleY( 1.0 )
38  , mRotation( 0.0 )
39  , mShearX( 0.0 )
40  , mShearY( 0.0 )
41  , mReflectX( false )
42  , mReflectY( false )
43 {
44 
45 }
46 
48 {
49 
50 }
51 
53 {
54  if ( !source() || !enabled() || !context.painter() )
55  return;
56 
57  QPainter* painter = context.painter();
58 
59  //apply transformations
60  painter->save();
61 
62  QTransform t = createTransform( context );
63  painter->setTransform( t, true );
64  drawSource( *painter );
65 
66  painter->restore();
67 }
68 
70 {
71  QgsStringMap props;
72  props.insert( "reflect_x", mReflectX ? "1" : "0" );
73  props.insert( "reflect_y", mReflectY ? "1" : "0" );
74  props.insert( "scale_x", QString::number( mScaleX ) );
75  props.insert( "scale_y", QString::number( mScaleY ) );
76  props.insert( "rotation", QString::number( mRotation ) );
77  props.insert( "shear_x", QString::number( mShearX ) );
78  props.insert( "shear_y", QString::number( mShearY ) );
79  props.insert( "translate_x", QString::number( mTranslateX ) );
80  props.insert( "translate_y", QString::number( mTranslateY ) );
81  props.insert( "translate_unit", QgsSymbolLayerV2Utils::encodeOutputUnit( mTranslateUnit ) );
82  props.insert( "translate_unit_scale", QgsSymbolLayerV2Utils::encodeMapUnitScale( mTranslateMapUnitScale ) );
83  props.insert( "enabled", mEnabled ? "1" : "0" );
84  props.insert( "draw_mode", QString::number( int( mDrawMode ) ) );
85  return props;
86 }
87 
89 {
90  mEnabled = props.value( "enabled", "1" ).toInt();
91  mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( "draw_mode", "2" ).toInt() );
92  mReflectX = props.value( "reflect_x", "0" ).toInt();
93  mReflectY = props.value( "reflect_y", "0" ).toInt();
94  mScaleX = props.value( "scale_x", "1.0" ).toDouble();
95  mScaleY = props.value( "scale_y", "1.0" ).toDouble();
96  mRotation = props.value( "rotation", "0.0" ).toDouble();
97  mTranslateX = props.value( "translate_x", "0.0" ).toDouble();
98  mTranslateY = props.value( "translate_y", "0.0" ).toDouble();
99  mTranslateUnit = QgsSymbolLayerV2Utils::decodeOutputUnit( props.value( "translate_unit" ) );
100  mTranslateMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( props.value( "translate_unit_scale" ) );
101 }
102 
104 {
105  QgsTransformEffect* newEffect = new QgsTransformEffect( *this );
106  return newEffect;
107 }
108 
110 {
111  QTransform t = createTransform( context );
112  return t.mapRect( rect );
113 }
114 
115 QTransform QgsTransformEffect::createTransform( const QgsRenderContext& context ) const
116 {
117  QTransform t;
118 
119  if ( !source() )
120  return t;
121 
122  int width = source()->boundingRect().width();
123  int height = source()->boundingRect().height();
124  int top = source()->boundingRect().top();
125  int left = source()->boundingRect().left();
126 
127  //remember that the below operations are effectively performed in the opposite order
128  //so, first the reflection applies, then scale, shear, rotate and lastly translation
129 
130  double translateX = mTranslateX *
131  QgsSymbolLayerV2Utils::pixelSizeScaleFactor( context, mTranslateUnit, mTranslateMapUnitScale );
132  double translateY = mTranslateY *
133  QgsSymbolLayerV2Utils::pixelSizeScaleFactor( context, mTranslateUnit, mTranslateMapUnitScale );
134 
135  t.translate( translateX + left + width / 2.0,
136  translateY + top + height / 2.0 );
137 
138  t.rotate( mRotation );
139  t.shear( mShearX, mShearY );
140  t.scale( mScaleX, mScaleY );
141 
142  if ( mReflectX || mReflectY )
143  {
144  t.scale( mReflectX ? -1 : 1, mReflectY ? -1 : 1 );
145  }
146 
147  t.translate( -left - width / 2.0,
148  -top - height / 2.0 );
149 
150  return t;
151 }
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
void setTransform(const QTransform &transform, bool combine)
QRect boundingRect() const
DrawMode mDrawMode
virtual 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...
virtual 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.
void save()
int height() const
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
double translateY() const
Returns the transform y translation.
static double pixelSizeScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns scale factor painter units -> pixel dimensions.
static QgsSymbolV2::OutputUnit decodeOutputUnit(const QString &str)
QTransform & translate(qreal dx, qreal dy)
QString number(int n, int base)
double translateX() const
Returns the transform x translation.
QTransform & scale(qreal sx, qreal sy)
int top() const
int left() const
static QgsPaintEffect * create(const QgsStringMap &map)
Creates a new QgsTransformEffect effect from a properties string map.
DrawMode
Drawing modes for effects.
A paint effect which applies transformations (such as move, scale and rotate) to a picture...
void restore()
QTransform & rotate(qreal angle, Qt::Axis axis)
Contains information about the context of a rendering operation.
int width() const
QPainter * painter()
virtual QgsStringMap properties() const override
Returns the properties describing the paint effect encoded in a string format.
void drawSource(QPainter &painter)
Draws the source QPicture onto the specified painter.
iterator insert(const Key &key, const T &value)
const QPicture * source() const
Returns the source QPicture.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
virtual QRectF boundingRect(const QRectF &rect, const QgsRenderContext &context) const override
Returns the bounding rect required for drawing the effect.
QTransform & shear(qreal sh, qreal sv)
virtual QgsTransformEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
QRect mapRect(const QRect &rectangle) const
const T value(const Key &key) const