QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
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 ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 90.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) || qgsDoubleNear( clippedRotation, 270.0 ) )
161  {
162  double rectScale;
163  if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
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 ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
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 {
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 
322 {
324  for ( ; i != dataDefinedNames->constEnd(); ++i )
325  {
326  QString elemName = i.value();
327  QDomNodeList ddNodeList = itemElem.elementsByTagName( elemName );
328  if ( !ddNodeList.isEmpty() )
329  {
330  QDomElement ddElem = ddNodeList.at( 0 ).toElement();
331  readDataDefinedProperty( i.key(), ddElem, dataDefinedProperties );
332  }
333  }
334 }
335 
337 {
338  if ( property == QgsComposerObject::AllProperties || property == QgsComposerObject::NoProperty )
339  {
340  //invalid property
341  return;
342  }
343 
345 
346  QgsDataDefined* dd = nullptr;
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  dd->setField( ddElem.attribute( "field" ) );
369  dd->setExpressionString( ddElem.attribute( "expr" ) );
370  QString useExpr = ddElem.attribute( "useExpr" );
371  if ( useExpr.compare( "true", Qt::CaseInsensitive ) == 0 )
372  {
373  dd->setUseExpression( true );
374  }
375  else
376  {
377  dd->setUseExpression( false );
378  }
379 }
380 
382 {
384  for ( ; i != dataDefinedNames->constEnd(); ++i )
385  {
386  QString newElemName = i.value();
387 
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 
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 
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 
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 
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, 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 double QgsComposerUtils::textHeightMM( const QFont &font, const QString &text, double multiLineHeight )
485 {
486  QStringList multiLineSplit = text.split( '\n' );
487  int lines = multiLineSplit.size();
488 
489  //upscale using FONT_WORKAROUND_SCALE
490  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
491  QFont metricsFont = scaledFontPixelSize( font );
492  QFontMetricsF fontMetrics( metricsFont );
493 
494  double fontHeight = fontMetrics.ascent() + fontMetrics.descent(); // ignore +1 for baseline
495  double textHeight = fontMetrics.ascent() + static_cast< double >(( lines - 1 ) * fontHeight * multiLineHeight );
496 
497  return textHeight / FONT_WORKAROUND_SCALE;
498 }
499 
500 void QgsComposerUtils::drawText( QPainter *painter, QPointF pos, const QString &text, const QFont &font, const QColor &color )
501 {
502  if ( !painter )
503  {
504  return;
505  }
506 
507  //upscale using FONT_WORKAROUND_SCALE
508  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
509  QFont textFont = scaledFontPixelSize( font );
510 
511  painter->save();
512  painter->setFont( textFont );
513  if ( color.isValid() )
514  {
515  painter->setPen( color );
516  }
517  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
518  painter->scale( scaleFactor, scaleFactor );
519  painter->drawText( pos * FONT_WORKAROUND_SCALE, text );
520  painter->restore();
521 }
522 
523 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 )
524 {
525  if ( !painter )
526  {
527  return;
528  }
529 
530  //upscale using FONT_WORKAROUND_SCALE
531  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
532  QFont textFont = scaledFontPixelSize( font );
533 
534  QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
536 
537  painter->save();
538  painter->setFont( textFont );
539  if ( color.isValid() )
540  {
541  painter->setPen( color );
542  }
543  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
544  painter->scale( scaleFactor, scaleFactor );
545  painter->drawText( scaledRect, halignment | valignment | flags, text );
546  painter->restore();
547 }
static void relativeResizeRect(QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter)
Resizes a QRectF relative to a resized bounding rectangle.
QDomNodeList elementsByTagName(const QString &tagname) const
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.
QDomNode appendChild(const QDomNode &newChild)
qreal x() const
qreal y() const
QString attribute(const QString &name, const QString &defValue) const
static double angle(QPointF p1, QPointF p2)
Calculates the angle of the line from p1 to p2 (counter clockwise, starting from a line from north to...
qreal pointSizeF() const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) 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.
void scale(qreal sx, qreal sy)
const_iterator constBegin() const
static void readDataDefinedPropertyMap(const QDomElement &itemElem, QMap< QgsComposerObject::DataDefinedProperty, QString > *dataDefinedNames, QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined * > *dataDefinedProperties)
Reads all data defined properties from xml.
static void drawText(QPainter *painter, 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 ...
void save()
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
void setJoinStyle(Qt::PenJoinStyle style)
qreal top() const
static double fontAscentMM(const QFont &font)
Calculate font ascent in millimeters, including workarounds for QT font rendering issues...
const_iterator constFind(const Key &key) const
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...
void setStyle(Qt::BrushStyle style)
qreal width(const QString &text) const
qreal left() const
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
DataDefinedProperty
Data defined properties for different item types.
int size() const
bool useExpression() const
Returns if the field or the expression part is active.
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.
QDomElement toElement() const
qreal bottom() const
bool isEmpty() const
void setPixelSize(int pixelSize)
void setUseExpression(bool use)
Controls if the field or the expression part is active.
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.
void setFont(const QFont &font)
static double fontHeightCharacterMM(const QFont &font, QChar character)
Calculate font height in millimeters of a single character, including workarounds for QT font renderi...
qreal x() const
qreal y() const
void setPen(const QColor &color)
QRectF boundingRect(const QString &text) const
void setAttribute(const QString &name, const QString &value)
void setField(const QString &field)
Set the field name which this QgsDataDefined represents.
QString expressionString() const
Returns the expression string of this QgsDataDefined.
bool isEmpty() const
const_iterator constEnd() const
#define M_PI
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.
void setBrush(const QBrush &brush)
void drawText(const QPointF &position, const QString &text)
const T & value() 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)
qreal right() const
const QBrush & brush() const
QString field() const
Get the field which this QgsDataDefined represents.
static bool decodePresetPaperSize(const QString &presetString, double &width, double &height)
Decodes a string representing a preset page size.
void restore()
const Key key(const T &value) const
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...
qreal width() const
qreal ascent() const
void setX(qreal x)
void setY(qreal y)
static double textHeightMM(const QFont &font, const QString &text, double multiLineHeight=1.0)
Calculate font height in millimeters for a string, including workarounds for QT font rendering issues...
qreal descent() const
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.
qreal height() const
#define FONT_WORKAROUND_SCALE
iterator insert(const Key &key, const T &value)
void setRect(qreal x, qreal y, qreal width, qreal height)
const_iterator constEnd() const
QDomElement createElement(const QString &tagName)
const_iterator constBegin() const
int compare(const QString &other) const
const QPen & pen() const
void setExpressionString(const QString &expr)
Sets the expression for this QgsDataDefined.
bool isActive() const
iterator find(const Key &key)
static QgsComposition::PaperOrientation decodePaperOrientation(const QString &orientationString, bool &ok)
Decodes a string representing a paper orientation.
qreal height() const
bool isValid() const
QDomNode at(int index) const
const T value(const Key &key) const
static double mmToPoints(const double mmSize)
Returns the size in mm corresponding to a font point size.