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 );
134 drawDocument( point, lFormat, document, metrics, context, alignment, rotation );
157 lFormat = updateShadowPosition( lFormat );
165 drawDocumentOnLine( line, lFormat, document, context, offsetAlongLine, offsetFromLine );
170 QPolygonF labelBaselineCurve = line;
179#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<11
180 if ( offsetFromLine < 0 )
183 std::unique_ptr < QgsLineString > reversed( offsetCurve->reversed() );
187 offsetCurve = std::move( reversed );
191 labelBaselineCurve = offsetCurve->asQPolygonF();
196 const QFont baseFont = format.
scaledFont( context, fontScale );
197 const double letterSpacing = baseFont.letterSpacing() / fontScale;
198 const double wordSpacing = baseFont.wordSpacing() / fontScale;
200 QStringList graphemes;
201 QVector< QgsTextCharacterFormat > graphemeFormats;
202 QVector< QgsTextDocument > graphemeDocuments;
203 QVector< QgsTextDocumentMetrics > graphemeMetrics;
205 for (
const QgsTextBlock &block : std::as_const( document ) )
210 for (
const QString &grapheme : fragmentGraphemes )
212 graphemes.append( grapheme );
213 graphemeFormats.append( fragment.characterFormat() );
218 graphemeDocuments.append( document );
224 QVector< double > characterWidths( graphemes.count() );
225 QVector< double > characterHeights( graphemes.count() );
226 QVector< double > characterDescents( graphemes.count() );
227 QFont previousNonSuperSubScriptFont;
229 for (
int i = 0; i < graphemes.count(); i++ )
234 double graphemeFirstCharHorizontalAdvanceWithLetterSpacing = 0;
235 double graphemeFirstCharHorizontalAdvance = 0;
236 double graphemeHorizontalAdvance = 0;
237 double characterDescent = 0;
238 double characterHeight = 0;
241 QFont graphemeFont = baseFont;
245 previousNonSuperSubScriptFont = graphemeFont;
252 previousNonSuperSubScriptFont = graphemeFont;
273 previousNonSuperSubScriptFont = graphemeFont;
276 const QFontMetricsF graphemeFontMetrics( graphemeFont );
277 graphemeFirstCharHorizontalAdvance = graphemeFontMetrics.horizontalAdvance( QString( graphemes[i].at( 0 ) ) ) / fontScale;
278 graphemeFirstCharHorizontalAdvanceWithLetterSpacing = graphemeFontMetrics.horizontalAdvance( graphemes[i].at( 0 ) ) / fontScale + letterSpacing;
279 graphemeHorizontalAdvance = graphemeFontMetrics.horizontalAdvance( QString( graphemes[i] ) ) / fontScale;
280 characterDescent = graphemeFontMetrics.descent() / fontScale;
281 characterHeight = graphemeFontMetrics.height() / fontScale;
283 qreal wordSpaceFix = qreal( 0.0 );
284 if ( graphemes[i] == QLatin1String(
" " ) )
288 wordSpaceFix = ( nxt < graphemes.count() && graphemes[nxt] != QLatin1String(
" " ) ) ? wordSpacing : qreal( 0.0 );
293 if ( graphemes[i].length() == 1 &&
294 !
qgsDoubleNear( graphemeFirstCharHorizontalAdvance, graphemeFirstCharHorizontalAdvanceWithLetterSpacing ) )
297 wordSpaceFix -= wordSpacing;
300 const double charWidth = graphemeHorizontalAdvance + wordSpaceFix;
301 characterWidths[i] = charWidth;
302 characterHeights[i] = characterHeight;
303 characterDescents[i] = characterDescent;
306 QgsPrecalculatedTextMetrics metrics( graphemes, std::move( characterWidths ), std::move( characterHeights ), std::move( characterDescents ) );
310 metrics, labelBaselineCurve, offsetAlongLine,
317 if ( placement->graphemePlacement.empty() )
320 std::vector< QgsTextRenderer::Component > components;
321 components.reserve( placement->graphemePlacement.size() );
324 QgsTextRenderer::Component component;
325 component.origin = QPointF( grapheme.x, grapheme.y );
326 component.rotation = -grapheme.angle;
332 component.origin.rx() += verticalOffset * std::cos( grapheme.angle + M_PI_2 );
333 component.origin.ry() += verticalOffset * std::sin( grapheme.angle + M_PI_2 );
336 components.emplace_back( component );
344 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
353 const QgsTextDocument &document = graphemeDocuments.
at( grapheme.graphemeIndex );
355 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
371 const QgsTextDocument &document = graphemeDocuments.
at( grapheme.graphemeIndex );
373 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
426 component.dpiRatio = 1.0;
427 component.origin = rect.topLeft();
428 component.rotation = rotation;
429 component.size = rect.size();
430 component.hAlign = alignment;
443 double xc = rect.width() / 2.0;
444 double yc = rect.height() / 2.0;
446 double angle = -rotation;
447 double xd = xc * std::cos( angle ) - yc * std::sin( angle );
448 double yd = xc * std::sin( angle ) + yc * std::cos( angle );
450 component.center = QPointF( component.origin.x() + xd, component.origin.y() + yd );
454 component.center = rect.center();
457 switch ( vAlignment )
483 drawTextInternal( part, context, format, component,
485 alignment, vAlignment, mode );
508 component.dpiRatio = 1.0;
509 component.origin = origin;
510 component.rotation = rotation;
511 component.hAlign = alignment;
520 QgsTextRenderer::drawBackground( context, component, format, metrics, mode );
533 drawTextInternal( part, context, format, component,
545 return QFontMetricsF( format.
scaledFont( context, scaleFactor ), context.
painter() ? context.
painter()->device() : nullptr );
552 QPainter *p = context.
painter();
557 if ( component.rotation >= -315 && component.rotation < -90 )
561 else if ( component.rotation >= -90 && component.rotation < -45 )
579 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
590 referenceScaleOverride.reset();
593 path.setFillRule( Qt::WindingFill );
595 double height = component.size.height();
596 switch ( orientation )
601 int fragmentIndex = 0;
604 QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, fragmentIndex );
606 if ( !fragment.isWhitespace() )
608 if ( component.extraWordSpacing || component.extraLetterSpacing )
609 applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing );
612 path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
626 double partYOffset = component.offset.y() * scaleFactor;
629 double partLastDescent = 0;
631 int fragmentIndex = 0;
634 const QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, component.firstFragmentIndex + fragmentIndex );
635 const double letterSpacing = fragmentFont.letterSpacing() / scaleFactor;
637 const QFontMetricsF fragmentMetrics( fragmentFont );
639 const double fragmentYOffset = metrics.
fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
642 for (
const QString &part : parts )
644 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / scaleFactor - letterSpacing ) ) / 2;
645 partYOffset += fragmentMetrics.ascent() / scaleFactor;
646 path.addText( partXOffset, partYOffset + fragmentYOffset, fragmentFont, part );
647 partYOffset += letterSpacing;
649 partLastDescent = fragmentMetrics.descent() / scaleFactor;
653 height = partYOffset + partLastDescent;
654 advance = partYOffset - component.offset.y() * scaleFactor;
659 QColor bufferColor = buffer.
color();
660 bufferColor.setAlphaF( buffer.
opacity() );
661 QPen pen( bufferColor );
662 pen.setWidthF( penSize * scaleFactor );
664 QColor tmpColor( bufferColor );
668 tmpColor.setAlpha( 0 );
674 buffp.begin( &buffPict );
678 std::unique_ptr< QgsPaintEffect > tmpEffect( buffer.
paintEffect()->
clone() );
680 tmpEffect->begin( context );
681 context.
painter()->setPen( pen );
682 context.
painter()->setBrush( tmpColor );
683 if ( scaleFactor != 1.0 )
684 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
685 context.
painter()->drawPath( path );
686 if ( scaleFactor != 1.0 )
687 context.
painter()->scale( scaleFactor, scaleFactor );
688 tmpEffect->end( context );
694 if ( scaleFactor != 1.0 )
695 buffp.scale( 1 / scaleFactor, 1 / scaleFactor );
697 buffp.setBrush( tmpColor );
698 buffp.drawPath( path );
704 QgsTextRenderer::Component bufferComponent = component;
705 bufferComponent.origin = QPointF( 0.0, 0.0 );
706 bufferComponent.picture = buffPict;
707 bufferComponent.pictureBuffer = penSize / 2.0;
708 bufferComponent.size.setHeight( height );
712 bufferComponent.offset.setY( - bufferComponent.size.height() );
714 drawShadow( context, bufferComponent, format );
722 p->setCompositionMode( buffer.
blendMode() );
726 p->scale( component.dpiRatio, component.dpiRatio );
728 p->drawPicture( 0, 0, buffPict );
730 return advance / scaleFactor;
750 path.setFillRule( Qt::WindingFill );
757 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
768 referenceScaleOverride.reset();
771 int fragmentIndex = 0;
774 if ( !fragment.isWhitespace() )
776 const QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, fragmentIndex );
778 const double fragmentYOffset = metrics.
fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
779 path.addText( xOffset, fragmentYOffset, fragmentFont, fragment.text() );
786 QColor bufferColor( Qt::gray );
787 bufferColor.setAlphaF( mask.
opacity() );
791 brush.setColor( bufferColor );
792 pen.setColor( bufferColor );
793 pen.setWidthF( penSize * scaleFactor );
800 p->scale( component.dpiRatio, component.dpiRatio );
806 if ( scaleFactor != 1.0 )
807 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
808 context.
painter()->setPen( pen );
809 context.
painter()->setBrush( brush );
810 context.
painter()->drawPath( path );
811 if ( scaleFactor != 1.0 )
812 context.
painter()->scale( scaleFactor, scaleFactor );
817 if ( scaleFactor != 1.0 )
818 p->scale( 1 / scaleFactor, 1 / scaleFactor );
820 p->setBrush( brush );
822 if ( scaleFactor != 1.0 )
823 p->scale( scaleFactor, scaleFactor );
839 if ( doc.
size() == 0 )
843 return textWidth( context, format, doc );
860 for (
const QString &line : textLines )
864 lines.append(
wrappedText( context, line, maxLineWidth, format ) );
868 lines.append( line );
886 bool isNullSize =
false;
887 const QFont baseFont = format.
scaledFont( context, scaleFactor, &isNullSize );
891 const QFontMetrics fm( baseFont );
892 const double height = ( character.isNull() ? fm.height() : fm.boundingRect( character ).height() ) / scaleFactor;
894 if ( !includeEffects )
897 double maxExtension = 0;
926 return height + maxExtension;
934 const QStringList multiLineSplit = text.split(
'\n' );
936 return currentTextWidth > width;
941 const QStringList lines = text.split(
'\n' );
942 QStringList outLines;
943 for (
const QString &line : lines )
948 const QStringList words = line.split(
' ' );
949 QStringList linesToProcess;
950 QString wordsInCurrentLine;
951 for (
const QString &word : words )
956 if ( !wordsInCurrentLine.isEmpty() )
957 linesToProcess << wordsInCurrentLine;
958 wordsInCurrentLine.clear();
959 linesToProcess << word;
963 if ( !wordsInCurrentLine.isEmpty() )
964 wordsInCurrentLine.append(
' ' );
965 wordsInCurrentLine.append( word );
968 if ( !wordsInCurrentLine.isEmpty() )
969 linesToProcess << wordsInCurrentLine;
971 for (
const QString &line : std::as_const( linesToProcess ) )
973 QString remainingText = line;
974 int lastPos = remainingText.lastIndexOf(
' ' );
975 while ( lastPos > -1 )
985 outLines << remainingText.left( lastPos );
986 remainingText = remainingText.mid( lastPos + 1 );
989 lastPos = remainingText.lastIndexOf(
' ', lastPos - 1 );
991 outLines << remainingText;
1022 QPainter *prevP = context.
painter();
1023 QPainter *p = context.
painter();
1024 std::unique_ptr< QgsPaintEffect > tmpEffect;
1028 tmpEffect->begin( context );
1037 const double originAdjustRotationRadians = -component.rotation;
1040 component.rotation = -( component.rotation * 180 / M_PI );
1041 component.rotationOffset =
1046 component.rotation = 0.0;
1047 component.rotationOffset = background.
rotation();
1056 double width = documentSize.width();
1057 double height = documentSize.height();
1064 switch ( component.hAlign )
1068 component.center = QPointF( component.origin.x() + width / 2.0,
1069 component.origin.y() + height / 2.0 );
1073 component.center = QPointF( component.origin.x() + component.size.width() / 2.0,
1074 component.origin.y() + height / 2.0 );
1078 component.center = QPointF( component.origin.x() + component.size.width() - width / 2.0,
1079 component.origin.y() + height / 2.0 );
1086 bool isNullSize =
false;
1087 QFontMetricsF fm( format.
scaledFont( context, scaleFactor, &isNullSize ) );
1088 double originAdjust = isNullSize ? 0 : ( fm.ascent() / scaleFactor / 2.0 - fm.leading() / scaleFactor / 2.0 );
1089 switch ( component.hAlign )
1093 component.center = QPointF( component.origin.x() + width / 2.0,
1094 component.origin.y() - height / 2.0 + originAdjust );
1098 component.center = QPointF( component.origin.x(),
1099 component.origin.y() - height / 2.0 + originAdjust );
1103 component.center = QPointF( component.origin.x() - width / 2.0,
1104 component.origin.y() - height / 2.0 + originAdjust );
1111 const double dx = component.center.x() - component.origin.x();
1112 const double dy = component.center.y() - component.origin.y();
1113 component.center.setX( component.origin.x() + ( std::cos( originAdjustRotationRadians ) * dx - std::sin( originAdjustRotationRadians ) * dy ) );
1114 component.center.setY( component.origin.y() + ( std::sin( originAdjustRotationRadians ) * dx + std::cos( originAdjustRotationRadians ) * dy ) );
1124 component.size = QSizeF( width, height );
1129 switch ( background.
type() )
1142 double sizeOut = 0.0;
1153 sizeOut = std::max( component.size.width(), component.size.height() );
1157 sizeOut += bufferSize * 2;
1163 if ( sizeOut < 1.0 )
1166 std::unique_ptr< QgsMarkerSymbol > renderedSymbol;
1170 map[QStringLiteral(
"name" )] = background.
svgFile().trimmed();
1171 map[QStringLiteral(
"size" )] = QString::number( sizeOut );
1173 map[QStringLiteral(
"angle" )] = QString::number( 0.0 );
1181 map[QStringLiteral(
"fill" )] = background.
fillColor().name();
1182 map[QStringLiteral(
"outline" )] = background.
strokeColor().name();
1183 map[QStringLiteral(
"outline-width" )] = QString::number( background.
strokeWidth() );
1190 QVariantMap shdwmap( map );
1191 shdwmap[QStringLiteral(
"fill" )] = shadow.
color().name();
1192 shdwmap[QStringLiteral(
"outline" )] = shadow.
color().name();
1193 shdwmap[QStringLiteral(
"size" )] = QString::number( sizeOut );
1198 svgp.begin( &svgPict );
1215 svgShdwM->
renderPoint( QPointF( sizeOut / 2, -sizeOut / 2 ), svgShdwContext );
1218 component.picture = svgPict;
1220 component.pictureBuffer = 0.0;
1222 component.size = QSizeF( sizeOut, sizeOut );
1223 component.offset = QPointF( 0.0, 0.0 );
1229 p->translate( component.center.x(), component.center.y() );
1230 p->rotate( component.rotation );
1233 p->translate( QPointF( xoff, yoff ) );
1234 p->rotate( component.rotationOffset );
1235 p->translate( -sizeOut / 2, sizeOut / 2 );
1237 drawShadow( context, component, format );
1239 renderedSymbol.reset( );
1247 renderedSymbol->setSize( sizeOut );
1251 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1259 p->setCompositionMode( background.
blendMode() );
1261 p->translate( component.center.x(), component.center.y() );
1262 p->rotate( component.rotation );
1265 p->translate( QPointF( xoff, yoff ) );
1266 p->rotate( component.rotationOffset );
1270 renderedSymbol->renderPoint( QPointF( 0, 0 ), &f, context );
1271 renderedSymbol->stopRender( context );
1272 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1282 double w = component.size.width();
1283 double h = component.size.height();
1304 h = std::sqrt( std::pow( w, 2 ) + std::pow( h, 2 ) );
1310 h = h * M_SQRT1_2 * 2;
1311 w = w * M_SQRT1_2 * 2;
1319 w += bufferWidth * 2;
1320 h += bufferHeight * 2;
1324 QRectF rect( -w / 2.0, - h / 2.0, w, h );
1326 if ( rect.isNull() )
1332 p->translate( QPointF( component.center.x(), component.center.y() ) );
1333 p->rotate( component.rotation );
1336 p->translate( QPointF( xoff, yoff ) );
1337 p->rotate( component.rotationOffset );
1343 QTransform t = QTransform::fromScale( 10, 10 );
1345 QTransform ti = t.inverted();
1352 path.addRoundedRect( rect, background.
radii().width(), background.
radii().height(), Qt::RelativeSize );
1358 path.addRoundedRect( rect, xRadius, yRadius );
1364 path.addEllipse( rect );
1366 QPolygonF tempPolygon = path.toFillPolygon( t );
1367 QPolygonF polygon = ti.map( tempPolygon );
1369 QPainter *oldp = context.
painter();
1372 shapep.begin( &shapePict );
1375 std::unique_ptr< QgsFillSymbol > renderedSymbol;
1377 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1381 renderedSymbol->renderPolygon( polygon,
nullptr, &f, context );
1382 renderedSymbol->stopRender( context );
1389 component.picture = shapePict;
1392 component.size = rect.size();
1393 component.offset = QPointF( rect.width() / 2, -rect.height() / 2 );
1394 drawShadow( context, component, format );
1399 p->setCompositionMode( background.
blendMode() );
1403 p->scale( component.dpiRatio, component.dpiRatio );
1405 p->drawPicture( 0, 0, shapePict );
1406 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1413 tmpEffect->end( context );
1426 QPainter *p = context.
painter();
1427 const double componentWidth = component.size.width();
1428 const double componentHeight = component.size.height();
1429 double xOffset = component.offset.x(), yOffset = component.offset.y();
1430 double pictbuffer = component.pictureBuffer;
1439 radius /= ( mapUnits ? context.
scaleFactor() / component.dpiRatio : 1 );
1440 radius =
static_cast< int >( radius + 0.5 );
1444 double blurBufferClippingScale = 3.75;
1445 int blurbuffer = ( radius > 17 ? 16 : radius ) * blurBufferClippingScale;
1447 QImage blurImg( componentWidth + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1448 componentHeight + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1449 QImage::Format_ARGB32_Premultiplied );
1453 int minBlurImgSize = 1;
1457 int maxBlurImgSize = 40000;
1458 if ( blurImg.isNull()
1459 || ( blurImg.width() < minBlurImgSize || blurImg.height() < minBlurImgSize )
1460 || ( blurImg.width() > maxBlurImgSize || blurImg.height() > maxBlurImgSize ) )
1463 blurImg.fill( QColor( Qt::transparent ).rgba() );
1465 if ( !pictp.begin( &blurImg ) )
1467 pictp.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
1468 QPointF imgOffset( blurbuffer + pictbuffer + xOffset,
1469 blurbuffer + pictbuffer + componentHeight + yOffset );
1471 pictp.drawPicture( imgOffset,
1472 component.picture );
1475 pictp.setCompositionMode( QPainter::CompositionMode_SourceIn );
1476 pictp.fillRect( blurImg.rect(), shadow.
color() );
1480 if ( shadow.
blurRadius() > 0.0 && radius > 0 )
1488 picti.begin( &blurImg );
1489 picti.setBrush( Qt::Dense7Pattern );
1490 QPen imgPen( QColor( 0, 0, 255, 255 ) );
1491 imgPen.setWidth( 1 );
1492 picti.setPen( imgPen );
1493 picti.setOpacity( 0.1 );
1494 picti.drawRect( 0, 0, blurImg.width(), blurImg.height() );
1501 double angleRad = shadow.
offsetAngle() * M_PI / 180;
1509 angleRad -= ( component.rotation * M_PI / 180 + component.rotationOffset * M_PI / 180 );
1512 QPointF transPt( -offsetDist * std::cos( angleRad + M_PI_2 ),
1513 -offsetDist * std::sin( angleRad + M_PI_2 ) );
1519 p->setRenderHint( QPainter::SmoothPixmapTransform );
1522 p->setCompositionMode( shadow.
blendMode() );
1524 p->setOpacity( shadow.
opacity() );
1526 double scale = shadow.
scale() / 100.0;
1528 p->scale( scale, scale );
1529 if ( component.useOrigin )
1531 p->translate( component.origin.x(), component.origin.y() );
1533 p->translate( transPt );
1534 p->translate( -imgOffset.x(),
1536 p->drawImage( 0, 0, blurImg );
1543 p->setBrush( Qt::NoBrush );
1544 QPen imgPen( QColor( 255, 0, 0, 10 ) );
1545 imgPen.setWidth( 2 );
1546 imgPen.setStyle( Qt::DashLine );
1547 p->setPen( imgPen );
1548 p->scale( scale, scale );
1549 if ( component.useOrigin() )
1551 p->translate( component.origin().x(), component.origin().y() );
1553 p->translate( transPt );
1554 p->translate( -imgOffset.x(),
1556 p->drawRect( 0, 0, blurImg.width(), blurImg.height() );
1561 p->setBrush( Qt::NoBrush );
1562 QPen componentRectPen( QColor( 0, 255, 0, 70 ) );
1563 componentRectPen.setWidth( 1 );
1564 if ( component.useOrigin() )
1566 p->translate( component.origin().x(), component.origin().y() );
1568 p->setPen( componentRectPen );
1569 p->drawRect( QRect( -xOffset, -componentHeight - yOffset, componentWidth, componentHeight ) );
1578 const Component &component,
1590 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1601 referenceScaleOverride.reset();
1603 double rotation = 0;
1604 const Qgis::TextOrientation orientation = calculateRotationAndOrientationForComponent( format, component, rotation );
1605 switch ( orientation )
1609 drawTextInternalHorizontal( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
1616 drawTextInternalVertical( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
1622Qgis::TextOrientation QgsTextRenderer::calculateRotationAndOrientationForComponent(
const QgsTextFormat &format,
const QgsTextRenderer::Component &component,
double &rotation )
1624 rotation = -component.rotation * 180 / M_PI;
1631 if ( rotation >= -315 && rotation < -90 )
1636 else if ( rotation >= -90 && rotation < -45 )
1652void QgsTextRenderer::calculateExtraSpacingForLineJustification(
const double spaceToDistribute,
const QgsTextBlock &block,
double &extraWordSpace,
double &extraLetterSpace )
1655 QTextBoundaryFinder
finder( QTextBoundaryFinder::Word, blockText );
1657 int wordBoundaries = 0;
1658 while (
finder.toNextBoundary() != -1 )
1660 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1664 if ( wordBoundaries > 0 )
1667 extraWordSpace = spaceToDistribute / wordBoundaries;
1672 QTextBoundaryFinder
finder( QTextBoundaryFinder::Grapheme, blockText );
1675 int graphemeBoundaries = 0;
1676 while (
finder.toNextBoundary() != -1 )
1678 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1679 graphemeBoundaries++;
1682 if ( graphemeBoundaries > 0 )
1684 extraLetterSpace = spaceToDistribute / graphemeBoundaries;
1689void QgsTextRenderer::applyExtraSpacingForLineJustification( QFont &font,
double extraWordSpace,
double extraLetterSpace )
1691 const double prevWordSpace = font.wordSpacing();
1692 font.setWordSpacing( prevWordSpace + extraWordSpace );
1693 const double prevLetterSpace = font.letterSpacing();
1694 font.setLetterSpacing( QFont::AbsoluteSpacing, prevLetterSpace + extraLetterSpace );
1701 const QStringList textLines = document.
toPlainText();
1705 double labelWidest = 0.0;
1710 labelWidest = documentSize.width();
1716 labelWidest = component.size.width();
1720 double verticalAlignOffset = 0;
1724 const double overallHeight = documentSize.height();
1725 switch ( vAlignment )
1731 verticalAlignOffset = ( component.size.height() - overallHeight ) * 0.5;
1735 verticalAlignOffset = ( component.size.height() - overallHeight );
1748 || textLines.size() > 1 );
1750 const bool isFinalLineInParagraph = ( blockIndex == document.
size() - 1 )
1751 || document.
at( blockIndex + 1 ).
toPlainText().trimmed().isEmpty();
1753 const double blockHeight = metrics.
blockHeight( blockIndex );
1757 context.
painter()->translate( component.origin );
1759 context.
painter()->rotate( rotation );
1764 maskPainter->save();
1765 maskPainter->translate( component.origin );
1767 maskPainter->rotate( rotation );
1771 double xMultiLineOffset = 0.0;
1772 double blockWidth = metrics.
blockWidth( blockIndex );
1773 double extraWordSpace = 0;
1774 double extraLetterSpace = 0;
1775 if ( adjustForAlignment )
1777 double labelWidthDiff = 0;
1778 switch ( blockAlignment )
1781 labelWidthDiff = ( labelWidest - blockWidth ) * 0.5;
1785 labelWidthDiff = labelWidest - blockWidth;
1789 if ( !isFinalLineInParagraph && labelWidest > blockWidth )
1791 calculateExtraSpacingForLineJustification( labelWidest - blockWidth, block, extraWordSpace, extraLetterSpace );
1792 blockWidth = labelWidest;
1806 xMultiLineOffset = labelWidthDiff;
1811 switch ( blockAlignment )
1814 xMultiLineOffset = labelWidthDiff - labelWidest;
1818 xMultiLineOffset = labelWidthDiff - labelWidest / 2.0;
1830 const double baseLineOffset = metrics.
baselineOffset( blockIndex, mode );
1832 context.
painter()->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
1834 maskPainter->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
1836 Component subComponent;
1837 subComponent.block = block;
1838 subComponent.blockIndex = blockIndex;
1839 subComponent.
size = QSizeF( blockWidth, blockHeight );
1840 subComponent.offset = QPointF( 0.0, -metrics.
ascentOffset() );
1841 subComponent.rotation = -component.rotation * 180 / M_PI;
1842 subComponent.rotationOffset = 0.0;
1843 subComponent.extraWordSpacing = extraWordSpace * fontScale;
1844 subComponent.extraLetterSpacing = extraLetterSpace * fontScale;
1849 QgsTextRenderer::drawMask( context, subComponent, format, metrics, mode );
1854 QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
1861 textp.begin( &textPict );
1862 textp.setPen( Qt::NoPen );
1864 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1872 referenceScaleOverride.reset();
1876 textp.scale( 1 / fontScale, 1 / fontScale );
1879 int fragmentIndex = 0;
1883 if ( !fragment.isWhitespace() )
1886 path.setFillRule( Qt::WindingFill );
1888 QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
1890 if ( extraWordSpace || extraLetterSpace )
1891 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1895 path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
1897 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
1898 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.opacity() );
1899 textp.setBrush( textColor );
1900 textp.drawPath( path );
1911 subComponent.picture = textPict;
1912 subComponent.pictureBuffer = 0.0;
1913 subComponent.origin = QPointF( 0.0, 0.0 );
1915 QgsTextRenderer::drawShadow( context, subComponent, format );
1925 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
1933 context.
painter()->drawPicture( 0, 0, textPict );
1940 int fragmentIndex = 0;
1943 if ( !fragment.isWhitespace() )
1945 QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
1947 if ( extraWordSpace || extraLetterSpace )
1948 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1952 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
1953 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.opacity() );
1955 context.
painter()->setPen( textColor );
1956 context.
painter()->setFont( fragmentFont );
1957 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
1959 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
1960 context.
painter()->drawText( QPointF( xOffset, yOffset ), fragment.text() );
1961 context.
painter()->scale( fontScale, fontScale );
1971 maskPainter->restore();
1977void 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 )
1980 const QStringList textLines = document.
toPlainText();
1982 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1993 referenceScaleOverride.reset();
1996 const double actualTextWidth = documentSize.width();
1997 double textRectWidth = 0.0;
2003 textRectWidth = actualTextWidth;
2009 textRectWidth = component.size.width();
2013 int maxLineLength = 0;
2014 for (
const QString &line : std::as_const( textLines ) )
2016 maxLineLength = std::max( maxLineLength,
static_cast<int>( line.length() ) );
2019 const double actualLabelHeight = documentSize.height();
2029 context.
painter()->translate( component.origin );
2031 context.
painter()->rotate( rotation );
2036 maskPainter->save();
2037 maskPainter->translate( component.origin );
2039 maskPainter->rotate( rotation );
2046 if ( adjustForAlignment )
2048 double hAlignmentOffset = 0;
2049 switch ( hAlignment )
2052 hAlignmentOffset = ( textRectWidth - actualTextWidth ) * 0.5;
2056 hAlignmentOffset = textRectWidth - actualTextWidth;
2070 xOffset += hAlignmentOffset;
2078 double yOffset = 0.0;
2084 if ( rotation >= -405 && rotation < -180 )
2088 else if ( rotation >= 0 && rotation < 45 )
2090 xOffset -= actualTextWidth;
2096 yOffset = -actualLabelHeight;
2101 yOffset = -actualLabelHeight;
2111 context.
painter()->translate( QPointF( xOffset, yOffset ) );
2113 double currentBlockYOffset = 0;
2114 int fragmentIndex = 0;
2122 const QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
2124 QFontMetricsF fragmentMetrics( fragmentFont );
2126 const double letterSpacing = fragmentFont.letterSpacing() / fontScale;
2127 const double labelHeight = fragmentMetrics.ascent() / fontScale + ( fragmentMetrics.ascent() / fontScale + letterSpacing ) * ( line.length() - 1 );
2129 Component subComponent;
2131 subComponent.blockIndex = blockIndex;
2132 subComponent.firstFragmentIndex = fragmentIndex;
2133 subComponent.size = QSizeF( blockMaximumCharacterWidth, labelHeight + fragmentMetrics.descent() / fontScale );
2134 subComponent.offset = QPointF( 0.0, currentBlockYOffset );
2135 subComponent.rotation = -component.rotation * 180 / M_PI;
2136 subComponent.rotationOffset = 0.0;
2143 QgsTextRenderer::drawMask( context, subComponent, format );
2149 currentBlockYOffset += QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
2155 path.setFillRule( Qt::WindingFill );
2157 double partYOffset = 0.0;
2158 for (
const QString &part : parts )
2160 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
2161 partYOffset += fragmentMetrics.ascent() / fontScale;
2162 path.addText( partXOffset * fontScale, partYOffset * fontScale, fragmentFont, part );
2163 partYOffset += letterSpacing;
2169 textp.begin( &textPict );
2170 textp.setPen( Qt::NoPen );
2171 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
2172 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.
opacity() );
2173 textp.setBrush( textColor );
2174 textp.scale( 1 / fontScale, 1 / fontScale );
2175 textp.drawPath( path );
2186 subComponent.picture = textPict;
2187 subComponent.pictureBuffer = 0.0;
2188 subComponent.origin = QPointF( 0.0, currentBlockYOffset );
2189 const double prevY = subComponent.offset.y();
2190 subComponent.offset = QPointF( 0, -subComponent.size.height() );
2191 subComponent.useOrigin =
true;
2192 QgsTextRenderer::drawShadow( context, subComponent, format );
2193 subComponent.useOrigin =
false;
2194 subComponent.offset = QPointF( 0, prevY );
2204 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
2211 context.
painter()->translate( 0, currentBlockYOffset );
2213 context.
painter()->drawPicture( 0, 0, textPict );
2214 currentBlockYOffset += partYOffset;
2220 context.
painter()->setFont( fragmentFont );
2221 context.
painter()->setPen( textColor );
2222 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
2224 double partYOffset = 0.0;
2225 for (
const QString &part : parts )
2227 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
2228 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
2229 context.
painter()->drawText( QPointF( partXOffset * fontScale, ( currentBlockYOffset + partYOffset ) * fontScale ), part );
2230 context.
painter()->scale( fontScale, fontScale );
2231 partYOffset += fragmentMetrics.ascent() / fontScale + letterSpacing;
2233 currentBlockYOffset += partYOffset;
2241 maskPainter->restore();
2259 if ( pixelSize < 50 )
2260 return 200 / pixelSize;
2263 else if ( pixelSize > 200 )
2264 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.
Qgis::TextHorizontalAlignment horizontalAlignment() const
Returns the format horizontal alignment.
bool hasHorizontalAlignmentSet() const
Returns true if the format has an explicit horizontal alignment set.
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.
const QgsTextBlockFormat & blockFormat() const
Returns the block formatting for the fragment.
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