QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgscomposerutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposerutils.cpp
3  -------------------
4  begin : July 2014
5  copyright : (C) 2014 by 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 "qgscomposerutils.h"
19 #include "qgscomposition.h"
20 #include "qgsdatadefined.h"
21 #include <QPainter>
22 
23 #define FONT_WORKAROUND_SCALE 10 //scale factor for upscaling fontsize and downscaling painter
24 
25 #ifndef M_DEG2RAD
26 #define M_DEG2RAD 0.0174532925
27 #endif
28 
29 void QgsComposerUtils::drawArrowHead( QPainter *p, const double x, const double y, const double angle, const double arrowHeadWidth )
30 {
31  if ( !p )
32  {
33  return;
34  }
35 
36  double angleRad = angle / 180.0 * M_PI;
37  QPointF middlePoint( x, y );
38  //rotate both arrow points
39  QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
40  QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
41 
42  QPointF p1Rotated, p2Rotated;
43  p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
44  p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
45  p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
46  p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );
47 
48  QPolygonF arrowHeadPoly;
49  arrowHeadPoly << middlePoint;
50  arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
51  arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
52 
53  p->save();
54 
55  QPen arrowPen = p->pen();
56  arrowPen.setJoinStyle( Qt::RoundJoin );
57  QBrush arrowBrush = p->brush();
58  arrowBrush.setStyle( Qt::SolidPattern );
59  p->setPen( arrowPen );
60  p->setBrush( arrowBrush );
61  arrowBrush.setStyle( Qt::SolidPattern );
62  p->drawPolygon( arrowHeadPoly );
63 
64  p->restore();
65 }
66 
67 double QgsComposerUtils::angle( const QPointF &p1, const QPointF &p2 )
68 {
69  double xDiff = p2.x() - p1.x();
70  double yDiff = p2.y() - p1.y();
71  double length = sqrt( xDiff * xDiff + yDiff * yDiff );
72  if ( length <= 0 )
73  {
74  return 0;
75  }
76 
77  double angle = acos(( -yDiff * length ) / ( length * length ) ) * 180 / M_PI;
78  if ( xDiff < 0 )
79  {
80  return ( 360 - angle );
81  }
82  return angle;
83 }
84 
85 void QgsComposerUtils::rotate( const double angle, double &x, double &y )
86 {
87  double rotToRad = angle * M_PI / 180.0;
88  double xRot, yRot;
89  xRot = x * cos( rotToRad ) - y * sin( rotToRad );
90  yRot = x * sin( rotToRad ) + y * cos( rotToRad );
91  x = xRot;
92  y = yRot;
93 }
94 
96 {
97  double clippedAngle = angle;
98  if ( clippedAngle >= 360.0 || clippedAngle <= -360.0 )
99  {
100  clippedAngle = fmod( clippedAngle, 360.0 );
101  }
102  if ( clippedAngle < 0.0 )
103  {
104  clippedAngle += 360.0;
105  }
106  return clippedAngle;
107 }
108 
109 double QgsComposerUtils::snappedAngle( const double angle )
110 {
111  //normalize angle to 0-360 degrees
112  double clippedAngle = normalizedAngle( angle );
113 
114  //snap angle to 45 degree
115  if ( clippedAngle >= 22.5 && clippedAngle < 67.5 )
116  {
117  return 45.0;
118  }
119  else if ( clippedAngle >= 67.5 && clippedAngle < 112.5 )
120  {
121  return 90.0;
122  }
123  else if ( clippedAngle >= 112.5 && clippedAngle < 157.5 )
124  {
125  return 135.0;
126  }
127  else if ( clippedAngle >= 157.5 && clippedAngle < 202.5 )
128  {
129  return 180.0;
130  }
131  else if ( clippedAngle >= 202.5 && clippedAngle < 247.5 )
132  {
133  return 225.0;
134  }
135  else if ( clippedAngle >= 247.5 && clippedAngle < 292.5 )
136  {
137  return 270.0;
138  }
139  else if ( clippedAngle >= 292.5 && clippedAngle < 337.5 )
140  {
141  return 315.0;
142  }
143  else
144  {
145  return 0.0;
146  }
147 }
148 
149 QRectF QgsComposerUtils::largestRotatedRectWithinBounds( const QRectF originalRect, const QRectF boundsRect, const double rotation )
150 {
151  double originalWidth = originalRect.width();
152  double originalHeight = originalRect.height();
153  double boundsWidth = boundsRect.width();
154  double boundsHeight = boundsRect.height();
155  double ratioBoundsRect = boundsWidth / boundsHeight;
156 
157  double clippedRotation = normalizedAngle( rotation );
158 
159  //shortcut for some rotation values
160  if ( clippedRotation == 0 || clippedRotation == 90 || clippedRotation == 180 || clippedRotation == 270 )
161  {
162  double rectScale;
163  if ( clippedRotation == 0 || clippedRotation == 180 )
164  {
165  rectScale = (( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
166  }
167  else
168  {
169  rectScale = (( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
170  }
171  double rectScaledWidth = rectScale * originalWidth;
172  double rectScaledHeight = rectScale * originalHeight;
173 
174  if ( clippedRotation == 0 || clippedRotation == 180 )
175  {
176  return QRectF(( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
177  }
178  else
179  {
180  return QRectF(( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
181  }
182  }
183 
184  //convert angle to radians and flip
185  double angleRad = -clippedRotation * M_DEG2RAD;
186  double cosAngle = cos( angleRad );
187  double sinAngle = sin( angleRad );
188 
189  //calculate size of bounds of rotated rectangle
190  double widthBoundsRotatedRect = originalWidth * fabs( cosAngle ) + originalHeight * fabs( sinAngle );
191  double heightBoundsRotatedRect = originalHeight * fabs( cosAngle ) + originalWidth * fabs( sinAngle );
192 
193  //compare ratio of rotated rect with bounds rect and calculate scaling of rotated
194  //rect to fit within bounds
195  double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
196  double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
197  double rectScaledWidth = rectScale * originalWidth;
198  double rectScaledHeight = rectScale * originalHeight;
199 
200  //now calculate offset so that rotated rectangle is centered within bounds
201  //first calculate min x and y coordinates
202  double currentCornerX = 0;
203  double minX = 0;
204  currentCornerX += rectScaledWidth * cosAngle;
205  minX = minX < currentCornerX ? minX : currentCornerX;
206  currentCornerX += rectScaledHeight * sinAngle;
207  minX = minX < currentCornerX ? minX : currentCornerX;
208  currentCornerX -= rectScaledWidth * cosAngle;
209  minX = minX < currentCornerX ? minX : currentCornerX;
210 
211  double currentCornerY = 0;
212  double minY = 0;
213  currentCornerY -= rectScaledWidth * sinAngle;
214  minY = minY < currentCornerY ? minY : currentCornerY;
215  currentCornerY += rectScaledHeight * cosAngle;
216  minY = minY < currentCornerY ? minY : currentCornerY;
217  currentCornerY += rectScaledWidth * sinAngle;
218  minY = minY < currentCornerY ? minY : currentCornerY;
219 
220  //now calculate offset position of rotated rectangle
221  double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
222  offsetX += fabs( minX );
223  double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
224  offsetY += fabs( minY );
225 
226  return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
227 }
228 
229 double QgsComposerUtils::pointsToMM( const double pointSize )
230 {
231  //conversion to mm based on 1 point = 1/72 inch
232  return ( pointSize * 0.3527 );
233 }
234 
235 double QgsComposerUtils::mmToPoints( const double mmSize )
236 {
237  //conversion to points based on 1 point = 1/72 inch
238  return ( mmSize / 0.3527 );
239 }
240 
241 void QgsComposerUtils::relativeResizeRect( QRectF& rectToResize, const QRectF& boundsBefore, const QRectF& boundsAfter )
242 {
243  //linearly scale rectToResize relative to the scaling from boundsBefore to boundsAfter
244  double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
245  double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
246  double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
247  double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
248 
249  rectToResize.setRect( left, top, right - left, bottom - top );
250 }
251 
252 double QgsComposerUtils::relativePosition( const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax )
253 {
254  //calculate parameters for linear scale between before and after ranges
255  double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
256  double c = afterMin - ( beforeMin * m );
257 
258  //return linearly scaled position
259  return m * position + c;
260 }
261 
263 {
264  if ( orientationString.compare( "Portrait", Qt::CaseInsensitive ) == 0 )
265  {
266  ok = true;
268  }
269  if ( orientationString.compare( "Landscape", Qt::CaseInsensitive ) == 0 )
270  {
271  ok = true;
273  }
274  ok = false;
275  return QgsComposition::Landscape; // default to landscape
276 }
277 
278 bool QgsComposerUtils::decodePresetPaperSize( const QString presetString, double &width, double &height )
279 {
280  QList< QPair< QString, QSizeF > > presets;
281  presets << qMakePair( QString( "A5" ), QSizeF( 148, 210 ) );
282  presets << qMakePair( QString( "A4" ), QSizeF( 210, 297 ) );
283  presets << qMakePair( QString( "A3" ), QSizeF( 297, 420 ) );
284  presets << qMakePair( QString( "A2" ), QSizeF( 420, 594 ) );
285  presets << qMakePair( QString( "A1" ), QSizeF( 594, 841 ) );
286  presets << qMakePair( QString( "A0" ), QSizeF( 841, 1189 ) );
287  presets << qMakePair( QString( "B5" ), QSizeF( 176, 250 ) );
288  presets << qMakePair( QString( "B4" ), QSizeF( 250, 353 ) );
289  presets << qMakePair( QString( "B3" ), QSizeF( 353, 500 ) );
290  presets << qMakePair( QString( "B2" ), QSizeF( 500, 707 ) );
291  presets << qMakePair( QString( "B1" ), QSizeF( 707, 1000 ) );
292  presets << qMakePair( QString( "B0" ), QSizeF( 1000, 1414 ) );
293  // North american formats
294  presets << qMakePair( QString( "Legal" ), QSizeF( 215.9, 355.6 ) );
295  presets << qMakePair( QString( "Letter" ), QSizeF( 215.9, 279.4 ) );
296  presets << qMakePair( QString( "ANSI A" ), QSizeF( 215.9, 279.4 ) );
297  presets << qMakePair( QString( "ANSI B" ), QSizeF( 279.4, 431.8 ) );
298  presets << qMakePair( QString( "ANSI C" ), QSizeF( 431.8, 558.8 ) );
299  presets << qMakePair( QString( "ANSI D" ), QSizeF( 558.8, 863.6 ) );
300  presets << qMakePair( QString( "ANSI E" ), QSizeF( 863.6, 1117.6 ) );
301  presets << qMakePair( QString( "Arch A" ), QSizeF( 228.6, 304.8 ) );
302  presets << qMakePair( QString( "Arch B" ), QSizeF( 304.8, 457.2 ) );
303  presets << qMakePair( QString( "Arch C" ), QSizeF( 457.2, 609.6 ) );
304  presets << qMakePair( QString( "Arch D" ), QSizeF( 609.6, 914.4 ) );
305  presets << qMakePair( QString( "Arch E" ), QSizeF( 914.4, 1219.2 ) );
306  presets << qMakePair( QString( "Arch E1" ), QSizeF( 762, 1066.8 ) );
307 
308  QList< QPair< QString, QSizeF > >::const_iterator presetIt = presets.constBegin();
309  for ( ;presetIt != presets.constEnd(); ++presetIt )
310  {
311  if ( presetString.compare(( *presetIt ).first, Qt::CaseInsensitive ) == 0 )
312  {
313  width = ( *presetIt ).second.width();
314  height = ( *presetIt ).second.height();
315  return true;
316  }
317  }
318  return false;
319 }
320 
321 void QgsComposerUtils::readDataDefinedPropertyMap( const QDomElement &itemElem, QMap<QgsComposerObject::DataDefinedProperty, QString> *dataDefinedNames, QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties )
322 {
323  QMap<QgsComposerObject::DataDefinedProperty, QString>::const_iterator i = dataDefinedNames->constBegin();
324  for ( ; i != dataDefinedNames->constEnd(); ++i )
325  {
326  QString elemName = i.value();
327  QDomNodeList ddNodeList = itemElem.elementsByTagName( elemName );
328  if ( ddNodeList.size() > 0 )
329  {
330  QDomElement ddElem = ddNodeList.at( 0 ).toElement();
331  readDataDefinedProperty( i.key(), ddElem, dataDefinedProperties );
332  }
333  }
334 }
335 
336 void QgsComposerUtils::readDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property, const QDomElement &ddElem, QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties )
337 {
338  if ( property == QgsComposerObject::AllProperties || property == QgsComposerObject::NoProperty )
339  {
340  //invalid property
341  return;
342  }
343 
344  QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >::const_iterator it = dataDefinedProperties->constFind( property );
345 
346  QgsDataDefined* dd = 0;
347  if ( it != dataDefinedProperties->constEnd() )
348  {
349  dd = it.value();
350  }
351  else
352  {
353  //QgsDataDefined for property doesn't currently exist, need to add new
354  dd = new QgsDataDefined( );
355  dataDefinedProperties->insert( property, dd );
356  }
357 
358  //set values for QgsDataDefined
359  QString active = ddElem.attribute( "active" );
360  if ( active.compare( "true", Qt::CaseInsensitive ) == 0 )
361  {
362  dd->setActive( true );
363  }
364  else
365  {
366  dd->setActive( false );
367  }
368  QString useExpr = ddElem.attribute( "useExpr" );
369  if ( useExpr.compare( "true", Qt::CaseInsensitive ) == 0 )
370  {
371  dd->setUseExpression( true );
372  }
373  else
374  {
375  dd->setUseExpression( false );
376  }
377  dd->setField( ddElem.attribute( "field" ) );
378  dd->setExpressionString( ddElem.attribute( "expr" ) );
379 }
380 
381 void QgsComposerUtils::writeDataDefinedPropertyMap( QDomElement &itemElem, QDomDocument &doc, const QMap<QgsComposerObject::DataDefinedProperty, QString> *dataDefinedNames, const QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties )
382 {
383  QMap<QgsComposerObject::DataDefinedProperty, QString >::const_iterator i = dataDefinedNames->constBegin();
384  for ( ; i != dataDefinedNames->constEnd(); ++i )
385  {
386  QString newElemName = i.value();
387 
388  QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >::const_iterator it = dataDefinedProperties->find( i.key() );
389  if ( it != dataDefinedProperties->constEnd() )
390  {
391  QgsDataDefined* dd = it.value();
392  if ( dd )
393  {
394  bool active = dd->isActive();
395  bool useExpr = dd->useExpression();
396  QString expr = dd->expressionString();
397  QString field = dd->field();
398 
399  bool defaultVals = ( !active && !useExpr && expr.isEmpty() && field.isEmpty() );
400 
401  if ( !defaultVals )
402  {
403  QDomElement ddElem = doc.createElement( newElemName );
404  if ( active )
405  {
406  ddElem.setAttribute( "active", "true" );
407  }
408  else
409  {
410  ddElem.setAttribute( "active", "false" );
411  }
412  if ( useExpr )
413  {
414  ddElem.setAttribute( "useExpr", "true" );
415  }
416  else
417  {
418  ddElem.setAttribute( "useExpr", "false" );
419  }
420  ddElem.setAttribute( "expr", expr );
421  ddElem.setAttribute( "field", field );
422  itemElem.appendChild( ddElem );
423  }
424  }
425  }
426  }
427 }
428 
429 QFont QgsComposerUtils::scaledFontPixelSize( const QFont &font )
430 {
431  //upscale using FONT_WORKAROUND_SCALE
432  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
433  QFont scaledFont = font;
434  double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
435  scaledFont.setPixelSize( pixelSize );
436  return scaledFont;
437 }
438 
439 double QgsComposerUtils::fontAscentMM( const QFont &font )
440 {
441  //upscale using FONT_WORKAROUND_SCALE
442  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
443  QFont metricsFont = scaledFontPixelSize( font );
444  QFontMetricsF fontMetrics( metricsFont );
445  return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
446 }
447 
448 double QgsComposerUtils::fontDescentMM( const QFont &font )
449 {
450  //upscale using FONT_WORKAROUND_SCALE
451  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
452  QFont metricsFont = scaledFontPixelSize( font );
453  QFontMetricsF fontMetrics( metricsFont );
454  return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
455 }
456 
457 double QgsComposerUtils::fontHeightMM( const QFont &font )
458 {
459  //upscale using FONT_WORKAROUND_SCALE
460  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
461  QFont metricsFont = scaledFontPixelSize( font );
462  QFontMetricsF fontMetrics( metricsFont );
463  return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
464 }
465 
466 double QgsComposerUtils::fontHeightCharacterMM( const QFont &font, const QChar &character )
467 {
468  //upscale using FONT_WORKAROUND_SCALE
469  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
470  QFont metricsFont = scaledFontPixelSize( font );
471  QFontMetricsF fontMetrics( metricsFont );
472  return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
473 }
474 
475 double QgsComposerUtils::textWidthMM( const QFont &font, const QString &text )
476 {
477  //upscale using FONT_WORKAROUND_SCALE
478  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
479  QFont metricsFont = scaledFontPixelSize( font );
480  QFontMetricsF fontMetrics( metricsFont );
481  return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
482 }
483 
484 void QgsComposerUtils::drawText( QPainter *painter, const QPointF &pos, const QString &text, const QFont &font, const QColor &color )
485 {
486  if ( !painter )
487  {
488  return;
489  }
490 
491  //upscale using FONT_WORKAROUND_SCALE
492  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
493  QFont textFont = scaledFontPixelSize( font );
494 
495  painter->save();
496  painter->setFont( textFont );
497  if ( color.isValid() )
498  {
499  painter->setPen( color );
500  }
501  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
502  painter->scale( scaleFactor, scaleFactor );
503  painter->drawText( pos * FONT_WORKAROUND_SCALE, text );
504  painter->restore();
505 }
506 
507 void QgsComposerUtils::drawText( QPainter *painter, const QRectF &rect, const QString &text, const QFont &font, const QColor &color, const Qt::AlignmentFlag halignment, const Qt::AlignmentFlag valignment, const int flags )
508 {
509  if ( !painter )
510  {
511  return;
512  }
513 
514  //upscale using FONT_WORKAROUND_SCALE
515  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
516  QFont textFont = scaledFontPixelSize( font );
517 
518  QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
519  rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
520 
521  painter->save();
522  painter->setFont( textFont );
523  if ( color.isValid() )
524  {
525  painter->setPen( color );
526  }
527  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
528  painter->scale( scaleFactor, scaleFactor );
529  painter->drawText( scaledRect, halignment | valignment | flags, text );
530  painter->restore();
531 }
static void relativeResizeRect(QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter)
Resizes a QRectF relative to a resized bounding rectangle.
void setActive(bool active)
#define M_DEG2RAD
A container class for data source field mapping or expression.
static double normalizedAngle(const double angle)
Ensures that an angle is in the range 0 <= angle < 360.
QString field() const
static double relativePosition(const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax)
Returns a scaled position given a before and after range.
static void readDataDefinedPropertyMap(const QDomElement &itemElem, QMap< QgsComposerObject::DataDefinedProperty, QString > *dataDefinedNames, QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined * > *dataDefinedProperties)
Reads all data defined properties from xml.
static QRectF largestRotatedRectWithinBounds(const QRectF originalRect, const QRectF boundsRect, const double rotation)
Calculates the largest scaled version of originalRect which fits within boundsRect, when it is rotated by a specified amount.
static void drawText(QPainter *painter, const QPointF &pos, const QString &text, const QFont &font, const QColor &color=QColor())
Draws text on a painter at a specific position, taking care of composer specific issues (calculation ...
QString expressionString() const
static double fontAscentMM(const QFont &font)
Calculate font ascent in millimeters, including workarounds for QT font rendering issues...
static QFont scaledFontPixelSize(const QFont &font)
Returns a font where size is set in pixels and the size has been upscaled with FONT_WORKAROUND_SCALE ...
static void writeDataDefinedPropertyMap(QDomElement &itemElem, QDomDocument &doc, const QMap< QgsComposerObject::DataDefinedProperty, QString > *dataDefinedNames, const QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined * > *dataDefinedProperties)
Writes data defined properties to xml.
static double fontDescentMM(const QFont &font)
Calculate font descent in millimeters, including workarounds for QT font rendering issues...
DataDefinedProperty
Data defined properties for different item types.
static void readDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property, const QDomElement &ddElem, QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined * > *dataDefinedProperties)
Reads a single data defined property from xml DOM element.
void setUseExpression(bool use)
static void drawArrowHead(QPainter *p, const double x, const double y, const double angle, const double arrowHeadWidth)
Draws an arrow head on to a QPainter.
static QgsComposition::PaperOrientation decodePaperOrientation(const QString orientationString, bool &ok)
Decodes a string representing a paper orientation.
static double fontHeightCharacterMM(const QFont &font, const QChar &character)
Calculate font height in millimeters of a single character, including workarounds for QT font renderi...
void setField(const QString &field)
#define M_PI
static bool decodePresetPaperSize(const QString presetString, double &width, double &height)
Decodes a string representing a preset page size.
bool useExpression() const
static void rotate(const double angle, double &x, double &y)
Rotates a point / vector around the origin.
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
static double textWidthMM(const QFont &font, const QString &text)
Calculate font width in millimeters for a string, including workarounds for QT font rendering issues...
static double fontHeightMM(const QFont &font)
Calculate font height in millimeters, including workarounds for QT font rendering issues The font hei...
static double pointsToMM(const double pointSize)
Returns the size in mm corresponding to a font point size.
static double snappedAngle(const double angle)
Snaps an angle to its closest 45 degree angle.
#define FONT_WORKAROUND_SCALE
static double angle(const QPointF &p1, const QPointF &p2)
Calculates the angle of the line from p1 to p2 (counter clockwise, starting from a line from north to...
void setExpressionString(const QString &expr)
bool isActive() const
static double mmToPoints(const double mmSize)
Returns the size in mm corresponding to a font point size.