37#include <QTextBoundaryFinder>
42 if ( alignment & Qt::AlignLeft )
44 else if ( alignment & Qt::AlignRight )
46 else if ( alignment & Qt::AlignHCenter )
48 else if ( alignment & Qt::AlignJustify )
57 if ( alignment & Qt::AlignTop )
59 else if ( alignment & Qt::AlignBottom )
61 else if ( alignment & Qt::AlignVCenter )
64 else if ( alignment & Qt::AlignBaseline )
72 return static_cast< int >(
c.convertToPainterUnits( size, unit, mapUnitScale ) + 0.5 );
84 QStringList textLines;
85 for (
const QString &line : text )
89 textLines.append(
wrappedText( context, line, rect.width(), lFormat ) );
93 textLines.append( line );
103 drawDocument( rect, lFormat, document, metrics, context, alignment, vAlignment, rotation, mode, flags );
108 const QgsTextFormat tmpFormat = updateShadowPosition( format );
128 lFormat = updateShadowPosition( lFormat );
136 drawDocument( point, lFormat, document, metrics, context, alignment, rotation );
159 lFormat = updateShadowPosition( lFormat );
167 drawDocumentOnLine( line, lFormat, document, context, offsetAlongLine, offsetFromLine );
172 QPolygonF labelBaselineCurve = line;
181#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<11
182 if ( offsetFromLine < 0 )
185 std::unique_ptr < QgsLineString > reversed( offsetCurve->reversed() );
189 offsetCurve = std::move( reversed );
193 labelBaselineCurve = offsetCurve->asQPolygonF();
198 const QFont baseFont = format.
scaledFont( context, fontScale );
199 const double letterSpacing = baseFont.letterSpacing() / fontScale;
200 const double wordSpacing = baseFont.wordSpacing() / fontScale;
202 QStringList graphemes;
203 QVector< QgsTextCharacterFormat > graphemeFormats;
204 QVector< QgsTextDocument > graphemeDocuments;
205 QVector< QgsTextDocumentMetrics > graphemeMetrics;
207 for (
const QgsTextBlock &block : std::as_const( document ) )
212 for (
const QString &grapheme : fragmentGraphemes )
214 graphemes.append( grapheme );
215 graphemeFormats.append( fragment.characterFormat() );
220 graphemeDocuments.append( document );
226 QVector< double > characterWidths( graphemes.count() );
227 QVector< double > characterHeights( graphemes.count() );
228 QVector< double > characterDescents( graphemes.count() );
229 QFont previousNonSuperSubScriptFont;
231 for (
int i = 0; i < graphemes.count(); i++ )
236 double graphemeFirstCharHorizontalAdvanceWithLetterSpacing = 0;
237 double graphemeFirstCharHorizontalAdvance = 0;
238 double graphemeHorizontalAdvance = 0;
239 double characterDescent = 0;
240 double characterHeight = 0;
243 QFont graphemeFont = baseFont;
247 previousNonSuperSubScriptFont = graphemeFont;
254 previousNonSuperSubScriptFont = graphemeFont;
275 previousNonSuperSubScriptFont = graphemeFont;
278 const QFontMetricsF graphemeFontMetrics( graphemeFont );
279 graphemeFirstCharHorizontalAdvance = graphemeFontMetrics.horizontalAdvance( QString( graphemes[i].at( 0 ) ) ) / fontScale;
280 graphemeFirstCharHorizontalAdvanceWithLetterSpacing = graphemeFontMetrics.horizontalAdvance( graphemes[i].at( 0 ) ) / fontScale + letterSpacing;
281 graphemeHorizontalAdvance = graphemeFontMetrics.horizontalAdvance( QString( graphemes[i] ) ) / fontScale;
282 characterDescent = graphemeFontMetrics.descent() / fontScale;
283 characterHeight = graphemeFontMetrics.height() / fontScale;
285 qreal wordSpaceFix = qreal( 0.0 );
286 if ( graphemes[i] == QLatin1String(
" " ) )
290 wordSpaceFix = ( nxt < graphemes.count() && graphemes[nxt] != QLatin1String(
" " ) ) ? wordSpacing : qreal( 0.0 );
295 if ( graphemes[i].length() == 1 &&
296 !
qgsDoubleNear( graphemeFirstCharHorizontalAdvance, graphemeFirstCharHorizontalAdvanceWithLetterSpacing ) )
299 wordSpaceFix -= wordSpacing;
302 const double charWidth = graphemeHorizontalAdvance + wordSpaceFix;
303 characterWidths[i] = charWidth;
304 characterHeights[i] = characterHeight;
305 characterDescents[i] = characterDescent;
308 QgsPrecalculatedTextMetrics metrics( graphemes, std::move( characterWidths ), std::move( characterHeights ), std::move( characterDescents ) );
312 metrics, labelBaselineCurve, offsetAlongLine,
319 if ( placement->graphemePlacement.empty() )
322 std::vector< QgsTextRenderer::Component > components;
323 components.reserve( placement->graphemePlacement.size() );
326 QgsTextRenderer::Component component;
327 component.origin = QPointF( grapheme.x, grapheme.y );
328 component.rotation = -grapheme.angle;
334 component.origin.rx() += verticalOffset * std::cos( grapheme.angle + M_PI_2 );
335 component.origin.ry() += verticalOffset * std::sin( grapheme.angle + M_PI_2 );
338 components.emplace_back( component );
346 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
355 const QgsTextDocument &document = graphemeDocuments.
at( grapheme.graphemeIndex );
357 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
373 const QgsTextDocument &document = graphemeDocuments.
at( grapheme.graphemeIndex );
375 const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
428 component.dpiRatio = 1.0;
429 component.origin = rect.topLeft();
430 component.rotation = rotation;
431 component.size = rect.size();
432 component.hAlign = alignment;
445 double xc = rect.width() / 2.0;
446 double yc = rect.height() / 2.0;
448 double angle = -rotation;
449 double xd = xc * std::cos( angle ) - yc * std::sin( angle );
450 double yd = xc * std::sin( angle ) + yc * std::cos( angle );
452 component.center = QPointF( component.origin.x() + xd, component.origin.y() + yd );
456 component.center = rect.center();
459 switch ( vAlignment )
485 drawTextInternal( part, context, format, component,
487 alignment, vAlignment, mode );
510 component.dpiRatio = 1.0;
511 component.origin = origin;
512 component.rotation = rotation;
513 component.hAlign = alignment;
522 QgsTextRenderer::drawBackground( context, component, format, metrics, mode );
535 drawTextInternal( part, context, format, component,
547 return QFontMetricsF( format.
scaledFont( context, scaleFactor ), context.
painter() ? context.
painter()->device() : nullptr );
554 QPainter *p = context.
painter();
559 if ( component.rotation >= -315 && component.rotation < -90 )
563 else if ( component.rotation >= -90 && component.rotation < -45 )
581 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
592 referenceScaleOverride.reset();
595 path.setFillRule( Qt::WindingFill );
597 double height = component.size.height();
598 switch ( orientation )
603 int fragmentIndex = 0;
606 QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, fragmentIndex );
608 if ( !fragment.isWhitespace() && !fragment.isImage() )
610 if ( component.extraWordSpacing || component.extraLetterSpacing )
611 applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing );
614 path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
628 double partYOffset = component.offset.y() * scaleFactor;
631 double partLastDescent = 0;
633 int fragmentIndex = 0;
636 const QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, component.firstFragmentIndex + fragmentIndex );
637 const double letterSpacing = fragmentFont.letterSpacing() / scaleFactor;
639 const QFontMetricsF fragmentMetrics( fragmentFont );
641 const double fragmentYOffset = metrics.
fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
644 for (
const QString &part : parts )
646 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / scaleFactor - letterSpacing ) ) / 2;
647 partYOffset += fragmentMetrics.ascent() / scaleFactor;
648 path.addText( partXOffset, partYOffset + fragmentYOffset, fragmentFont, part );
649 partYOffset += letterSpacing;
651 partLastDescent = fragmentMetrics.descent() / scaleFactor;
655 height = partYOffset + partLastDescent;
656 advance = partYOffset - component.offset.y() * scaleFactor;
661 QColor bufferColor = buffer.
color();
662 bufferColor.setAlphaF( buffer.
opacity() );
663 QPen pen( bufferColor );
664 pen.setWidthF( penSize * scaleFactor );
666 QColor tmpColor( bufferColor );
670 tmpColor.setAlpha( 0 );
676 buffp.begin( &buffPict );
680 std::unique_ptr< QgsPaintEffect > tmpEffect( buffer.
paintEffect()->
clone() );
682 tmpEffect->begin( context );
683 context.
painter()->setPen( pen );
684 context.
painter()->setBrush( tmpColor );
685 if ( scaleFactor != 1.0 )
686 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
687 context.
painter()->drawPath( path );
688 if ( scaleFactor != 1.0 )
689 context.
painter()->scale( scaleFactor, scaleFactor );
690 tmpEffect->end( context );
696 if ( scaleFactor != 1.0 )
697 buffp.scale( 1 / scaleFactor, 1 / scaleFactor );
699 buffp.setBrush( tmpColor );
700 buffp.drawPath( path );
706 QgsTextRenderer::Component bufferComponent = component;
707 bufferComponent.origin = QPointF( 0.0, 0.0 );
708 bufferComponent.picture = buffPict;
709 bufferComponent.pictureBuffer = penSize / 2.0;
710 bufferComponent.size.setHeight( height );
714 bufferComponent.offset.setY( - bufferComponent.size.height() );
716 drawShadow( context, bufferComponent, format );
724 p->setCompositionMode( buffer.
blendMode() );
728 p->scale( component.dpiRatio, component.dpiRatio );
730 p->drawPicture( 0, 0, buffPict );
732 return advance / scaleFactor;
752 path.setFillRule( Qt::WindingFill );
759 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
770 referenceScaleOverride.reset();
773 int fragmentIndex = 0;
776 if ( !fragment.isWhitespace() && !fragment.isImage() )
778 const QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, fragmentIndex );
780 const double fragmentYOffset = metrics.
fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
781 path.addText( xOffset, fragmentYOffset, fragmentFont, fragment.text() );
788 QColor bufferColor( Qt::gray );
789 bufferColor.setAlphaF( mask.
opacity() );
793 brush.setColor( bufferColor );
794 pen.setColor( bufferColor );
795 pen.setWidthF( penSize * scaleFactor );
802 p->scale( component.dpiRatio, component.dpiRatio );
808 if ( scaleFactor != 1.0 )
809 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
810 context.
painter()->setPen( pen );
811 context.
painter()->setBrush( brush );
812 context.
painter()->drawPath( path );
813 if ( scaleFactor != 1.0 )
814 context.
painter()->scale( scaleFactor, scaleFactor );
819 if ( scaleFactor != 1.0 )
820 p->scale( 1 / scaleFactor, 1 / scaleFactor );
822 p->setBrush( brush );
824 if ( scaleFactor != 1.0 )
825 p->scale( scaleFactor, scaleFactor );
841 if ( doc.
size() == 0 )
845 return textWidth( context, format, doc );
862 for (
const QString &line : textLines )
866 lines.append(
wrappedText( context, line, maxLineWidth, format ) );
870 lines.append( line );
888 bool isNullSize =
false;
889 const QFont baseFont = format.
scaledFont( context, scaleFactor, &isNullSize );
893 const QFontMetrics fm( baseFont );
894 const double height = ( character.isNull() ? fm.height() : fm.boundingRect( character ).height() ) / scaleFactor;
896 if ( !includeEffects )
899 double maxExtension = 0;
928 return height + maxExtension;
936 const QStringList multiLineSplit = text.split(
'\n' );
938 return currentTextWidth > width;
943 const QStringList lines = text.split(
'\n' );
944 QStringList outLines;
945 for (
const QString &line : lines )
950 const QStringList words = line.split(
' ' );
951 QStringList linesToProcess;
952 QString wordsInCurrentLine;
953 for (
const QString &word : words )
958 if ( !wordsInCurrentLine.isEmpty() )
959 linesToProcess << wordsInCurrentLine;
960 wordsInCurrentLine.clear();
961 linesToProcess << word;
965 if ( !wordsInCurrentLine.isEmpty() )
966 wordsInCurrentLine.append(
' ' );
967 wordsInCurrentLine.append( word );
970 if ( !wordsInCurrentLine.isEmpty() )
971 linesToProcess << wordsInCurrentLine;
973 for (
const QString &line : std::as_const( linesToProcess ) )
975 QString remainingText = line;
976 int lastPos = remainingText.lastIndexOf(
' ' );
977 while ( lastPos > -1 )
987 outLines << remainingText.left( lastPos );
988 remainingText = remainingText.mid( lastPos + 1 );
991 lastPos = remainingText.lastIndexOf(
' ', lastPos - 1 );
993 outLines << remainingText;
1024 QPainter *prevP = context.
painter();
1025 QPainter *p = context.
painter();
1026 std::unique_ptr< QgsPaintEffect > tmpEffect;
1030 tmpEffect->begin( context );
1039 const double originAdjustRotationRadians = -component.rotation;
1042 component.rotation = -( component.rotation * 180 / M_PI );
1043 component.rotationOffset =
1048 component.rotation = 0.0;
1049 component.rotationOffset = background.
rotation();
1058 double width = documentSize.width();
1059 double height = documentSize.height();
1066 switch ( component.hAlign )
1070 component.center = QPointF( component.origin.x() + width / 2.0,
1071 component.origin.y() + height / 2.0 );
1075 component.center = QPointF( component.origin.x() + component.size.width() / 2.0,
1076 component.origin.y() + height / 2.0 );
1080 component.center = QPointF( component.origin.x() + component.size.width() - width / 2.0,
1081 component.origin.y() + height / 2.0 );
1088 bool isNullSize =
false;
1089 QFontMetricsF fm( format.
scaledFont( context, scaleFactor, &isNullSize ) );
1090 double originAdjust = isNullSize ? 0 : ( fm.ascent() / scaleFactor / 2.0 - fm.leading() / scaleFactor / 2.0 );
1091 switch ( component.hAlign )
1095 component.center = QPointF( component.origin.x() + width / 2.0,
1096 component.origin.y() - height / 2.0 + originAdjust );
1100 component.center = QPointF( component.origin.x(),
1101 component.origin.y() - height / 2.0 + originAdjust );
1105 component.center = QPointF( component.origin.x() - width / 2.0,
1106 component.origin.y() - height / 2.0 + originAdjust );
1113 const double dx = component.center.x() - component.origin.x();
1114 const double dy = component.center.y() - component.origin.y();
1115 component.center.setX( component.origin.x() + ( std::cos( originAdjustRotationRadians ) * dx - std::sin( originAdjustRotationRadians ) * dy ) );
1116 component.center.setY( component.origin.y() + ( std::sin( originAdjustRotationRadians ) * dx + std::cos( originAdjustRotationRadians ) * dy ) );
1126 component.size = QSizeF( width, height );
1131 switch ( background.
type() )
1144 double sizeOut = 0.0;
1155 sizeOut = std::max( component.size.width(), component.size.height() );
1159 sizeOut += bufferSize * 2;
1165 if ( sizeOut < 1.0 )
1168 std::unique_ptr< QgsMarkerSymbol > renderedSymbol;
1172 map[QStringLiteral(
"name" )] = background.
svgFile().trimmed();
1173 map[QStringLiteral(
"size" )] = QString::number( sizeOut );
1175 map[QStringLiteral(
"angle" )] = QString::number( 0.0 );
1183 map[QStringLiteral(
"fill" )] = background.
fillColor().name();
1184 map[QStringLiteral(
"outline" )] = background.
strokeColor().name();
1185 map[QStringLiteral(
"outline-width" )] = QString::number( background.
strokeWidth() );
1192 QVariantMap shdwmap( map );
1193 shdwmap[QStringLiteral(
"fill" )] = shadow.
color().name();
1194 shdwmap[QStringLiteral(
"outline" )] = shadow.
color().name();
1195 shdwmap[QStringLiteral(
"size" )] = QString::number( sizeOut );
1200 svgp.begin( &svgPict );
1217 svgShdwM->
renderPoint( QPointF( sizeOut / 2, -sizeOut / 2 ), svgShdwContext );
1220 component.picture = svgPict;
1222 component.pictureBuffer = 0.0;
1224 component.size = QSizeF( sizeOut, sizeOut );
1225 component.offset = QPointF( 0.0, 0.0 );
1231 p->translate( component.center.x(), component.center.y() );
1232 p->rotate( component.rotation );
1235 p->translate( QPointF( xoff, yoff ) );
1236 p->rotate( component.rotationOffset );
1237 p->translate( -sizeOut / 2, sizeOut / 2 );
1239 drawShadow( context, component, format );
1241 renderedSymbol.reset( );
1249 renderedSymbol->setSize( sizeOut );
1253 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1261 p->setCompositionMode( background.
blendMode() );
1263 p->translate( component.center.x(), component.center.y() );
1264 p->rotate( component.rotation );
1267 p->translate( QPointF( xoff, yoff ) );
1268 p->rotate( component.rotationOffset );
1272 renderedSymbol->renderPoint( QPointF( 0, 0 ), &f, context );
1273 renderedSymbol->stopRender( context );
1274 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1284 double w = component.size.width();
1285 double h = component.size.height();
1306 h = std::sqrt( std::pow( w, 2 ) + std::pow( h, 2 ) );
1312 h = h * M_SQRT1_2 * 2;
1313 w = w * M_SQRT1_2 * 2;
1321 w += bufferWidth * 2;
1322 h += bufferHeight * 2;
1326 QRectF rect( -w / 2.0, - h / 2.0, w, h );
1328 if ( rect.isNull() )
1334 p->translate( QPointF( component.center.x(), component.center.y() ) );
1335 p->rotate( component.rotation );
1338 p->translate( QPointF( xoff, yoff ) );
1339 p->rotate( component.rotationOffset );
1345 QTransform t = QTransform::fromScale( 10, 10 );
1347 QTransform ti = t.inverted();
1354 path.addRoundedRect( rect, background.
radii().width(), background.
radii().height(), Qt::RelativeSize );
1360 path.addRoundedRect( rect, xRadius, yRadius );
1366 path.addEllipse( rect );
1368 QPolygonF tempPolygon = path.toFillPolygon( t );
1369 QPolygonF polygon = ti.map( tempPolygon );
1371 QPainter *oldp = context.
painter();
1374 shapep.begin( &shapePict );
1377 std::unique_ptr< QgsFillSymbol > renderedSymbol;
1379 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1383 renderedSymbol->renderPolygon( polygon,
nullptr, &f, context );
1384 renderedSymbol->stopRender( context );
1391 component.picture = shapePict;
1394 component.size = rect.size();
1395 component.offset = QPointF( rect.width() / 2, -rect.height() / 2 );
1396 drawShadow( context, component, format );
1401 p->setCompositionMode( background.
blendMode() );
1405 p->scale( component.dpiRatio, component.dpiRatio );
1407 p->drawPicture( 0, 0, shapePict );
1408 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1415 tmpEffect->end( context );
1428 QPainter *p = context.
painter();
1429 const double componentWidth = component.size.width();
1430 const double componentHeight = component.size.height();
1431 double xOffset = component.offset.x(), yOffset = component.offset.y();
1432 double pictbuffer = component.pictureBuffer;
1441 radius /= ( mapUnits ? context.
scaleFactor() / component.dpiRatio : 1 );
1442 radius =
static_cast< int >( radius + 0.5 );
1446 double blurBufferClippingScale = 3.75;
1447 int blurbuffer = ( radius > 17 ? 16 : radius ) * blurBufferClippingScale;
1449 QImage blurImg( componentWidth + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1450 componentHeight + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1451 QImage::Format_ARGB32_Premultiplied );
1455 int minBlurImgSize = 1;
1459 int maxBlurImgSize = 40000;
1460 if ( blurImg.isNull()
1461 || ( blurImg.width() < minBlurImgSize || blurImg.height() < minBlurImgSize )
1462 || ( blurImg.width() > maxBlurImgSize || blurImg.height() > maxBlurImgSize ) )
1465 blurImg.fill( QColor( Qt::transparent ).rgba() );
1467 if ( !pictp.begin( &blurImg ) )
1469 pictp.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
1470 QPointF imgOffset( blurbuffer + pictbuffer + xOffset,
1471 blurbuffer + pictbuffer + componentHeight + yOffset );
1473 pictp.drawPicture( imgOffset,
1474 component.picture );
1477 pictp.setCompositionMode( QPainter::CompositionMode_SourceIn );
1478 pictp.fillRect( blurImg.rect(), shadow.
color() );
1482 if ( shadow.
blurRadius() > 0.0 && radius > 0 )
1490 picti.begin( &blurImg );
1491 picti.setBrush( Qt::Dense7Pattern );
1492 QPen imgPen( QColor( 0, 0, 255, 255 ) );
1493 imgPen.setWidth( 1 );
1494 picti.setPen( imgPen );
1495 picti.setOpacity( 0.1 );
1496 picti.drawRect( 0, 0, blurImg.width(), blurImg.height() );
1503 double angleRad = shadow.
offsetAngle() * M_PI / 180;
1511 angleRad -= ( component.rotation * M_PI / 180 + component.rotationOffset * M_PI / 180 );
1514 QPointF transPt( -offsetDist * std::cos( angleRad + M_PI_2 ),
1515 -offsetDist * std::sin( angleRad + M_PI_2 ) );
1521 p->setRenderHint( QPainter::SmoothPixmapTransform );
1524 p->setCompositionMode( shadow.
blendMode() );
1526 p->setOpacity( shadow.
opacity() );
1528 double scale = shadow.
scale() / 100.0;
1530 p->scale( scale, scale );
1531 if ( component.useOrigin )
1533 p->translate( component.origin.x(), component.origin.y() );
1535 p->translate( transPt );
1536 p->translate( -imgOffset.x(),
1538 p->drawImage( 0, 0, blurImg );
1545 p->setBrush( Qt::NoBrush );
1546 QPen imgPen( QColor( 255, 0, 0, 10 ) );
1547 imgPen.setWidth( 2 );
1548 imgPen.setStyle( Qt::DashLine );
1549 p->setPen( imgPen );
1550 p->scale( scale, scale );
1551 if ( component.useOrigin() )
1553 p->translate( component.origin().x(), component.origin().y() );
1555 p->translate( transPt );
1556 p->translate( -imgOffset.x(),
1558 p->drawRect( 0, 0, blurImg.width(), blurImg.height() );
1563 p->setBrush( Qt::NoBrush );
1564 QPen componentRectPen( QColor( 0, 255, 0, 70 ) );
1565 componentRectPen.setWidth( 1 );
1566 if ( component.useOrigin() )
1568 p->translate( component.origin().x(), component.origin().y() );
1570 p->setPen( componentRectPen );
1571 p->drawRect( QRect( -xOffset, -componentHeight - yOffset, componentWidth, componentHeight ) );
1580 const Component &component,
1592 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1603 referenceScaleOverride.reset();
1605 double rotation = 0;
1606 const Qgis::TextOrientation orientation = calculateRotationAndOrientationForComponent( format, component, rotation );
1607 switch ( orientation )
1611 drawTextInternalHorizontal( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
1618 drawTextInternalVertical( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
1624Qgis::TextOrientation QgsTextRenderer::calculateRotationAndOrientationForComponent(
const QgsTextFormat &format,
const QgsTextRenderer::Component &component,
double &rotation )
1626 rotation = -component.rotation * 180 / M_PI;
1633 if ( rotation >= -315 && rotation < -90 )
1638 else if ( rotation >= -90 && rotation < -45 )
1654void QgsTextRenderer::calculateExtraSpacingForLineJustification(
const double spaceToDistribute,
const QgsTextBlock &block,
double &extraWordSpace,
double &extraLetterSpace )
1657 QTextBoundaryFinder
finder( QTextBoundaryFinder::Word, blockText );
1659 int wordBoundaries = 0;
1660 while (
finder.toNextBoundary() != -1 )
1662 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1666 if ( wordBoundaries > 0 )
1669 extraWordSpace = spaceToDistribute / wordBoundaries;
1674 QTextBoundaryFinder
finder( QTextBoundaryFinder::Grapheme, blockText );
1677 int graphemeBoundaries = 0;
1678 while (
finder.toNextBoundary() != -1 )
1680 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1681 graphemeBoundaries++;
1684 if ( graphemeBoundaries > 0 )
1686 extraLetterSpace = spaceToDistribute / graphemeBoundaries;
1691void QgsTextRenderer::applyExtraSpacingForLineJustification( QFont &font,
double extraWordSpace,
double extraLetterSpace )
1693 const double prevWordSpace = font.wordSpacing();
1694 font.setWordSpacing( prevWordSpace + extraWordSpace );
1695 const double prevLetterSpace = font.letterSpacing();
1696 font.setLetterSpacing( QFont::AbsoluteSpacing, prevLetterSpace + extraLetterSpace );
1703 const QStringList textLines = document.
toPlainText();
1707 double labelWidest = 0.0;
1712 labelWidest = documentSize.width();
1718 labelWidest = component.size.width();
1722 double verticalAlignOffset = 0;
1726 const double overallHeight = documentSize.height();
1727 switch ( vAlignment )
1733 verticalAlignOffset = ( component.size.height() - overallHeight ) * 0.5;
1737 verticalAlignOffset = ( component.size.height() - overallHeight );
1750 || textLines.size() > 1 );
1752 const bool isFinalLineInParagraph = ( blockIndex == document.
size() - 1 )
1753 || document.
at( blockIndex + 1 ).
toPlainText().trimmed().isEmpty();
1755 const double blockHeight = metrics.
blockHeight( blockIndex );
1759 context.
painter()->translate( component.origin );
1761 context.
painter()->rotate( rotation );
1766 maskPainter->save();
1767 maskPainter->translate( component.origin );
1769 maskPainter->rotate( rotation );
1773 double xMultiLineOffset = 0.0;
1774 double blockWidth = metrics.
blockWidth( blockIndex );
1775 double extraWordSpace = 0;
1776 double extraLetterSpace = 0;
1777 if ( adjustForAlignment )
1779 double labelWidthDiff = 0;
1780 switch ( blockAlignment )
1783 labelWidthDiff = ( labelWidest - blockWidth ) * 0.5;
1787 labelWidthDiff = labelWidest - blockWidth;
1791 if ( !isFinalLineInParagraph && labelWidest > blockWidth )
1793 calculateExtraSpacingForLineJustification( labelWidest - blockWidth, block, extraWordSpace, extraLetterSpace );
1794 blockWidth = labelWidest;
1808 xMultiLineOffset = labelWidthDiff;
1813 switch ( blockAlignment )
1816 xMultiLineOffset = labelWidthDiff - labelWidest;
1820 xMultiLineOffset = labelWidthDiff - labelWidest / 2.0;
1832 const double baseLineOffset = metrics.
baselineOffset( blockIndex, mode );
1834 context.
painter()->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
1836 maskPainter->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
1838 Component subComponent;
1839 subComponent.block = block;
1840 subComponent.blockIndex = blockIndex;
1841 subComponent.
size = QSizeF( blockWidth, blockHeight );
1842 subComponent.offset = QPointF( 0.0, -metrics.
ascentOffset() );
1843 subComponent.rotation = -component.rotation * 180 / M_PI;
1844 subComponent.rotationOffset = 0.0;
1845 subComponent.extraWordSpacing = extraWordSpace * fontScale;
1846 subComponent.extraLetterSpacing = extraLetterSpace * fontScale;
1851 QgsTextRenderer::drawMask( context, subComponent, format, metrics, mode );
1856 QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
1863 textp.begin( &textPict );
1864 textp.setPen( Qt::NoPen );
1866 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1874 referenceScaleOverride.reset();
1878 textp.scale( 1 / fontScale, 1 / fontScale );
1881 int fragmentIndex = 0;
1885 if ( !fragment.isWhitespace() && !fragment.isImage() )
1888 path.setFillRule( Qt::WindingFill );
1890 QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
1892 if ( extraWordSpace || extraLetterSpace )
1893 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1897 path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
1899 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
1900 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.opacity() );
1901 textp.setBrush( textColor );
1902 textp.drawPath( path );
1904 else if ( fragment.isImage() )
1906 bool fitsInCache =
false;
1908 const double imageHeight = metrics.
fragmentFixedHeight( blockIndex, fragmentIndex, mode ) * fontScale;
1911 QSize(
static_cast< int >( std::round( imageWidth ) ),
1912 static_cast< int >( std::round( imageHeight ) ) ),
1916 const double yOffset = imageBaseline - image.height();
1917 if ( !image.isNull() )
1918 textp.drawImage( QPointF( xOffset, yOffset ), image );
1929 subComponent.picture = textPict;
1930 subComponent.pictureBuffer = 0.0;
1931 subComponent.origin = QPointF( 0.0, 0.0 );
1933 QgsTextRenderer::drawShadow( context, subComponent, format );
1943 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
1951 context.
painter()->drawPicture( 0, 0, textPict );
1958 int fragmentIndex = 0;
1961 if ( !fragment.isWhitespace() && !fragment.isImage() )
1963 QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
1965 if ( extraWordSpace || extraLetterSpace )
1966 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1970 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
1971 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.opacity() );
1973 context.
painter()->setPen( textColor );
1974 context.
painter()->setFont( fragmentFont );
1975 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
1977 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
1978 context.
painter()->drawText( QPointF( xOffset, yOffset ), fragment.text() );
1979 context.
painter()->scale( fontScale, fontScale );
1989 maskPainter->restore();
1995void 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 )
1998 const QStringList textLines = document.
toPlainText();
2000 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
2011 referenceScaleOverride.reset();
2014 const double actualTextWidth = documentSize.width();
2015 double textRectWidth = 0.0;
2021 textRectWidth = actualTextWidth;
2027 textRectWidth = component.size.width();
2031 int maxLineLength = 0;
2032 for (
const QString &line : std::as_const( textLines ) )
2034 maxLineLength = std::max( maxLineLength,
static_cast<int>( line.length() ) );
2037 const double actualLabelHeight = documentSize.height();
2047 context.
painter()->translate( component.origin );
2049 context.
painter()->rotate( rotation );
2054 maskPainter->save();
2055 maskPainter->translate( component.origin );
2057 maskPainter->rotate( rotation );
2064 if ( adjustForAlignment )
2066 double hAlignmentOffset = 0;
2067 switch ( hAlignment )
2070 hAlignmentOffset = ( textRectWidth - actualTextWidth ) * 0.5;
2074 hAlignmentOffset = textRectWidth - actualTextWidth;
2088 xOffset += hAlignmentOffset;
2096 double yOffset = 0.0;
2102 if ( rotation >= -405 && rotation < -180 )
2106 else if ( rotation >= 0 && rotation < 45 )
2108 xOffset -= actualTextWidth;
2114 yOffset = -actualLabelHeight;
2119 yOffset = -actualLabelHeight;
2129 context.
painter()->translate( QPointF( xOffset, yOffset ) );
2131 double currentBlockYOffset = 0;
2132 int fragmentIndex = 0;
2140 const QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
2142 QFontMetricsF fragmentMetrics( fragmentFont );
2144 const double letterSpacing = fragmentFont.letterSpacing() / fontScale;
2145 const double labelHeight = fragmentMetrics.ascent() / fontScale + ( fragmentMetrics.ascent() / fontScale + letterSpacing ) * ( line.length() - 1 );
2147 Component subComponent;
2149 subComponent.blockIndex = blockIndex;
2150 subComponent.firstFragmentIndex = fragmentIndex;
2151 subComponent.size = QSizeF( blockMaximumCharacterWidth, labelHeight + fragmentMetrics.descent() / fontScale );
2152 subComponent.offset = QPointF( 0.0, currentBlockYOffset );
2153 subComponent.rotation = -component.rotation * 180 / M_PI;
2154 subComponent.rotationOffset = 0.0;
2161 QgsTextRenderer::drawMask( context, subComponent, format );
2167 currentBlockYOffset += QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
2173 path.setFillRule( Qt::WindingFill );
2175 double partYOffset = 0.0;
2176 for (
const QString &part : parts )
2178 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
2179 partYOffset += fragmentMetrics.ascent() / fontScale;
2180 path.addText( partXOffset * fontScale, partYOffset * fontScale, fragmentFont, part );
2181 partYOffset += letterSpacing;
2187 textp.begin( &textPict );
2188 textp.setPen( Qt::NoPen );
2189 QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
2190 textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.
opacity() );
2191 textp.setBrush( textColor );
2192 textp.scale( 1 / fontScale, 1 / fontScale );
2193 textp.drawPath( path );
2204 subComponent.picture = textPict;
2205 subComponent.pictureBuffer = 0.0;
2206 subComponent.origin = QPointF( 0.0, currentBlockYOffset );
2207 const double prevY = subComponent.offset.y();
2208 subComponent.offset = QPointF( 0, -subComponent.size.height() );
2209 subComponent.useOrigin =
true;
2210 QgsTextRenderer::drawShadow( context, subComponent, format );
2211 subComponent.useOrigin =
false;
2212 subComponent.offset = QPointF( 0, prevY );
2222 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
2229 context.
painter()->translate( 0, currentBlockYOffset );
2231 context.
painter()->drawPicture( 0, 0, textPict );
2232 currentBlockYOffset += partYOffset;
2238 context.
painter()->setFont( fragmentFont );
2239 context.
painter()->setPen( textColor );
2240 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
2242 double partYOffset = 0.0;
2243 for (
const QString &part : parts )
2245 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
2246 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
2247 context.
painter()->drawText( QPointF( partXOffset * fontScale, ( currentBlockYOffset + partYOffset ) * fontScale ), part );
2248 context.
painter()->scale( fontScale, fontScale );
2249 partYOffset += fragmentMetrics.ascent() / fontScale + letterSpacing;
2251 currentBlockYOffset += partYOffset;
2259 maskPainter->restore();
2277 if ( pixelSize < 50 )
2278 return 200 / pixelSize;
2281 else if ( pixelSize > 200 )
2282 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 ...
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
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.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
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*.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
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.
double fragmentFixedHeight(int blockIndex, int fragmentIndex, Qgis::TextLayoutMode mode) const
Returns the fixed height of the fragment at the specified block and fragment 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 document 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