QGIS API Documentation  2.12.0-Lyon
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 <QPicture>
21 #include <QTransform>
22 
24 {
25  QgsTransformEffect* newEffect = new QgsTransformEffect();
26  newEffect->readProperties( map );
27  return newEffect;
28 }
29 
31  : QgsPaintEffect()
32  , mTranslateX( 0.0 )
33  , mTranslateY( 0.0 )
34  , mTranslateUnit( QgsSymbolV2::MM )
35  , mScaleX( 1.0 )
36  , mScaleY( 1.0 )
37  , mRotation( 0.0 )
38  , mShearX( 0.0 )
39  , mShearY( 0.0 )
40  , mReflectX( false )
41  , mReflectY( false )
42 {
43 
44 }
45 
47 {
48 
49 }
50 
52 {
53  if ( !source() || !enabled() || !context.painter() )
54  return;
55 
56  QPainter* painter = context.painter();
57 
58  //apply transformations
59  painter->save();
60 
61  QTransform t = createTransform( context );
62  painter->setTransform( t, true );
63  drawSource( *painter );
64 
65  painter->restore();
66 }
67 
69 {
70  QgsStringMap props;
71  props.insert( "reflect_x", mReflectX ? "1" : "0" );
72  props.insert( "reflect_y", mReflectY ? "1" : "0" );
73  props.insert( "scale_x", QString::number( mScaleX ) );
74  props.insert( "scale_y", QString::number( mScaleY ) );
75  props.insert( "rotation", QString::number( mRotation ) );
76  props.insert( "shear_x", QString::number( mShearX ) );
77  props.insert( "shear_y", QString::number( mShearY ) );
78  props.insert( "translate_x", QString::number( mTranslateX ) );
79  props.insert( "translate_y", QString::number( mTranslateY ) );
80  props.insert( "translate_unit", QgsSymbolLayerV2Utils::encodeOutputUnit( mTranslateUnit ) );
81  props.insert( "translate_unit_scale", QgsSymbolLayerV2Utils::encodeMapUnitScale( mTranslateMapUnitScale ) );
82  props.insert( "enabled", mEnabled ? "1" : "0" );
83  props.insert( "draw_mode", QString::number( int( mDrawMode ) ) );
84  return props;
85 }
86 
88 {
89  mEnabled = props.value( "enabled", "1" ).toInt();
90  mDrawMode = ( QgsPaintEffect::DrawMode )props.value( "draw_mode", "2" ).toInt();
91  mReflectX = props.value( "reflect_x", "0" ).toInt();
92  mReflectY = props.value( "reflect_y", "0" ).toInt();
93  mScaleX = props.value( "scale_x", "1.0" ).toDouble();
94  mScaleY = props.value( "scale_y", "1.0" ).toDouble();
95  mRotation = props.value( "rotation", "0.0" ).toDouble();
96  mTranslateX = props.value( "translate_x", "0.0" ).toDouble();
97  mTranslateY = props.value( "translate_y", "0.0" ).toDouble();
98  mTranslateUnit = QgsSymbolLayerV2Utils::decodeOutputUnit( props.value( "translate_unit" ) );
99  mTranslateMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( props.value( "translate_unit_scale" ) );
100 }
101 
103 {
104  QgsTransformEffect* newEffect = new QgsTransformEffect( *this );
105  return newEffect;
106 }
107 
109 {
110  QTransform t = createTransform( context );
111  return t.mapRect( rect );
112 }
113 
114 QTransform QgsTransformEffect::createTransform( const QgsRenderContext& context ) const
115 {
116  QTransform t;
117 
118  if ( !source() )
119  return t;
120 
121  int width = source()->boundingRect().width();
122  int height = source()->boundingRect().height();
123  int top = source()->boundingRect().top();
124  int left = source()->boundingRect().left();
125 
126  //remember that the below operations are effectively performed in the opposite order
127  //so, first the reflection applies, then scale, shear, rotate and lastly translation
128 
129  double translateX = mTranslateX *
130  QgsSymbolLayerV2Utils::pixelSizeScaleFactor( context, mTranslateUnit, mTranslateMapUnitScale );
131  double translateY = mTranslateY *
132  QgsSymbolLayerV2Utils::pixelSizeScaleFactor( context, mTranslateUnit, mTranslateMapUnitScale );
133 
134  t.translate( translateX + left + width / 2.0,
135  translateY + top + height / 2.0 );
136 
137  t.rotate( mRotation );
138  t.shear( mShearX, mShearY );
139  t.scale( mScaleX, mScaleY );
140 
141  if ( mReflectX || mReflectY )
142  {
143  t.scale( mReflectX ? -1 : 1, mReflectY ? -1 : 1 );
144  }
145 
146  t.translate( -left - width / 2.0,
147  -top - height / 2.0 );
148 
149  return t;
150 }
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's properties and restores the effect to the state described by the pr...
static QgsPaintEffect * create(const QgsStringMap &)
Creates a new QgsTransformEffect effect from a properties string map.
virtual void draw(QgsRenderContext &context) override
Handles drawing of the effect'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
virtual QgsPaintEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
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)
QRect mapRect(const QRect &rectangle) const
const T value(const Key &key) const