QGIS API Documentation 4.3.0-Master (e0370aa57ef)
Loading...
Searching...
No Matches
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
20#include <cmath>
21
22#include "qgsdatadefinedutils.h"
23#include "qgslayout.h"
24#include "qgslayoutitemmap.h"
27#include "qgspainting.h"
29#include "qgsrendercontext.h"
31
32#include <QPainter>
33#include <QString>
34#include <QStyleOptionGraphicsItem>
35
36using namespace Qt::StringLiterals;
37
38#ifndef M_DEG2RAD
39#define M_DEG2RAD 0.0174532925
40#endif
41
42void QgsLayoutUtils::rotate( double angle, double &x, double &y )
43{
44 double rotToRad = angle * M_PI / 180.0;
45 double xRot, yRot;
46 xRot = x * std::cos( rotToRad ) - y * std::sin( rotToRad );
47 yRot = x * std::sin( rotToRad ) + y * std::cos( rotToRad );
48 x = xRot;
49 y = yRot;
50}
51
52double QgsLayoutUtils::normalizedAngle( const double angle, const bool allowNegative )
53{
54 double clippedAngle = angle;
55 if ( clippedAngle >= 360.0 || clippedAngle <= -360.0 )
56 {
57 clippedAngle = std::fmod( clippedAngle, 360.0 );
58 }
59 if ( !allowNegative && clippedAngle < 0.0 )
60 {
61 clippedAngle += 360.0;
62 }
63 return clippedAngle;
64}
65
66double QgsLayoutUtils::snappedAngle( double angle )
67{
68 //normalize angle to 0-360 degrees
69 double clippedAngle = normalizedAngle( angle );
70
71 //snap angle to 45 degree
72 if ( clippedAngle >= 22.5 && clippedAngle < 67.5 )
73 {
74 return 45.0;
75 }
76 else if ( clippedAngle >= 67.5 && clippedAngle < 112.5 )
77 {
78 return 90.0;
79 }
80 else if ( clippedAngle >= 112.5 && clippedAngle < 157.5 )
81 {
82 return 135.0;
83 }
84 else if ( clippedAngle >= 157.5 && clippedAngle < 202.5 )
85 {
86 return 180.0;
87 }
88 else if ( clippedAngle >= 202.5 && clippedAngle < 247.5 )
89 {
90 return 225.0;
91 }
92 else if ( clippedAngle >= 247.5 && clippedAngle < 292.5 )
93 {
94 return 270.0;
95 }
96 else if ( clippedAngle >= 292.5 && clippedAngle < 337.5 )
97 {
98 return 315.0;
99 }
100 else
101 {
102 return 0.0;
103 }
104}
105
107{
108 if ( !map )
109 {
110 QgsRenderContext context;
111 context.setPainter( painter );
112 if ( dpi < 0 && painter && painter->device() )
113 {
114 context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
115 }
116 else if ( dpi > 0 )
117 {
118 context.setScaleFactor( dpi / 25.4 );
119 }
120 else
121 {
122 context.setScaleFactor( 3.465 ); //assume 88 dpi as standard value
123 }
124 return context;
125 }
126 else
127 {
128 // default to 88 dpi if no painter specified
129 if ( dpi < 0 )
130 {
131 dpi = ( painter && painter->device() ) ? painter->device()->logicalDpiX() : 88;
132 }
133 double dotsPerMM = dpi / 25.4;
134
135 // get map settings from reference map
136 QgsRectangle extent = map->extent();
137 QSizeF mapSizeLayoutUnits = map->rect().size();
138 QSizeF mapSizeMM = map->layout()->convertFromLayoutUnits( mapSizeLayoutUnits, Qgis::LayoutUnit::Millimeters ).toQSizeF();
139 QgsMapSettings ms = map->mapSettings( extent, mapSizeMM * dotsPerMM, dpi, false );
141 if ( painter )
142 context.setPainter( painter );
143
144 context.setFlags( map->layout()->renderContext().renderContextFlags() );
146 return context;
147 }
148}
149
151{
152 QgsLayoutItemMap *referenceMap = layout ? layout->referenceMap() : nullptr;
153 QgsRenderContext context = createRenderContextForMap( referenceMap, painter, dpi );
154 if ( layout )
155 {
156 // TODO -- handle RasterizedRenderingPolicy here!!!!
157 context.setFlags( layout->renderContext().renderContextFlags() );
159 }
160
161 return context;
162}
163
164void QgsLayoutUtils::relativeResizeRect( QRectF &rectToResize, const QRectF &boundsBefore, const QRectF &boundsAfter )
165{
166 //linearly scale rectToResize relative to the scaling from boundsBefore to boundsAfter
167 const double left = !qgsDoubleNear( boundsBefore.left(), boundsBefore.right() )
168 ? relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() )
169 : boundsAfter.left();
170 const double right = !qgsDoubleNear( boundsBefore.left(), boundsBefore.right() )
171 ? relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() )
172 : boundsAfter.right();
173 const double top = !qgsDoubleNear( boundsBefore.top(), boundsBefore.bottom() )
174 ? relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() )
175 : boundsAfter.top();
176 const double bottom = !qgsDoubleNear( boundsBefore.top(), boundsBefore.bottom() )
177 ? relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() )
178 : boundsAfter.bottom();
179
180 rectToResize.setRect( left, top, right - left, bottom - top );
181}
182
183double QgsLayoutUtils::relativePosition( const double position, const double beforeMin, const double beforeMax, const double afterMin, const double afterMax )
184{
185 //calculate parameters for linear scale between before and after ranges
186 double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
187 double c = afterMin - ( beforeMin * m );
188
189 //return linearly scaled position
190 return m * position + c;
191}
192QFont QgsLayoutUtils::scaledFontPixelSize( const QFont &font )
193{
194 //upscale using FONT_WORKAROUND_SCALE
195 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
196 QFont scaledFont = font;
197 double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
198 scaledFont.setPixelSize( pixelSize );
199 return scaledFont;
200}
201
202double QgsLayoutUtils::fontAscentMM( const QFont &font )
203{
204 //upscale using FONT_WORKAROUND_SCALE
205 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
206 QFont metricsFont = scaledFontPixelSize( font );
207 QFontMetricsF fontMetrics( metricsFont );
208 return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
209}
210
211double QgsLayoutUtils::fontDescentMM( const QFont &font )
212{
213 //upscale using FONT_WORKAROUND_SCALE
214 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
215 QFont metricsFont = scaledFontPixelSize( font );
216 QFontMetricsF fontMetrics( metricsFont );
217 return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
218}
219
220double QgsLayoutUtils::fontHeightMM( const QFont &font )
221{
222 //upscale using FONT_WORKAROUND_SCALE
223 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
224 QFont metricsFont = scaledFontPixelSize( font );
225 QFontMetricsF fontMetrics( metricsFont );
226 return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
227}
228
229double QgsLayoutUtils::fontHeightCharacterMM( const QFont &font, QChar character )
230{
231 //upscale using FONT_WORKAROUND_SCALE
232 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
233 QFont metricsFont = scaledFontPixelSize( font );
234 QFontMetricsF fontMetrics( metricsFont );
235 return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
236}
237
238double QgsLayoutUtils::textWidthMM( const QFont &font, const QString &text )
239{
240 //upscale using FONT_WORKAROUND_SCALE
241 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
242
243 const QStringList multiLineSplit = text.split( '\n' );
244 QFont metricsFont = scaledFontPixelSize( font );
245 QFontMetricsF fontMetrics( metricsFont );
246
247 double maxWidth = 0;
248 for ( const QString &line : multiLineSplit )
249 {
250 maxWidth = std::max( maxWidth, ( fontMetrics.horizontalAdvance( line ) / FONT_WORKAROUND_SCALE ) );
251 }
252 return maxWidth;
253}
254
255double QgsLayoutUtils::textHeightMM( const QFont &font, const QString &text, double multiLineHeight )
256{
257 QStringList multiLineSplit = text.split( '\n' );
258 int lines = multiLineSplit.size();
259
260 //upscale using FONT_WORKAROUND_SCALE
261 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
262 QFont metricsFont = scaledFontPixelSize( font );
263 QFontMetricsF fontMetrics( metricsFont );
264
265 double fontHeight = fontMetrics.ascent() + fontMetrics.descent(); // ignore +1 for baseline
266 double textHeight = fontMetrics.ascent() + static_cast< double >( ( lines - 1 ) * fontHeight * multiLineHeight );
267
268 return textHeight / FONT_WORKAROUND_SCALE;
269}
270
271void QgsLayoutUtils::drawText( QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color )
272{
273 if ( !painter )
274 {
275 return;
276 }
277
278 //upscale using FONT_WORKAROUND_SCALE
279 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
280 QFont textFont = scaledFontPixelSize( font );
281
282 QgsScopedQPainterState painterState( painter );
283 painter->setFont( textFont );
284 if ( color.isValid() )
285 {
286 painter->setPen( color );
287 }
288 double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
289 painter->scale( scaleFactor, scaleFactor );
290 painter->drawText( position * FONT_WORKAROUND_SCALE, text );
291}
292
294 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
295)
296{
297 if ( !painter )
298 {
299 return;
300 }
301
302 //upscale using FONT_WORKAROUND_SCALE
303 //ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
304 QFont textFont = scaledFontPixelSize( font );
305
306 QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE, rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
307
308 QgsScopedQPainterState painterState( painter );
309 painter->setFont( textFont );
310 if ( color.isValid() )
311 {
312 painter->setPen( color );
313 }
314 double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
315 painter->scale( scaleFactor, scaleFactor );
316 painter->drawText( scaledRect, halignment | valignment | flags, text );
317}
318
319QRectF QgsLayoutUtils::largestRotatedRectWithinBounds( const QRectF &originalRect, const QRectF &boundsRect, const double rotation )
320{
321 double originalWidth = originalRect.width();
322 double originalHeight = originalRect.height();
323 double boundsWidth = boundsRect.width();
324 double boundsHeight = boundsRect.height();
325 double ratioBoundsRect = boundsWidth / boundsHeight;
326
327 double clippedRotation = normalizedAngle( rotation );
328
329 //shortcut for some rotation values
330 if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 90.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) || qgsDoubleNear( clippedRotation, 270.0 ) )
331 {
332 double rectScale;
333 if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
334 {
335 rectScale = ( ( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
336 }
337 else
338 {
339 rectScale = ( ( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
340 }
341 double rectScaledWidth = rectScale * originalWidth;
342 double rectScaledHeight = rectScale * originalHeight;
343
344 if ( qgsDoubleNear( clippedRotation, 0.0 ) || qgsDoubleNear( clippedRotation, 180.0 ) )
345 {
346 return QRectF( ( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
347 }
348 else
349 {
350 return QRectF( ( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
351 }
352 }
353
354 //convert angle to radians and flip
355 double angleRad = -clippedRotation * M_DEG2RAD;
356 double cosAngle = std::cos( angleRad );
357 double sinAngle = std::sin( angleRad );
358
359 //calculate size of bounds of rotated rectangle
360 double widthBoundsRotatedRect = originalWidth * std::fabs( cosAngle ) + originalHeight * std::fabs( sinAngle );
361 double heightBoundsRotatedRect = originalHeight * std::fabs( cosAngle ) + originalWidth * std::fabs( sinAngle );
362
363 //compare ratio of rotated rect with bounds rect and calculate scaling of rotated
364 //rect to fit within bounds
365 double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
366 double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
367 double rectScaledWidth = rectScale * originalWidth;
368 double rectScaledHeight = rectScale * originalHeight;
369
370 //now calculate offset so that rotated rectangle is centered within bounds
371 //first calculate min x and y coordinates
372 double currentCornerX = 0;
373 double minX = 0;
374 currentCornerX += rectScaledWidth * cosAngle;
375 minX = minX < currentCornerX ? minX : currentCornerX;
376 currentCornerX += rectScaledHeight * sinAngle;
377 minX = minX < currentCornerX ? minX : currentCornerX;
378 currentCornerX -= rectScaledWidth * cosAngle;
379 minX = minX < currentCornerX ? minX : currentCornerX;
380
381 double currentCornerY = 0;
382 double minY = 0;
383 currentCornerY -= rectScaledWidth * sinAngle;
384 minY = minY < currentCornerY ? minY : currentCornerY;
385 currentCornerY += rectScaledHeight * cosAngle;
386 minY = minY < currentCornerY ? minY : currentCornerY;
387 currentCornerY += rectScaledWidth * sinAngle;
388 minY = minY < currentCornerY ? minY : currentCornerY;
389
390 //now calculate offset position of rotated rectangle
391 double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
392 offsetX += std::fabs( minX );
393 double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
394 offsetY += std::fabs( minY );
395
396 return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
397}
398
400{
401 static constexpr auto ORIENTATION_MAP = makeDataDefinedStringDecoder<QgsLayoutItemPage::Orientation>( {
404 } );
405
406 auto evaluatedAnchor = ORIENTATION_MAP.lookup( string );
407 if ( evaluatedAnchor )
408 {
409 ok = true;
410 return *evaluatedAnchor;
411 }
412 else
413 {
414 ok = false;
415 return QgsLayoutItemPage::Landscape; // default to landscape
416 }
417}
418
419double QgsLayoutUtils::scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style )
420{
421 Q_UNUSED( style )
422 return 1;
423}
424
425double QgsLayoutUtils::scaleFactorFromItemStyle( const QStyleOptionGraphicsItem *style, QPainter *painter )
426{
427 Q_UNUSED( style );
428 return QStyleOptionGraphicsItem::levelOfDetailFromTransform( painter->worldTransform() );
429}
430
432{
433 // Maybe it's a layer id?
434 if ( QgsMapLayer *ml = project->mapLayer( string ) )
435 return ml;
436
437 // Still nothing? Check for layer name
438 if ( QgsMapLayer *ml = project->mapLayersByName( string ).value( 0 ) )
439 return ml;
440
441 // Still nothing? Check for layer name, case-insensitive
442 const auto layers = project->mapLayers();
443 for ( auto it = layers.constBegin(); it != layers.constEnd(); ++it )
444 {
445 if ( it.value()->name().compare( string, Qt::CaseInsensitive ) == 0 )
446 return it.value();
447 }
448
449 return nullptr;
450}
451
452// nextNiceNumber(4573.23, d) = 5000 (d=1) -> 4600 (d=10) -> 4580 (d=100) -> 4574 (d=1000) -> etc
453inline double nextNiceNumber( double a, double d = 1 )
454{
455 double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
456 return std::ceil( a / s ) * s;
457}
458
459// prevNiceNumber(4573.23, d) = 4000 (d=1) -> 4500 (d=10) -> 4570 (d=100) -> 4573 (d=1000) -> etc
460inline double prevNiceNumber( double a, double d = 1 )
461{
462 double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
463 return std::floor( a / s ) * s;
464}
465
466double QgsLayoutUtils::calculatePrettySize( const double minimumSize, const double maximumSize )
467{
468 if ( maximumSize < minimumSize )
469 {
470 return 0;
471 }
472 else
473 {
474 // Start with coarsest "nice" number closest to minimumSize resp
475 // maximumSize, then proceed to finer numbers as long as neither
476 // lowerNiceUnitsPerSeg nor upperNiceUnitsPerSeg are in
477 // [minimumSize, maximumSize]
478 double lowerNiceUnitsPerSeg = nextNiceNumber( minimumSize );
479 double upperNiceUnitsPerSeg = prevNiceNumber( maximumSize );
480
481 double d = 1;
482 while ( lowerNiceUnitsPerSeg > maximumSize && upperNiceUnitsPerSeg < minimumSize )
483 {
484 d *= 10;
485 lowerNiceUnitsPerSeg = nextNiceNumber( minimumSize, d );
486 upperNiceUnitsPerSeg = prevNiceNumber( maximumSize, d );
487 }
488
489 // Pick size from {lowerNiceUnitsPerSeg, upperNiceUnitsPerSeg}, use the larger if possible
490 return upperNiceUnitsPerSeg < minimumSize ? lowerNiceUnitsPerSeg : upperNiceUnitsPerSeg;
491 }
492}
493
495{
497 return false; // not a clipping provider, so shortcut out
498
499 // maps
500 QList< QgsLayoutItemMap * > maps;
501 item->layout()->layoutItems( maps );
502 for ( QgsLayoutItemMap *map : std::as_const( maps ) )
503 {
504 if ( map->itemClippingSettings()->isActive() && map->itemClippingSettings()->sourceItem() == item )
505 return true;
506 }
507
508 // pictures
509 QList< QgsLayoutItemPicture * > pictures;
510 item->layout()->layoutItems( pictures );
511 for ( QgsLayoutItemPicture *picture : std::as_const( pictures ) )
512 {
513 if ( picture->clipToItem() && picture->clippingItem() == item )
514 return true;
515 }
516
517 return false;
518}
519
520constexpr double pointToMM = 25.4 / 72.0;
521
522double QgsLayoutUtils::pointsToMM( const double pointSize )
523{
524 //conversion to mm based on 1 point = 1/72 inch
525 return ( pointSize * pointToMM );
526}
527
528double QgsLayoutUtils::mmToPoints( const double mmSize )
529{
530 //conversion to points based on 1 point = 1/72 inch
531 return ( mmSize / pointToMM );
532}
533
534QVector< double > QgsLayoutUtils::predefinedScales( const QgsLayout *layout )
535{
536 QgsProject *lProject = layout ? layout->project() : nullptr;
537 QVector< double > mapScales;
538 if ( lProject )
539 mapScales = lProject->viewSettings()->mapScales();
540
541 bool hasProjectScales( lProject ? lProject->viewSettings()->useProjectScales() : false );
542 if ( !hasProjectScales || mapScales.isEmpty() )
543 {
544 // default to global map tool scales
545 const QStringList scales = QgsSettingsRegistryCore::settingsMapScales->value();
546 for ( const QString &scale : scales )
547 {
548 QStringList parts( scale.split( ':' ) );
549 if ( parts.size() == 2 )
550 {
551 mapScales.push_back( parts[1].toDouble() );
552 }
553 }
554 }
555
556 return mapScales;
557}
@ Millimeters
Millimeters.
Definition qgis.h:5791
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.
A layout item subclass that displays SVG files or raster format images (jpg, png, ....
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.
Qgis::TextRenderFormat textRenderFormat() const
Returns the text render format, which dictates how text is rendered (e.g.
Qgis::RenderContextFlags renderContextFlags() const
Returns the combination of render context flags matched to the layout context's settings.
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 Q_DECL_DEPRECATED 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:51
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
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...
QgsLayoutMeasurement convertFromLayoutUnits(double length, Qgis::LayoutUnit unit) const
Converts a length measurement from the layout's native units to a specified target unit.
QgsProject * project() const
The project associated with the layout.
Base class for all map layer types.
Definition qgsmaplayer.h:83
Contains configuration for rendering maps.
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:114
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
Q_INVOKABLE 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.
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(Qgis::TextRenderFormat format)
Sets the text render format, which dictates how text is rendered (e.g.
void setFlags(Qgis::RenderContextFlags flags)
Set combination of flags that will be used for rendering.
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
Scoped object for saving and restoring a QPainter object's state.
static const QgsSettingsEntryStringList * settingsMapScales
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:7795
constexpr QgsDataDefinedStringDecoder< V, N > makeDataDefinedStringDecoder(const DataDefinedDecoderEntry< V >(&values)[N])
Creates a QgsDataDefinedStringDecoder from a hardcoded lookup table.
double prevNiceNumber(double a, double d=1)
constexpr double pointToMM
#define M_DEG2RAD
double nextNiceNumber(double a, double d=1)