@@ -38,6 +38,7 @@ QgsComposerPicture::QgsComposerPicture( QgsComposition *composition ) :
38
38
mPictureRotation( 0 ),
39
39
mRotationMap( 0 ),
40
40
mResizeMode( QgsComposerPicture::Zoom ),
41
+ mPictureAnchor( UpperLeft ),
41
42
mPictureExpr( 0 )
42
43
{
43
44
mPictureWidth = rect ().width ();
@@ -50,6 +51,7 @@ QgsComposerPicture::QgsComposerPicture() : QgsComposerItem( 0 ),
50
51
mPictureRotation( 0 ),
51
52
mRotationMap( 0 ),
52
53
mResizeMode( QgsComposerPicture::Zoom ),
54
+ mPictureAnchor( UpperLeft ),
53
55
mPictureExpr( 0 )
54
56
{
55
57
mPictureHeight = rect ().height ();
@@ -90,40 +92,99 @@ void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsIte
90
92
91
93
// int newDpi = ( painter->device()->logicalDpiX() + painter->device()->logicalDpiY() ) / 2;
92
94
95
+ // picture resizing
93
96
if ( mMode != Unknown )
94
97
{
95
98
double boundRectWidthMM;
96
99
double boundRectHeightMM;
97
- double imageRectWidthMM;
98
- double imageRectHeightMM;
100
+ QRect imageRect;
99
101
if ( mResizeMode == QgsComposerPicture::Zoom || mResizeMode == QgsComposerPicture::ZoomResizeFrame )
100
102
{
101
103
boundRectWidthMM = mPictureWidth ;
102
104
boundRectHeightMM = mPictureHeight ;
103
- imageRectWidthMM = mImage .width ();
104
- imageRectHeightMM = mImage .height ();
105
+ imageRect = QRect ( 0 , 0 , mImage .width (), mImage .height () );
105
106
}
106
107
else if ( mResizeMode == QgsComposerPicture::Stretch )
107
108
{
108
109
boundRectWidthMM = rect ().width ();
109
110
boundRectHeightMM = rect ().height ();
110
- imageRectWidthMM = mImage .width ();
111
- imageRectHeightMM = mImage .height ();
111
+ imageRect = QRect ( 0 , 0 , mImage .width (), mImage .height () );
112
+ }
113
+ else if ( mResizeMode == QgsComposerPicture::Clip )
114
+ {
115
+ boundRectWidthMM = rect ().width ();
116
+ boundRectHeightMM = rect ().height ();
117
+ int imageRectWidthPixels = mImage .width ();
118
+ int imageRectHeightPixels = mImage .height ();
119
+ imageRect = clippedImageRect ( boundRectWidthMM, boundRectHeightMM ,
120
+ QSize ( imageRectWidthPixels, imageRectHeightPixels ) );
112
121
}
113
122
else
114
123
{
115
124
boundRectWidthMM = rect ().width ();
116
125
boundRectHeightMM = rect ().height ();
117
- imageRectWidthMM = rect ().width () * mComposition ->printResolution () / 25.4 ;
118
- imageRectHeightMM = rect ().height () * mComposition ->printResolution () / 25.4 ;
126
+ imageRect = QRect ( 0 , 0 , rect ().width () * mComposition ->printResolution () / 25.4 ,
127
+ rect ().height () * mComposition ->printResolution () / 25.4 ) ;
119
128
}
120
129
painter->save ();
121
130
131
+ // zoom mode - calculate anchor point and rotation
122
132
if ( mResizeMode == Zoom )
123
133
{
124
- painter->translate ( rect ().width () / 2.0 , rect ().height () / 2.0 );
125
- painter->rotate ( mPictureRotation );
126
- painter->translate ( -boundRectWidthMM / 2.0 , -boundRectHeightMM / 2.0 );
134
+ // TODO - allow placement modes with rotation set. for now, setting a rotation
135
+ // always places picture in center of frame
136
+ if ( mPictureRotation != 0 )
137
+ {
138
+ painter->translate ( rect ().width () / 2.0 , rect ().height () / 2.0 );
139
+ painter->rotate ( mPictureRotation );
140
+ painter->translate ( -boundRectWidthMM / 2.0 , -boundRectHeightMM / 2.0 );
141
+ }
142
+ else
143
+ {
144
+ // shift painter to edge/middle of frame depending on placement
145
+ double diffX = rect ().width () - boundRectWidthMM;
146
+ double diffY = rect ().height () - boundRectHeightMM;
147
+
148
+ double dX = 0 ;
149
+ double dY = 0 ;
150
+ switch ( mPictureAnchor )
151
+ {
152
+ case UpperLeft:
153
+ case MiddleLeft:
154
+ case LowerLeft:
155
+ // nothing to do
156
+ break ;
157
+ case UpperMiddle:
158
+ case Middle:
159
+ case LowerMiddle:
160
+ dX = diffX / 2.0 ;
161
+ break ;
162
+ case UpperRight:
163
+ case MiddleRight:
164
+ case LowerRight:
165
+ dX = diffX;
166
+ break ;
167
+ }
168
+ switch ( mPictureAnchor )
169
+ {
170
+ case UpperLeft:
171
+ case UpperMiddle:
172
+ case UpperRight:
173
+ // nothing to do
174
+ break ;
175
+ case MiddleLeft:
176
+ case Middle:
177
+ case MiddleRight:
178
+ dY = diffY / 2.0 ;
179
+ break ;
180
+ case LowerLeft:
181
+ case LowerMiddle:
182
+ case LowerRight:
183
+ dY = diffY;
184
+ break ;
185
+ }
186
+ painter->translate ( dX, dY );
187
+ }
127
188
}
128
189
129
190
if ( mMode == SVG )
@@ -132,7 +193,7 @@ void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsIte
132
193
}
133
194
else if ( mMode == RASTER )
134
195
{
135
- painter->drawImage ( QRectF ( 0 , 0 , boundRectWidthMM, boundRectHeightMM ), mImage , QRectF ( 0 , 0 , imageRectWidthMM, imageRectHeightMM ) );
196
+ painter->drawImage ( QRectF ( 0 , 0 , boundRectWidthMM, boundRectHeightMM ), mImage , imageRect );
136
197
}
137
198
138
199
painter->restore ();
@@ -146,6 +207,64 @@ void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsIte
146
207
}
147
208
}
148
209
210
+ QRect QgsComposerPicture::clippedImageRect ( double &boundRectWidthMM, double &boundRectHeightMM, QSize imageRectPixels )
211
+ {
212
+ int boundRectWidthPixels = boundRectWidthMM * mComposition ->printResolution () / 25.4 ;
213
+ int boundRectHeightPixels = boundRectHeightMM * mComposition ->printResolution () / 25.4 ;
214
+
215
+ // update boundRectWidth/Height so that they exactly match pixel bounds
216
+ boundRectWidthMM = boundRectWidthPixels * 25.4 / mComposition ->printResolution ();
217
+ boundRectHeightMM = boundRectHeightPixels * 25.4 / mComposition ->printResolution ();
218
+
219
+ // calculate part of image which fits in bounds
220
+ int leftClip = 0 ;
221
+ int topClip = 0 ;
222
+
223
+ // calculate left crop
224
+ switch ( mPictureAnchor )
225
+ {
226
+ case UpperLeft:
227
+ case MiddleLeft:
228
+ case LowerLeft:
229
+ leftClip = 0 ;
230
+ break ;
231
+ case UpperMiddle:
232
+ case Middle:
233
+ case LowerMiddle:
234
+ leftClip = ( imageRectPixels.width () - boundRectWidthPixels ) / 2 ;
235
+ break ;
236
+ case UpperRight:
237
+ case MiddleRight:
238
+ case LowerRight:
239
+ leftClip = imageRectPixels.width () - boundRectWidthPixels;
240
+ break ;
241
+ }
242
+
243
+ // calculate top crop
244
+ switch ( mPictureAnchor )
245
+ {
246
+ case UpperLeft:
247
+ case UpperMiddle:
248
+ case UpperRight:
249
+ topClip = 0 ;
250
+ break ;
251
+ case MiddleLeft:
252
+ case Middle:
253
+ case MiddleRight:
254
+ topClip = ( imageRectPixels.height () - boundRectHeightPixels ) / 2 ;
255
+ break ;
256
+ case LowerLeft:
257
+ case LowerMiddle:
258
+ case LowerRight:
259
+ topClip = imageRectPixels.height () - boundRectHeightPixels;
260
+ break ;
261
+ }
262
+
263
+
264
+ return QRect ( leftClip, topClip, boundRectWidthPixels, boundRectHeightPixels );
265
+
266
+ }
267
+
149
268
void QgsComposerPicture::setPictureFile ( const QString& path )
150
269
{
151
270
mSourceFile .setFileName ( path );
@@ -525,6 +644,8 @@ bool QgsComposerPicture::writeXML( QDomElement& elem, QDomDocument & doc ) const
525
644
composerPictureElem.setAttribute ( " pictureWidth" , QString::number ( mPictureWidth ) );
526
645
composerPictureElem.setAttribute ( " pictureHeight" , QString::number ( mPictureHeight ) );
527
646
composerPictureElem.setAttribute ( " resizeMode" , QString::number (( int )mResizeMode ) );
647
+ composerPictureElem.setAttribute ( " anchorPoint" , QString::number (( int )mPictureAnchor ) );
648
+
528
649
if ( mUseSourceExpression )
529
650
{
530
651
composerPictureElem.setAttribute ( " useExpression" , " true" );
@@ -561,6 +682,7 @@ bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocumen
561
682
mPictureWidth = itemElem.attribute ( " pictureWidth" , " 10" ).toDouble ();
562
683
mPictureHeight = itemElem.attribute ( " pictureHeight" , " 10" ).toDouble ();
563
684
mResizeMode = QgsComposerPicture::ResizeMode ( itemElem.attribute ( " resizeMode" , " 0" ).toInt () );
685
+ mPictureAnchor = QgsComposerItem::ItemPositionMode ( itemElem.attribute ( " anchorPoint" , QString ( QgsComposerItem::UpperLeft ) ).toInt () );
564
686
565
687
QDomNodeList composerItemList = itemElem.elementsByTagName ( " ComposerItem" );
566
688
if ( composerItemList.size () > 0 )
@@ -594,8 +716,6 @@ bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocumen
594
716
QString fileName = QgsProject::instance ()->readPath ( itemElem.attribute ( " file" ) );
595
717
mSourceFile .setFileName ( fileName );
596
718
597
- refreshPicture ();
598
-
599
719
// picture rotation
600
720
if ( itemElem.attribute ( " pictureRotation" , " 0" ).toDouble () != 0 )
601
721
{
@@ -619,6 +739,8 @@ bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocumen
619
739
QObject::connect ( mRotationMap , SIGNAL ( mapRotationChanged ( double ) ), this , SLOT ( setRotation ( double ) ) );
620
740
}
621
741
742
+ refreshPicture ();
743
+
622
744
emit itemChanged ();
623
745
return true ;
624
746
}
@@ -635,6 +757,12 @@ int QgsComposerPicture::rotationMap() const
635
757
}
636
758
}
637
759
760
+ void QgsComposerPicture::setPictureAnchor ( QgsComposerItem::ItemPositionMode anchor )
761
+ {
762
+ mPictureAnchor = anchor;
763
+ update ();
764
+ }
765
+
638
766
bool QgsComposerPicture::imageSizeConsideringRotation ( double & width, double & height ) const
639
767
{
640
768
// kept for api compatibility with QGIS 2.0 - use mPictureRotation
0 commit comments