QGIS API Documentation  2.99.0-Master (23ddace)
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 "qgsproperty.h"
21 #include "qgsmapsettings.h"
22 #include "qgscomposermap.h"
23 #include <QPainter>
24 
25 #define FONT_WORKAROUND_SCALE 10 //scale factor for upscaling fontsize and downscaling painter
26 
27 #ifndef M_DEG2RAD
28 #define M_DEG2RAD 0.0174532925
29 #endif
30 
31 void QgsComposerUtils::drawArrowHead( QPainter *p, const double x, const double y, const double angle, const double arrowHeadWidth )
32 {
33  if ( !p )
34  {
35  return;
36  }
37 
38  double angleRad = angle / 180.0 * M_PI;
39  QPointF middlePoint( x, y );
40  //rotate both arrow points
41  QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
42  QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
43 
44  QPointF p1Rotated, p2Rotated;
45  p1Rotated.setX( p1.x() * cos( angleRad ) + p1.y() * -sin( angleRad ) );
46  p1Rotated.setY( p1.x() * sin( angleRad ) + p1.y() * cos( angleRad ) );
47  p2Rotated.setX( p2.x() * cos( angleRad ) + p2.y() * -sin( angleRad ) );
48  p2Rotated.setY( p2.x() * sin( angleRad ) + p2.y() * cos( angleRad ) );
49 
50  QPolygonF arrowHeadPoly;
51  arrowHeadPoly << middlePoint;
52  arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
53  arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
54 
55  p->save();
56 
57  QPen arrowPen = p->pen();
58  arrowPen.setJoinStyle( Qt::RoundJoin );
59  QBrush arrowBrush = p->brush();
60  arrowBrush.setStyle( Qt::SolidPattern );
61  p->setPen( arrowPen );
62  p->setBrush( arrowBrush );
63  arrowBrush.setStyle( Qt::SolidPattern );
64  p->drawPolygon( arrowHeadPoly );
65 
66  p->restore();
67 }
68 
69 double QgsComposerUtils::angle( QPointF p1, QPointF p2 )
70 {
71  double xDiff = p2.x() - p1.x();
72  double yDiff = p2.y() - p1.y();
73  double length = sqrt( xDiff * xDiff + yDiff * yDiff );
74  if ( length <= 0 )
75  {
76  return 0;
77  }
78 
79  double angle = acos( ( -yDiff * length ) / ( length * length ) ) * 180 / M_PI;
80  if ( xDiff < 0 )
81  {
82  return ( 360 - angle );
83  }
84  return angle;
85 }
86 
87 void QgsComposerUtils::rotate( const double angle, double &x, double &y )
88 {
89  double rotToRad = angle * M_PI / 180.0;
90  double xRot, yRot;
91  xRot = x * cos( rotToRad ) - y * sin( rotToRad );
92  yRot = x * sin( rotToRad ) + y * cos( rotToRad );
93  x = xRot;
94  y = yRot;
95 }
96 
98 {
99  double clippedAngle = angle;
100  if ( clippedAngle >= 360.0 || clippedAngle <= -360.0 )
101  {
102  clippedAngle = fmod( clippedAngle, 360.0 );
103  }
104  if ( clippedAngle < 0.0 )
105  {
106  clippedAngle += 360.0;
107  }
108  return clippedAngle;
109 }
110 
111 double QgsComposerUtils::snappedAngle( const double angle )
112 {
113  //normalize angle to 0-360 degrees
114  double clippedAngle = normalizedAngle( angle );
115 
116  //snap angle to 45 degree
117  if ( clippedAngle >= 22.5 && clippedAngle < 67.5 )
118  {
119  return 45.0;
120  }
121  else if ( clippedAngle >= 67.5 && clippedAngle < 112.5 )
122  {
123  return 90.0;
124  }
125  else if ( clippedAngle >= 112.5 && clippedAngle < 157.5 )
126  {
127  return 135.0;
128  }
129  else if ( clippedAngle >= 157.5 && clippedAngle < 202.5 )
130  {
131  return 180.0;
132  }
133  else if ( clippedAngle >= 202.5 && clippedAngle < 247.5 )
134  {
135  return 225.0;
136  }
137  else if ( clippedAngle >= 247.5 && clippedAngle < 292.5 )
138  {
139  return 270.0;
140  }
141  else if ( clippedAngle >= 292.5 && clippedAngle < 337.5 )
142  {
143  return 315.0;
144  }
145  else
146  {
147  return 0.0;
148  }
149 }
150 
151 QRectF QgsComposerUtils::largestRotatedRectWithinBounds( const QRectF &originalRect, const QRectF &boundsRect, const double rotation )
152 {
153  double originalWidth = originalRect.width();
154  double originalHeight = originalRect.height();
155  double boundsWidth = boundsRect.width();
156  double boundsHeight = boundsRect.height();
157  double ratioBoundsRect = boundsWidth / boundsHeight;
158 
159  double clippedRotation = normalizedAngle( rotation );
160 
161  //shortcut for some rotation values
162  if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 90.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) || qgsDoubleNear( clippedRotation, 270.0 ) )
163  {
164  double rectScale;
165  if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
166  {
167  rectScale = ( ( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
168  }
169  else
170  {
171  rectScale = ( ( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
172  }
173  double rectScaledWidth = rectScale * originalWidth;
174  double rectScaledHeight = rectScale * originalHeight;
175 
176  if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
177  {
178  return QRectF( ( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
179  }
180  else
181  {
182  return QRectF( ( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
183  }
184  }
185 
186  //convert angle to radians and flip
187  double angleRad = -clippedRotation * M_DEG2RAD;
188  double cosAngle = cos( angleRad );
189  double sinAngle = sin( angleRad );
190 
191  //calculate size of bounds of rotated rectangle
192  double widthBoundsRotatedRect = originalWidth * fabs( cosAngle ) + originalHeight * fabs( sinAngle );
193  double heightBoundsRotatedRect = originalHeight * fabs( cosAngle ) + originalWidth * fabs( sinAngle );
194 
195  //compare ratio of rotated rect with bounds rect and calculate scaling of rotated
196  //rect to fit within bounds
197  double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
198  double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
199  double rectScaledWidth = rectScale * originalWidth;
200  double rectScaledHeight = rectScale * originalHeight;
201 
202  //now calculate offset so that rotated rectangle is centered within bounds
203  //first calculate min x and y coordinates
204  double currentCornerX = 0;
205  double minX = 0;
206  currentCornerX += rectScaledWidth * cosAngle;
207  minX = minX < currentCornerX ? minX : currentCornerX;
208  currentCornerX += rectScaledHeight * sinAngle;
209  minX = minX < currentCornerX ? minX : currentCornerX;
210  currentCornerX -= rectScaledWidth * cosAngle;
211  minX = minX < currentCornerX ? minX : currentCornerX;
212 
213  double currentCornerY = 0;
214  double minY = 0;
215  currentCornerY -= rectScaledWidth * sinAngle;
216  minY = minY < currentCornerY ? minY : currentCornerY;
217  currentCornerY += rectScaledHeight * cosAngle;
218  minY = minY < currentCornerY ? minY : currentCornerY;
219  currentCornerY += rectScaledWidth * sinAngle;
220  minY = minY < currentCornerY ? minY : currentCornerY;
221 
222  //now calculate offset position of rotated rectangle
223  double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
224  offsetX += fabs( minX );
225  double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
226  offsetY += fabs( minY );
227 
228  return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
229 }
230 
231 double QgsComposerUtils::pointsToMM( const double pointSize )
232 {
233  //conversion to mm based on 1 point = 1/72 inch
234  return ( pointSize * 0.3527 );
235 }
236 
237 double QgsComposerUtils::mmToPoints( const double mmSize )
238 {
239  //conversion to points based on 1 point = 1/72 inch
240  return ( mmSize / 0.3527 );
241 }
242 
243 void QgsComposerUtils::relativeResizeRect( QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter )
244 {
245  //linearly scale rectToResize relative to the scaling from boundsBefore to boundsAfter
246  double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
247  double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
248  double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
249  double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
250 
251  rectToResize.setRect( left, top, right - left, bottom - top );
252 }
253 
254 double QgsComposerUtils::relativePosition( const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax )
255 {
256  //calculate parameters for linear scale between before and after ranges
257  double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
258  double c = afterMin - ( beforeMin * m );
259 
260  //return linearly scaled position
261  return m * position + c;
262 }
263 
265 {
266  if ( orientationString.compare( QLatin1String( "Portrait" ), Qt::CaseInsensitive ) == 0 )
267  {
268  ok = true;
270  }
271  if ( orientationString.compare( QLatin1String( "Landscape" ), Qt::CaseInsensitive ) == 0 )
272  {
273  ok = true;
275  }
276  ok = false;
277  return QgsComposition::Landscape; // default to landscape
278 }
279 
280 bool QgsComposerUtils::decodePresetPaperSize( const QString &presetString, double &width, double &height )
281 {
282  QList< QPair< QString, QSizeF > > presets;
283  presets << qMakePair( QStringLiteral( "A5" ), QSizeF( 148, 210 ) );
284  presets << qMakePair( QStringLiteral( "A4" ), QSizeF( 210, 297 ) );
285  presets << qMakePair( QStringLiteral( "A3" ), QSizeF( 297, 420 ) );
286  presets << qMakePair( QStringLiteral( "A2" ), QSizeF( 420, 594 ) );
287  presets << qMakePair( QStringLiteral( "A1" ), QSizeF( 594, 841 ) );
288  presets << qMakePair( QStringLiteral( "A0" ), QSizeF( 841, 1189 ) );
289  presets << qMakePair( QStringLiteral( "B5" ), QSizeF( 176, 250 ) );
290  presets << qMakePair( QStringLiteral( "B4" ), QSizeF( 250, 353 ) );
291  presets << qMakePair( QStringLiteral( "B3" ), QSizeF( 353, 500 ) );
292  presets << qMakePair( QStringLiteral( "B2" ), QSizeF( 500, 707 ) );
293  presets << qMakePair( QStringLiteral( "B1" ), QSizeF( 707, 1000 ) );
294  presets << qMakePair( QStringLiteral( "B0" ), QSizeF( 1000, 1414 ) );
295  // North american formats
296  presets << qMakePair( QStringLiteral( "Legal" ), QSizeF( 215.9, 355.6 ) );
297  presets << qMakePair( QStringLiteral( "Letter" ), QSizeF( 215.9, 279.4 ) );
298  presets << qMakePair( QStringLiteral( "ANSI A" ), QSizeF( 215.9, 279.4 ) );
299  presets << qMakePair( QStringLiteral( "ANSI B" ), QSizeF( 279.4, 431.8 ) );
300  presets << qMakePair( QStringLiteral( "ANSI C" ), QSizeF( 431.8, 558.8 ) );
301  presets << qMakePair( QStringLiteral( "ANSI D" ), QSizeF( 558.8, 863.6 ) );
302  presets << qMakePair( QStringLiteral( "ANSI E" ), QSizeF( 863.6, 1117.6 ) );
303  presets << qMakePair( QStringLiteral( "Arch A" ), QSizeF( 228.6, 304.8 ) );
304  presets << qMakePair( QStringLiteral( "Arch B" ), QSizeF( 304.8, 457.2 ) );
305  presets << qMakePair( QStringLiteral( "Arch C" ), QSizeF( 457.2, 609.6 ) );
306  presets << qMakePair( QStringLiteral( "Arch D" ), QSizeF( 609.6, 914.4 ) );
307  presets << qMakePair( QStringLiteral( "Arch E" ), QSizeF( 914.4, 1219.2 ) );
308  presets << qMakePair( QStringLiteral( "Arch E1" ), QSizeF( 762, 1066.8 ) );
309 
310  QList< QPair< QString, QSizeF > >::const_iterator presetIt = presets.constBegin();
311  for ( ; presetIt != presets.constEnd(); ++presetIt )
312  {
313  if ( presetString.compare( ( *presetIt ).first, Qt::CaseInsensitive ) == 0 )
314  {
315  width = ( *presetIt ).second.width();
316  height = ( *presetIt ).second.height();
317  return true;
318  }
319  }
320  return false;
321 }
322 
323 void QgsComposerUtils::readOldDataDefinedPropertyMap( const QDomElement &itemElem, QgsPropertyCollection &dataDefinedProperties )
324 {
325  QgsPropertiesDefinition::const_iterator i = QgsComposerObject::propertyDefinitions().constBegin();
326  for ( ; i != QgsComposerObject::propertyDefinitions().constEnd(); ++i )
327  {
328  QString elemName = i.value().name();
329  QDomNodeList ddNodeList = itemElem.elementsByTagName( elemName );
330  if ( !ddNodeList.isEmpty() )
331  {
332  QDomElement ddElem = ddNodeList.at( 0 ).toElement();
333  QgsProperty prop = readOldDataDefinedProperty( static_cast< QgsComposerObject::DataDefinedProperty >( i.key() ), ddElem );
334  if ( prop )
335  dataDefinedProperties.setProperty( i.key(), prop );
336  }
337  }
338 }
339 
341 {
342  if ( property == QgsComposerObject::AllProperties || property == QgsComposerObject::NoProperty )
343  {
344  //invalid property
345  return QgsProperty();
346  }
347 
348  QString active = ddElem.attribute( QStringLiteral( "active" ) );
349  bool isActive = false;
350  if ( active.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
351  {
352  isActive = true;
353  }
354  QString field = ddElem.attribute( QStringLiteral( "field" ) );
355  QString expr = ddElem.attribute( QStringLiteral( "expr" ) );
356 
357  QString useExpr = ddElem.attribute( QStringLiteral( "useExpr" ) );
358  bool isExpression = false;
359  if ( useExpr.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
360  {
361  isExpression = true;
362  }
363 
364  if ( isExpression )
365  return QgsProperty::fromExpression( expr, isActive );
366  else
367  return QgsProperty::fromField( field, isActive );
368 }
369 
370 QFont QgsComposerUtils::scaledFontPixelSize( const QFont &font )
371 {
372  //upscale using FONT_WORKAROUND_SCALE
373  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
374  QFont scaledFont = font;
375  double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
376  scaledFont.setPixelSize( pixelSize );
377  return scaledFont;
378 }
379 
380 double QgsComposerUtils::fontAscentMM( const QFont &font )
381 {
382  //upscale using FONT_WORKAROUND_SCALE
383  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
384  QFont metricsFont = scaledFontPixelSize( font );
385  QFontMetricsF fontMetrics( metricsFont );
386  return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
387 }
388 
389 double QgsComposerUtils::fontDescentMM( const QFont &font )
390 {
391  //upscale using FONT_WORKAROUND_SCALE
392  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
393  QFont metricsFont = scaledFontPixelSize( font );
394  QFontMetricsF fontMetrics( metricsFont );
395  return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
396 }
397 
398 double QgsComposerUtils::fontHeightMM( const QFont &font )
399 {
400  //upscale using FONT_WORKAROUND_SCALE
401  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
402  QFont metricsFont = scaledFontPixelSize( font );
403  QFontMetricsF fontMetrics( metricsFont );
404  return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
405 }
406 
407 double QgsComposerUtils::fontHeightCharacterMM( const QFont &font, QChar character )
408 {
409  //upscale using FONT_WORKAROUND_SCALE
410  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
411  QFont metricsFont = scaledFontPixelSize( font );
412  QFontMetricsF fontMetrics( metricsFont );
413  return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
414 }
415 
416 double QgsComposerUtils::textWidthMM( const QFont &font, const QString &text )
417 {
418  //upscale using FONT_WORKAROUND_SCALE
419  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
420  QFont metricsFont = scaledFontPixelSize( font );
421  QFontMetricsF fontMetrics( metricsFont );
422  return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
423 }
424 
425 double QgsComposerUtils::textHeightMM( const QFont &font, const QString &text, double multiLineHeight )
426 {
427  QStringList multiLineSplit = text.split( '\n' );
428  int lines = multiLineSplit.size();
429 
430  //upscale using FONT_WORKAROUND_SCALE
431  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
432  QFont metricsFont = scaledFontPixelSize( font );
433  QFontMetricsF fontMetrics( metricsFont );
434 
435  double fontHeight = fontMetrics.ascent() + fontMetrics.descent(); // ignore +1 for baseline
436  double textHeight = fontMetrics.ascent() + static_cast< double >( ( lines - 1 ) * fontHeight * multiLineHeight );
437 
438  return textHeight / FONT_WORKAROUND_SCALE;
439 }
440 
441 void QgsComposerUtils::drawText( QPainter *painter, QPointF pos, const QString &text, const QFont &font, const QColor &color )
442 {
443  if ( !painter )
444  {
445  return;
446  }
447 
448  //upscale using FONT_WORKAROUND_SCALE
449  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
450  QFont textFont = scaledFontPixelSize( font );
451 
452  painter->save();
453  painter->setFont( textFont );
454  if ( color.isValid() )
455  {
456  painter->setPen( color );
457  }
458  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
459  painter->scale( scaleFactor, scaleFactor );
460  painter->drawText( pos * FONT_WORKAROUND_SCALE, text );
461  painter->restore();
462 }
463 
464 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 )
465 {
466  if ( !painter )
467  {
468  return;
469  }
470 
471  //upscale using FONT_WORKAROUND_SCALE
472  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
473  QFont textFont = scaledFontPixelSize( font );
474 
475  QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
476  rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
477 
478  painter->save();
479  painter->setFont( textFont );
480  if ( color.isValid() )
481  {
482  painter->setPen( color );
483  }
484  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
485  painter->scale( scaleFactor, scaleFactor );
486  painter->drawText( scaledRect, halignment | valignment | flags, text );
487  painter->restore();
488 }
489 
491 {
492  if ( !map )
493  {
494  QgsRenderContext context;
495  context.setPainter( painter );
496  if ( dpi < 0 && painter && painter->device() )
497  {
498  context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
499  }
500  else if ( dpi > 0 )
501  {
502  context.setScaleFactor( dpi / 25.4 );
503  }
504  else
505  {
506  context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
507  }
508  return context;
509  }
510 
511  // default to 88 dpi if no painter specified
512  if ( dpi < 0 )
513  {
514  dpi = ( painter && painter->device() ) ? painter->device()->logicalDpiX() : 88;
515  }
516  double dotsPerMM = dpi / 25.4;
517 
518  // get map settings from reference map
519  QgsRectangle extent = *( map->currentMapExtent() );
520  QSizeF mapSizeMM = map->rect().size();
521  QgsMapSettings ms = map->mapSettings( extent, mapSizeMM * dotsPerMM, dpi );
522 
524  if ( painter )
525  context.setPainter( painter );
526  return context;
527 }
528 
530 {
531  QgsComposerMap *referenceMap = composition ? composition->referenceMap() : nullptr;
532  return createRenderContextForMap( referenceMap, painter );
533 }
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
static void relativeResizeRect(QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter)
Resizes a QRectF relative to a resized bounding rectangle.
QgsMapSettings mapSettings(const QgsRectangle &extent, QSizeF size, int dpi) const
Return map settings that would be used for drawing of the map.
A rectangle specified with double values.
Definition: qgsrectangle.h:38
#define M_DEG2RAD
static double normalizedAngle(const double angle)
Ensures that an angle is in the range 0 <= angle < 360.
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...
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 QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
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 ...
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 double fontDescentMM(const QFont &font)
Calculate font descent in millimeters, including workarounds for QT font rendering issues...
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:203
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cc:857
DataDefinedProperty
Data defined properties for different item types.
The QgsMapSettings class contains configuration for rendering of the map.
static QgsRenderContext createRenderContextForMap(QgsComposerMap *map, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified composer map and painter destination.
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 double fontHeightCharacterMM(const QFont &font, QChar character)
Calculate font height in millimeters of a single character, including workarounds for QT font renderi...
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the composer object property definitions.
QgsComposerMap * referenceMap() const
Returns the map item which will be used to generate corresponding world files when the composition is...
#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 setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
A store for object properties.
Definition: qgsproperty.h:189
Graphics scene for map printing.
Object representing map window.
static void rotate(const double angle, double &x, double &y)
Rotates a point / vector around the origin.
static void readOldDataDefinedPropertyMap(const QDomElement &itemElem, QgsPropertyCollection &dataDefinedProperties)
Reads all pre 3.0 data defined properties from an XML element.
static bool decodePresetPaperSize(const QString &presetString, double &width, double &height)
Decodes a string representing a preset page size.
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...
Contains information about the context of a rendering operation.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
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...
static double pointsToMM(const double pointSize)
Returns the size in mm corresponding to a font point size.
static QgsProperty readOldDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property, const QDomElement &ddElem)
Reads a pre 3.0 data defined property from an XML DOM element.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
static double snappedAngle(const double angle)
Snaps an angle to its closest 45 degree angle.
#define FONT_WORKAROUND_SCALE
static QgsRenderContext createRenderContextForComposition(QgsComposition *composition, QPainter *painter)
Creates a render context suitable for the specified composition and painter destination.
const QgsRectangle * currentMapExtent() const
Returns a pointer to the current map extent, which is either the original user specified extent or th...
static QgsComposition::PaperOrientation decodePaperOrientation(const QString &orientationString, bool &ok)
Decodes a string representing a paper orientation.
All properties for item.
static double mmToPoints(const double mmSize)
Returns the size in mm corresponding to a font point size.