QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgslayoututils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoututils.cpp
3  ------------------
4  begin : July 2017
5  copyright : (C) 2017 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 "qgslayoututils.h"
19 #include "qgslayout.h"
20 #include "qgslayoutitemmap.h"
21 #include "qgsprojectviewsettings.h"
22 #include "qgsrendercontext.h"
23 #include "qgssettings.h"
24 
25 #include <QStyleOptionGraphicsItem>
26 #include <QPainter>
27 #include <cmath>
28 
29 #ifndef M_DEG2RAD
30 #define M_DEG2RAD 0.0174532925
31 #endif
32 
33 void QgsLayoutUtils::rotate( double angle, double &x, double &y )
34 {
35  double rotToRad = angle * M_PI / 180.0;
36  double xRot, yRot;
37  xRot = x * std::cos( rotToRad ) - y * std::sin( rotToRad );
38  yRot = x * std::sin( rotToRad ) + y * std::cos( rotToRad );
39  x = xRot;
40  y = yRot;
41 }
42 
43 double QgsLayoutUtils::normalizedAngle( const double angle, const bool allowNegative )
44 {
45  double clippedAngle = angle;
46  if ( clippedAngle >= 360.0 || clippedAngle <= -360.0 )
47  {
48  clippedAngle = std::fmod( clippedAngle, 360.0 );
49  }
50  if ( !allowNegative && clippedAngle < 0.0 )
51  {
52  clippedAngle += 360.0;
53  }
54  return clippedAngle;
55 }
56 
58 {
59  //normalize angle to 0-360 degrees
60  double clippedAngle = normalizedAngle( angle );
61 
62  //snap angle to 45 degree
63  if ( clippedAngle >= 22.5 && clippedAngle < 67.5 )
64  {
65  return 45.0;
66  }
67  else if ( clippedAngle >= 67.5 && clippedAngle < 112.5 )
68  {
69  return 90.0;
70  }
71  else if ( clippedAngle >= 112.5 && clippedAngle < 157.5 )
72  {
73  return 135.0;
74  }
75  else if ( clippedAngle >= 157.5 && clippedAngle < 202.5 )
76  {
77  return 180.0;
78  }
79  else if ( clippedAngle >= 202.5 && clippedAngle < 247.5 )
80  {
81  return 225.0;
82  }
83  else if ( clippedAngle >= 247.5 && clippedAngle < 292.5 )
84  {
85  return 270.0;
86  }
87  else if ( clippedAngle >= 292.5 && clippedAngle < 337.5 )
88  {
89  return 315.0;
90  }
91  else
92  {
93  return 0.0;
94  }
95 }
96 
98 {
99  if ( !map )
100  {
101  QgsRenderContext context;
102  context.setPainter( painter );
103  if ( dpi < 0 && painter && painter->device() )
104  {
105  context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
106  }
107  else if ( dpi > 0 )
108  {
109  context.setScaleFactor( dpi / 25.4 );
110  }
111  else
112  {
113  context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
114  }
115  return context;
116  }
117  else
118  {
119  // default to 88 dpi if no painter specified
120  if ( dpi < 0 )
121  {
122  dpi = ( painter && painter->device() ) ? painter->device()->logicalDpiX() : 88;
123  }
124  double dotsPerMM = dpi / 25.4;
125 
126  // get map settings from reference map
127  QgsRectangle extent = map->extent();
128  QSizeF mapSizeLayoutUnits = map->rect().size();
129  QSizeF mapSizeMM = map->layout()->convertFromLayoutUnits( mapSizeLayoutUnits, QgsUnitTypes::LayoutMillimeters ).toQSizeF();
130  QgsMapSettings ms = map->mapSettings( extent, mapSizeMM * dotsPerMM, dpi, false );
132  if ( painter )
133  context.setPainter( painter );
134 
135  context.setFlags( map->layout()->renderContext().renderContextFlags() );
137  return context;
138  }
139 }
140 
142 {
143  QgsLayoutItemMap *referenceMap = layout ? layout->referenceMap() : nullptr;
144  QgsRenderContext context = createRenderContextForMap( referenceMap, painter, dpi );
145  if ( layout )
146  {
147  context.setFlags( layout->renderContext().renderContextFlags() );
148  context.setTextRenderFormat( layout->renderContext().textRenderFormat() );
149  }
150 
151  return context;
152 }
153 
154 void QgsLayoutUtils::relativeResizeRect( QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter )
155 {
156  //linearly scale rectToResize relative to the scaling from boundsBefore to boundsAfter
157  double left = relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
158  double right = relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() );
159  double top = relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
160  double bottom = relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() );
161 
162  rectToResize.setRect( left, top, right - left, bottom - top );
163 }
164 
165 double QgsLayoutUtils::relativePosition( const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax )
166 {
167  //calculate parameters for linear scale between before and after ranges
168  double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
169  double c = afterMin - ( beforeMin * m );
170 
171  //return linearly scaled position
172  return m * position + c;
173 }
174 QFont QgsLayoutUtils::scaledFontPixelSize( const QFont &font )
175 {
176  //upscale using FONT_WORKAROUND_SCALE
177  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
178  QFont scaledFont = font;
179  double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
180  scaledFont.setPixelSize( pixelSize );
181  return scaledFont;
182 }
183 
184 double QgsLayoutUtils::fontAscentMM( const QFont &font )
185 {
186  //upscale using FONT_WORKAROUND_SCALE
187  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
188  QFont metricsFont = scaledFontPixelSize( font );
189  QFontMetricsF fontMetrics( metricsFont );
190  return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
191 }
192 
193 double QgsLayoutUtils::fontDescentMM( const QFont &font )
194 {
195  //upscale using FONT_WORKAROUND_SCALE
196  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
197  QFont metricsFont = scaledFontPixelSize( font );
198  QFontMetricsF fontMetrics( metricsFont );
199  return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
200 
201 }
202 
203 double QgsLayoutUtils::fontHeightMM( const QFont &font )
204 {
205  //upscale using FONT_WORKAROUND_SCALE
206  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
207  QFont metricsFont = scaledFontPixelSize( font );
208  QFontMetricsF fontMetrics( metricsFont );
209  return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
210 
211 }
212 
213 double QgsLayoutUtils::fontHeightCharacterMM( const QFont &font, QChar character )
214 {
215  //upscale using FONT_WORKAROUND_SCALE
216  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
217  QFont metricsFont = scaledFontPixelSize( font );
218  QFontMetricsF fontMetrics( metricsFont );
219  return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
220 }
221 
222 double QgsLayoutUtils::textWidthMM( const QFont &font, const QString &text )
223 {
224  //upscale using FONT_WORKAROUND_SCALE
225  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
226 
227  const QStringList multiLineSplit = text.split( '\n' );
228  QFont metricsFont = scaledFontPixelSize( font );
229  QFontMetricsF fontMetrics( metricsFont );
230 
231  double maxWidth = 0;
232  for ( const QString &line : multiLineSplit )
233  {
234 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
235  maxWidth = std::max( maxWidth, ( fontMetrics.width( line ) / FONT_WORKAROUND_SCALE ) );
236 #else
237  maxWidth = std::max( maxWidth, ( fontMetrics.horizontalAdvance( line ) / FONT_WORKAROUND_SCALE ) );
238 #endif
239  }
240  return maxWidth;
241 }
242 
243 double QgsLayoutUtils::textHeightMM( const QFont &font, const QString &text, double multiLineHeight )
244 {
245  QStringList multiLineSplit = text.split( '\n' );
246  int lines = multiLineSplit.size();
247 
248  //upscale using FONT_WORKAROUND_SCALE
249  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
250  QFont metricsFont = scaledFontPixelSize( font );
251  QFontMetricsF fontMetrics( metricsFont );
252 
253  double fontHeight = fontMetrics.ascent() + fontMetrics.descent(); // ignore +1 for baseline
254  double textHeight = fontMetrics.ascent() + static_cast< double >( ( lines - 1 ) * fontHeight * multiLineHeight );
255 
256  return textHeight / FONT_WORKAROUND_SCALE;
257 }
258 
259 void QgsLayoutUtils::drawText( QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color )
260 {
261  if ( !painter )
262  {
263  return;
264  }
265 
266  //upscale using FONT_WORKAROUND_SCALE
267  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
268  QFont textFont = scaledFontPixelSize( font );
269 
270  QgsScopedQPainterState painterState( painter );
271  painter->setFont( textFont );
272  if ( color.isValid() )
273  {
274  painter->setPen( color );
275  }
276  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
277  painter->scale( scaleFactor, scaleFactor );
278  painter->drawText( position * FONT_WORKAROUND_SCALE, text );
279 }
280 
281 void QgsLayoutUtils::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 )
282 {
283  if ( !painter )
284  {
285  return;
286  }
287 
288  //upscale using FONT_WORKAROUND_SCALE
289  //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
290  QFont textFont = scaledFontPixelSize( font );
291 
292  QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
293  rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
294 
295  QgsScopedQPainterState painterState( painter );
296  painter->setFont( textFont );
297  if ( color.isValid() )
298  {
299  painter->setPen( color );
300  }
301  double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
302  painter->scale( scaleFactor, scaleFactor );
303  painter->drawText( scaledRect, halignment | valignment | flags, text );
304 }
305 
306 QRectF QgsLayoutUtils::largestRotatedRectWithinBounds( const QRectF &originalRect, const QRectF &boundsRect, const double rotation )
307 {
308  double originalWidth = originalRect.width();
309  double originalHeight = originalRect.height();
310  double boundsWidth = boundsRect.width();
311  double boundsHeight = boundsRect.height();
312  double ratioBoundsRect = boundsWidth / boundsHeight;
313 
314  double clippedRotation = normalizedAngle( rotation );
315 
316  //shortcut for some rotation values
317  if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 90.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) || qgsDoubleNear( clippedRotation, 270.0 ) )
318  {
319  double rectScale;
320  if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
321  {
322  rectScale = ( ( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
323  }
324  else
325  {
326  rectScale = ( ( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
327  }
328  double rectScaledWidth = rectScale * originalWidth;
329  double rectScaledHeight = rectScale * originalHeight;
330 
331  if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
332  {
333  return QRectF( ( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
334  }
335  else
336  {
337  return QRectF( ( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
338  }
339  }
340 
341  //convert angle to radians and flip
342  double angleRad = -clippedRotation * M_DEG2RAD;
343  double cosAngle = std::cos( angleRad );
344  double sinAngle = std::sin( angleRad );
345 
346  //calculate size of bounds of rotated rectangle
347  double widthBoundsRotatedRect = originalWidth * std::fabs( cosAngle ) + originalHeight * std::fabs( sinAngle );
348  double heightBoundsRotatedRect = originalHeight * std::fabs( cosAngle ) + originalWidth * std::fabs( sinAngle );
349 
350  //compare ratio of rotated rect with bounds rect and calculate scaling of rotated
351  //rect to fit within bounds
352  double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
353  double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
354  double rectScaledWidth = rectScale * originalWidth;
355  double rectScaledHeight = rectScale * originalHeight;
356 
357  //now calculate offset so that rotated rectangle is centered within bounds
358  //first calculate min x and y coordinates
359  double currentCornerX = 0;
360  double minX = 0;
361  currentCornerX += rectScaledWidth * cosAngle;
362  minX = minX < currentCornerX ? minX : currentCornerX;
363  currentCornerX += rectScaledHeight * sinAngle;
364  minX = minX < currentCornerX ? minX : currentCornerX;
365  currentCornerX -= rectScaledWidth * cosAngle;
366  minX = minX < currentCornerX ? minX : currentCornerX;
367 
368  double currentCornerY = 0;
369  double minY = 0;
370  currentCornerY -= rectScaledWidth * sinAngle;
371  minY = minY < currentCornerY ? minY : currentCornerY;
372  currentCornerY += rectScaledHeight * cosAngle;
373  minY = minY < currentCornerY ? minY : currentCornerY;
374  currentCornerY += rectScaledWidth * sinAngle;
375  minY = minY < currentCornerY ? minY : currentCornerY;
376 
377  //now calculate offset position of rotated rectangle
378  double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
379  offsetX += std::fabs( minX );
380  double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
381  offsetY += std::fabs( minY );
382 
383  return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
384 }
385 
387 {
388  QString s = string.trimmed();
389  if ( s.compare( QLatin1String( "Portrait" ), Qt::CaseInsensitive ) == 0 )
390  {
391  ok = true;
393  }
394  else if ( s.compare( QLatin1String( "Landscape" ), Qt::CaseInsensitive ) == 0 )
395  {
396  ok = true;
398  }
399  ok = false;
400  return QgsLayoutItemPage::Landscape; // default to landscape
401 }
402 
403 double QgsLayoutUtils::scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style )
404 {
405  // workaround Qt bug 66185
406 
407  // Refs #18027 - if a QGraphicsItem is rotated by 90 or 270 degrees, then the item
408  // style given to QGraphicsItem::paint incorrectly uses the shear parameter of the matrix (m12)
409  // to store the current view scale, instead of the horizontal scale parameter (m11) which
410  // is used in all other cases
411 
412  // TODO - ifdef this out if Qt fixes upstream
413  return !qgsDoubleNear( style->matrix.m11(), 0.0 ) ? style->matrix.m11() : style->matrix.m12();
414 }
415 
416 QgsMapLayer *QgsLayoutUtils::mapLayerFromString( const QString &string, QgsProject *project )
417 {
418  // Maybe it's a layer id?
419  if ( QgsMapLayer *ml = project->mapLayer( string ) )
420  return ml;
421 
422  // Still nothing? Check for layer name
423  if ( QgsMapLayer *ml = project->mapLayersByName( string ).value( 0 ) )
424  return ml;
425 
426  // Still nothing? Check for layer name, case-insensitive
427  const auto layers = project->mapLayers();
428  for ( auto it = layers.constBegin(); it != layers.constEnd(); ++it )
429  {
430  if ( it.value()->name().compare( string, Qt::CaseInsensitive ) == 0 )
431  return it.value();
432  }
433 
434  return nullptr;
435 }
436 
437 // nextNiceNumber(4573.23, d) = 5000 (d=1) -> 4600 (d=10) -> 4580 (d=100) -> 4574 (d=1000) -> etc
438 inline double nextNiceNumber( double a, double d = 1 )
439 {
440  double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
441  return std::ceil( a / s ) * s;
442 }
443 
444 // prevNiceNumber(4573.23, d) = 4000 (d=1) -> 4500 (d=10) -> 4570 (d=100) -> 4573 (d=1000) -> etc
445 inline double prevNiceNumber( double a, double d = 1 )
446 {
447  double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
448  return std::floor( a / s ) * s;
449 }
450 
451 double QgsLayoutUtils::calculatePrettySize( const double minimumSize, const double maximumSize )
452 {
453  if ( maximumSize < minimumSize )
454  {
455  return 0;
456  }
457  else
458  {
459  // Start with coarsest "nice" number closest to minimumSize resp
460  // maximumSize, then proceed to finer numbers as long as neither
461  // lowerNiceUnitsPerSeg nor upperNiceUnitsPerSeg are in
462  // [minimumSize, maximumSize]
463  double lowerNiceUnitsPerSeg = nextNiceNumber( minimumSize );
464  double upperNiceUnitsPerSeg = prevNiceNumber( maximumSize );
465 
466  double d = 1;
467  while ( lowerNiceUnitsPerSeg > maximumSize && upperNiceUnitsPerSeg < minimumSize )
468  {
469  d *= 10;
470  lowerNiceUnitsPerSeg = nextNiceNumber( minimumSize, d );
471  upperNiceUnitsPerSeg = prevNiceNumber( maximumSize, d );
472  }
473 
474  // Pick size from {lowerNiceUnitsPerSeg, upperNiceUnitsPerSeg}, use the larger if possible
475  return upperNiceUnitsPerSeg < minimumSize ? lowerNiceUnitsPerSeg : upperNiceUnitsPerSeg;
476  }
477 }
478 
480 {
481  if ( !( item->itemFlags() & QgsLayoutItem::FlagProvidesClipPath ) )
482  return false; // not a clipping provider, so shortcut out
483 
484  // current only maps can be clipped
485  QList< QgsLayoutItemMap * > maps;
486  item->layout()->layoutItems( maps );
487  for ( QgsLayoutItemMap *map : qgis::as_const( maps ) )
488  {
489  if ( map->itemClippingSettings()->isActive() && map->itemClippingSettings()->sourceItem() == item )
490  return true;
491  }
492  return false;
493 }
494 
495 double QgsLayoutUtils::pointsToMM( const double pointSize )
496 {
497  //conversion to mm based on 1 point = 1/72 inch
498  return ( pointSize * 0.3527 );
499 }
500 
501 double QgsLayoutUtils::mmToPoints( const double mmSize )
502 {
503  //conversion to points based on 1 point = 1/72 inch
504  return ( mmSize / 0.3527 );
505 }
506 
507 QVector< double > QgsLayoutUtils::predefinedScales( const QgsLayout *layout )
508 {
509  QVector< double > mapScales;
510  if ( layout->project() )
511  mapScales = layout->project()->viewSettings()->mapScales();
512 
513  bool hasProjectScales( layout->project()->viewSettings()->useProjectScales() );
514  if ( !hasProjectScales || mapScales.isEmpty() )
515  {
516  // default to global map tool scales
517  QgsSettings settings;
518  QString scalesStr( settings.value( QStringLiteral( "Map/scales" ), Qgis::defaultProjectScales() ).toString() );
519  const QStringList scales = scalesStr.split( ',' );
520  for ( const QString &scale : scales )
521  {
522  QStringList parts( scale.split( ':' ) );
523  if ( parts.size() == 2 )
524  {
525  mapScales.push_back( parts[1].toDouble() );
526  }
527  }
528  }
529 
530  return mapScales;
531 }
static QString defaultProjectScales()
A string with default project scales.
Definition: qgis.cpp:270
Layout graphical items for displaying a map.
QgsMapSettings mapSettings(const QgsRectangle &extent, QSizeF size, double dpi, bool includeLayerSettings) const
Returns map settings that will be used for drawing of the map.
QgsRectangle extent() const
Returns the current map extent.
Orientation
Page orientation.
@ Landscape
Landscape orientation.
@ Portrait
Portrait orientation.
Base class for graphical items within a QgsLayout.
@ FlagProvidesClipPath
Item can act as a clipping path provider (see clipPath())
virtual Flags itemFlags() const
Returns the item's flags, which indicate how the item behaves.
const QgsLayout * layout() const
Returns the layout the object is attached to.
QgsRenderContext::Flags renderContextFlags() const
Returns the combination of render context flags matched to the layout context's settings.
QgsRenderContext::TextRenderFormat textRenderFormat() const
Returns the text render format, which dictates how text is rendered (e.g.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
static QVector< double > predefinedScales(const QgsLayout *layout)
Returns a list of predefined scales associated with a layout.
static double fontHeightMM(const QFont &font)
Calculate a font height in millimeters, including workarounds for QT font rendering issues.
static double relativePosition(double position, double beforeMin, double beforeMax, double afterMin, double afterMax)
Returns a scaled position given a before and after range.
static double fontDescentMM(const QFont &font)
Calculate a font descent in millimeters, including workarounds for QT font rendering issues.
static double fontAscentMM(const QFont &font)
Calculates a font ascent in millimeters, including workarounds for QT font rendering issues.
static QRectF largestRotatedRectWithinBounds(const QRectF &originalRect, const QRectF &boundsRect, double rotation)
Calculates the largest scaled version of originalRect which fits within boundsRect,...
static QFont scaledFontPixelSize(const QFont &font)
Returns a font where size is set in points and the size has been upscaled with FONT_WORKAROUND_SCALE ...
static QgsRenderContext createRenderContextForMap(QgsLayoutItemMap *map, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout map and painter destination.
static bool itemIsAClippingSource(const QgsLayoutItem *item)
Returns true if an item is a clipping item for another layout item.
static double snappedAngle(double angle)
Snaps an angle (in degrees) to its closest 45 degree angle.
static double textHeightMM(const QFont &font, const QString &text, double multiLineHeight=1.0)
Calculate a font height in millimeters for a text string, including workarounds for QT font rendering...
static QgsLayoutItemPage::Orientation decodePaperOrientation(const QString &string, bool &ok)
Decodes a string representing a paper orientation and returns the decoded orientation.
static void rotate(double angle, double &x, double &y)
Rotates a point / vector around the origin.
static double fontHeightCharacterMM(const QFont &font, QChar character)
Calculate a font height in millimeters of a single character, including workarounds for QT font rende...
static double normalizedAngle(double angle, bool allowNegative=false)
Ensures that an angle (in degrees) is in the range 0 <= angle < 360.
static void drawText(QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color=QColor())
Draws text on a painter at a specific position, taking care of layout specific issues (calculation to...
static double textWidthMM(const QFont &font, const QString &text)
Calculate a font width in millimeters for a text string, including workarounds for QT font rendering ...
static double calculatePrettySize(double minimumSize, double maximumSize)
Calculates a "pretty" size which falls between the range [minimumSize, maximumSize].
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProject *project)
Resolves a string into a map layer from a given project.
static double scaleFactorFromItemStyle(const QStyleOptionGraphicsItem *style)
Extracts the scale factor from an item style.
static void relativeResizeRect(QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter)
Resizes a QRectF relative to a resized bounding rectangle.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:50
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
Definition: qgslayout.cpp:359
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:121
QgsLayoutItemMap * referenceMap() const
Returns the map item which will be used to generate corresponding world files when the layout is expo...
Definition: qgslayout.cpp:430
QgsLayoutMeasurement convertFromLayoutUnits(double length, QgsUnitTypes::LayoutUnit unit) const
Converts a length measurement from the layout's native units to a specified target unit.
Definition: qgslayout.cpp:344
QgsProject * project() const
The project associated with the layout.
Definition: qgslayout.cpp:132
Base class for all map layer types.
Definition: qgsmaplayer.h:85
The QgsMapSettings class contains configuration for rendering of the map.
bool useProjectScales() const
Returns true if project mapScales() are enabled.
QVector< double > mapScales() const
Returns the list of custom project map scales.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:99
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
const QgsProjectViewSettings * viewSettings() const
Returns the project's view settings, which contains settings and properties relating to how a QgsProj...
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
Contains information about the context of a rendering operation.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
void setTextRenderFormat(TextRenderFormat format)
Sets the text render format, which dictates how text is rendered (e.g.
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
void setFlags(QgsRenderContext::Flags flags)
Set combination of flags that will be used for rendering.
Scoped object for saving and restoring a QPainter object's state.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
@ LayoutMillimeters
Millimeters.
Definition: qgsunittypes.h:182
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.cpp:786
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:316
double prevNiceNumber(double a, double d=1)
#define M_DEG2RAD
double nextNiceNumber(double a, double d=1)