35#include <QTextBoundaryFinder>
40 if ( alignment & Qt::AlignLeft )
42 else if ( alignment & Qt::AlignRight )
44 else if ( alignment & Qt::AlignHCenter )
46 else if ( alignment & Qt::AlignJustify )
55 if ( alignment & Qt::AlignTop )
57 else if ( alignment & Qt::AlignBottom )
59 else if ( alignment & Qt::AlignVCenter )
62 else if ( alignment & Qt::AlignBaseline )
70 return static_cast< int >(
c.convertToPainterUnits( size, unit, mapUnitScale ) + 0.5 );
82 QStringList textLines;
83 for (
const QString &line : text )
87 textLines.append(
wrappedText( context, line, rect.width(), lFormat ) );
91 textLines.append( line );
101 drawDocument( rect, lFormat, document, metrics, context, alignment, vAlignment, rotation, mode, flags );
106 const QgsTextFormat tmpFormat = updateShadowPosition( format );
126 lFormat = updateShadowPosition( lFormat );
152 lFormat = updateShadowPosition( lFormat );
160 drawDocumentOnLine( line, lFormat, document, context, offsetAlongLine, offsetFromLine );
165 QPolygonF labelBaselineCurve = line;
174#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<11
175 if ( offsetFromLine < 0 )
178 std::unique_ptr < QgsLineString > reversed( offsetCurve->reversed() );
182 offsetCurve = std::move( reversed );
186 labelBaselineCurve = offsetCurve->asQPolygonF();
191 const QFont baseFont = format.
scaledFont( context, fontScale );
192 const double letterSpacing = baseFont.letterSpacing() / fontScale;
193 const double wordSpacing = baseFont.wordSpacing() / fontScale;
195 QStringList graphemes;
196 QVector< QgsTextCharacterFormat > graphemeFormats;
197 QVector< QgsTextDocument > graphemeDocuments;
198 QVector< QgsTextDocumentMetrics > graphemeMetrics;
200 for (
const QgsTextBlock &block : std::as_const( document ) )
205 for (
const QString &grapheme : fragmentGraphemes )
207 graphemes.append( grapheme );
208 graphemeFormats.append( fragment.characterFormat() );
213 graphemeDocuments.append( document );
219 QVector< double > characterWidths( graphemes.count() );
220 QVector< double > characterHeights( graphemes.count() );
221 QVector< double > characterDescents( graphemes.count() );
222 QFont previousNonSuperSubScriptFont;
224 for (
int i = 0; i < graphemes.count(); i++ )
229 double graphemeFirstCharHorizontalAdvanceWithLetterSpacing = 0;
230 double graphemeFirstCharHorizontalAdvance = 0;
231 double graphemeHorizontalAdvance = 0;
232 double characterDescent = 0;
233 double characterHeight = 0;
236 QFont graphemeFont = baseFont;
240 previousNonSuperSubScriptFont = graphemeFont;
247 previousNonSuperSubScriptFont = graphemeFont;
268 previousNonSuperSubScriptFont = graphemeFont;
271 const QFontMetricsF graphemeFontMetrics( graphemeFont );
272 graphemeFirstCharHorizontalAdvance = graphemeFontMetrics.horizontalAdvance( QString( graphemes[i].at( 0 ) ) ) / fontScale;
273 graphemeFirstCharHorizontalAdvanceWithLetterSpacing = graphemeFontMetrics.horizontalAdvance( graphemes[i].at( 0 ) ) / fontScale + letterSpacing;
274 graphemeHorizontalAdvance = graphemeFontMetrics.horizontalAdvance( QString( graphemes[i] ) ) / fontScale;
275 characterDescent = graphemeFontMetrics.descent() / fontScale;
276 characterHeight = graphemeFontMetrics.height() / fontScale;
278 qreal wordSpaceFix = qreal( 0.0 );
279 if ( graphemes[i] == QLatin1String(
" " ) )
283 wordSpaceFix = ( nxt < graphemes.count() && graphemes[nxt] != QLatin1String(
" " ) ) ? wordSpacing : qreal( 0.0 );
288 if ( graphemes[i].length() == 1 &&
289 !
qgsDoubleNear( graphemeFirstCharHorizontalAdvance, graphemeFirstCharHorizontalAdvanceWithLetterSpacing ) )
292 wordSpaceFix -= wordSpacing;
295 const double charWidth = graphemeHorizontalAdvance + wordSpaceFix;
296 characterWidths[i] = charWidth;
297 characterHeights[i] = characterHeight;
298 characterDescents[i] = characterDescent;
301 QgsPrecalculatedTextMetrics metrics( graphemes, std::move( characterWidths ), std::move( characterHeights ), std::move( characterDescents ) );
305 metrics, labelBaselineCurve, offsetAlongLine,
312 if ( placement->graphemePlacement.empty() )
315 std::vector< QgsTextRenderer::Component > components;
316 components.reserve( placement->graphemePlacement.size() );
319 QgsTextRenderer::Component component;
320 component.origin = QPointF( grapheme.x, grapheme.y );
321 component.rotation = -grapheme.angle;
327 component.origin.rx() += verticalOffset * std::cos( grapheme.angle + M_PI_2 );
328 component.origin.ry() += verticalOffset * std::sin( grapheme.angle + M_PI_2 );
331 components.emplace_back( component );
339 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
348 const QgsTextDocument &document = graphemeDocuments.
at( grapheme.graphemeIndex );
350 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
366 const QgsTextDocument &document = graphemeDocuments.
at( grapheme.graphemeIndex );
368 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
421 component.dpiRatio = 1.0;
422 component.origin = rect.topLeft();
423 component.rotation = rotation;
424 component.size = rect.size();
425 component.hAlign = alignment;
438 double xc = rect.width() / 2.0;
439 double yc = rect.height() / 2.0;
441 double angle = -rotation;
442 double xd = xc * std::cos( angle ) - yc * std::sin( angle );
443 double yd = xc * std::sin( angle ) + yc * std::cos( angle );
445 component.center = QPointF( component.origin.x() + xd, component.origin.y() + yd );
449 component.center = rect.center();
452 switch ( vAlignment )
478 drawTextInternal( part, context, format, component,
480 alignment, vAlignment, mode );
503 component.dpiRatio = 1.0;
504 component.origin = origin;
505 component.rotation = rotation;
506 component.hAlign = alignment;
515 QgsTextRenderer::drawBackground( context, component, format, metrics, mode );
528 drawTextInternal( part, context, format, component,
540 return QFontMetricsF( format.
scaledFont( context, scaleFactor ), context.
painter() ? context.
painter()->device() : nullptr );
547 QPainter *p = context.
painter();
552 if ( component.rotation >= -315 && component.rotation < -90 )
556 else if ( component.rotation >= -90 && component.rotation < -45 )
574 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
585 referenceScaleOverride.reset();
588 path.setFillRule( Qt::WindingFill );
590 double height = component.size.height();
591 switch ( orientation )
596 int fragmentIndex = 0;
599 QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, fragmentIndex );
601 if ( !fragment.isWhitespace() )
603 if ( component.extraWordSpacing || component.extraLetterSpacing )
604 applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing );
607 path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
621 double partYOffset = component.offset.y() * scaleFactor;
624 double partLastDescent = 0;
626 int fragmentIndex = 0;
629 const QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, component.firstFragmentIndex + fragmentIndex );
630 const double letterSpacing = fragmentFont.letterSpacing() / scaleFactor;
632 const QFontMetricsF fragmentMetrics( fragmentFont );
634 const double fragmentYOffset = metrics.
fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
637 for (
const QString &part : parts )
639 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / scaleFactor - letterSpacing ) ) / 2;
640 partYOffset += fragmentMetrics.ascent() / scaleFactor;
641 path.addText( partXOffset, partYOffset + fragmentYOffset, fragmentFont, part );
642 partYOffset += letterSpacing;
644 partLastDescent = fragmentMetrics.descent() / scaleFactor;
648 height = partYOffset + partLastDescent;
649 advance = partYOffset - component.offset.y() * scaleFactor;
654 QColor bufferColor = buffer.
color();
655 bufferColor.setAlphaF( buffer.
opacity() );
656 QPen pen( bufferColor );
657 pen.setWidthF( penSize * scaleFactor );
659 QColor tmpColor( bufferColor );
663 tmpColor.setAlpha( 0 );
669 buffp.begin( &buffPict );
673 std::unique_ptr< QgsPaintEffect > tmpEffect( buffer.
paintEffect()->
clone() );
675 tmpEffect->begin( context );
676 context.
painter()->setPen( pen );
677 context.
painter()->setBrush( tmpColor );
678 if ( scaleFactor != 1.0 )
679 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
680 context.
painter()->drawPath( path );
681 if ( scaleFactor != 1.0 )
682 context.
painter()->scale( scaleFactor, scaleFactor );
683 tmpEffect->end( context );
689 if ( scaleFactor != 1.0 )
690 buffp.scale( 1 / scaleFactor, 1 / scaleFactor );
692 buffp.setBrush( tmpColor );
693 buffp.drawPath( path );
699 QgsTextRenderer::Component bufferComponent = component;
700 bufferComponent.origin = QPointF( 0.0, 0.0 );
701 bufferComponent.picture = buffPict;
702 bufferComponent.pictureBuffer = penSize / 2.0;
703 bufferComponent.size.setHeight( height );
707 bufferComponent.offset.setY( - bufferComponent.size.height() );
709 drawShadow( context, bufferComponent, format );
717 p->setCompositionMode( buffer.
blendMode() );
721 p->scale( component.dpiRatio, component.dpiRatio );
723 p->drawPicture( 0, 0, buffPict );
725 return advance / scaleFactor;
745 path.setFillRule( Qt::WindingFill );
752 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
763 referenceScaleOverride.reset();
766 int fragmentIndex = 0;
769 if ( !fragment.isWhitespace() )
771 const QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, fragmentIndex );
773 const double fragmentYOffset = metrics.
fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
774 path.addText( xOffset, fragmentYOffset, fragmentFont, fragment.text() );
781 QColor bufferColor( Qt::gray );
782 bufferColor.setAlphaF( mask.
opacity() );
786 brush.setColor( bufferColor );
787 pen.setColor( bufferColor );
788 pen.setWidthF( penSize * scaleFactor );
795 p->scale( component.dpiRatio, component.dpiRatio );
801 if ( scaleFactor != 1.0 )
802 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
803 context.
painter()->setPen( pen );
804 context.
painter()->setBrush( brush );
805 context.
painter()->drawPath( path );
806 if ( scaleFactor != 1.0 )
807 context.
painter()->scale( scaleFactor, scaleFactor );
812 if ( scaleFactor != 1.0 )
813 p->scale( 1 / scaleFactor, 1 / scaleFactor );
815 p->setBrush( brush );
817 if ( scaleFactor != 1.0 )
818 p->scale( scaleFactor, scaleFactor );
834 if ( doc.
size() == 0 )
838 return textWidth( context, format, doc );
855 for (
const QString &line : textLines )
859 lines.append(
wrappedText( context, line, maxLineWidth, format ) );
863 lines.append( line );
881 bool isNullSize =
false;
882 const QFont baseFont = format.
scaledFont( context, scaleFactor, &isNullSize );
886 const QFontMetrics fm( baseFont );
887 const double height = ( character.isNull() ? fm.height() : fm.boundingRect( character ).height() ) / scaleFactor;
889 if ( !includeEffects )
892 double maxExtension = 0;
921 return height + maxExtension;
929 const QStringList multiLineSplit = text.split(
'\n' );
931 return currentTextWidth > width;
936 const QStringList lines = text.split(
'\n' );
937 QStringList outLines;
938 for (
const QString &line : lines )
943 const QStringList words = line.split(
' ' );
944 QStringList linesToProcess;
945 QString wordsInCurrentLine;
946 for (
const QString &word : words )
951 if ( !wordsInCurrentLine.isEmpty() )
952 linesToProcess << wordsInCurrentLine;
953 wordsInCurrentLine.clear();
954 linesToProcess << word;
958 if ( !wordsInCurrentLine.isEmpty() )
959 wordsInCurrentLine.append(
' ' );
960 wordsInCurrentLine.append( word );
963 if ( !wordsInCurrentLine.isEmpty() )
964 linesToProcess << wordsInCurrentLine;
966 for (
const QString &line : std::as_const( linesToProcess ) )
968 QString remainingText = line;
969 int lastPos = remainingText.lastIndexOf(
' ' );
970 while ( lastPos > -1 )
980 outLines << remainingText.left( lastPos );
981 remainingText = remainingText.mid( lastPos + 1 );
984 lastPos = remainingText.lastIndexOf(
' ', lastPos - 1 );
986 outLines << remainingText;
1017 QPainter *prevP = context.
painter();
1018 QPainter *p = context.
painter();
1019 std::unique_ptr< QgsPaintEffect > tmpEffect;
1023 tmpEffect->begin( context );
1032 const double originAdjustRotationRadians = -component.rotation;
1035 component.rotation = -( component.rotation * 180 / M_PI );
1036 component.rotationOffset =
1041 component.rotation = 0.0;
1042 component.rotationOffset = background.
rotation();
1051 double width = documentSize.width();
1052 double height = documentSize.height();
1059 switch ( component.hAlign )
1063 component.center = QPointF( component.origin.x() + width / 2.0,
1064 component.origin.y() + height / 2.0 );
1068 component.center = QPointF( component.origin.x() + component.size.width() / 2.0,
1069 component.origin.y() + height / 2.0 );
1073 component.center = QPointF( component.origin.x() + component.size.width() - width / 2.0,
1074 component.origin.y() + height / 2.0 );
1081 bool isNullSize =
false;
1082 QFontMetricsF fm( format.
scaledFont( context, scaleFactor, &isNullSize ) );
1083 double originAdjust = isNullSize ? 0 : ( fm.ascent() / scaleFactor / 2.0 - fm.leading() / scaleFactor / 2.0 );
1084 switch ( component.hAlign )
1088 component.center = QPointF( component.origin.x() + width / 2.0,
1089 component.origin.y() - height / 2.0 + originAdjust );
1093 component.center = QPointF( component.origin.x(),
1094 component.origin.y() - height / 2.0 + originAdjust );
1098 component.center = QPointF( component.origin.x() - width / 2.0,
1099 component.origin.y() - height / 2.0 + originAdjust );
1106 const double dx = component.center.x() - component.origin.x();
1107 const double dy = component.center.y() - component.origin.y();
1108 component.center.setX( component.origin.x() + ( std::cos( originAdjustRotationRadians ) * dx - std::sin( originAdjustRotationRadians ) * dy ) );
1109 component.center.setY( component.origin.y() + ( std::sin( originAdjustRotationRadians ) * dx + std::cos( originAdjustRotationRadians ) * dy ) );
1119 component.size = QSizeF( width, height );
1124 switch ( background.
type() )
1137 double sizeOut = 0.0;
1148 sizeOut = std::max( component.size.width(), component.size.height() );
1152 sizeOut += bufferSize * 2;
1158 if ( sizeOut < 1.0 )
1161 std::unique_ptr< QgsMarkerSymbol > renderedSymbol;
1165 map[QStringLiteral(
"name" )] = background.
svgFile().trimmed();
1166 map[QStringLiteral(
"size" )] = QString::number( sizeOut );
1168 map[QStringLiteral(
"angle" )] = QString::number( 0.0 );
1176 map[QStringLiteral(
"fill" )] = background.
fillColor().name();
1177 map[QStringLiteral(
"outline" )] = background.
strokeColor().name();
1178 map[QStringLiteral(
"outline-width" )] = QString::number( background.
strokeWidth() );
1185 QVariantMap shdwmap( map );
1186 shdwmap[QStringLiteral(
"fill" )] = shadow.
color().name();
1187 shdwmap[QStringLiteral(
"outline" )] = shadow.
color().name();
1188 shdwmap[QStringLiteral(
"size" )] = QString::number( sizeOut );
1193 svgp.begin( &svgPict );
1210 svgShdwM->
renderPoint( QPointF( sizeOut / 2, -sizeOut / 2 ), svgShdwContext );
1213 component.picture = svgPict;
1215 component.pictureBuffer = 0.0;
1217 component.size = QSizeF( sizeOut, sizeOut );
1218 component.offset = QPointF( 0.0, 0.0 );
1224 p->translate( component.center.x(), component.center.y() );
1225 p->rotate( component.rotation );
1228 p->translate( QPointF( xoff, yoff ) );
1229 p->rotate( component.rotationOffset );
1230 p->translate( -sizeOut / 2, sizeOut / 2 );
1232 drawShadow( context, component, format );
1234 renderedSymbol.reset( );
1242 renderedSymbol->setSize( sizeOut );
1246 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1254 p->setCompositionMode( background.
blendMode() );
1256 p->translate( component.center.x(), component.center.y() );
1257 p->rotate( component.rotation );
1260 p->translate( QPointF( xoff, yoff ) );
1261 p->rotate( component.rotationOffset );
1265 renderedSymbol->renderPoint( QPointF( 0, 0 ), &f, context );
1266 renderedSymbol->stopRender( context );
1267 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1277 double w = component.size.width();
1278 double h = component.size.height();
1299 h = std::sqrt( std::pow( w, 2 ) + std::pow( h, 2 ) );
1305 h = h * M_SQRT1_2 * 2;
1306 w = w * M_SQRT1_2 * 2;
1314 w += bufferWidth * 2;
1315 h += bufferHeight * 2;
1319 QRectF rect( -w / 2.0, - h / 2.0, w, h );
1321 if ( rect.isNull() )
1327 p->translate( QPointF( component.center.x(), component.center.y() ) );
1328 p->rotate( component.rotation );
1331 p->translate( QPointF( xoff, yoff ) );
1332 p->rotate( component.rotationOffset );
1338 QTransform t = QTransform::fromScale( 10, 10 );
1340 QTransform ti = t.inverted();
1347 path.addRoundedRect( rect, background.
radii().width(), background.
radii().height(), Qt::RelativeSize );
1353 path.addRoundedRect( rect, xRadius, yRadius );
1359 path.addEllipse( rect );
1361 QPolygonF tempPolygon = path.toFillPolygon( t );
1362 QPolygonF polygon = ti.map( tempPolygon );
1364 QPainter *oldp = context.
painter();
1367 shapep.begin( &shapePict );
1370 std::unique_ptr< QgsFillSymbol > renderedSymbol;
1372 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1376 renderedSymbol->renderPolygon( polygon,
nullptr, &f, context );
1377 renderedSymbol->stopRender( context );
1384 component.picture = shapePict;
1387 component.size = rect.size();
1388 component.offset = QPointF( rect.width() / 2, -rect.height() / 2 );
1389 drawShadow( context, component, format );
1394 p->setCompositionMode( background.
blendMode() );
1398 p->scale( component.dpiRatio, component.dpiRatio );
1400 p->drawPicture( 0, 0, shapePict );
1401 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1408 tmpEffect->end( context );
1421 QPainter *p = context.
painter();
1422 const double componentWidth = component.size.width();
1423 const double componentHeight = component.size.height();
1424 double xOffset = component.offset.x(), yOffset = component.offset.y();
1425 double pictbuffer = component.pictureBuffer;
1434 radius /= ( mapUnits ? context.
scaleFactor() / component.dpiRatio : 1 );
1435 radius =
static_cast< int >( radius + 0.5 );
1439 double blurBufferClippingScale = 3.75;
1440 int blurbuffer = ( radius > 17 ? 16 : radius ) * blurBufferClippingScale;
1442 QImage blurImg( componentWidth + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1443 componentHeight + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1444 QImage::Format_ARGB32_Premultiplied );
1448 int minBlurImgSize = 1;
1452 int maxBlurImgSize = 40000;
1453 if ( blurImg.isNull()
1454 || ( blurImg.width() < minBlurImgSize || blurImg.height() < minBlurImgSize )
1455 || ( blurImg.width() > maxBlurImgSize || blurImg.height() > maxBlurImgSize ) )
1458 blurImg.fill( QColor( Qt::transparent ).rgba() );
1460 if ( !pictp.begin( &blurImg ) )
1462 pictp.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
1463 QPointF imgOffset( blurbuffer + pictbuffer + xOffset,
1464 blurbuffer + pictbuffer + componentHeight + yOffset );
1466 pictp.drawPicture( imgOffset,
1467 component.picture );
1470 pictp.setCompositionMode( QPainter::CompositionMode_SourceIn );
1471 pictp.fillRect( blurImg.rect(), shadow.
color() );
1475 if ( shadow.
blurRadius() > 0.0 && radius > 0 )
1483 picti.begin( &blurImg );
1484 picti.setBrush( Qt::Dense7Pattern );
1485 QPen imgPen( QColor( 0, 0, 255, 255 ) );
1486 imgPen.setWidth( 1 );
1487 picti.setPen( imgPen );
1488 picti.setOpacity( 0.1 );
1489 picti.drawRect( 0, 0, blurImg.width(), blurImg.height() );
1496 double angleRad = shadow.
offsetAngle() * M_PI / 180;
1504 angleRad -= ( component.rotation * M_PI / 180 + component.rotationOffset * M_PI / 180 );
1507 QPointF transPt( -offsetDist * std::cos( angleRad + M_PI_2 ),
1508 -offsetDist * std::sin( angleRad + M_PI_2 ) );
1514 p->setRenderHint( QPainter::SmoothPixmapTransform );
1517 p->setCompositionMode( shadow.
blendMode() );
1519 p->setOpacity( shadow.
opacity() );
1521 double scale = shadow.
scale() / 100.0;
1523 p->scale( scale, scale );
1524 if ( component.useOrigin )
1526 p->translate( component.origin.x(), component.origin.y() );
1528 p->translate( transPt );
1529 p->translate( -imgOffset.x(),
1531 p->drawImage( 0, 0, blurImg );
1538 p->setBrush( Qt::NoBrush );
1539 QPen imgPen( QColor( 255, 0, 0, 10 ) );
1540 imgPen.setWidth( 2 );
1541 imgPen.setStyle( Qt::DashLine );
1542 p->setPen( imgPen );
1543 p->scale( scale, scale );
1544 if ( component.useOrigin() )
1546 p->translate( component.origin().x(), component.origin().y() );
1548 p->translate( transPt );
1549 p->translate( -imgOffset.x(),
1551 p->drawRect( 0, 0, blurImg.width(), blurImg.height() );
1556 p->setBrush( Qt::NoBrush );
1557 QPen componentRectPen( QColor( 0, 255, 0, 70 ) );
1558 componentRectPen.setWidth( 1 );
1559 if ( component.useOrigin() )
1561 p->translate( component.origin().x(), component.origin().y() );
1563 p->setPen( componentRectPen );
1564 p->drawRect( QRect( -xOffset, -componentHeight - yOffset, componentWidth, componentHeight ) );
1573 const Component &component,
1585 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1596 referenceScaleOverride.reset();
1598 double rotation = 0;
1599 const Qgis::TextOrientation orientation = calculateRotationAndOrientationForComponent( format, component, rotation );
1600 switch ( orientation )
1604 drawTextInternalHorizontal( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
1611 drawTextInternalVertical( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
1617Qgis::TextOrientation QgsTextRenderer::calculateRotationAndOrientationForComponent(
const QgsTextFormat &format,
const QgsTextRenderer::Component &component,
double &rotation )
1619 rotation = -component.rotation * 180 / M_PI;
1626 if ( rotation >= -315 && rotation < -90 )
1631 else if ( rotation >= -90 && rotation < -45 )
1647void QgsTextRenderer::calculateExtraSpacingForLineJustification(
const double spaceToDistribute,
const QgsTextBlock &block,
double &extraWordSpace,
double &extraLetterSpace )
1650 QTextBoundaryFinder
finder( QTextBoundaryFinder::Word, blockText );
1652 int wordBoundaries = 0;
1653 while (
finder.toNextBoundary() != -1 )
1655 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1659 if ( wordBoundaries > 0 )
1662 extraWordSpace = spaceToDistribute / wordBoundaries;
1667 QTextBoundaryFinder
finder( QTextBoundaryFinder::Grapheme, blockText );
1670 int graphemeBoundaries = 0;
1671 while (
finder.toNextBoundary() != -1 )
1673 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1674 graphemeBoundaries++;
1677 if ( graphemeBoundaries > 0 )
1679 extraLetterSpace = spaceToDistribute / graphemeBoundaries;
1684void QgsTextRenderer::applyExtraSpacingForLineJustification( QFont &font,
double extraWordSpace,
double extraLetterSpace )
1686 const double prevWordSpace = font.wordSpacing();
1687 font.setWordSpacing( prevWordSpace + extraWordSpace );
1688 const double prevLetterSpace = font.letterSpacing();
1689 font.setLetterSpacing( QFont::AbsoluteSpacing, prevLetterSpace + extraLetterSpace );
1696 const QStringList textLines = document.
toPlainText();
1700 double labelWidest = 0.0;
1705 labelWidest = documentSize.width();
1711 labelWidest = component.size.width();
1715 double verticalAlignOffset = 0;
1721 const double overallHeight = documentSize.height();
1722 switch ( vAlignment )
1728 verticalAlignOffset = ( component.size.height() - overallHeight ) * 0.5;
1732 verticalAlignOffset = ( component.size.height() - overallHeight );
1740 const bool isFinalLineInParagraph = ( blockIndex == document.
size() - 1 )
1741 || document.
at( blockIndex + 1 ).
toPlainText().trimmed().isEmpty();
1743 const double blockHeight = metrics.
blockHeight( blockIndex );
1747 context.
painter()->translate( component.origin );
1749 context.
painter()->rotate( rotation );
1754 maskPainter->save();
1755 maskPainter->translate( component.origin );
1757 maskPainter->rotate( rotation );
1761 double xMultiLineOffset = 0.0;
1762 double blockWidth = metrics.
blockWidth( blockIndex );
1763 double extraWordSpace = 0;
1764 double extraLetterSpace = 0;
1765 if ( adjustForAlignment )
1767 double labelWidthDiff = 0;
1768 switch ( hAlignment )
1771 labelWidthDiff = ( labelWidest - blockWidth ) * 0.5;
1775 labelWidthDiff = labelWidest - blockWidth;
1779 if ( !isFinalLineInParagraph && labelWidest > blockWidth )
1781 calculateExtraSpacingForLineJustification( labelWidest - blockWidth, block, extraWordSpace, extraLetterSpace );
1782 blockWidth = labelWidest;
1796 xMultiLineOffset = labelWidthDiff;
1801 switch ( hAlignment )
1804 xMultiLineOffset = labelWidthDiff - labelWidest;
1808 xMultiLineOffset = labelWidthDiff - labelWidest / 2.0;
1820 const double baseLineOffset = metrics.
baselineOffset( blockIndex, mode );
1822 context.
painter()->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
1824 maskPainter->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
1826 Component subComponent;
1827 subComponent.block = block;
1828 subComponent.blockIndex = blockIndex;
1829 subComponent.
size = QSizeF( blockWidth, blockHeight );
1830 subComponent.offset = QPointF( 0.0, -metrics.
ascentOffset() );
1831 subComponent.rotation = -component.rotation * 180 / M_PI;
1832 subComponent.rotationOffset = 0.0;
1833 subComponent.extraWordSpacing = extraWordSpace * fontScale;
1834 subComponent.extraLetterSpacing = extraLetterSpace * fontScale;
1839 QgsTextRenderer::drawMask( context, subComponent, format, metrics, mode );
1844 QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
1851 textp.begin( &textPict );
1852 textp.setPen( Qt::NoPen );
1854 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1862 referenceScaleOverride.reset();
1866 textp.scale( 1 / fontScale, 1 / fontScale );
1869 int fragmentIndex = 0;
1873 if ( !fragment.isWhitespace() )
1876 path.setFillRule( Qt::WindingFill );
1878 QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
1880 if ( extraWordSpace || extraLetterSpace )
1881 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1885 path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
1887 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
1888 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.opacity() );
1889 textp.setBrush( textColor );
1890 textp.drawPath( path );
1901 subComponent.picture = textPict;
1902 subComponent.pictureBuffer = 0.0;
1903 subComponent.origin = QPointF( 0.0, 0.0 );
1905 QgsTextRenderer::drawShadow( context, subComponent, format );
1915 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
1923 context.
painter()->drawPicture( 0, 0, textPict );
1930 int fragmentIndex = 0;
1933 if ( !fragment.isWhitespace() )
1935 QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
1937 if ( extraWordSpace || extraLetterSpace )
1938 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1942 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
1943 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.opacity() );
1945 context.
painter()->setPen( textColor );
1946 context.
painter()->setFont( fragmentFont );
1947 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
1949 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
1950 context.
painter()->drawText( QPointF( xOffset, yOffset ), fragment.text() );
1951 context.
painter()->scale( fontScale, fontScale );
1961 maskPainter->restore();
1967void QgsTextRenderer::drawTextInternalVertical(
QgsRenderContext &context,
const QgsTextFormat &format,
Qgis::TextComponent drawType,
Qgis::TextLayoutMode mode,
const QgsTextRenderer::Component &component,
const QgsTextDocument &document,
const QgsTextDocumentMetrics &metrics,
double fontScale,
Qgis::TextHorizontalAlignment hAlignment,
Qgis::TextVerticalAlignment,
double rotation )
1970 const QStringList textLines = document.
toPlainText();
1972 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1983 referenceScaleOverride.reset();
1986 const double actualTextWidth = documentSize.width();
1987 double textRectWidth = 0.0;
1993 textRectWidth = actualTextWidth;
1999 textRectWidth = component.size.width();
2003 int maxLineLength = 0;
2004 for (
const QString &line : std::as_const( textLines ) )
2006 maxLineLength = std::max( maxLineLength,
static_cast<int>( line.length() ) );
2009 const double actualLabelHeight = documentSize.height();
2019 context.
painter()->translate( component.origin );
2021 context.
painter()->rotate( rotation );
2026 maskPainter->save();
2027 maskPainter->translate( component.origin );
2029 maskPainter->rotate( rotation );
2036 if ( adjustForAlignment )
2038 double hAlignmentOffset = 0;
2039 switch ( hAlignment )
2042 hAlignmentOffset = ( textRectWidth - actualTextWidth ) * 0.5;
2046 hAlignmentOffset = textRectWidth - actualTextWidth;
2060 xOffset += hAlignmentOffset;
2068 double yOffset = 0.0;
2074 if ( rotation >= -405 && rotation < -180 )
2078 else if ( rotation >= 0 && rotation < 45 )
2080 xOffset -= actualTextWidth;
2086 yOffset = -actualLabelHeight;
2091 yOffset = -actualLabelHeight;
2101 context.
painter()->translate( QPointF( xOffset, yOffset ) );
2103 double currentBlockYOffset = 0;
2104 int fragmentIndex = 0;
2112 const QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
2114 QFontMetricsF fragmentMetrics( fragmentFont );
2116 const double letterSpacing = fragmentFont.letterSpacing() / fontScale;
2117 const double labelHeight = fragmentMetrics.ascent() / fontScale + ( fragmentMetrics.ascent() / fontScale + letterSpacing ) * ( line.length() - 1 );
2119 Component subComponent;
2121 subComponent.blockIndex = blockIndex;
2122 subComponent.firstFragmentIndex = fragmentIndex;
2123 subComponent.size = QSizeF( blockMaximumCharacterWidth, labelHeight + fragmentMetrics.descent() / fontScale );
2124 subComponent.offset = QPointF( 0.0, currentBlockYOffset );
2125 subComponent.rotation = -component.rotation * 180 / M_PI;
2126 subComponent.rotationOffset = 0.0;
2133 QgsTextRenderer::drawMask( context, subComponent, format );
2139 currentBlockYOffset += QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
2145 path.setFillRule( Qt::WindingFill );
2147 double partYOffset = 0.0;
2148 for (
const QString &part : parts )
2150 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
2151 partYOffset += fragmentMetrics.ascent() / fontScale;
2152 path.addText( partXOffset * fontScale, partYOffset * fontScale, fragmentFont, part );
2153 partYOffset += letterSpacing;
2159 textp.begin( &textPict );
2160 textp.setPen( Qt::NoPen );
2161 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
2162 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.
opacity() );
2163 textp.setBrush( textColor );
2164 textp.scale( 1 / fontScale, 1 / fontScale );
2165 textp.drawPath( path );
2176 subComponent.picture = textPict;
2177 subComponent.pictureBuffer = 0.0;
2178 subComponent.origin = QPointF( 0.0, currentBlockYOffset );
2179 const double prevY = subComponent.offset.y();
2180 subComponent.offset = QPointF( 0, -subComponent.size.height() );
2181 subComponent.useOrigin =
true;
2182 QgsTextRenderer::drawShadow( context, subComponent, format );
2183 subComponent.useOrigin =
false;
2184 subComponent.offset = QPointF( 0, prevY );
2194 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
2201 context.
painter()->translate( 0, currentBlockYOffset );
2203 context.
painter()->drawPicture( 0, 0, textPict );
2204 currentBlockYOffset += partYOffset;
2210 context.
painter()->setFont( fragmentFont );
2211 context.
painter()->setPen( textColor );
2212 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
2214 double partYOffset = 0.0;
2215 for (
const QString &part : parts )
2217 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
2218 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
2219 context.
painter()->drawText( QPointF( partXOffset * fontScale, ( currentBlockYOffset + partYOffset ) * fontScale ), part );
2220 context.
painter()->scale( fontScale, fontScale );
2221 partYOffset += fragmentMetrics.ascent() / fontScale + letterSpacing;
2223 currentBlockYOffset += partYOffset;
2231 maskPainter->restore();
2249 if ( pixelSize < 50 )
2250 return 200 / pixelSize;
2253 else if ( pixelSize > 200 )
2254 return 200 / pixelSize;
TextLayoutMode
Text layout modes.
@ Labeling
Labeling-specific layout mode.
@ Point
Text at point of origin layout mode.
@ RectangleAscentBased
Similar to Rectangle mode, but uses ascents only when calculating font and line heights....
@ RectangleCapHeightBased
Similar to Rectangle mode, but uses cap height only when calculating font heights for the first line ...
@ Rectangle
Text within rectangle layout mode.
QFlags< TextRendererFlag > TextRendererFlags
TextOrientation
Text orientations.
@ Vertical
Vertically oriented text.
@ RotationBased
Horizontally or vertically oriented text based on rotation (only available for map labeling)
@ Horizontal
Horizontally oriented text.
@ Round
Use rounded joins.
@ Normal
Adjacent characters are positioned in the standard way for text in the writing system in use.
@ SubScript
Characters are placed below the base line for normal text.
@ SuperScript
Characters are placed above the base line for normal text.
@ AlwaysOutlines
Always render text using path objects (AKA outlines/curves). This setting guarantees the best quality...
@ AlwaysText
Always render text as text objects. While this mode preserves text objects as text for post-processin...
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Unknown
Mixed or unknown units.
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
TextVerticalAlignment
Text vertical alignment.
@ VerticalCenter
Center align.
TextHorizontalAlignment
Text horizontal alignment.
@ WrapLines
Automatically wrap long lines of text.
TextComponent
Text components.
@ Buffer
Buffer component.
@ Background
Background shape.
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.
Does vector analysis using the geos library and handles import, export, exception handling*.
Line string geometry type, with support for z-dimension and m-values.
static QgsLineString * fromQPolygonF(const QPolygonF &polygon)
Returns a new linestring from a QPolygonF polygon input.
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.
bool enabled() const
Returns whether the effect is enabled.
virtual QgsPaintEffect * clone() const =0
Duplicates an effect by creating a deep copy of the effect.
A class to manage painter saving and restoring required for drawing on a different painter (mask pain...
static void applyScaleFixForQPictureDpi(QPainter *painter)
Applies a workaround to a painter to avoid an issue with incorrect scaling when drawing QPictures.
static QStringList splitToGraphemes(const QString &text)
Splits a text string to a list of graphemes, which are the smallest allowable character divisions in ...
Contains precalculated properties regarding text metrics for text to be renderered at a later stage.
void setGraphemeFormats(const QVector< QgsTextCharacterFormat > &formats)
Sets the character formats associated with the text graphemes().
bool hasActiveProperties() const final
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.
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.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
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.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QPainter * maskPainter(int id=0)
Returns a mask QPainter for the render operation.
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.
Qgis::RenderUnit radiiUnit() const
Returns the units used for the shape's radii.
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.
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...
Qgis::RenderUnit strokeWidthUnit() const
Returns the units used for the shape's stroke width.
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.
Qgis::RenderUnit offsetUnit() const
Returns the units used for the shape's offset.
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.
Qgis::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.
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.
Qgis::RenderUnit sizeUnit() const
Returns the units for the buffer size.
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.
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.
Stores information relating to individual character formatting.
void updateFontForFormat(QFont &font, const QgsRenderContext &context, double scaleFactor=1.0) const
Updates the specified font in place, applying character formatting options which are applicable on a ...
Qgis::TextCharacterVerticalAlignment verticalAlignment() const
Returns the format vertical alignment.
bool hasVerticalAlignmentSet() const
Returns true if the format has an explicit vertical alignment set.
double fontPointSize() const
Returns the font point size, or -1 if the font size is not set and should be inherited.
Contains pre-calculated metrics of a QgsTextDocument.
double verticalOrientationXOffset(int blockIndex) const
Returns the vertical orientation x offset for the specified block.
double fragmentVerticalOffset(int blockIndex, int fragmentIndex, Qgis::TextLayoutMode mode) const
Returns the vertical offset from a text block's baseline which should be applied to the fragment at t...
double blockMaximumDescent(int blockIndex) const
Returns the maximum descent encountered in the specified block.
QSizeF documentSize(Qgis::TextLayoutMode mode, Qgis::TextOrientation orientation) const
Returns the overall size of the document.
QFont fragmentFont(int blockIndex, int fragmentIndex) const
Returns the calculated font for the fragment at the specified block and fragment indices.
double blockMaximumCharacterWidth(int blockIndex) const
Returns the maximum character width for the specified block.
double baselineOffset(int blockIndex, Qgis::TextLayoutMode mode) const
Returns the offset from the top of the document to the text baseline for the given block index.
static QgsTextDocumentMetrics calculateMetrics(const QgsTextDocument &document, const QgsTextFormat &format, const QgsRenderContext &context, double scaleFactor=1.0)
Returns precalculated text metrics for a text document, when rendered using the given base format and...
double blockHeight(int blockIndex) const
Returns the height of the block at the specified index.
double fragmentHorizontalAdvance(int blockIndex, int fragmentIndex, Qgis::TextLayoutMode mode) const
Returns the horizontal advance of the fragment at the specified block and fragment index.
bool isNullFontSize() const
Returns true if the metrics could not be calculated because the text format has a null font size.
double blockWidth(int blockIndex) const
Returns the width of the block at the specified index.
double ascentOffset() const
Returns the ascent offset of the first block in the document.
Represents a document consisting of one or more QgsTextBlock objects.
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.
void append(const QgsTextBlock &block)
Appends a block to the document.
void applyCapitalization(Qgis::Capitalization capitalization)
Applies a capitalization style to the document's text.
Container for all settings relating to text rendering.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the size.
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.
Qgis::Capitalization capitalization() const
Returns the text capitalization style.
QgsTextMaskSettings & mask()
Returns a reference to the masking settings.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
Qgis::RenderUnit sizeUnit() const
Returns the units for the size of rendered 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.
Qgis::TextOrientation orientation() const
Returns the orientation of the text.
double size() const
Returns the size for rendered text.
QgsTextShadowSettings & shadow()
Returns a reference to the text drop shadow settings.
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.
Container for settings relating to a selective masking around a text.
Qgis::RenderUnit sizeUnit() const
Returns the units for the buffer size.
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.
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.
Contains placement information for a single grapheme in a curved text layout.
@ RespectPainterOrientation
Curved text will be placed respecting the painter orientation, and the actual line direction will be ...
@ TruncateStringWhenLineIsTooShort
When a string is too long for the line, truncate characters instead of aborting the placement.
@ UseBaselinePlacement
Generate placement based on the character baselines instead of centers.
static std::unique_ptr< CurvePlacementProperties > generateCurvedTextPlacement(const QgsPrecalculatedTextMetrics &metrics, const QPolygonF &line, double offsetAlongLine, LabelLineDirection direction=RespectPainterOrientation, double maxConcaveAngle=-1, double maxConvexAngle=-1, CurvedTextFlags flags=CurvedTextFlags())
Calculates curved text placement properties.
static void drawDocumentOnLine(const QPolygonF &line, const QgsTextFormat &format, const QgsTextDocument &document, QgsRenderContext &context, double offsetAlongLine=0, double offsetFromLine=0)
Draws a text document along a line using the specified settings.
static Qgis::TextVerticalAlignment convertQtVAlignment(Qt::Alignment alignment)
Converts a Qt vertical alignment flag to a Qgis::TextVerticalAlignment value.
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 void drawDocument(const QRectF &rect, const QgsTextFormat &format, const QgsTextDocument &document, const QgsTextDocumentMetrics &metrics, QgsRenderContext &context, Qgis::TextHorizontalAlignment horizontalAlignment=Qgis::TextHorizontalAlignment::Left, Qgis::TextVerticalAlignment verticalAlignment=Qgis::TextVerticalAlignment::Top, double rotation=0, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags())
Draws a text document within a rectangle using the specified settings.
static int sizeToPixel(double size, const QgsRenderContext &c, Qgis::RenderUnit unit, const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
Calculates pixel size (considering output size should be in pixel or map units, scale factors and opt...
static Q_DECL_DEPRECATED void drawPart(const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, Qgis::TextComponent part, bool drawAsOutlines=true)
Draws a single component of rendered text using the specified settings.
static void drawText(const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, Qgis::TextVerticalAlignment vAlignment=Qgis::TextVerticalAlignment::Top, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle)
Draws text within a rectangle using the specified settings.
static bool textRequiresWrapping(const QgsRenderContext &context, const QString &text, double width, const QgsTextFormat &format)
Returns true if the specified text requires line wrapping in order to fit within the specified width ...
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 void drawTextOnLine(const QPolygonF &line, const QString &text, QgsRenderContext &context, const QgsTextFormat &format, double offsetAlongLine=0, double offsetFromLine=0)
Draws text along a line using the specified settings.
static double calculateScaleFactorForFormat(const QgsRenderContext &context, const QgsTextFormat &format)
Returns the scale factor used for upscaling font sizes and downscaling destination painter devices.
static QStringList wrappedText(const QgsRenderContext &context, const QString &text, double width, const QgsTextFormat &format)
Wraps a text string to multiple lines, such that each individual line will fit within the specified w...
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Point, QFontMetricsF *fontMetrics=nullptr, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), double maxLineWidth=0)
Returns the height of a text based on a given format.
static constexpr double SUPERSCRIPT_SUBSCRIPT_FONT_SIZE_SCALING_FACTOR
Scale factor to use for super or subscript text which doesn't have an explicit font size set.
static Qgis::TextHorizontalAlignment convertQtHAlignment(Qt::Alignment alignment)
Converts a Qt horizontal alignment flag to a Qgis::TextHorizontalAlignment value.
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).
Qgis::RenderUnit offsetUnit() const
Returns the units used for the shadow's offset.
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.
Qgis::RenderUnit blurRadiusUnit() const
Returns the units used for the shadow's blur radius.
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.
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.
double blurRadius() const
Returns the blur radius for the shadow.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
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)
Contains geos related utilities and functions.
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