27#include <QStyleOptionGraphicsItem>
32#define M_DEG2RAD 0.0174532925
37 double rotToRad = angle * M_PI / 180.0;
39 xRot = x * std::cos( rotToRad ) - y * std::sin( rotToRad );
40 yRot = x * std::sin( rotToRad ) + y * std::cos( rotToRad );
47 double clippedAngle = angle;
48 if ( clippedAngle >= 360.0 || clippedAngle <= -360.0 )
50 clippedAngle = std::fmod( clippedAngle, 360.0 );
52 if ( !allowNegative && clippedAngle < 0.0 )
54 clippedAngle += 360.0;
65 if ( clippedAngle >= 22.5 && clippedAngle < 67.5 )
69 else if ( clippedAngle >= 67.5 && clippedAngle < 112.5 )
73 else if ( clippedAngle >= 112.5 && clippedAngle < 157.5 )
77 else if ( clippedAngle >= 157.5 && clippedAngle < 202.5 )
81 else if ( clippedAngle >= 202.5 && clippedAngle < 247.5 )
85 else if ( clippedAngle >= 247.5 && clippedAngle < 292.5 )
89 else if ( clippedAngle >= 292.5 && clippedAngle < 337.5 )
105 if ( dpi < 0 && painter && painter->device() )
107 context.
setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
124 dpi = ( painter && painter->device() ) ? painter->device()->logicalDpiX() : 88;
126 double dotsPerMM = dpi / 25.4;
130 QSizeF mapSizeLayoutUnits = map->rect().size();
159 const double left = !
qgsDoubleNear( boundsBefore.left(), boundsBefore.right() )
160 ?
relativePosition( rectToResize.left(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() )
161 : boundsAfter.left();
162 const double right = !
qgsDoubleNear( boundsBefore.left(), boundsBefore.right() )
163 ?
relativePosition( rectToResize.right(), boundsBefore.left(), boundsBefore.right(), boundsAfter.left(), boundsAfter.right() )
164 : boundsAfter.right();
165 const double top = !
qgsDoubleNear( boundsBefore.top(), boundsBefore.bottom() )
166 ?
relativePosition( rectToResize.top(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() )
168 const double bottom = !
qgsDoubleNear( boundsBefore.top(), boundsBefore.bottom() )
169 ?
relativePosition( rectToResize.bottom(), boundsBefore.top(), boundsBefore.bottom(), boundsAfter.top(), boundsAfter.bottom() )
170 : boundsAfter.bottom();
172 rectToResize.setRect( left, top, right - left, bottom - top );
178 double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
179 double c = afterMin - ( beforeMin * m );
182 return m * position +
c;
188 QFont scaledFont = font;
189 double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
190 scaledFont.setPixelSize( pixelSize );
199 QFontMetricsF fontMetrics( metricsFont );
200 return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
208 QFontMetricsF fontMetrics( metricsFont );
209 return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
218 QFontMetricsF fontMetrics( metricsFont );
219 return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
228 QFontMetricsF fontMetrics( metricsFont );
229 return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
237 const QStringList multiLineSplit = text.split(
'\n' );
239 QFontMetricsF fontMetrics( metricsFont );
242 for (
const QString &line : multiLineSplit )
244 maxWidth = std::max( maxWidth, ( fontMetrics.horizontalAdvance( line ) / FONT_WORKAROUND_SCALE ) );
251 QStringList multiLineSplit = text.split(
'\n' );
252 int lines = multiLineSplit.size();
257 QFontMetricsF fontMetrics( metricsFont );
259 double fontHeight = fontMetrics.ascent() + fontMetrics.descent();
260 double textHeight = fontMetrics.ascent() +
static_cast< double >( ( lines - 1 ) * fontHeight * multiLineHeight );
262 return textHeight / FONT_WORKAROUND_SCALE;
277 painter->setFont( textFont );
278 if ( color.isValid() )
280 painter->setPen( color );
282 double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
283 painter->scale( scaleFactor, scaleFactor );
284 painter->drawText( position * FONT_WORKAROUND_SCALE, text );
287void 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 )
298 QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
299 rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
302 painter->setFont( textFont );
303 if ( color.isValid() )
305 painter->setPen( color );
307 double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
308 painter->scale( scaleFactor, scaleFactor );
309 painter->drawText( scaledRect, halignment | valignment | flags, text );
314 double originalWidth = originalRect.width();
315 double originalHeight = originalRect.height();
316 double boundsWidth = boundsRect.width();
317 double boundsHeight = boundsRect.height();
318 double ratioBoundsRect = boundsWidth / boundsHeight;
328 rectScale = ( ( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
332 rectScale = ( ( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
334 double rectScaledWidth = rectScale * originalWidth;
335 double rectScaledHeight = rectScale * originalHeight;
339 return QRectF( ( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
343 return QRectF( ( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
348 double angleRad = -clippedRotation *
M_DEG2RAD;
349 double cosAngle = std::cos( angleRad );
350 double sinAngle = std::sin( angleRad );
353 double widthBoundsRotatedRect = originalWidth * std::fabs( cosAngle ) + originalHeight * std::fabs( sinAngle );
354 double heightBoundsRotatedRect = originalHeight * std::fabs( cosAngle ) + originalWidth * std::fabs( sinAngle );
358 double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
359 double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
360 double rectScaledWidth = rectScale * originalWidth;
361 double rectScaledHeight = rectScale * originalHeight;
365 double currentCornerX = 0;
367 currentCornerX += rectScaledWidth * cosAngle;
368 minX = minX < currentCornerX ? minX : currentCornerX;
369 currentCornerX += rectScaledHeight * sinAngle;
370 minX = minX < currentCornerX ? minX : currentCornerX;
371 currentCornerX -= rectScaledWidth * cosAngle;
372 minX = minX < currentCornerX ? minX : currentCornerX;
374 double currentCornerY = 0;
376 currentCornerY -= rectScaledWidth * sinAngle;
377 minY = minY < currentCornerY ? minY : currentCornerY;
378 currentCornerY += rectScaledHeight * cosAngle;
379 minY = minY < currentCornerY ? minY : currentCornerY;
380 currentCornerY += rectScaledWidth * sinAngle;
381 minY = minY < currentCornerY ? minY : currentCornerY;
384 double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
385 offsetX += std::fabs( minX );
386 double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
387 offsetY += std::fabs( minY );
389 return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
394 QString s =
string.trimmed();
395 if ( s.compare( QLatin1String(
"Portrait" ), Qt::CaseInsensitive ) == 0 )
400 else if ( s.compare( QLatin1String(
"Landscape" ), Qt::CaseInsensitive ) == 0 )
411#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
420 return !
qgsDoubleNear( style->matrix.m11(), 0.0 ) ? style->matrix.m11() : style->matrix.m12();
430 return QStyleOptionGraphicsItem::levelOfDetailFromTransform( painter->worldTransform() );
444 const auto layers = project->
mapLayers();
445 for (
auto it = layers.constBegin(); it != layers.constEnd(); ++it )
447 if ( it.value()->name().compare(
string, Qt::CaseInsensitive ) == 0 )
457 double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
458 return std::ceil( a / s ) * s;
464 double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
465 return std::floor( a / s ) * s;
470 if ( maximumSize < minimumSize )
484 while ( lowerNiceUnitsPerSeg > maximumSize && upperNiceUnitsPerSeg < minimumSize )
492 return upperNiceUnitsPerSeg < minimumSize ? lowerNiceUnitsPerSeg : upperNiceUnitsPerSeg;
502 QList< QgsLayoutItemMap * > maps;
506 if ( map->itemClippingSettings()->isActive() && map->itemClippingSettings()->sourceItem() == item )
512double QgsLayoutUtils::pointsToMM(
const double pointSize )
515 return ( pointSize * 0.3527 );
518double QgsLayoutUtils::mmToPoints(
const double mmSize )
521 return ( mmSize / 0.3527 );
527 QVector< double > mapScales;
532 if ( !hasProjectScales || mapScales.isEmpty() )
537 for (
const QString &scale : scales )
539 QStringList parts( scale.split(
':' ) );
540 if ( parts.size() == 2 )
542 mapScales.push_back( parts[1].toDouble() );
@ Millimeters
Millimeters.
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.
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.
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.
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.
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,...
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.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
static const QgsSettingsEntryStringList * settingsMapScales
This class is a composition of two QSettings instances:
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)
double prevNiceNumber(double a, double d=1)
double nextNiceNumber(double a, double d=1)