31#include <QTextBoundaryFinder>
36static void _fixQPictureDPI( QPainter *p )
42 p->scale(
static_cast< double >(
qt_defaultDpiX() ) / p->device()->logicalDpiX(),
43 static_cast< double >(
qt_defaultDpiY() ) / p->device()->logicalDpiY() );
48 if ( alignment & Qt::AlignLeft )
49 return Qgis::TextHorizontalAlignment::Left;
50 else if ( alignment & Qt::AlignRight )
51 return Qgis::TextHorizontalAlignment::Right;
52 else if ( alignment & Qt::AlignHCenter )
53 return Qgis::TextHorizontalAlignment::Center;
54 else if ( alignment & Qt::AlignJustify )
55 return Qgis::TextHorizontalAlignment::Justify;
58 return Qgis::TextHorizontalAlignment::Left;
63 if ( alignment & Qt::AlignTop )
64 return Qgis::TextVerticalAlignment::Top;
65 else if ( alignment & Qt::AlignBottom )
66 return Qgis::TextVerticalAlignment::Bottom;
67 else if ( alignment & Qt::AlignVCenter )
68 return Qgis::TextVerticalAlignment::VerticalCenter;
70 else if ( alignment & Qt::AlignBaseline )
71 return Qgis::TextVerticalAlignment::Bottom;
73 return Qgis::TextVerticalAlignment::Top;
78 return static_cast< int >(
c.convertToPainterUnits( size, unit, mapUnitScale ) + 0.5 );
86 tmpFormat = updateShadowPosition( tmpFormat );
88 QStringList textLines;
89 for (
const QString &line : text )
93 textLines.append(
wrappedText( context, line, rect.width(), format ) );
97 textLines.append( line );
104 const double fontScale = calculateScaleFactorForFormat( context, format );
125 tmpFormat = updateShadowPosition( tmpFormat );
129 const double fontScale = calculateScaleFactorForFormat( context, format );
170 const double fontScale = calculateScaleFactorForFormat( context, format );
173 drawPart( rect, rotation, alignment, Qgis::TextVerticalAlignment::Top, document, metrics, context, format, part, Qgis::TextLayoutMode::Rectangle );
184 component.dpiRatio = 1.0;
185 component.origin = rect.topLeft();
186 component.rotation = rotation;
187 component.size = rect.size();
188 component.hAlign = alignment;
201 double xc = rect.width() / 2.0;
202 double yc = rect.height() / 2.0;
204 double angle = -rotation;
205 double xd = xc * std::cos(
angle ) - yc * std::sin(
angle );
206 double yd = xc * std::sin(
angle ) + yc * std::cos(
angle );
208 component.center = QPointF( component.origin.x() + xd, component.origin.y() + yd );
212 component.center = rect.center();
215 switch ( vAlignment )
217 case Qgis::TextVerticalAlignment::Top:
219 case Qgis::TextVerticalAlignment::VerticalCenter:
222 case Qgis::TextVerticalAlignment::Bottom:
227 QgsTextRenderer::drawBackground( context, component, format, metrics, Qgis::TextLayoutMode::Rectangle );
241 drawTextInternal( part, context, format, component,
243 alignment, vAlignment );
252 const double fontScale = calculateScaleFactorForFormat( context, format );
266 component.dpiRatio = 1.0;
267 component.origin = origin;
268 component.rotation = rotation;
269 component.hAlign = alignment;
278 QgsTextRenderer::drawBackground( context, component, format, metrics, mode );
291 drawTextInternal( part, context, format, component,
294 alignment, Qgis::TextVerticalAlignment::Top,
303 return QFontMetricsF( format.
scaledFont( context, scaleFactor ), context.
painter() ? context.
painter()->device() :
nullptr );
310 QPainter *p = context.
painter();
313 if ( format.
orientation() == Qgis::TextOrientation::RotationBased )
315 if ( component.rotation >= -315 && component.rotation < -90 )
317 orientation = Qgis::TextOrientation::Vertical;
319 else if ( component.rotation >= -90 && component.rotation < -45 )
321 orientation = Qgis::TextOrientation::Vertical;
325 orientation = Qgis::TextOrientation::Horizontal;
335 const double scaleFactor = calculateScaleFactorForFormat( context, format );
337 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
338 if ( mode == Qgis::TextLayoutMode::Labeling )
345 bool isNullSize =
false;
346 const QFont font = format.
scaledFont( context, scaleFactor, &isNullSize );
350 referenceScaleOverride.reset();
353 path.setFillRule( Qt::WindingFill );
355 double height = component.size.height();
356 switch ( orientation )
358 case Qgis::TextOrientation::Horizontal:
363 QFont fragmentFont = font;
366 if ( component.extraWordSpacing || component.extraLetterSpacing )
367 applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing );
369 path.addText( xOffset, 0, fragmentFont, fragment.
text() );
371 xOffset += fragment.
horizontalAdvance( fragmentFont, context,
true, scaleFactor );
377 case Qgis::TextOrientation::Vertical:
378 case Qgis::TextOrientation::RotationBased:
380 double partYOffset = component.offset.y() * scaleFactor;
383 double partLastDescent = 0;
387 QFont fragmentFont = font;
389 const double letterSpacing = fragmentFont.letterSpacing() / scaleFactor;
391 const QFontMetricsF fragmentMetrics( fragmentFont );
394 for (
const QString &part : parts )
396 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / scaleFactor - letterSpacing ) ) / 2;
397 partYOffset += fragmentMetrics.ascent() / scaleFactor;
398 path.addText( partXOffset, partYOffset, fragmentFont, part );
399 partYOffset += letterSpacing;
401 partLastDescent = fragmentMetrics.descent() / scaleFactor;
403 height = partYOffset + partLastDescent;
404 advance = partYOffset - component.offset.y() * scaleFactor;
409 QColor bufferColor = buffer.
color();
410 bufferColor.setAlphaF( buffer.
opacity() );
411 QPen pen( bufferColor );
412 pen.setWidthF( penSize * scaleFactor );
414 QColor tmpColor( bufferColor );
418 tmpColor.setAlpha( 0 );
424 buffp.begin( &buffPict );
428 std::unique_ptr< QgsPaintEffect > tmpEffect( buffer.
paintEffect()->
clone() );
430 tmpEffect->begin( context );
431 context.
painter()->setPen( pen );
432 context.
painter()->setBrush( tmpColor );
433 if ( scaleFactor != 1.0 )
434 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
435 context.
painter()->drawPath( path );
436 if ( scaleFactor != 1.0 )
437 context.
painter()->scale( scaleFactor, scaleFactor );
438 tmpEffect->end( context );
444 if ( scaleFactor != 1.0 )
445 buffp.scale( 1 / scaleFactor, 1 / scaleFactor );
447 buffp.setBrush( tmpColor );
448 buffp.drawPath( path );
454 QgsTextRenderer::Component bufferComponent = component;
455 bufferComponent.origin = QPointF( 0.0, 0.0 );
456 bufferComponent.picture = buffPict;
457 bufferComponent.pictureBuffer = penSize / 2.0;
458 bufferComponent.size.setHeight( height );
460 if ( format.
orientation() == Qgis::TextOrientation::Vertical || format.
orientation() == Qgis::TextOrientation::RotationBased )
462 bufferComponent.offset.setY( - bufferComponent.size.height() );
464 drawShadow( context, bufferComponent, format );
472 p->setCompositionMode( buffer.
blendMode() );
476 p->scale( component.dpiRatio, component.dpiRatio );
477 _fixQPictureDPI( p );
478 p->drawPicture( 0, 0, buffPict );
480 return advance / scaleFactor;
500 path.setFillRule( Qt::WindingFill );
502 const double scaleFactor = calculateScaleFactorForFormat( context, format );
507 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
508 if ( mode == Qgis::TextLayoutMode::Labeling )
515 bool isNullSize =
false;
516 const QFont font = format.
scaledFont( context, scaleFactor, &isNullSize );
520 referenceScaleOverride.reset();
525 QFont fragmentFont = font;
528 path.addText( xOffset, 0, fragmentFont, fragment.
text() );
530 xOffset += fragment.
horizontalAdvance( fragmentFont, context,
true, scaleFactor );
533 QColor bufferColor( Qt::gray );
534 bufferColor.setAlphaF( mask.
opacity() );
538 brush.setColor( bufferColor );
539 pen.setColor( bufferColor );
540 pen.setWidthF( penSize * scaleFactor );
547 p->scale( component.dpiRatio, component.dpiRatio );
553 if ( scaleFactor != 1.0 )
554 context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
555 context.
painter()->setPen( pen );
556 context.
painter()->setBrush( brush );
557 context.
painter()->drawPath( path );
558 if ( scaleFactor != 1.0 )
559 context.
painter()->scale( scaleFactor, scaleFactor );
564 if ( scaleFactor != 1.0 )
565 p->scale( 1 / scaleFactor, 1 / scaleFactor );
567 p->setBrush( brush );
569 if ( scaleFactor != 1.0 )
570 p->scale( scaleFactor, scaleFactor );
586 if ( doc.
size() == 0 )
590 return textWidth( context, format, doc );
596 const double scaleFactor = calculateScaleFactorForFormat( context, format );
607 for (
const QString &line : textLines )
611 lines.append(
wrappedText( context, line, maxLineWidth, format ) );
615 lines.append( line );
631 const double scaleFactor = calculateScaleFactorForFormat( context, format );
632 bool isNullSize =
false;
633 const QFont baseFont = format.
scaledFont( context, scaleFactor, &isNullSize );
637 const QFontMetrics fm( baseFont );
638 const double height = ( character.isNull() ? fm.height() : fm.boundingRect( character ).height() ) / scaleFactor;
640 if ( !includeEffects )
643 double maxExtension = 0;
672 return height + maxExtension;
680 const QStringList multiLineSplit = text.split(
'\n' );
682 return currentTextWidth > width;
687 const QStringList lines = text.split(
'\n' );
688 QStringList outLines;
689 for (
const QString &line : lines )
694 const QStringList words = line.split(
' ' );
695 QStringList linesToProcess;
696 QString wordsInCurrentLine;
697 for (
const QString &word : words )
702 if ( !wordsInCurrentLine.isEmpty() )
703 linesToProcess << wordsInCurrentLine;
704 wordsInCurrentLine.clear();
705 linesToProcess << word;
709 if ( !wordsInCurrentLine.isEmpty() )
710 wordsInCurrentLine.append(
' ' );
711 wordsInCurrentLine.append( word );
714 if ( !wordsInCurrentLine.isEmpty() )
715 linesToProcess << wordsInCurrentLine;
717 for (
const QString &line : std::as_const( linesToProcess ) )
719 QString remainingText = line;
720 int lastPos = remainingText.lastIndexOf(
' ' );
721 while ( lastPos > -1 )
731 outLines << remainingText.left( lastPos );
732 remainingText = remainingText.mid( lastPos + 1 );
735 lastPos = remainingText.lastIndexOf(
' ', lastPos - 1 );
737 outLines << remainingText;
755 const double scaleFactor = calculateScaleFactorForFormat( context, format );
757 bool isNullSize =
false;
758 format.
scaledFont( context, scaleFactor, &isNullSize );
770 QPainter *prevP = context.
painter();
771 QPainter *p = context.
painter();
772 std::unique_ptr< QgsPaintEffect > tmpEffect;
776 tmpEffect->begin( context );
785 const double originAdjustRotationRadians = -component.rotation;
788 component.rotation = -( component.rotation * 180 / M_PI );
789 component.rotationOffset =
794 component.rotation = 0.0;
795 component.rotationOffset = background.
rotation();
798 const double scaleFactor = calculateScaleFactorForFormat( context, format );
800 if ( mode != Qgis::TextLayoutMode::Labeling )
804 double width = documentSize.width();
805 double height = documentSize.height();
809 case Qgis::TextLayoutMode::Rectangle:
810 switch ( component.hAlign )
812 case Qgis::TextHorizontalAlignment::Left:
813 case Qgis::TextHorizontalAlignment::Justify:
814 component.center = QPointF( component.origin.x() + width / 2.0,
815 component.origin.y() + height / 2.0 );
818 case Qgis::TextHorizontalAlignment::Center:
819 component.center = QPointF( component.origin.x() + component.size.width() / 2.0,
820 component.origin.y() + height / 2.0 );
823 case Qgis::TextHorizontalAlignment::Right:
824 component.center = QPointF( component.origin.x() + component.size.width() - width / 2.0,
825 component.origin.y() + height / 2.0 );
832 bool isNullSize =
false;
833 QFontMetricsF fm( format.
scaledFont( context, scaleFactor, &isNullSize ) );
834 double originAdjust = isNullSize ? 0 : ( fm.ascent() / scaleFactor / 2.0 - fm.leading() / scaleFactor / 2.0 );
835 switch ( component.hAlign )
837 case Qgis::TextHorizontalAlignment::Left:
838 case Qgis::TextHorizontalAlignment::Justify:
839 component.center = QPointF( component.origin.x() + width / 2.0,
840 component.origin.y() - height / 2.0 + originAdjust );
843 case Qgis::TextHorizontalAlignment::Center:
844 component.center = QPointF( component.origin.x(),
845 component.origin.y() - height / 2.0 + originAdjust );
848 case Qgis::TextHorizontalAlignment::Right:
849 component.center = QPointF( component.origin.x() - width / 2.0,
850 component.origin.y() - height / 2.0 + originAdjust );
857 const double dx = component.center.x() - component.origin.x();
858 const double dy = component.center.y() - component.origin.y();
859 component.center.setX( component.origin.x() + ( std::cos( originAdjustRotationRadians ) * dx - std::sin( originAdjustRotationRadians ) * dy ) );
860 component.center.setY( component.origin.y() + ( std::sin( originAdjustRotationRadians ) * dx + std::cos( originAdjustRotationRadians ) * dy ) );
865 case Qgis::TextLayoutMode::Labeling:
870 component.size = QSizeF( width, height );
875 switch ( background.
type() )
888 double sizeOut = 0.0;
896 sizeOut = std::max( component.size.width(), component.size.height() );
900 sizeOut += bufferSize * 2;
908 std::unique_ptr< QgsMarkerSymbol > renderedSymbol;
912 map[QStringLiteral(
"name" )] = background.
svgFile().trimmed();
913 map[QStringLiteral(
"size" )] = QString::number( sizeOut );
915 map[QStringLiteral(
"angle" )] = QString::number( 0.0 );
923 map[QStringLiteral(
"fill" )] = background.
fillColor().name();
924 map[QStringLiteral(
"outline" )] = background.
strokeColor().name();
925 map[QStringLiteral(
"outline-width" )] = QString::number( background.
strokeWidth() );
932 QVariantMap shdwmap( map );
933 shdwmap[QStringLiteral(
"fill" )] = shadow.
color().name();
934 shdwmap[QStringLiteral(
"outline" )] = shadow.
color().name();
935 shdwmap[QStringLiteral(
"size" )] = QString::number( sizeOut );
940 svgp.begin( &svgPict );
957 svgShdwM->
renderPoint( QPointF( sizeOut / 2, -sizeOut / 2 ), svgShdwContext );
960 component.picture = svgPict;
962 component.pictureBuffer = 0.0;
964 component.size = QSizeF( sizeOut, sizeOut );
965 component.offset = QPointF( 0.0, 0.0 );
971 p->translate( component.center.x(), component.center.y() );
972 p->rotate( component.rotation );
975 p->translate( QPointF( xoff, yoff ) );
976 p->rotate( component.rotationOffset );
977 p->translate( -sizeOut / 2, sizeOut / 2 );
979 drawShadow( context, component, format );
981 renderedSymbol.reset( );
989 renderedSymbol->setSize( sizeOut );
993 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1001 p->setCompositionMode( background.
blendMode() );
1003 p->translate( component.center.x(), component.center.y() );
1004 p->rotate( component.rotation );
1007 p->translate( QPointF( xoff, yoff ) );
1008 p->rotate( component.rotationOffset );
1012 renderedSymbol->renderPoint( QPointF( 0, 0 ), &f, context );
1013 renderedSymbol->stopRender( context );
1014 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1024 double w = component.size.width();
1025 double h = component.size.height();
1046 h = std::sqrt( std::pow( w, 2 ) + std::pow( h, 2 ) );
1052 h = h * M_SQRT1_2 * 2;
1053 w = w * M_SQRT1_2 * 2;
1061 w += bufferWidth * 2;
1062 h += bufferHeight * 2;
1066 QRectF rect( -w / 2.0, - h / 2.0, w, h );
1068 if ( rect.isNull() )
1074 p->translate( QPointF( component.center.x(), component.center.y() ) );
1075 p->rotate( component.rotation );
1078 p->translate( QPointF( xoff, yoff ) );
1079 p->rotate( component.rotationOffset );
1085 QTransform t = QTransform::fromScale( 10, 10 );
1087 QTransform ti = t.inverted();
1094 path.addRoundedRect( rect, background.
radii().width(), background.
radii().height(), Qt::RelativeSize );
1100 path.addRoundedRect( rect, xRadius, yRadius );
1106 path.addEllipse( rect );
1108 QPolygonF tempPolygon = path.toFillPolygon( t );
1109 QPolygonF polygon = ti.map( tempPolygon );
1111 QPainter *oldp = context.
painter();
1114 shapep.begin( &shapePict );
1117 std::unique_ptr< QgsFillSymbol > renderedSymbol;
1119 renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
1123 renderedSymbol->renderPolygon( polygon,
nullptr, &f, context );
1124 renderedSymbol->stopRender( context );
1131 component.picture = shapePict;
1134 component.size = rect.size();
1135 component.offset = QPointF( rect.width() / 2, -rect.height() / 2 );
1136 drawShadow( context, component, format );
1141 p->setCompositionMode( background.
blendMode() );
1145 p->scale( component.dpiRatio, component.dpiRatio );
1146 _fixQPictureDPI( p );
1147 p->drawPicture( 0, 0, shapePict );
1148 p->setCompositionMode( QPainter::CompositionMode_SourceOver );
1155 tmpEffect->end( context );
1168 QPainter *p = context.
painter();
1169 const double componentWidth = component.size.width();
1170 const double componentHeight = component.size.height();
1171 double xOffset = component.offset.x(), yOffset = component.offset.y();
1172 double pictbuffer = component.pictureBuffer;
1181 radius /= ( mapUnits ? context.
scaleFactor() / component.dpiRatio : 1 );
1182 radius =
static_cast< int >( radius + 0.5 );
1186 double blurBufferClippingScale = 3.75;
1187 int blurbuffer = ( radius > 17 ? 16 : radius ) * blurBufferClippingScale;
1189 QImage blurImg( componentWidth + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1190 componentHeight + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
1191 QImage::Format_ARGB32_Premultiplied );
1195 int minBlurImgSize = 1;
1199 int maxBlurImgSize = 40000;
1200 if ( blurImg.isNull()
1201 || ( blurImg.width() < minBlurImgSize || blurImg.height() < minBlurImgSize )
1202 || ( blurImg.width() > maxBlurImgSize || blurImg.height() > maxBlurImgSize ) )
1205 blurImg.fill( QColor( Qt::transparent ).rgba() );
1207 if ( !pictp.begin( &blurImg ) )
1209 pictp.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
1210 QPointF imgOffset( blurbuffer + pictbuffer + xOffset,
1211 blurbuffer + pictbuffer + componentHeight + yOffset );
1213 pictp.drawPicture( imgOffset,
1214 component.picture );
1217 pictp.setCompositionMode( QPainter::CompositionMode_SourceIn );
1218 pictp.fillRect( blurImg.rect(), shadow.
color() );
1222 if ( shadow.
blurRadius() > 0.0 && radius > 0 )
1230 picti.begin( &blurImg );
1231 picti.setBrush( Qt::Dense7Pattern );
1232 QPen imgPen( QColor( 0, 0, 255, 255 ) );
1233 imgPen.setWidth( 1 );
1234 picti.setPen( imgPen );
1235 picti.setOpacity( 0.1 );
1236 picti.drawRect( 0, 0, blurImg.width(), blurImg.height() );
1243 double angleRad = shadow.
offsetAngle() * M_PI / 180;
1251 angleRad -= ( component.rotation * M_PI / 180 + component.rotationOffset * M_PI / 180 );
1254 QPointF transPt( -offsetDist * std::cos( angleRad + M_PI_2 ),
1255 -offsetDist * std::sin( angleRad + M_PI_2 ) );
1261 p->setRenderHint( QPainter::SmoothPixmapTransform );
1264 p->setCompositionMode( shadow.
blendMode() );
1266 p->setOpacity( shadow.
opacity() );
1268 double scale = shadow.
scale() / 100.0;
1270 p->scale( scale, scale );
1271 if ( component.useOrigin )
1273 p->translate( component.origin.x(), component.origin.y() );
1275 p->translate( transPt );
1276 p->translate( -imgOffset.x(),
1278 p->drawImage( 0, 0, blurImg );
1285 p->setBrush( Qt::NoBrush );
1286 QPen imgPen( QColor( 255, 0, 0, 10 ) );
1287 imgPen.setWidth( 2 );
1288 imgPen.setStyle( Qt::DashLine );
1289 p->setPen( imgPen );
1290 p->scale( scale, scale );
1291 if ( component.useOrigin() )
1293 p->translate( component.origin().x(), component.origin().y() );
1295 p->translate( transPt );
1296 p->translate( -imgOffset.x(),
1298 p->drawRect( 0, 0, blurImg.width(), blurImg.height() );
1303 p->setBrush( Qt::NoBrush );
1304 QPen componentRectPen( QColor( 0, 255, 0, 70 ) );
1305 componentRectPen.setWidth( 1 );
1306 if ( component.useOrigin() )
1308 p->translate( component.origin().x(), component.origin().y() );
1310 p->setPen( componentRectPen );
1311 p->drawRect( QRect( -xOffset, -componentHeight - yOffset, componentWidth, componentHeight ) );
1320 const Component &component,
1330 const double fontScale = calculateScaleFactorForFormat( context, format );
1332 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1333 if ( mode == Qgis::TextLayoutMode::Labeling )
1340 bool isNullSize =
false;
1341 format.
scaledFont( context, fontScale, &isNullSize );
1345 referenceScaleOverride.reset();
1347 double rotation = 0;
1348 const Qgis::TextOrientation orientation = calculateRotationAndOrientationForComponent( format, component, rotation );
1349 switch ( orientation )
1351 case Qgis::TextOrientation::Horizontal:
1353 drawTextInternalHorizontal( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
1357 case Qgis::TextOrientation::Vertical:
1358 case Qgis::TextOrientation::RotationBased:
1360 drawTextInternalVertical( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
1366Qgis::TextOrientation QgsTextRenderer::calculateRotationAndOrientationForComponent(
const QgsTextFormat &format,
const QgsTextRenderer::Component &component,
double &rotation )
1368 rotation = -component.rotation * 180 / M_PI;
1372 case Qgis::TextOrientation::RotationBased:
1375 if ( rotation >= -315 && rotation < -90 )
1378 return Qgis::TextOrientation::Vertical;
1380 else if ( rotation >= -90 && rotation < -45 )
1383 return Qgis::TextOrientation::Vertical;
1386 return Qgis::TextOrientation::Horizontal;
1389 case Qgis::TextOrientation::Horizontal:
1390 case Qgis::TextOrientation::Vertical:
1393 return Qgis::TextOrientation::Horizontal;
1396void QgsTextRenderer::calculateExtraSpacingForLineJustification(
const double spaceToDistribute,
const QgsTextBlock &block,
double &extraWordSpace,
double &extraLetterSpace )
1399 QTextBoundaryFinder
finder( QTextBoundaryFinder::Word, blockText );
1401 int wordBoundaries = 0;
1402 while (
finder.toNextBoundary() != -1 )
1404 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1408 if ( wordBoundaries > 0 )
1411 extraWordSpace = spaceToDistribute / wordBoundaries;
1416 QTextBoundaryFinder
finder( QTextBoundaryFinder::Grapheme, blockText );
1419 int graphemeBoundaries = 0;
1420 while (
finder.toNextBoundary() != -1 )
1422 if (
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
1423 graphemeBoundaries++;
1426 if ( graphemeBoundaries > 0 )
1428 extraLetterSpace = spaceToDistribute / graphemeBoundaries;
1433void QgsTextRenderer::applyExtraSpacingForLineJustification( QFont &font,
double extraWordSpace,
double extraLetterSpace )
1435 const double prevWordSpace = font.wordSpacing();
1436 font.setWordSpacing( prevWordSpace + extraWordSpace );
1437 const double prevLetterSpace = font.letterSpacing();
1438 font.setLetterSpacing( QFont::AbsoluteSpacing, prevLetterSpace + extraLetterSpace );
1445 const QStringList textLines = document.
toPlainText();
1447 const QSizeF documentSize = metrics.
documentSize( mode, Qgis::TextOrientation::Horizontal );
1449 double labelWidest = 0.0;
1452 case Qgis::TextLayoutMode::Labeling:
1454 labelWidest = documentSize.width();
1457 case Qgis::TextLayoutMode::Rectangle:
1458 labelWidest = component.size.width();
1462 double verticalAlignOffset = 0;
1464 bool adjustForAlignment = hAlignment != Qgis::TextHorizontalAlignment::Left && ( mode != Qgis::TextLayoutMode::Labeling || textLines.size() > 1 );
1466 if ( mode == Qgis::TextLayoutMode::Rectangle && vAlignment != Qgis::TextVerticalAlignment::Top )
1468 const double overallHeight = documentSize.height();
1469 switch ( vAlignment )
1471 case Qgis::TextVerticalAlignment::Top:
1474 case Qgis::TextVerticalAlignment::VerticalCenter:
1475 verticalAlignOffset = ( component.size.height() - overallHeight ) * 0.5;
1478 case Qgis::TextVerticalAlignment::Bottom:
1479 verticalAlignOffset = ( component.size.height() - overallHeight );
1487 const bool isFinalLineInParagraph = ( blockIndex == document.size() - 1 )
1488 || document.at( blockIndex + 1 ).toPlainText().trimmed().isEmpty();
1490 const double blockHeight = metrics.
blockHeight( blockIndex );
1494 context.
painter()->translate( component.origin );
1496 context.
painter()->rotate( rotation );
1501 maskPainter->save();
1502 maskPainter->translate( component.origin );
1504 maskPainter->rotate( rotation );
1508 double xMultiLineOffset = 0.0;
1509 double blockWidth = metrics.
blockWidth( blockIndex );
1510 double extraWordSpace = 0;
1511 double extraLetterSpace = 0;
1512 if ( adjustForAlignment )
1514 double labelWidthDiff = 0;
1515 switch ( hAlignment )
1517 case Qgis::TextHorizontalAlignment::Center:
1518 labelWidthDiff = ( labelWidest - blockWidth ) * 0.5;
1521 case Qgis::TextHorizontalAlignment::Right:
1522 labelWidthDiff = labelWidest - blockWidth;
1525 case Qgis::TextHorizontalAlignment::Justify:
1526 if ( !isFinalLineInParagraph && labelWidest > blockWidth )
1528 calculateExtraSpacingForLineJustification( labelWidest - blockWidth, block, extraWordSpace, extraLetterSpace );
1529 blockWidth = labelWidest;
1533 case Qgis::TextHorizontalAlignment::Left:
1539 case Qgis::TextLayoutMode::Labeling:
1540 case Qgis::TextLayoutMode::Rectangle:
1541 xMultiLineOffset = labelWidthDiff;
1546 switch ( hAlignment )
1548 case Qgis::TextHorizontalAlignment::Right:
1549 xMultiLineOffset = labelWidthDiff - labelWidest;
1552 case Qgis::TextHorizontalAlignment::Center:
1553 xMultiLineOffset = labelWidthDiff - labelWidest / 2.0;
1556 case Qgis::TextHorizontalAlignment::Left:
1557 case Qgis::TextHorizontalAlignment::Justify:
1565 const double baseLineOffset = metrics.
baselineOffset( blockIndex, mode );
1567 context.
painter()->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
1569 maskPainter->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
1571 Component subComponent;
1572 subComponent.block = block;
1573 subComponent.blockIndex = blockIndex;
1574 subComponent.
size = QSizeF( blockWidth, blockHeight );
1575 subComponent.offset = QPointF( 0.0, -metrics.
ascentOffset() );
1576 subComponent.rotation = -component.rotation * 180 / M_PI;
1577 subComponent.rotationOffset = 0.0;
1578 subComponent.extraWordSpacing = extraWordSpace * fontScale;
1579 subComponent.extraLetterSpacing = extraLetterSpace * fontScale;
1584 QgsTextRenderer::drawMask( context, subComponent, format, mode );
1589 QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
1596 textp.begin( &textPict );
1597 textp.setPen( Qt::NoPen );
1599 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1600 if ( mode == Qgis::TextLayoutMode::Labeling )
1606 bool isNullSize =
false;
1607 const QFont font = format.
scaledFont( context, fontScale, &isNullSize );
1608 referenceScaleOverride.reset();
1612 textp.scale( 1 / fontScale, 1 / fontScale );
1619 path.setFillRule( Qt::WindingFill );
1621 QFont fragmentFont = font;
1624 if ( extraWordSpace || extraLetterSpace )
1625 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1627 path.addText( xOffset, 0, fragmentFont, fragment.
text() );
1631 textp.setBrush( textColor );
1632 textp.drawPath( path );
1634 xOffset += fragment.
horizontalAdvance( fragmentFont, context,
true, fontScale );
1641 subComponent.picture = textPict;
1642 subComponent.pictureBuffer = 0.0;
1643 subComponent.origin = QPointF( 0.0, 0.0 );
1645 QgsTextRenderer::drawShadow( context, subComponent, format );
1655 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
1659 case Qgis::TextRenderFormat::AlwaysOutlines:
1662 _fixQPictureDPI( context.
painter() );
1663 context.
painter()->drawPicture( 0, 0, textPict );
1667 case Qgis::TextRenderFormat::AlwaysText:
1672 QFont fragmentFont = font;
1675 if ( extraWordSpace || extraLetterSpace )
1676 applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
1681 context.
painter()->setPen( textColor );
1682 context.
painter()->setFont( fragmentFont );
1683 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
1685 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
1686 context.
painter()->drawText( xOffset, 0, fragment.
text() );
1687 context.
painter()->scale( fontScale, fontScale );
1689 xOffset += fragment.
horizontalAdvance( fragmentFont, context,
true, fontScale );
1695 maskPainter->restore();
1701void 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 )
1704 const QStringList textLines = document.
toPlainText();
1706 std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
1707 if ( mode == Qgis::TextLayoutMode::Labeling )
1714 bool isNullSize =
false;
1715 const QFont font = format.
scaledFont( context, fontScale, &isNullSize );
1719 referenceScaleOverride.reset();
1721 const QSizeF documentSize = metrics.
documentSize( mode, Qgis::TextOrientation::Vertical );
1722 const double actualTextWidth = documentSize.width();
1723 double textRectWidth = 0.0;
1727 case Qgis::TextLayoutMode::Labeling:
1729 textRectWidth = actualTextWidth;
1732 case Qgis::TextLayoutMode::Rectangle:
1733 textRectWidth = component.size.width();
1737 int maxLineLength = 0;
1738 for (
const QString &line : std::as_const( textLines ) )
1740 maxLineLength = std::max( maxLineLength,
static_cast<int>( line.length() ) );
1743 const double actualLabelHeight = documentSize.height();
1746 bool adjustForAlignment = hAlignment != Qgis::TextHorizontalAlignment::Left && ( mode != Qgis::TextLayoutMode::Labeling || textLines.size() > 1 );
1753 context.
painter()->translate( component.origin );
1755 context.
painter()->rotate( rotation );
1760 maskPainter->save();
1761 maskPainter->translate( component.origin );
1763 maskPainter->rotate( rotation );
1770 if ( adjustForAlignment )
1772 double hAlignmentOffset = 0;
1773 switch ( hAlignment )
1775 case Qgis::TextHorizontalAlignment::Center:
1776 hAlignmentOffset = ( textRectWidth - actualTextWidth ) * 0.5;
1779 case Qgis::TextHorizontalAlignment::Right:
1780 hAlignmentOffset = textRectWidth - actualTextWidth;
1783 case Qgis::TextHorizontalAlignment::Left:
1784 case Qgis::TextHorizontalAlignment::Justify:
1790 case Qgis::TextLayoutMode::Labeling:
1791 case Qgis::TextLayoutMode::Rectangle:
1792 xOffset += hAlignmentOffset;
1800 double yOffset = 0.0;
1803 case Qgis::TextLayoutMode::Labeling:
1804 if ( format.
orientation() == Qgis::TextOrientation::RotationBased )
1806 if ( rotation >= -405 && rotation < -180 )
1810 else if ( rotation >= 0 && rotation < 45 )
1812 xOffset -= actualTextWidth;
1818 yOffset = -actualLabelHeight;
1823 yOffset = -actualLabelHeight;
1826 case Qgis::TextLayoutMode::Rectangle:
1831 context.
painter()->translate( QPointF( xOffset, yOffset ) );
1833 double currentBlockYOffset = 0;
1834 int fragmentIndex = 0;
1842 QFont fragmentFont( font );
1845 QFontMetricsF fragmentMetrics( fragmentFont );
1847 const double letterSpacing = fragmentFont.letterSpacing() / fontScale;
1848 const double labelHeight = fragmentMetrics.ascent() / fontScale + ( fragmentMetrics.ascent() / fontScale + letterSpacing ) * ( line.length() - 1 );
1850 Component subComponent;
1852 subComponent.blockIndex = blockIndex;
1853 subComponent.size = QSizeF( blockMaximumCharacterWidth, labelHeight + fragmentMetrics.descent() / fontScale );
1854 subComponent.offset = QPointF( 0.0, currentBlockYOffset );
1855 subComponent.rotation = -component.rotation * 180 / M_PI;
1856 subComponent.rotationOffset = 0.0;
1863 QgsTextRenderer::drawMask( context, subComponent, format );
1869 currentBlockYOffset += QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
1875 path.setFillRule( Qt::WindingFill );
1877 double partYOffset = 0.0;
1878 for (
const QString &part : parts )
1880 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
1881 partYOffset += fragmentMetrics.ascent() / fontScale;
1882 path.addText( partXOffset * fontScale, partYOffset * fontScale, fragmentFont, part );
1883 partYOffset += letterSpacing;
1889 textp.begin( &textPict );
1890 textp.setPen( Qt::NoPen );
1893 textp.setBrush( textColor );
1894 textp.scale( 1 / fontScale, 1 / fontScale );
1895 textp.drawPath( path );
1906 subComponent.picture = textPict;
1907 subComponent.pictureBuffer = 0.0;
1908 subComponent.origin = QPointF( 0.0, currentBlockYOffset );
1909 const double prevY = subComponent.offset.y();
1910 subComponent.offset = QPointF( 0, -subComponent.size.height() );
1911 subComponent.useOrigin =
true;
1912 QgsTextRenderer::drawShadow( context, subComponent, format );
1913 subComponent.useOrigin =
false;
1914 subComponent.offset = QPointF( 0, prevY );
1924 context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
1928 case Qgis::TextRenderFormat::AlwaysOutlines:
1931 context.
painter()->translate( 0, currentBlockYOffset );
1932 _fixQPictureDPI( context.
painter() );
1933 context.
painter()->drawPicture( 0, 0, textPict );
1934 currentBlockYOffset += partYOffset;
1938 case Qgis::TextRenderFormat::AlwaysText:
1940 context.
painter()->setFont( fragmentFont );
1941 context.
painter()->setPen( textColor );
1942 context.
painter()->setRenderHint( QPainter::TextAntialiasing );
1944 double partYOffset = 0.0;
1945 for (
const QString &part : parts )
1947 double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
1948 context.
painter()->scale( 1 / fontScale, 1 / fontScale );
1949 context.
painter()->drawText( partXOffset * fontScale, ( currentBlockYOffset + partYOffset ) * fontScale, part );
1950 context.
painter()->scale( fontScale, fontScale );
1951 partYOffset += fragmentMetrics.ascent() / fontScale + letterSpacing;
1953 currentBlockYOffset += partYOffset;
1961 maskPainter->restore();
1976 if ( pixelSize < 50 )
1980 else if ( pixelSize > 200 )
1981 return 200 / pixelSize;
TextLayoutMode
Text layout modes.
@ Point
Text at point of origin layout mode.
TextOrientation
Text orientations.
@ ApplyScalingWorkaroundForTextRendering
Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters ...
TextVerticalAlignment
Text vertical alignment.
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.
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 QStringList splitToGraphemes(const QString &text)
Splits a text string to a list of graphemes, which are the smallest allowable character divisions in ...
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
bool useAdvancedEffects() const
Returns true if advanced effects such as blend modes such be used.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
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.
QgsUnitTypes::RenderUnit strokeWidthUnit() const
Returns the units used for the shape's stroke width.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the background shape.
@ SizeBuffer
Shape size is determined by adding a buffer margin around text.
bool enabled() const
Returns whether the background is enabled.
double opacity() const
Returns the background shape's opacity.
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shape's offset.
double rotation() const
Returns the rotation for the background shape, in degrees clockwise.
QColor fillColor() const
Returns the color used for filing the background shape.
SizeType sizeType() const
Returns the method used to determine the size of the background shape (e.g., fixed size or buffer aro...
ShapeType type() const
Returns the type of background shape (e.g., square, ellipse, SVG).
double strokeWidth() const
Returns the width of the shape's stroke (stroke).
@ ShapeMarkerSymbol
Marker symbol.
@ ShapeSquare
Square - buffered sizes only.
@ ShapeRectangle
Rectangle.
QColor strokeColor() const
Returns the color used for outlining the background shape.
QgsFillSymbol * fillSymbol() const
Returns the fill symbol to be rendered in the background.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the shape size.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units used for the shape's size.
@ RotationOffset
Shape rotation is offset from text rotation.
@ RotationFixed
Shape rotation is a fixed angle.
QgsUnitTypes::RenderUnit radiiUnit() const
Returns the units used for the shape's radii.
QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol to be rendered in the background.
const QgsPaintEffect * paintEffect() const
Returns the current paint effect for the background shape.
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shape offset.
QPointF offset() const
Returns the offset used for drawing the background shape.
Represents a block of text consisting of one or more QgsTextFragment objects.
int size() const
Returns the number of fragments in the block.
QString toPlainText() const
Converts the block to plain text.
Container for settings relating to a text buffer.
Qt::PenJoinStyle joinStyle() const
Returns the buffer join style.
double size() const
Returns the size of the buffer.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
bool enabled() const
Returns whether the buffer is enabled.
double opacity() const
Returns the buffer opacity.
bool fillBufferInterior() const
Returns whether the interior of the buffer will be filled in.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
const QgsPaintEffect * paintEffect() const
Returns the current paint effect for the buffer.
QColor color() const
Returns the color of the buffer.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the buffer.
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 ...
QColor textColor() const
Returns the character's text color, or an invalid color if no color override is set and the default f...
Contains pre-calculated metrics of a QgsTextDocument.
double verticalOrientationXOffset(int blockIndex) const
Returns the vertical orientation x offset for the specified block.
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.
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 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.
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 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.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the size of rendered text.
void updateDataDefinedProperties(QgsRenderContext &context)
Updates the format by evaluating current values of data defined properties.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the format's property collection, used for data defined overrides.
QFont scaledFont(const QgsRenderContext &context, double scaleFactor=1.0, bool *isZeroSize=nullptr) const
Returns a font with the size scaled to match the format's size settings (including units and map unit...
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the text.
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.
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.
QString text() const
Returns the text content of the fragment.
const QgsTextCharacterFormat & characterFormat() const
Returns the character formatting for the fragment.
double horizontalAdvance(const QFont &font, const QgsRenderContext &context, bool fontHasBeenUpdatedForFragment=false, double scaleFactor=1.0) const
Returns the horizontal advance associated with this fragment, when rendered using the specified base ...
Container for settings relating to a selective masking around a text.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
double size() const
Returns the size of the buffer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the mask.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
double opacity() const
Returns the mask's opacity.
bool enabled() const
Returns whether the mask is enabled.
Qt::PenJoinStyle joinStyle() const
Returns the buffer join style.
static 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 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 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 int sizeToPixel(double size, const QgsRenderContext &c, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
Calculates pixel size (considering output size should be in pixel or map units, scale factors and opt...
static 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 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())
Draws text within a rectangle using the specified settings.
static constexpr double FONT_WORKAROUND_SCALE
Scale factor for upscaling font sizes and downscaling destination painter devices.
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).
void setShadowPlacement(QgsTextShadowSettings::ShadowPlacement placement)
Sets the placement for the drop shadow.
double opacity() const
Returns the shadow's opacity.
QgsMapUnitScale blurRadiusMapUnitScale() const
Returns the map unit scale object for the shadow blur radius.
QColor color() const
Returns the color of the drop shadow.
@ ShadowBuffer
Draw shadow under buffer.
@ ShadowShape
Draw shadow under background shape.
@ ShadowLowest
Draw shadow below all text components.
@ ShadowText
Draw shadow under text.
QgsTextShadowSettings::ShadowPlacement shadowPlacement() const
Returns the placement for the drop shadow.
double offsetDistance() const
Returns the distance for offsetting the position of the shadow from the text.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the drop shadow.
QgsMapUnitScale offsetMapUnitScale() const
Returns the map unit scale object for the shadow offset distance.
QgsUnitTypes::RenderUnit blurRadiusUnit() const
Returns the units used for the shadow's blur radius.
bool blurAlphaOnly() const
Returns whether only the alpha channel for the shadow will be blurred.
bool offsetGlobal() const
Returns true if the global shadow offset will be used.
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shadow's offset.
double blurRadius() const
Returns the blur radius for the shadow.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
RenderUnit
Rendering size units.
@ RenderUnknownUnit
Mixed or unknown units.
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
@ RenderMapUnits
Map units.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QList< QgsSymbolLayer * > QgsSymbolLayerList
Q_GUI_EXPORT int qt_defaultDpiX()
Q_GUI_EXPORT int qt_defaultDpiY()