25 #include <QStyleOptionGraphicsItem>
30 #define M_DEG2RAD 0.0174532925
35 double rotToRad =
angle * M_PI / 180.0;
37 xRot = x * std::cos( rotToRad ) - y * std::sin( rotToRad );
38 yRot = x * std::sin( rotToRad ) + y * std::cos( rotToRad );
45 double clippedAngle =
angle;
46 if ( clippedAngle >= 360.0 || clippedAngle <= -360.0 )
48 clippedAngle = std::fmod( clippedAngle, 360.0 );
50 if ( !allowNegative && clippedAngle < 0.0 )
52 clippedAngle += 360.0;
63 if ( clippedAngle >= 22.5 && clippedAngle < 67.5 )
67 else if ( clippedAngle >= 67.5 && clippedAngle < 112.5 )
71 else if ( clippedAngle >= 112.5 && clippedAngle < 157.5 )
75 else if ( clippedAngle >= 157.5 && clippedAngle < 202.5 )
79 else if ( clippedAngle >= 202.5 && clippedAngle < 247.5 )
83 else if ( clippedAngle >= 247.5 && clippedAngle < 292.5 )
87 else if ( clippedAngle >= 292.5 && clippedAngle < 337.5 )
103 if ( dpi < 0 && painter && painter->device() )
105 context.
setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
122 dpi = ( painter && painter->device() ) ? painter->device()->logicalDpiX() : 88;
124 double dotsPerMM = dpi / 25.4;
128 QSizeF mapSizeLayoutUnits = map->rect().size();
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() );
162 rectToResize.setRect( left, top, right - left, bottom - top );
168 double m = ( afterMax - afterMin ) / ( beforeMax - beforeMin );
169 double c = afterMin - ( beforeMin * m );
172 return m * position +
c;
178 QFont scaledFont = font;
179 double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
180 scaledFont.setPixelSize( pixelSize );
189 QFontMetricsF fontMetrics( metricsFont );
190 return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
198 QFontMetricsF fontMetrics( metricsFont );
199 return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
208 QFontMetricsF fontMetrics( metricsFont );
209 return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
218 QFontMetricsF fontMetrics( metricsFont );
219 return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
227 const QStringList multiLineSplit = text.split(
'\n' );
229 QFontMetricsF fontMetrics( metricsFont );
232 for (
const QString &line : multiLineSplit )
234 maxWidth = std::max( maxWidth, ( fontMetrics.horizontalAdvance( line ) / FONT_WORKAROUND_SCALE ) );
241 QStringList multiLineSplit = text.split(
'\n' );
242 int lines = multiLineSplit.size();
247 QFontMetricsF fontMetrics( metricsFont );
249 double fontHeight = fontMetrics.ascent() + fontMetrics.descent();
250 double textHeight = fontMetrics.ascent() +
static_cast< double >( ( lines - 1 ) * fontHeight * multiLineHeight );
252 return textHeight / FONT_WORKAROUND_SCALE;
267 painter->setFont( textFont );
268 if ( color.isValid() )
270 painter->setPen( color );
272 double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
273 painter->scale( scaleFactor, scaleFactor );
274 painter->drawText( position * FONT_WORKAROUND_SCALE, text );
277 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 )
288 QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
289 rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
292 painter->setFont( textFont );
293 if ( color.isValid() )
295 painter->setPen( color );
297 double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
298 painter->scale( scaleFactor, scaleFactor );
299 painter->drawText( scaledRect, halignment | valignment | flags, text );
304 double originalWidth = originalRect.width();
305 double originalHeight = originalRect.height();
306 double boundsWidth = boundsRect.width();
307 double boundsHeight = boundsRect.height();
308 double ratioBoundsRect = boundsWidth / boundsHeight;
318 rectScale = ( ( originalWidth / originalHeight ) > ratioBoundsRect ) ? boundsWidth / originalWidth : boundsHeight / originalHeight;
322 rectScale = ( ( originalHeight / originalWidth ) > ratioBoundsRect ) ? boundsWidth / originalHeight : boundsHeight / originalWidth;
324 double rectScaledWidth = rectScale * originalWidth;
325 double rectScaledHeight = rectScale * originalHeight;
329 return QRectF( ( boundsWidth - rectScaledWidth ) / 2.0, ( boundsHeight - rectScaledHeight ) / 2.0, rectScaledWidth, rectScaledHeight );
333 return QRectF( ( boundsWidth - rectScaledHeight ) / 2.0, ( boundsHeight - rectScaledWidth ) / 2.0, rectScaledWidth, rectScaledHeight );
338 double angleRad = -clippedRotation *
M_DEG2RAD;
339 double cosAngle = std::cos( angleRad );
340 double sinAngle = std::sin( angleRad );
343 double widthBoundsRotatedRect = originalWidth * std::fabs( cosAngle ) + originalHeight * std::fabs( sinAngle );
344 double heightBoundsRotatedRect = originalHeight * std::fabs( cosAngle ) + originalWidth * std::fabs( sinAngle );
348 double ratioBoundsRotatedRect = widthBoundsRotatedRect / heightBoundsRotatedRect;
349 double rectScale = ratioBoundsRotatedRect > ratioBoundsRect ? boundsWidth / widthBoundsRotatedRect : boundsHeight / heightBoundsRotatedRect;
350 double rectScaledWidth = rectScale * originalWidth;
351 double rectScaledHeight = rectScale * originalHeight;
355 double currentCornerX = 0;
357 currentCornerX += rectScaledWidth * cosAngle;
358 minX = minX < currentCornerX ? minX : currentCornerX;
359 currentCornerX += rectScaledHeight * sinAngle;
360 minX = minX < currentCornerX ? minX : currentCornerX;
361 currentCornerX -= rectScaledWidth * cosAngle;
362 minX = minX < currentCornerX ? minX : currentCornerX;
364 double currentCornerY = 0;
366 currentCornerY -= rectScaledWidth * sinAngle;
367 minY = minY < currentCornerY ? minY : currentCornerY;
368 currentCornerY += rectScaledHeight * cosAngle;
369 minY = minY < currentCornerY ? minY : currentCornerY;
370 currentCornerY += rectScaledWidth * sinAngle;
371 minY = minY < currentCornerY ? minY : currentCornerY;
374 double offsetX = ratioBoundsRotatedRect > ratioBoundsRect ? 0 : ( boundsWidth - rectScale * widthBoundsRotatedRect ) / 2.0;
375 offsetX += std::fabs( minX );
376 double offsetY = ratioBoundsRotatedRect > ratioBoundsRect ? ( boundsHeight - rectScale * heightBoundsRotatedRect ) / 2.0 : 0;
377 offsetY += std::fabs( minY );
379 return QRectF( offsetX, offsetY, rectScaledWidth, rectScaledHeight );
384 QString s =
string.trimmed();
385 if ( s.compare( QLatin1String(
"Portrait" ), Qt::CaseInsensitive ) == 0 )
390 else if ( s.compare( QLatin1String(
"Landscape" ), Qt::CaseInsensitive ) == 0 )
401 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
410 return !
qgsDoubleNear( style->matrix.m11(), 0.0 ) ? style->matrix.m11() : style->matrix.m12();
420 return QStyleOptionGraphicsItem::levelOfDetailFromTransform( painter->worldTransform() );
434 const auto layers = project->
mapLayers();
435 for (
auto it = layers.constBegin(); it != layers.constEnd(); ++it )
437 if ( it.value()->name().compare(
string, Qt::CaseInsensitive ) == 0 )
447 double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
448 return std::ceil( a / s ) * s;
454 double s = std::pow( 10.0, std::floor( std::log10( a ) ) ) / d;
455 return std::floor( a / s ) * s;
460 if ( maximumSize < minimumSize )
474 while ( lowerNiceUnitsPerSeg > maximumSize && upperNiceUnitsPerSeg < minimumSize )
482 return upperNiceUnitsPerSeg < minimumSize ? lowerNiceUnitsPerSeg : upperNiceUnitsPerSeg;
492 QList< QgsLayoutItemMap * > maps;
496 if ( map->itemClippingSettings()->isActive() && map->itemClippingSettings()->sourceItem() == item )
502 double QgsLayoutUtils::pointsToMM(
const double pointSize )
505 return ( pointSize * 0.3527 );
508 double QgsLayoutUtils::mmToPoints(
const double mmSize )
511 return ( mmSize / 0.3527 );
517 QVector< double > mapScales;
522 if ( !hasProjectScales || mapScales.isEmpty() )
527 const QStringList scales = scalesStr.split(
',' );
528 for (
const QString &scale : scales )
530 QStringList parts( scale.split(
':' ) );
531 if ( parts.size() == 2 )
533 mapScales.push_back( parts[1].toDouble() );