30 #include <QTextBoundaryFinder>
35 static void _fixQPictureDPI( QPainter *p )
41 p->scale(
static_cast< double >(
qt_defaultDpiX() ) / p->device()->logicalDpiX(),
42 static_cast< double >(
qt_defaultDpiY() ) / p->device()->logicalDpiY() );
47 if ( alignment & Qt::AlignLeft )
49 else if ( alignment & Qt::AlignRight )
51 else if ( alignment & Qt::AlignHCenter )
53 else if ( alignment & Qt::AlignJustify )
62 if ( alignment & Qt::AlignTop )
64 else if ( alignment & Qt::AlignBottom )
66 else if ( alignment & Qt::AlignVCenter )
69 else if ( alignment & Qt::AlignBaseline )
77 return static_cast< int >(
c.convertToPainterUnits( size, unit, mapUnitScale ) + 0.5 );
85 tmpFormat = updateShadowPosition( tmpFormat );
92 drawPart( rect, rotation, alignment, vAlignment, document, context, tmpFormat,
Background );
97 drawPart( rect, rotation, alignment, vAlignment, document, context, tmpFormat,
Buffer );
100 drawPart( rect, rotation, alignment, vAlignment, document, context, tmpFormat,
Text );
108 tmpFormat = updateShadowPosition( tmpFormat );
120 drawPart( point, rotation, alignment, document, context, tmpFormat,
Buffer );
123 drawPart( point, rotation, alignment, document, context, tmpFormat,
Text );
152 drawPart( rect, rotation, alignment,
AlignTop, document, context, format, part );
163 component.dpiRatio = 1.0;
164 component.origin = rect.topLeft();
165 component.rotation = rotation;
166 component.size = rect.size();
167 component.hAlign = alignment;
180 double xc = rect.width() / 2.0;
181 double yc = rect.height() / 2.0;
183 double angle = -rotation;
184 double xd = xc * std::cos(
angle ) - yc * std::sin(
angle );
185 double yd = xc * std::sin(
angle ) + yc * std::cos(
angle );
187 component.center = QPointF( component.origin.x() + xd, component.origin.y() + yd );
191 component.center = rect.center();
194 QgsTextRenderer::drawBackground( context, component, format, document,
Rect );
208 drawTextInternal( part, context, format, component,
211 alignment, vAlignment );
220 drawPart( origin, rotation, alignment, document, context, format, part );
231 component.dpiRatio = 1.0;
232 component.origin = origin;
233 component.rotation = rotation;
234 component.hAlign = alignment;
243 QgsTextRenderer::drawBackground( context, component, format, document,
Point );
256 drawTextInternal( part, context, format, component,
268 return QFontMetricsF( format.
scaledFont( context, scaleFactor ), context.
painter() ? context.
painter()->device() :
nullptr );
274 QPainter *p = context.
painter();
279 if ( component.rotation >= -315 && component.rotation < -90 )
283 else if ( component.rotation >= -90 && component.rotation < -45 )
297 const double scaleFactor = calculateScaleFactorForFormat( context, format );
299 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
307 bool isNullSize =
false;
308 const QFont font = format.
scaledFont( context, scaleFactor, &isNullSize );
312 referenceScaleOverride.reset();
315 path.setFillRule( Qt::WindingFill );
317 switch ( orientation )
324 QFont fragmentFont = font;
327 if ( component.extraWordSpacing || component.extraLetterSpacing )
328 applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing );
330 path.addText( xOffset, 0, fragmentFont, fragment.
text() );
341 double letterSpacing = font.letterSpacing();
342 double partYOffset = component.offset.y() * scaleFactor;
345 QFont fragmentFont = font;
348 QFontMetricsF fragmentMetrics( fragmentFont );
349 const double labelWidth = fragmentMetrics.maxWidth();
352 for (
const QString &part : parts )
354 double partXOffset = ( labelWidth - ( fragmentMetrics.horizontalAdvance( part ) - letterSpacing ) ) / 2;
355 path.addText( partXOffset, partYOffset, fragmentFont, part );
356 partYOffset += fragmentMetrics.ascent() + letterSpacing;
359 advance = partYOffset - component.offset.y() * scaleFactor;
364 QColor bufferColor = buffer.
color();
365 bufferColor.setAlphaF( buffer.
opacity() );
366 QPen pen( bufferColor );
367 pen.setWidthF( penSize * scaleFactor );
369 QColor tmpColor( bufferColor );
373 tmpColor.setAlpha( 0 );
379 buffp.begin( &buffPict );
383 std::unique_ptr< QgsPaintEffect > tmpEffect( buffer.
paintEffect()->
clone() );
385 tmpEffect->begin( context );
386 context.
painter()->setPen( pen );
387 context.
painter()->setBrush( tmpColor );
388 if ( scaleFactor != 1.0 )
389 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
390 context.
painter()->drawPath( path );
391 if ( scaleFactor != 1.0 )
392 context.
painter()->scale( scaleFactor, scaleFactor );
393 tmpEffect->end( context );
399 if ( scaleFactor != 1.0 )
400 buffp.scale( 1 / scaleFactor, 1 / scaleFactor );
402 buffp.setBrush( tmpColor );
403 buffp.drawPath( path );
409 QgsTextRenderer::Component bufferComponent = component;
410 bufferComponent.origin = QPointF( 0.0, 0.0 );
411 bufferComponent.picture = buffPict;
412 bufferComponent.pictureBuffer = penSize / 2.0;
416 bufferComponent.offset.setY( bufferComponent.offset.y() - bufferComponent.size.height() );
418 drawShadow( context, bufferComponent, format );
426 p->setCompositionMode( buffer.
blendMode() );
430 p->scale( component.dpiRatio, component.dpiRatio );
431 _fixQPictureDPI( p );
432 p->drawPicture( 0, 0, buffPict );
434 return advance / scaleFactor;
452 path.setFillRule( Qt::WindingFill );
454 const double scaleFactor = calculateScaleFactorForFormat( context, format );
459 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
467 bool isNullSize =
false;
468 const QFont font = format.
scaledFont( context, scaleFactor, &isNullSize );
472 referenceScaleOverride.reset();
477 QFont fragmentFont = font;
480 path.addText( xOffset, 0, fragmentFont, fragment.
text() );
485 QColor bufferColor( Qt::gray );
486 bufferColor.setAlphaF( mask.
opacity() );
490 brush.setColor( bufferColor );
491 pen.setColor( bufferColor );
492 pen.setWidthF( penSize * scaleFactor );
499 p->scale( component.dpiRatio, component.dpiRatio );
505 if ( scaleFactor != 1.0 )
506 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
507 context.
painter()->setPen( pen );
508 context.
painter()->setBrush( brush );
509 context.
painter()->drawPath( path );
510 if ( scaleFactor != 1.0 )
511 context.
painter()->scale( scaleFactor, scaleFactor );
516 if ( scaleFactor != 1.0 )
517 p->scale( 1 / scaleFactor, 1 / scaleFactor );
519 p->setBrush( brush );
521 if ( scaleFactor != 1.0 )
522 p->scale( scaleFactor, scaleFactor );
539 return textWidth( context, format, doc );
545 const double scaleFactor = calculateScaleFactorForFormat( context, format );
547 bool isNullSize =
false;
548 const QFont baseFont = format.
scaledFont( context, scaleFactor, &isNullSize );
557 double maxLineWidth = 0;
560 double blockWidth = 0;
565 maxLineWidth = std::max( maxLineWidth, blockWidth );
567 width = maxLineWidth;
573 double totalLineWidth = 0;
577 double blockWidth = 0;
580 QFont fragmentFont = baseFont;
582 blockWidth = std::max( QFontMetricsF( fragmentFont ).maxWidth(), blockWidth );
585 totalLineWidth += blockIndex == 0 ? blockWidth : blockWidth * format.
lineHeight();
588 width = totalLineWidth;
599 return width / scaleFactor;
616 const double scaleFactor = calculateScaleFactorForFormat( context, format );
617 bool isNullSize =
false;
618 const QFont baseFont = format.
scaledFont( context, scaleFactor, &isNullSize );
622 const QFontMetrics fm( baseFont );
623 const double height = ( character.isNull() ? fm.height() : fm.boundingRect( character ).height() ) / scaleFactor;
625 if ( !includeEffects )
628 double maxExtension = 0;
648 return height + maxExtension;
657 const double scaleFactor = calculateScaleFactorForFormat( context, format );
659 bool isNullSize =
false;
660 const QFont baseFont = format.
scaledFont( context, scaleFactor, &isNullSize );
669 double totalHeight = 0;
670 double lastLineLeading = 0;
673 double maxBlockHeight = 0;
674 double maxBlockLineSpacing = 0;
675 double maxBlockLeading = 0;
678 QFont fragmentFont = baseFont;
680 const QFontMetricsF fm( fragmentFont );
682 const double fragmentHeight = fm.ascent() + fm.descent();
684 maxBlockHeight = std::max( maxBlockHeight, fragmentHeight );
685 if ( fm.lineSpacing() > maxBlockLineSpacing )
687 maxBlockLineSpacing = fm.lineSpacing();
688 maxBlockLeading = fm.leading();
698 totalHeight += blockIndex == 0 ? maxBlockHeight : maxBlockHeight * format.
lineHeight();
704 totalHeight += blockIndex == 0 ? maxBlockHeight : maxBlockLineSpacing * format.
lineHeight();
705 if ( blockIndex > 0 )
706 lastLineLeading = maxBlockLeading;
713 return ( totalHeight - lastLineLeading ) / scaleFactor;
718 double maxBlockHeight = 0;
721 double blockHeight = 0;
722 int fragmentIndex = 0;
725 QFont fragmentFont = baseFont;
727 const QFontMetricsF fm( fragmentFont );
729 const double labelHeight = fm.ascent();
730 const double letterSpacing = fragmentFont.letterSpacing();
732 blockHeight += fragmentIndex = 0 ? labelHeight * fragment.
text().size() + ( fragment.
text().size() - 1 ) * letterSpacing
733 : fragment.
text().size() * ( labelHeight + letterSpacing );
736 maxBlockHeight = std::max( maxBlockHeight, blockHeight );
739 return maxBlockHeight / scaleFactor;
756 QPainter *prevP = context.
painter();
757 QPainter *p = context.
painter();
758 std::unique_ptr< QgsPaintEffect > tmpEffect;
762 tmpEffect->begin( context );
771 const double originAdjustRotationRadians = -component.rotation;
774 component.rotation = -( component.rotation * 180 / M_PI );
775 component.rotationOffset =
780 component.rotation = 0.0;
781 component.rotationOffset = background.
rotation();
784 const double scaleFactor = calculateScaleFactorForFormat( context, format );
789 double width =
textWidth( context, format, document );
790 double height =
textHeight( context, format, document, mode );
795 switch ( component.hAlign )
799 component.center = QPointF( component.origin.x() + width / 2.0,
800 component.origin.y() + height / 2.0 );
804 component.center = QPointF( component.origin.x() + component.size.width() / 2.0,
805 component.origin.y() + height / 2.0 );
809 component.center = QPointF( component.origin.x() + component.size.width() - width / 2.0,
810 component.origin.y() + height / 2.0 );
817 bool isNullSize =
false;
818 QFontMetricsF fm( format.
scaledFont( context, scaleFactor, &isNullSize ) );
819 double originAdjust = isNullSize ? 0 : ( fm.ascent() / scaleFactor / 2.0 - fm.leading() / scaleFactor / 2.0 );
820 switch ( component.hAlign )
824 component.center = QPointF( component.origin.x() + width / 2.0,
825 component.origin.y() - height / 2.0 + originAdjust );
829 component.center = QPointF( component.origin.x(),
830 component.origin.y() - height / 2.0 + originAdjust );
834 component.center = QPointF( component.origin.x() - width / 2.0,
835 component.origin.y() - height / 2.0 + originAdjust );
842 const double dx = component.center.x() - component.origin.x();
843 const double dy = component.center.y() - component.origin.y();
844 component.center.setX( component.origin.x() + ( std::cos( originAdjustRotationRadians ) * dx - std::sin( originAdjustRotationRadians ) * dy ) );
845 component.center.setY( component.origin.y() + ( std::sin( originAdjustRotationRadians ) * dx + std::cos( originAdjustRotationRadians ) * dy ) );
855 component.size = QSizeF( width, height );
860 switch ( background.
type() )
873 double sizeOut = 0.0;
881 sizeOut = std::max( component.size.width(), component.size.height() );
885 sizeOut += bufferSize * 2;
893 std::unique_ptr< QgsMarkerSymbol > renderedSymbol;
897 map[QStringLiteral(
"name" )] = background.
svgFile().trimmed();
898 map[QStringLiteral(
"size" )] = QString::number( sizeOut );
900 map[QStringLiteral(
"angle" )] = QString::number( 0.0 );
908 map[QStringLiteral(
"fill" )] = background.
fillColor().name();
909 map[QStringLiteral(
"outline" )] = background.
strokeColor().name();
910 map[QStringLiteral(
"outline-width" )] = QString::number( background.
strokeWidth() );
917 QVariantMap shdwmap( map );
918 shdwmap[QStringLiteral(
"fill" )] = shadow.
color().name();
919 shdwmap[QStringLiteral(
"outline" )] = shadow.
color().name();
920 shdwmap[QStringLiteral(
"size" )] = QString::number( sizeOut );
925 svgp.begin( &svgPict );
942 svgShdwM->
renderPoint( QPointF( sizeOut / 2, -sizeOut / 2 ), svgShdwContext );
945 component.picture = svgPict;
947 component.pictureBuffer = 0.0;
949 component.size = QSizeF( sizeOut, sizeOut );
950 component.offset = QPointF( 0.0, 0.0 );
956 p->translate( component.center.x(), component.center.y() );
957 p->rotate( component.rotation );
960 p->translate( QPointF( xoff, yoff ) );
961 p->rotate( component.rotationOffset );
962 p->translate( -sizeOut / 2, sizeOut / 2 );
964 drawShadow( context, component, format );
966 renderedSymbol.reset( );
974 renderedSymbol->setSize( sizeOut );
978 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
986 p->setCompositionMode( background.
blendMode() );
988 p->translate( component.center.x(), component.center.y() );
989 p->rotate( component.rotation );
992 p->translate( QPointF( xoff, yoff ) );
993 p->rotate( component.rotationOffset );
997 renderedSymbol->renderPoint( QPointF( 0, 0 ), &f, context );
998 renderedSymbol->stopRender( context );
999 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1009 double w = component.size.width();
1010 double h = component.size.height();
1031 h = std::sqrt( std::pow( w, 2 ) + std::pow( h, 2 ) );
1037 h = h * M_SQRT1_2 * 2;
1038 w = w * M_SQRT1_2 * 2;
1046 w += bufferWidth * 2;
1047 h += bufferHeight * 2;
1051 QRectF rect( -w / 2.0, - h / 2.0, w, h );
1053 if ( rect.isNull() )
1059 p->translate( QPointF( component.center.x(), component.center.y() ) );
1060 p->rotate( component.rotation );
1063 p->translate( QPointF( xoff, yoff ) );
1064 p->rotate( component.rotationOffset );
1070 QTransform t = QTransform::fromScale( 10, 10 );
1072 QTransform ti = t.inverted();
1079 path.addRoundedRect( rect, background.
radii().width(), background.
radii().height(), Qt::RelativeSize );
1085 path.addRoundedRect( rect, xRadius, yRadius );
1091 path.addEllipse( rect );
1093 QPolygonF tempPolygon = path.toFillPolygon( t );
1094 QPolygonF polygon = ti.map( tempPolygon );
1096 QPainter *oldp = context.
painter();
1099 shapep.begin( &shapePict );
1102 std::unique_ptr< QgsFillSymbol > renderedSymbol;
1104 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1108 renderedSymbol->renderPolygon( polygon,
nullptr, &f, context );
1109 renderedSymbol->stopRender( context );
1116 component.picture = shapePict;
1119 component.size = rect.size();
1120 component.offset = QPointF( rect.width() / 2, -rect.height() / 2 );
1121 drawShadow( context, component, format );
1126 p->setCompositionMode( background.
blendMode() );
1130 p->scale( component.dpiRatio, component.dpiRatio );
1131 _fixQPictureDPI( p );
1132 p->drawPicture( 0, 0, shapePict );
1133 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1140 tmpEffect->end( context );
1153 QPainter *p = context.
painter();
1154 double componentWidth = component.size.width(), componentHeight = component.size.height();
1155 double xOffset = component.offset.x(), yOffset = component.offset.y();
1156 double pictbuffer = component.pictureBuffer;
1161 radius /= ( mapUnits ? context.
scaleFactor() / component.dpiRatio : 1 );
1162 radius =
static_cast< int >( radius + 0.5 );
1166 double blurBufferClippingScale = 3.75;
1167 int blurbuffer = ( radius > 17 ? 16 : radius ) * blurBufferClippingScale;
1169 QImage blurImg( componentWidth + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1170 componentHeight + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1171 QImage::Format_ARGB32_Premultiplied );
1175 int minBlurImgSize = 1;
1179 int maxBlurImgSize = 40000;
1180 if ( blurImg.isNull()
1181 || ( blurImg.width() < minBlurImgSize || blurImg.height() < minBlurImgSize )
1182 || ( blurImg.width() > maxBlurImgSize || blurImg.height() > maxBlurImgSize ) )
1185 blurImg.fill( QColor( Qt::transparent ).rgba() );
1187 if ( !pictp.begin( &blurImg ) )
1189 pictp.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
1190 QPointF imgOffset( blurbuffer + pictbuffer + xOffset,
1191 blurbuffer + pictbuffer + componentHeight + yOffset );
1193 pictp.drawPicture( imgOffset,
1194 component.picture );
1197 pictp.setCompositionMode( QPainter::CompositionMode_SourceIn );
1198 pictp.fillRect( blurImg.rect(), shadow.
color() );
1202 if ( shadow.
blurRadius() > 0.0 && radius > 0 )
1210 picti.begin( &blurImg );
1211 picti.setBrush( Qt::Dense7Pattern );
1212 QPen imgPen( QColor( 0, 0, 255, 255 ) );
1213 imgPen.setWidth( 1 );
1214 picti.setPen( imgPen );
1215 picti.setOpacity( 0.1 );
1216 picti.drawRect( 0, 0, blurImg.width(), blurImg.height() );
1221 double angleRad = shadow.
offsetAngle() * M_PI / 180;
1229 angleRad -= ( component.rotation * M_PI / 180 + component.rotationOffset * M_PI / 180 );
1232 QPointF transPt( -offsetDist * std::cos( angleRad + M_PI_2 ),
1233 -offsetDist * std::sin( angleRad + M_PI_2 ) );
1236 p->setRenderHint( QPainter::SmoothPixmapTransform );
1240 p->setCompositionMode( shadow.
blendMode() );
1242 p->setOpacity( shadow.
opacity() );
1244 double scale = shadow.
scale() / 100.0;
1246 p->scale( scale, scale );
1247 if ( component.useOrigin )
1249 p->translate( component.origin.x(), component.origin.y() );
1251 p->translate( transPt );
1252 p->translate( -imgOffset.x(),
1254 p->drawImage( 0, 0, blurImg );
1261 p->setBrush( Qt::NoBrush );
1262 QPen imgPen( QColor( 255, 0, 0, 10 ) );
1263 imgPen.setWidth( 2 );
1264 imgPen.setStyle( Qt::DashLine );
1265 p->setPen( imgPen );
1266 p->scale( scale, scale );
1267 if ( component.useOrigin() )
1269 p->translate( component.origin().x(), component.origin().y() );
1271 p->translate( transPt );
1272 p->translate( -imgOffset.x(),
1274 p->drawRect( 0, 0, blurImg.width(), blurImg.height() );
1279 p->setBrush( Qt::NoBrush );
1280 QPen componentRectPen( QColor( 0, 255, 0, 70 ) );
1281 componentRectPen.setWidth( 1 );
1282 if ( component.useOrigin() )
1284 p->translate( component.origin().x(), component.origin().y() );
1286 p->setPen( componentRectPen );
1287 p->drawRect( QRect( -xOffset, -componentHeight - yOffset, componentWidth, componentHeight ) );
1293 void QgsTextRenderer::drawTextInternal( TextPart drawType,
1296 const Component &component,
1298 const QFontMetricsF *fontMetrics,
1299 HAlignment alignment, VAlignment vAlignment, DrawMode mode )
1306 double fontScale = 1.0;
1307 std::unique_ptr< QFontMetricsF > tmpMetrics;
1310 fontScale = calculateScaleFactorForFormat( context, format );
1312 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1313 if ( mode ==
Label )
1320 bool isNullSize =
false;
1321 const QFont f = format.
scaledFont( context, fontScale, &isNullSize );
1325 tmpMetrics = std::make_unique< QFontMetricsF >( f );
1328 referenceScaleOverride.reset();
1331 double rotation = 0;
1333 switch ( orientation )
1337 drawTextInternalHorizontal( context, format, drawType, mode, component, document, fontScale,
fontMetrics, alignment, vAlignment, rotation );
1344 drawTextInternalVertical( context, format, drawType, mode, component, document, fontScale,
fontMetrics, alignment, vAlignment, rotation );
1352 rotation = -component.rotation * 180 / M_PI;
1359 if ( rotation >= -315 && rotation < -90 )
1364 else if ( rotation >= -90 && rotation < -45 )
1380 void QgsTextRenderer::calculateExtraSpacingForLineJustification(
const double spaceToDistribute,
const QgsTextBlock &block,
double &extraWordSpace,
double &extraLetterSpace )
1383 QTextBoundaryFinder
finder( QTextBoundaryFinder::Word, blockText );
1385 int wordBoundaries = 0;
1386 while (
finder.toNextBoundary() != -1 )
1388 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1392 if ( wordBoundaries > 0 )
1395 extraWordSpace = spaceToDistribute / wordBoundaries;
1400 QTextBoundaryFinder
finder( QTextBoundaryFinder::Grapheme, blockText );
1403 int graphemeBoundaries = 0;
1404 while (
finder.toNextBoundary() != -1 )
1406 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1407 graphemeBoundaries++;
1410 if ( graphemeBoundaries > 0 )
1412 extraLetterSpace = spaceToDistribute / graphemeBoundaries;
1417 void QgsTextRenderer::applyExtraSpacingForLineJustification( QFont &font,
double extraWordSpace,
double extraLetterSpace )
1419 const double prevWordSpace = font.wordSpacing();
1420 font.setWordSpacing( prevWordSpace + extraWordSpace );
1421 const double prevLetterSpace = font.letterSpacing();
1422 font.setLetterSpacing( QFont::AbsoluteSpacing, prevLetterSpace + extraLetterSpace );
1425 void QgsTextRenderer::drawTextInternalHorizontal(
QgsRenderContext &context,
const QgsTextFormat &format, TextPart drawType, DrawMode mode,
const Component &component,
const QgsTextDocument &document,
double fontScale,
const QFontMetricsF *fontMetrics, HAlignment hAlignment,
1426 VAlignment vAlignment,
double rotation )
1429 const QStringList textLines = document.
toPlainText();
1431 double labelWidest = 0.0;
1436 for (
const QString &line : textLines )
1438 double labelWidth =
fontMetrics->horizontalAdvance( line ) / fontScale;
1439 if ( labelWidth > labelWidest )
1441 labelWidest = labelWidth;
1447 labelWidest = component.size.width();
1455 double ascentOffset = 0.25 *
fontMetrics->ascent() / fontScale;
1459 bool adjustForAlignment = hAlignment !=
AlignLeft && ( mode !=
Label || textLines.size() > 1 );
1463 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1465 const double overallHeight =
textHeight( context, format, textLines,
Rect );
1466 switch ( vAlignment )
1472 ascentOffset = -( component.size.height() - overallHeight ) * 0.5 + ascentOffset;
1476 ascentOffset = -( component.size.height() - overallHeight ) + ascentOffset;
1479 referenceScaleOverride.reset();
1482 for (
const QString &line : std::as_const( textLines ) )
1486 const bool isFinalLineInParagraph = ( i == document.
size() - 1 )
1491 context.
painter()->translate( component.origin );
1493 context.
painter()->rotate( rotation );
1498 maskPainter->save();
1499 maskPainter->translate( component.origin );
1501 maskPainter->rotate( rotation );
1505 double xMultiLineOffset = 0.0;
1506 double labelWidth =
fontMetrics->horizontalAdvance( line ) / fontScale;
1507 double extraWordSpace = 0;
1508 double extraLetterSpace = 0;
1509 if ( adjustForAlignment )
1511 double labelWidthDiff = 0;
1512 switch ( hAlignment )
1515 labelWidthDiff = ( labelWidest - labelWidth ) * 0.5;
1519 labelWidthDiff = labelWidest - labelWidth;
1523 if ( !isFinalLineInParagraph && labelWidest > labelWidth )
1525 calculateExtraSpacingForLineJustification( labelWidest - labelWidth, block, extraWordSpace, extraLetterSpace );
1526 labelWidth = labelWidest;
1538 xMultiLineOffset = labelWidthDiff;
1543 switch ( hAlignment )
1546 xMultiLineOffset = labelWidthDiff - labelWidest;
1550 xMultiLineOffset = labelWidthDiff - labelWidest / 2.0;
1562 double yMultiLineOffset = ascentOffset;
1569 yMultiLineOffset = - ascentOffset - ( textLines.size() - 1 - i ) * labelHeight * format.
lineHeight();
1574 yMultiLineOffset = - ascentOffset + labelHeight - 1 + format.
lineHeight() *
fontMetrics->lineSpacing() * i / fontScale;
1579 yMultiLineOffset = 0 - ( textLines.size() - 1 - i ) *
fontMetrics->lineSpacing() * format.
lineHeight() / fontScale;
1584 context.
painter()->translate( QPointF( xMultiLineOffset, yMultiLineOffset ) );
1586 maskPainter->translate( QPointF( xMultiLineOffset, yMultiLineOffset ) );
1588 Component subComponent;
1589 subComponent.block = block;
1590 subComponent.
size = QSizeF( labelWidth, labelHeight );
1591 subComponent.offset = QPointF( 0.0, -ascentOffset );
1592 subComponent.rotation = -component.rotation * 180 / M_PI;
1593 subComponent.rotationOffset = 0.0;
1594 subComponent.extraWordSpacing = extraWordSpace * fontScale;
1595 subComponent.extraLetterSpacing = extraLetterSpace * fontScale;
1600 QgsTextRenderer::drawMask( context, subComponent, format, mode );
1605 QgsTextRenderer::drawBuffer( context, subComponent, format, mode );
1612 textp.begin( &textPict );
1613 textp.setPen( Qt::NoPen );
1615 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1616 if ( mode ==
Label )
1622 bool isNullSize =
false;
1623 const QFont font = format.
scaledFont( context, fontScale, &isNullSize );
1624 referenceScaleOverride.reset();
1628 textp.scale( 1 / fontScale, 1 / fontScale );
1635 path.setFillRule( Qt::WindingFill );
1637 QFont fragmentFont = font;
1640 if ( extraWordSpace || extraLetterSpace )
1641 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1643 path.addText( xOffset, 0, fragmentFont, fragment.
text() );
1647 textp.setBrush( textColor );
1648 textp.drawPath( path );
1657 subComponent.picture = textPict;
1658 subComponent.pictureBuffer = 0.0;
1659 subComponent.origin = QPointF( 0.0, 0.0 );
1661 QgsTextRenderer::drawShadow( context, subComponent, format );
1671 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
1675 case Qgis::TextRenderFormat::AlwaysOutlines:
1678 _fixQPictureDPI( context.
painter() );
1679 context.
painter()->drawPicture( 0, 0, textPict );
1683 case Qgis::TextRenderFormat::AlwaysText:
1688 QFont fragmentFont = font;
1691 if ( extraWordSpace || extraLetterSpace )
1692 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1697 context.
painter()->setPen( textColor );
1698 context.
painter()->setFont( fragmentFont );
1699 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
1701 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
1702 context.
painter()->drawText( xOffset, 0, fragment.
text() );
1703 context.
painter()->scale( fontScale, fontScale );
1711 maskPainter->restore();
1716 void QgsTextRenderer::drawTextInternalVertical(
QgsRenderContext &context,
const QgsTextFormat &format,
QgsTextRenderer::TextPart drawType,
QgsTextRenderer::DrawMode mode,
const QgsTextRenderer::Component &component,
const QgsTextDocument &document,
double fontScale,
const QFontMetricsF *fontMetrics,
QgsTextRenderer::HAlignment hAlignment,
QgsTextRenderer::VAlignment,
double rotation )
1719 const QStringList textLines = document.
toPlainText();
1721 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1722 if ( mode ==
Label )
1729 bool isNullSize =
false;
1730 const QFont font = format.
scaledFont( context, fontScale, &isNullSize );
1734 referenceScaleOverride.reset();
1736 double letterSpacing = font.letterSpacing() / fontScale;
1738 double labelWidth =
fontMetrics->maxWidth() / fontScale;
1739 double actualLabelWidest = labelWidth + ( textLines.size() - 1 ) * labelWidth * format.
lineHeight();
1740 double labelWidest = 0.0;
1745 labelWidest = actualLabelWidest;
1749 labelWidest = component.size.width();
1753 int maxLineLength = 0;
1754 for (
const QString &line : std::as_const( textLines ) )
1756 maxLineLength = std::max( maxLineLength,
static_cast<int>( line.length() ) );
1758 double actualLabelHeight =
fontMetrics->ascent() / fontScale + (
fontMetrics->ascent() / fontScale + letterSpacing ) * ( maxLineLength - 1 );
1759 double ascentOffset =
fontMetrics->ascent() / fontScale;
1763 bool adjustForAlignment = hAlignment !=
AlignLeft && ( mode !=
Label || textLines.size() > 1 );
1770 context.
painter()->translate( component.origin );
1772 context.
painter()->rotate( rotation );
1777 maskPainter->save();
1778 maskPainter->translate( component.origin );
1780 maskPainter->rotate( rotation );
1784 double xOffset = actualLabelWidest - labelWidth - ( i * labelWidth * format.
lineHeight() );
1785 if ( adjustForAlignment )
1787 double labelWidthDiff = 0;
1788 switch ( hAlignment )
1791 labelWidthDiff = ( labelWidest - actualLabelWidest ) * 0.5;
1795 labelWidthDiff = labelWidest - actualLabelWidest;
1807 xOffset += labelWidthDiff;
1815 double yOffset = 0.0;
1821 if ( rotation >= -405 && rotation < -180 )
1823 yOffset = ascentOffset;
1825 else if ( rotation >= 0 && rotation < 45 )
1827 xOffset -= actualLabelWidest;
1828 yOffset = -actualLabelHeight + ascentOffset +
fontMetrics->descent() / fontScale;
1833 yOffset = -actualLabelHeight + ascentOffset;
1838 yOffset = -actualLabelHeight + ascentOffset;
1842 yOffset = ascentOffset;
1846 context.
painter()->translate( QPointF( xOffset, yOffset ) );
1848 double fragmentYOffset = 0;
1854 QFont fragmentFont( font );
1857 QFontMetricsF fragmentMetrics( fragmentFont );
1859 double labelHeight = fragmentMetrics.ascent() / fontScale + ( fragmentMetrics.ascent() / fontScale + letterSpacing ) * ( line.length() - 1 );
1861 Component subComponent;
1863 subComponent.size = QSizeF( labelWidth, labelHeight );
1864 subComponent.offset = QPointF( 0.0, fragmentYOffset );
1865 subComponent.rotation = -component.rotation * 180 / M_PI;
1866 subComponent.rotationOffset = 0.0;
1873 QgsTextRenderer::drawMask( context, subComponent, format );
1879 fragmentYOffset += QgsTextRenderer::drawBuffer( context, subComponent, format, mode );
1885 path.setFillRule( Qt::WindingFill );
1887 double partYOffset = 0.0;
1888 for (
const auto &part : parts )
1890 double partXOffset = ( labelWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
1891 path.addText( partXOffset * fontScale, partYOffset * fontScale, fragmentFont, part );
1892 partYOffset += fragmentMetrics.ascent() / fontScale + letterSpacing;
1898 textp.begin( &textPict );
1899 textp.setPen( Qt::NoPen );
1902 textp.setBrush( textColor );
1903 textp.scale( 1 / fontScale, 1 / fontScale );
1904 textp.drawPath( path );
1914 subComponent.picture = textPict;
1915 subComponent.pictureBuffer = 0.0;
1916 subComponent.origin = QPointF( 0.0, fragmentYOffset );
1917 const double prevY = subComponent.offset.y();
1918 subComponent.offset = QPointF( 0, -labelHeight );
1919 subComponent.useOrigin =
true;
1920 QgsTextRenderer::drawShadow( context, subComponent, format );
1921 subComponent.useOrigin =
false;
1922 subComponent.offset = QPointF( 0, prevY );
1932 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
1936 case Qgis::TextRenderFormat::AlwaysOutlines:
1939 _fixQPictureDPI( context.
painter() );
1940 context.
painter()->drawPicture( 0, fragmentYOffset, textPict );
1941 fragmentYOffset += partYOffset;
1945 case Qgis::TextRenderFormat::AlwaysText:
1947 context.
painter()->setFont( fragmentFont );
1948 context.
painter()->setPen( textColor );
1949 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
1951 double partYOffset = 0.0;
1952 for (
const QString &part : parts )
1954 double partXOffset = ( labelWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
1955 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
1956 context.
painter()->drawText( partXOffset * fontScale, ( fragmentYOffset + partYOffset ) * fontScale, part );
1957 context.
painter()->scale( fontScale, fontScale );
1958 partYOffset += fragmentMetrics.ascent() / fontScale + letterSpacing;
1960 fragmentYOffset += partYOffset;
1967 maskPainter->restore();
1982 if ( pixelSize < 50 )
1986 else if ( pixelSize > 200 )
1987 return 200 / pixelSize;
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
A class to manager painter saving and restoring required for effect drawing.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
Struct for storing maximum and minimum scales for measurements in map units.
A marker symbol type, for rendering Point and MultiPoint geometries.
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
virtual QgsPaintEffect * clone() const =0
Duplicates an effect by creating a deep copy of the effect.
bool enabled() const
Returns whether the effect is enabled.
A class to manage painter saving and restoring required for drawing on a different painter (mask pain...
static QStringList splitToGraphemes(const QString &text)
Splits a text string to a list of graphemes, which are the smallest allowable character divisions in ...
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
QPainter * maskPainter(int id=0)
Returns a mask QPainter for the render operation.
bool useAdvancedEffects() const
Returns true if advanced effects such as blend modes such be used.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
bool isGuiPreview() const
Returns the Gui preview mode.
Qgis::TextRenderFormat textRenderFormat() const
Returns the text render format, which dictates how text is rendered (e.g.
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
int currentMaskId() const
Returns the current mask id, which can be used with maskPainter()
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
Scoped object for saving and restoring a QPainter object's state.
Scoped object for temporary override of the symbologyReferenceScale property of a QgsRenderContext.
static QString substituteVerticalCharacters(QString string)
Returns a string with characters having vertical representation form substituted.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates the symbol.
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
static void blurImageInPlace(QImage &image, QRect rect, int radius, bool alphaOnly)
Blurs an image in place, e.g. creating Qt-independent drop shadows.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
Container for settings relating to a text background object.
QgsMapUnitScale strokeWidthMapUnitScale() const
Returns the map unit scale object for the shape stroke width.
RotationType rotationType() const
Returns the method used for rotating the background shape.
QString svgFile() const
Returns the absolute path to the background SVG file, if set.
QSizeF size() const
Returns the size of the background shape.
QSizeF radii() const
Returns the radii used for rounding the corners of shapes.
QgsMapUnitScale radiiMapUnitScale() const
Returns the map unit scale object for the shape radii.
QgsUnitTypes::RenderUnit strokeWidthUnit() const
Returns the units used for the shape's stroke width.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the background shape.
@ SizeBuffer
Shape size is determined by adding a buffer margin around text.
bool enabled() const
Returns whether the background is enabled.
double opacity() const
Returns the background shape's opacity.
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shape's offset.
double rotation() const
Returns the rotation for the background shape, in degrees clockwise.
QColor fillColor() const
Returns the color used for filing the background shape.
SizeType sizeType() const
Returns the method used to determine the size of the background shape (e.g., fixed size or buffer aro...
ShapeType type() const
Returns the type of background shape (e.g., square, ellipse, SVG).
double strokeWidth() const
Returns the width of the shape's stroke (stroke).
@ ShapeMarkerSymbol
Marker symbol.
@ ShapeSquare
Square - buffered sizes only.
@ ShapeRectangle
Rectangle.
QColor strokeColor() const
Returns the color used for outlining the background shape.
QgsFillSymbol * fillSymbol() const
Returns the fill symbol to be rendered in the background.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the shape size.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units used for the shape's size.
@ RotationOffset
Shape rotation is offset from text rotation.
@ RotationFixed
Shape rotation is a fixed angle.
QgsUnitTypes::RenderUnit radiiUnit() const
Returns the units used for the shape's radii.
QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol to be rendered in the background.
const QgsPaintEffect * paintEffect() const
Returns the current paint effect for the background shape.
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shape offset.
QPointF offset() const
Returns the offset used for drawing the background shape.
Represents a block of text consisting of one or more QgsTextFragment objects.
int size() const
Returns the number of fragments in the block.
QString toPlainText() const
Converts the block to plain text.
Container for settings relating to a text buffer.
Qt::PenJoinStyle joinStyle() const
Returns the buffer join style.
double size() const
Returns the size of the buffer.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
bool enabled() const
Returns whether the buffer is enabled.
double opacity() const
Returns the buffer opacity.
bool fillBufferInterior() const
Returns whether the interior of the buffer will be filled in.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
const QgsPaintEffect * paintEffect() const
Returns the current paint effect for the buffer.
QColor color() const
Returns the color of the buffer.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the buffer.
QColor textColor() const
Returns the character's text color, or an invalid color if no color override is set and the default f...
void updateFontForFormat(QFont &font, double scaleFactor=1.0) const
Updates the specified font in place, applying character formatting options which are applicable on a ...
Represents a document consisting of one or more QgsTextBlock objects.
void applyCapitalization(QgsStringUtils::Capitalization capitalization)
Applies a capitalization style to the document's text.
const QgsTextBlock & at(int index) const
Returns the block at the specified index.
QStringList toPlainText() const
Returns a list of plain text lines of text representing the document.
int size() const
Returns the number of blocks in the document.
static QgsTextDocument fromHtml(const QStringList &lines)
Constructor for QgsTextDocument consisting of a set of HTML formatted lines.
static QgsTextDocument fromPlainText(const QStringList &lines)
Constructor for QgsTextDocument consisting of a set of plain text lines.
Container for all settings relating to text rendering.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the size.
double lineHeight() const
Returns the line height for text.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the size of rendered text.
void updateDataDefinedProperties(QgsRenderContext &context)
Updates the format by evaluating current values of data defined properties.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the format's property collection, used for data defined overrides.
QFont scaledFont(const QgsRenderContext &context, double scaleFactor=1.0, bool *isZeroSize=nullptr) const
Returns a font with the size scaled to match the format's size settings (including units and map unit...
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the text.
TextOrientation orientation() const
Returns the orientation of the text.
QgsTextMaskSettings & mask()
Returns a reference to the masking settings.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
TextOrientation
Text orientation.
@ HorizontalOrientation
Vertically oriented text.
@ RotationBasedOrientation
Horizontally or vertically oriented text based on rotation (only available for map labeling)
@ VerticalOrientation
Horizontally oriented text.
bool allowHtmlFormatting() const
Returns true if text should be treated as a HTML document and HTML tags should be used for formatting...
double opacity() const
Returns the text's opacity.
double size() const
Returns the size for rendered text.
QgsTextShadowSettings & shadow()
Returns a reference to the text drop shadow settings.
QgsStringUtils::Capitalization capitalization() const
Returns the text capitalization style.
QColor color() const
Returns the color that text will be rendered in.
QgsTextBufferSettings & buffer()
Returns a reference to the text buffer settings.
Stores a fragment of text along with formatting overrides to be used when rendering the fragment.
QString text() const
Returns the text content of the fragment.
double horizontalAdvance(const QFont &font, bool fontHasBeenUpdatedForFragment=false, double scaleFactor=1.0) const
Returns the horizontal advance associated with this fragment, when rendered using the specified base ...
const QgsTextCharacterFormat & characterFormat() const
Returns the character formatting for the fragment.
Container for settings relating to a selective masking around a text.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
double size() const
Returns the size of the buffer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the mask.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
double opacity() const
Returns the mask's opacity.
bool enabled() const
Returns whether the mask is enabled.
Qt::PenJoinStyle joinStyle() const
Returns the buffer join style.
static double textWidth(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF *fontMetrics=nullptr)
Returns the width of a text based on a given format.
static Q_DECL_DEPRECATED void drawPart(const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, TextPart part, bool drawAsOutlines=true)
Draws a single component of rendered text using the specified settings.
VAlignment
Vertical alignment.
@ AlignBottom
Align to bottom.
@ AlignVCenter
Center align.
TextPart
Components of text.
@ Buffer
Buffer component.
@ Background
Background shape.
HAlignment
Horizontal alignment.
@ AlignCenter
Center align.
@ AlignJustify
Justify align.
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, DrawMode mode=Point, QFontMetricsF *fontMetrics=nullptr)
Returns the height of a text based on a given format.
static QFontMetricsF fontMetrics(QgsRenderContext &context, const QgsTextFormat &format, double scaleFactor=1.0)
Returns the font metrics for the given text format, when rendered in the specified render context.
static HAlignment convertQtHAlignment(Qt::Alignment alignment)
Converts a Qt horizontal alignment flag to a QgsTextRenderer::HAlignment value.
static int sizeToPixel(double size, const QgsRenderContext &c, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
Calculates pixel size (considering output size should be in pixel or map units, scale factors and opt...
static VAlignment convertQtVAlignment(Qt::Alignment alignment)
Converts a Qt vertical alignment flag to a QgsTextRenderer::VAlignment value.
static void drawText(const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, VAlignment vAlignment=AlignTop)
Draws text within a rectangle using the specified settings.
DrawMode
Draw mode to calculate width and height.
@ Point
Text at point of origin draw mode.
@ Rect
Text within rectangle draw mode.
@ Label
Label-specific draw mode.
static constexpr double FONT_WORKAROUND_SCALE
Scale factor for upscaling font sizes and downscaling destination painter devices.
Container for settings relating to a text shadow.
int offsetAngle() const
Returns the angle for offsetting the position of the shadow from the text.
bool enabled() const
Returns whether the shadow is enabled.
int scale() const
Returns the scaling used for the drop shadow (in percentage of original size).
void setShadowPlacement(QgsTextShadowSettings::ShadowPlacement placement)
Sets the placement for the drop shadow.
double opacity() const
Returns the shadow's opacity.
QgsMapUnitScale blurRadiusMapUnitScale() const
Returns the map unit scale object for the shadow blur radius.
QColor color() const
Returns the color of the drop shadow.
@ ShadowBuffer
Draw shadow under buffer.
@ ShadowShape
Draw shadow under background shape.
@ ShadowLowest
Draw shadow below all text components.
@ ShadowText
Draw shadow under text.
QgsTextShadowSettings::ShadowPlacement shadowPlacement() const
Returns the placement for the drop shadow.
double offsetDistance() const
Returns the distance for offsetting the position of the shadow from the text.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the drop shadow.
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shadow offset distance.
QgsUnitTypes::RenderUnit blurRadiusUnit() const
Returns the units used for the shadow's blur radius.
bool blurAlphaOnly() const
Returns whether only the alpha channel for the shadow will be blurred.
bool offsetGlobal() const
Returns true if the global shadow offset will be used.
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shadow's offset.
double blurRadius() const
Returns the blur radius for the shadow.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
RenderUnit
Rendering size units.
@ RenderUnknownUnit
Mixed or unknown units.
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
@ RenderMapUnits
Map units.
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)
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)
QList< QgsSymbolLayer * > QgsSymbolLayerList
Q_GUI_EXPORT int qt_defaultDpiX()
Q_GUI_EXPORT int qt_defaultDpiY()