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 ); 
 
 
   92  drawDocument( rect, lFormat, metrics.
document(), metrics, context, alignment, vAlignment, rotation, mode, flags );
 
 
   97  const QgsTextFormat tmpFormat = updateShadowPosition( format );
 
 
  117  lFormat = updateShadowPosition( lFormat );
 
 
  147  lFormat = updateShadowPosition( lFormat );
 
  154  drawDocumentOnLine( line, lFormat, document, context, offsetAlongLine, offsetFromLine );
 
 
  159  QPolygonF labelBaselineCurve = line;
 
  168#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<11 
  169    if ( offsetFromLine < 0 )
 
  172      std::unique_ptr < QgsLineString > reversed( offsetCurve->reversed() );
 
  176      offsetCurve = std::move( reversed );
 
  180    labelBaselineCurve = offsetCurve->asQPolygonF();
 
  185  const QFont baseFont = format.
scaledFont( context, fontScale );
 
  186  const double letterSpacing = baseFont.letterSpacing() / fontScale;
 
  187  const double wordSpacing = baseFont.wordSpacing() / fontScale;
 
  189  QStringList graphemes;
 
  190  QVector< QgsTextCharacterFormat > graphemeFormats;
 
  191  QVector< QgsTextDocumentMetrics > graphemeMetrics;
 
  193  for ( 
const QgsTextBlock &block : std::as_const( document ) )
 
  198      for ( 
const QString &grapheme : fragmentGraphemes )
 
  200        graphemes.append( grapheme );
 
  201        graphemeFormats.append( fragment.characterFormat() );
 
  211  QVector< double > characterWidths( graphemes.count() );
 
  212  QVector< double > characterHeights( graphemes.count() );
 
  213  QVector< double > characterDescents( graphemes.count() );
 
  214  QFont previousNonSuperSubScriptFont;
 
  216  for ( 
int i = 0; i < graphemes.count(); i++ )
 
  221    double graphemeFirstCharHorizontalAdvanceWithLetterSpacing = 0;
 
  222    double graphemeFirstCharHorizontalAdvance = 0;
 
  223    double graphemeHorizontalAdvance = 0;
 
  224    double characterDescent = 0;
 
  225    double characterHeight = 0;
 
  228    QFont graphemeFont = baseFont;
 
  232      previousNonSuperSubScriptFont = graphemeFont;
 
  239          previousNonSuperSubScriptFont = graphemeFont;
 
  260      previousNonSuperSubScriptFont = graphemeFont;
 
  263    const QFontMetricsF graphemeFontMetrics( graphemeFont );
 
  264    graphemeFirstCharHorizontalAdvance = graphemeFontMetrics.horizontalAdvance( QString( graphemes[i].at( 0 ) ) ) / fontScale;
 
  265    graphemeFirstCharHorizontalAdvanceWithLetterSpacing = graphemeFontMetrics.horizontalAdvance( graphemes[i].at( 0 ) )  / fontScale + letterSpacing;
 
  266    graphemeHorizontalAdvance = graphemeFontMetrics.horizontalAdvance( QString( graphemes[i] ) )  / fontScale;
 
  267    characterDescent = graphemeFontMetrics.descent() / fontScale;
 
  268    characterHeight = graphemeFontMetrics.height() / fontScale;
 
  270    qreal wordSpaceFix = qreal( 0.0 );
 
  271    if ( graphemes[i] == QLatin1String( 
" " ) )
 
  275      wordSpaceFix = ( nxt < graphemes.count() && graphemes[nxt] != QLatin1String( 
" " ) ) ? wordSpacing : qreal( 0.0 );
 
  280    if ( graphemes[i].length() == 1 &&
 
  281         !
qgsDoubleNear( graphemeFirstCharHorizontalAdvance, graphemeFirstCharHorizontalAdvanceWithLetterSpacing ) )
 
  284      wordSpaceFix -= wordSpacing;
 
  287    const double charWidth = graphemeHorizontalAdvance + wordSpaceFix;
 
  288    characterWidths[i] = charWidth;
 
  289    characterHeights[i] = characterHeight;
 
  290    characterDescents[i] = characterDescent;
 
  293  QgsPrecalculatedTextMetrics metrics( graphemes, std::move( characterWidths ), std::move( characterHeights ), std::move( characterDescents ) );
 
  297        metrics, labelBaselineCurve, offsetAlongLine,
 
  304  if ( placement->graphemePlacement.empty() )
 
  307  std::vector< QgsTextRenderer::Component > components;
 
  308  components.reserve( placement->graphemePlacement.size() );
 
  311    QgsTextRenderer::Component component;
 
  312    component.origin = QPointF( grapheme.x, grapheme.y );
 
  313    component.rotation = -grapheme.angle;
 
  319      component.origin.rx() += verticalOffset * std::cos( grapheme.angle + M_PI_2 );
 
  320      component.origin.ry() += verticalOffset * std::sin( grapheme.angle + M_PI_2 );
 
  323    components.emplace_back( component );
 
  331      const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
 
  341      const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
 
  358    const QgsTextRenderer::Component &component = components[grapheme.graphemeIndex ];
 
 
  411  component.dpiRatio = 1.0;
 
  412  component.origin = rect.topLeft();
 
  413  component.rotation = rotation;
 
  414  component.size = rect.size();
 
  415  component.hAlign = alignment;
 
  428        double xc = rect.width() / 2.0;
 
  429        double yc = rect.height() / 2.0;
 
  431        double angle = -rotation;
 
  432        double xd = xc * std::cos( angle ) - yc * std::sin( angle );
 
  433        double yd = xc * std::sin( angle ) + yc * std::cos( angle );
 
  435        component.center = QPointF( component.origin.x() + xd, component.origin.y() + yd );
 
  439        component.center = rect.center();
 
  442      switch ( vAlignment )
 
  468      drawTextInternal( part, context, format, component,
 
  470                        alignment, vAlignment, mode );
 
  493  component.dpiRatio = 1.0;
 
  494  component.origin = origin;
 
  495  component.rotation = rotation;
 
  496  component.hAlign = alignment;
 
  505      QgsTextRenderer::drawBackground( context, component, format, metrics, mode );
 
  518      drawTextInternal( part, context, format, component,
 
  530  return QFontMetricsF( format.
scaledFont( context, scaleFactor ), context.
painter() ? context.
painter()->device() : nullptr );
 
 
  537  QPainter *p = context.
painter();
 
  542    if ( component.rotation >= -315 && component.rotation < -90 )
 
  546    else if ( component.rotation >= -90 && component.rotation < -45 )
 
  564  std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
 
  575  referenceScaleOverride.reset();
 
  578  path.setFillRule( Qt::WindingFill );
 
  580  double height = component.size.height();
 
  581  switch ( orientation )
 
  586      int fragmentIndex = 0;
 
  589        QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, fragmentIndex );
 
  591        if ( !fragment.isWhitespace() && !fragment.isImage() )
 
  593          if ( component.extraWordSpacing || component.extraLetterSpacing )
 
  594            applyExtraSpacingForLineJustification( fragmentFont, component.extraWordSpacing, component.extraLetterSpacing );
 
  597          path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
 
  611      double partYOffset = component.offset.y() * scaleFactor;
 
  614      double partLastDescent = 0;
 
  616      int fragmentIndex = 0;
 
  619        const QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, component.firstFragmentIndex + fragmentIndex );
 
  620        const double letterSpacing = fragmentFont.letterSpacing() / scaleFactor;
 
  622        const QFontMetricsF fragmentMetrics( fragmentFont );
 
  624        const double fragmentYOffset = metrics.
fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
 
  627        for ( 
const QString &part : parts )
 
  629          double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / scaleFactor - letterSpacing ) ) / 2;
 
  630          partYOffset += fragmentMetrics.ascent() / scaleFactor;
 
  631          path.addText( partXOffset, partYOffset + fragmentYOffset, fragmentFont, part );
 
  632          partYOffset += letterSpacing;
 
  634        partLastDescent = fragmentMetrics.descent() / scaleFactor;
 
  638      height = partYOffset + partLastDescent;
 
  639      advance = partYOffset - component.offset.y() * scaleFactor;
 
  644  QColor bufferColor = buffer.
color();
 
  645  bufferColor.setAlphaF( buffer.
opacity() );
 
  646  QPen pen( bufferColor );
 
  647  pen.setWidthF( penSize * scaleFactor );
 
  649  QColor tmpColor( bufferColor );
 
  653    tmpColor.setAlpha( 0 );
 
  659  buffp.begin( &buffPict );
 
  663    std::unique_ptr< QgsPaintEffect > tmpEffect( buffer.
paintEffect()->
clone() );
 
  665    tmpEffect->begin( context );
 
  666    context.
painter()->setPen( pen );
 
  667    context.
painter()->setBrush( tmpColor );
 
  668    if ( scaleFactor != 1.0 )
 
  669      context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
 
  670    context.
painter()->drawPath( path );
 
  671    if ( scaleFactor != 1.0 )
 
  672      context.
painter()->scale( scaleFactor, scaleFactor );
 
  673    tmpEffect->end( context );
 
  679    if ( scaleFactor != 1.0 )
 
  680      buffp.scale( 1 / scaleFactor, 1 / scaleFactor );
 
  682    buffp.setBrush( tmpColor );
 
  683    buffp.drawPath( path );
 
  689    QgsTextRenderer::Component bufferComponent = component;
 
  690    bufferComponent.origin = QPointF( 0.0, 0.0 );
 
  691    bufferComponent.picture = buffPict;
 
  692    bufferComponent.pictureBuffer = penSize / 2.0;
 
  693    bufferComponent.size.setHeight( height );
 
  697      bufferComponent.offset.setY( - bufferComponent.size.height() );
 
  699    drawShadow( context, bufferComponent, format );
 
  707    p->setCompositionMode( buffer.
blendMode() );
 
  711  p->scale( component.dpiRatio, component.dpiRatio );
 
  713  p->drawPicture( 0, 0, buffPict );
 
  715  return advance / scaleFactor;
 
  735  path.setFillRule( Qt::WindingFill );
 
  742  std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
 
  753  referenceScaleOverride.reset();
 
  756  int fragmentIndex = 0;
 
  759    if ( !fragment.isWhitespace() && !fragment.isImage() )
 
  761      const QFont fragmentFont = metrics.
fragmentFont( component.blockIndex, fragmentIndex );
 
  763      const double fragmentYOffset = metrics.
fragmentVerticalOffset( component.blockIndex, fragmentIndex, mode );
 
  764      path.addText( xOffset, fragmentYOffset, fragmentFont, fragment.text() );
 
  771  QColor bufferColor( Qt::gray );
 
  772  bufferColor.setAlphaF( mask.
opacity() );
 
  776  brush.setColor( bufferColor );
 
  777  pen.setColor( bufferColor );
 
  778  pen.setWidthF( penSize * scaleFactor );
 
  785  p->scale( component.dpiRatio, component.dpiRatio );
 
  791      if ( scaleFactor != 1.0 )
 
  792        context.
painter()->scale( 1 / scaleFactor, 1 / scaleFactor );
 
  793      context.
painter()->setPen( pen );
 
  794      context.
painter()->setBrush( brush );
 
  795      context.
painter()->drawPath( path );
 
  796      if ( scaleFactor != 1.0 )
 
  797        context.
painter()->scale( scaleFactor, scaleFactor );
 
  802    if ( scaleFactor != 1.0 )
 
  803      p->scale( 1 / scaleFactor, 1 / scaleFactor );
 
  805    p->setBrush( brush );
 
  807    if ( scaleFactor != 1.0 )
 
  808      p->scale( scaleFactor, scaleFactor );
 
  816  if ( doc.
size() == 0 )
 
  819  return textWidth( context, format, doc );
 
 
  836  for ( 
const QString &line : textLines )
 
  840      lines.append( 
wrappedText( context, line, maxLineWidth, format ) );
 
  844      lines.append( line );
 
  849  return textHeight( context, format, doc, mode );
 
 
  856  bool isNullSize = 
false;
 
  857  const QFont baseFont = format.
scaledFont( context, scaleFactor, &isNullSize );
 
  861  const QFontMetrics fm( baseFont );
 
  862  const double height = ( character.isNull() ? fm.height() : fm.boundingRect( character ).height() ) / scaleFactor;
 
  864  if ( !includeEffects )
 
  867  double maxExtension = 0;
 
  896  return height + maxExtension;
 
 
  904  const QStringList multiLineSplit = text.split( 
'\n' );
 
  906  return currentTextWidth > width;
 
 
  911  const QStringList lines = text.split( 
'\n' );
 
  912  QStringList outLines;
 
  913  for ( 
const QString &line : lines )
 
  918      const QStringList words = line.split( 
' ' );
 
  919      QStringList linesToProcess;
 
  920      QString wordsInCurrentLine;
 
  921      for ( 
const QString &word : words )
 
  926          if ( !wordsInCurrentLine.isEmpty() )
 
  927            linesToProcess << wordsInCurrentLine;
 
  928          wordsInCurrentLine.clear();
 
  929          linesToProcess << word;
 
  933          if ( !wordsInCurrentLine.isEmpty() )
 
  934            wordsInCurrentLine.append( 
' ' );
 
  935          wordsInCurrentLine.append( word );
 
  938      if ( !wordsInCurrentLine.isEmpty() )
 
  939        linesToProcess << wordsInCurrentLine;
 
  941      for ( 
const QString &line : std::as_const( linesToProcess ) )
 
  943        QString remainingText = line;
 
  944        int lastPos = remainingText.lastIndexOf( 
' ' );
 
  945        while ( lastPos > -1 )
 
  955            outLines << remainingText.left( lastPos );
 
  956            remainingText = remainingText.mid( lastPos + 1 );
 
  959          lastPos = remainingText.lastIndexOf( 
' ', lastPos - 1 );
 
  961        outLines << remainingText;
 
 
  992  QPainter *prevP = context.
painter();
 
  993  QPainter *p = context.
painter();
 
  994  std::unique_ptr< QgsPaintEffect > tmpEffect;
 
  998    tmpEffect->begin( context );
 
 1007  const double originAdjustRotationRadians = -component.rotation;
 
 1010    component.rotation = -( component.rotation * 180 / M_PI ); 
 
 1011    component.rotationOffset =
 
 1016    component.rotation = 0.0; 
 
 1017    component.rotationOffset = background.
rotation();
 
 1026    double width = documentSize.width();
 
 1027    double height = documentSize.height();
 
 1034        switch ( component.hAlign )
 
 1038            component.center = QPointF( component.origin.x() + width / 2.0,
 
 1039                                        component.origin.y() + height / 2.0 );
 
 1043            component.center = QPointF( component.origin.x() + component.size.width() / 2.0,
 
 1044                                        component.origin.y() + height / 2.0 );
 
 1048            component.center = QPointF( component.origin.x() + component.size.width() - width / 2.0,
 
 1049                                        component.origin.y() + height / 2.0 );
 
 1056        bool isNullSize = 
false;
 
 1057        QFontMetricsF fm( format.
scaledFont( context, scaleFactor, &isNullSize ) );
 
 1058        double originAdjust = isNullSize ? 0 : ( fm.ascent() / scaleFactor / 2.0 - fm.leading() / scaleFactor / 2.0 );
 
 1059        switch ( component.hAlign )
 
 1063            component.center = QPointF( component.origin.x() + width / 2.0,
 
 1064                                        component.origin.y() - height / 2.0 + originAdjust );
 
 1068            component.center = QPointF( component.origin.x(),
 
 1069                                        component.origin.y() - height / 2.0 + originAdjust );
 
 1073            component.center = QPointF( component.origin.x() - width / 2.0,
 
 1074                                        component.origin.y() - height / 2.0 + originAdjust );
 
 1081          const double dx = component.center.x() - component.origin.x();
 
 1082          const double dy = component.center.y() - component.origin.y();
 
 1083          component.center.setX( component.origin.x() + ( std::cos( originAdjustRotationRadians ) * dx - std::sin( originAdjustRotationRadians ) * dy ) );
 
 1084          component.center.setY( component.origin.y() + ( std::sin( originAdjustRotationRadians ) * dx + std::cos( originAdjustRotationRadians ) * dy ) );
 
 1094      component.size = QSizeF( width, height );
 
 1099  switch ( background.
type() )
 
 1112      double sizeOut = 0.0;
 
 1123          sizeOut = std::max( component.size.width(), component.size.height() );
 
 1127          sizeOut += bufferSize * 2;
 
 1133      if ( sizeOut < 1.0 )
 
 1136      std::unique_ptr< QgsMarkerSymbol > renderedSymbol;
 
 1140        map[QStringLiteral( 
"name" )] = background.
svgFile().trimmed();
 
 1141        map[QStringLiteral( 
"size" )] = QString::number( sizeOut );
 
 1143        map[QStringLiteral( 
"angle" )] = QString::number( 0.0 ); 
 
 1151        map[QStringLiteral( 
"fill" )] = background.
fillColor().name();
 
 1152        map[QStringLiteral( 
"outline" )] = background.
strokeColor().name();
 
 1153        map[QStringLiteral( 
"outline-width" )] = QString::number( background.
strokeWidth() );
 
 1160          QVariantMap shdwmap( map );
 
 1161          shdwmap[QStringLiteral( 
"fill" )] = shadow.
color().name();
 
 1162          shdwmap[QStringLiteral( 
"outline" )] = shadow.
color().name();
 
 1163          shdwmap[QStringLiteral( 
"size" )] = QString::number( sizeOut );
 
 1168          svgp.begin( &svgPict );
 
 1185          svgShdwM->
renderPoint( QPointF( sizeOut / 2, -sizeOut / 2 ), svgShdwContext );
 
 1188          component.picture = svgPict;
 
 1190          component.pictureBuffer = 0.0;
 
 1192          component.size = QSizeF( sizeOut, sizeOut );
 
 1193          component.offset = QPointF( 0.0, 0.0 );
 
 1199          p->translate( component.center.x(), component.center.y() );
 
 1200          p->rotate( component.rotation );
 
 1203          p->translate( QPointF( xoff, yoff ) );
 
 1204          p->rotate( component.rotationOffset );
 
 1205          p->translate( -sizeOut / 2, sizeOut / 2 );
 
 1207          drawShadow( context, component, format );
 
 1209        renderedSymbol.reset( );
 
 1217        renderedSymbol->setSize( sizeOut );
 
 1221      renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
 
 1229        p->setCompositionMode( background.
blendMode() );
 
 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 );
 
 1240      renderedSymbol->renderPoint( QPointF( 0, 0 ), &f, context );
 
 1241      renderedSymbol->stopRender( context );
 
 1242      p->setCompositionMode( QPainter::CompositionMode_SourceOver ); 
 
 1252      double w = component.size.width();
 
 1253      double h = component.size.height();
 
 1274          h = std::sqrt( std::pow( w, 2 ) + std::pow( h, 2 ) );
 
 1280          h = h * M_SQRT1_2 * 2;
 
 1281          w = w * M_SQRT1_2 * 2;
 
 1289        w += bufferWidth * 2;
 
 1290        h += bufferHeight * 2;
 
 1294      QRectF rect( -w / 2.0, - h / 2.0, w, h );
 
 1296      if ( rect.isNull() )
 
 1302      p->translate( QPointF( component.center.x(), component.center.y() ) );
 
 1303      p->rotate( component.rotation );
 
 1306      p->translate( QPointF( xoff, yoff ) );
 
 1307      p->rotate( component.rotationOffset );
 
 1313      QTransform t = QTransform::fromScale( 10, 10 );
 
 1315      QTransform ti = t.inverted();
 
 1322          path.addRoundedRect( rect, background.
radii().width(), background.
radii().height(), Qt::RelativeSize );
 
 1328          path.addRoundedRect( rect, xRadius, yRadius );
 
 1334        path.addEllipse( rect );
 
 1336      QPolygonF tempPolygon = path.toFillPolygon( t );
 
 1337      QPolygonF polygon = ti.map( tempPolygon );
 
 1339      QPainter *oldp = context.
painter();
 
 1342      shapep.begin( &shapePict );
 
 1345      std::unique_ptr< QgsFillSymbol > renderedSymbol;
 
 1347      renderedSymbol->setOpacity( renderedSymbol->opacity() * background.
opacity() );
 
 1351      renderedSymbol->renderPolygon( polygon, 
nullptr, &f, context );
 
 1352      renderedSymbol->stopRender( context );
 
 1359        component.picture = shapePict;
 
 1362        component.size = rect.size();
 
 1363        component.offset = QPointF( rect.width() / 2, -rect.height() / 2 );
 
 1364        drawShadow( context, component, format );
 
 1369        p->setCompositionMode( background.
blendMode() );
 
 1373      p->scale( component.dpiRatio, component.dpiRatio );
 
 1375      p->drawPicture( 0, 0, shapePict );
 
 1376      p->setCompositionMode( QPainter::CompositionMode_SourceOver ); 
 
 1383    tmpEffect->end( context );
 
 1396  QPainter *p = context.
painter();
 
 1397  const double componentWidth = component.size.width();
 
 1398  const double componentHeight = component.size.height();
 
 1399  double xOffset = component.offset.x(), yOffset = component.offset.y();
 
 1400  double pictbuffer = component.pictureBuffer;
 
 1409  radius /= ( mapUnits ? context.
scaleFactor() / component.dpiRatio : 1 );
 
 1410  radius = 
static_cast< int >( radius + 0.5 ); 
 
 1414  double blurBufferClippingScale = 3.75;
 
 1415  int blurbuffer = ( radius > 17 ? 16 : radius ) * blurBufferClippingScale;
 
 1417  QImage blurImg( componentWidth + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
 
 1418                  componentHeight + ( pictbuffer * 2.0 ) + ( blurbuffer * 2.0 ),
 
 1419                  QImage::Format_ARGB32_Premultiplied );
 
 1423  int minBlurImgSize = 1;
 
 1427  int maxBlurImgSize = 40000;
 
 1428  if ( blurImg.isNull()
 
 1429       || ( blurImg.width() < minBlurImgSize || blurImg.height() < minBlurImgSize )
 
 1430       || ( blurImg.width() > maxBlurImgSize || blurImg.height() > maxBlurImgSize ) )
 
 1433  blurImg.fill( QColor( Qt::transparent ).rgba() );
 
 1435  if ( !pictp.begin( &blurImg ) )
 
 1437  pictp.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
 
 1438  QPointF imgOffset( blurbuffer + pictbuffer + xOffset,
 
 1439                     blurbuffer + pictbuffer + componentHeight + yOffset );
 
 1441  pictp.drawPicture( imgOffset,
 
 1442                     component.picture );
 
 1445  pictp.setCompositionMode( QPainter::CompositionMode_SourceIn );
 
 1446  pictp.fillRect( blurImg.rect(), shadow.
color() );
 
 1450  if ( shadow.
blurRadius() > 0.0 && radius > 0 )
 
 1458  picti.begin( &blurImg );
 
 1459  picti.setBrush( Qt::Dense7Pattern );
 
 1460  QPen imgPen( QColor( 0, 0, 255, 255 ) );
 
 1461  imgPen.setWidth( 1 );
 
 1462  picti.setPen( imgPen );
 
 1463  picti.setOpacity( 0.1 );
 
 1464  picti.drawRect( 0, 0, blurImg.width(), blurImg.height() );
 
 1471  double angleRad = shadow.
offsetAngle() * M_PI / 180; 
 
 1479    angleRad -= ( component.rotation * M_PI / 180 + component.rotationOffset * M_PI / 180 );
 
 1482  QPointF transPt( -offsetDist * std::cos( angleRad + M_PI_2 ),
 
 1483                   -offsetDist * std::sin( angleRad + M_PI_2 ) );
 
 1489  p->setRenderHint( QPainter::SmoothPixmapTransform );
 
 1492    p->setCompositionMode( shadow.
blendMode() );
 
 1494  p->setOpacity( shadow.
opacity() );
 
 1496  double scale = shadow.
scale() / 100.0;
 
 1498  p->scale( scale, scale );
 
 1499  if ( component.useOrigin )
 
 1501    p->translate( component.origin.x(), component.origin.y() );
 
 1503  p->translate( transPt );
 
 1504  p->translate( -imgOffset.x(),
 
 1506  p->drawImage( 0, 0, blurImg );
 
 1513  p->setBrush( Qt::NoBrush );
 
 1514  QPen imgPen( QColor( 255, 0, 0, 10 ) );
 
 1515  imgPen.setWidth( 2 );
 
 1516  imgPen.setStyle( Qt::DashLine );
 
 1517  p->setPen( imgPen );
 
 1518  p->scale( scale, scale );
 
 1519  if ( component.useOrigin() )
 
 1521    p->translate( component.origin().x(), component.origin().y() );
 
 1523  p->translate( transPt );
 
 1524  p->translate( -imgOffset.x(),
 
 1526  p->drawRect( 0, 0, blurImg.width(), blurImg.height() );
 
 1531  p->setBrush( Qt::NoBrush );
 
 1532  QPen componentRectPen( QColor( 0, 255, 0, 70 ) );
 
 1533  componentRectPen.setWidth( 1 );
 
 1534  if ( component.useOrigin() )
 
 1536    p->translate( component.origin().x(), component.origin().y() );
 
 1538  p->setPen( componentRectPen );
 
 1539  p->drawRect( QRect( -xOffset, -componentHeight - yOffset, componentWidth, componentHeight ) );
 
 1548                                        const Component &component,
 
 1560  std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
 
 1571  referenceScaleOverride.reset();
 
 1573  double rotation = 0;
 
 1574  const Qgis::TextOrientation orientation = calculateRotationAndOrientationForComponent( format, component, rotation );
 
 1575  switch ( orientation )
 
 1579      drawTextInternalHorizontal( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
 
 1586      drawTextInternalVertical( context, format, drawType, mode, component, document, metrics, fontScale, alignment, vAlignment, rotation );
 
 1592Qgis::TextOrientation QgsTextRenderer::calculateRotationAndOrientationForComponent( 
const QgsTextFormat &format, 
const QgsTextRenderer::Component &component, 
double &rotation )
 
 1594  rotation = -component.rotation * 180 / M_PI;
 
 1601      if ( rotation >= -315 && rotation < -90 )
 
 1606      else if ( rotation >= -90 && rotation < -45 )
 
 1622void QgsTextRenderer::calculateExtraSpacingForLineJustification( 
const double spaceToDistribute, 
const QgsTextBlock &block, 
double &extraWordSpace, 
double &extraLetterSpace )
 
 1625  QTextBoundaryFinder 
finder( QTextBoundaryFinder::Word, blockText );
 
 1627  int wordBoundaries = 0;
 
 1628  while ( 
finder.toNextBoundary() != -1 )
 
 1630    if ( 
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
 
 1634  if ( wordBoundaries > 0 )
 
 1637    extraWordSpace = spaceToDistribute / wordBoundaries;
 
 1642    QTextBoundaryFinder 
finder( QTextBoundaryFinder::Grapheme, blockText );
 
 1645    int graphemeBoundaries = 0;
 
 1646    while ( 
finder.toNextBoundary() != -1 )
 
 1648      if ( 
finder.boundaryReasons() & QTextBoundaryFinder::StartOfItem )
 
 1649        graphemeBoundaries++;
 
 1652    if ( graphemeBoundaries > 0 )
 
 1654      extraLetterSpace = spaceToDistribute / graphemeBoundaries;
 
 1659void QgsTextRenderer::applyExtraSpacingForLineJustification( QFont &font, 
double extraWordSpace, 
double extraLetterSpace )
 
 1661  const double prevWordSpace = font.wordSpacing();
 
 1662  font.setWordSpacing( prevWordSpace + extraWordSpace );
 
 1663  const double prevLetterSpace = font.letterSpacing();
 
 1664  font.setLetterSpacing( QFont::AbsoluteSpacing, prevLetterSpace + extraLetterSpace );
 
 1668void QgsTextRenderer::renderBlockHorizontal( 
const QgsTextBlock &block, 
int blockIndex,
 
 1671    QPainter *painter, 
bool usePaths,
 
 1672    double fontScale, 
double extraWordSpace, 
double extraLetterSpace,
 
 1678    int fragmentIndex = 0;
 
 1682      if ( !fragment.isWhitespace() && !fragment.isImage() )
 
 1684        QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
 
 1687          applyExtraSpacingForLineJustification( fragmentFont, extraWordSpace * fontScale, extraLetterSpace * fontScale );
 
 1691        QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
 
 1692        textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.opacity() );
 
 1696          painter->setBrush( textColor );
 
 1698          path.setFillRule( Qt::WindingFill );
 
 1699          path.addText( xOffset, yOffset, fragmentFont, fragment.text() );
 
 1700          painter->drawPath( path );
 
 1704          painter->setPen( textColor );
 
 1705          painter->setFont( fragmentFont );
 
 1706          painter->drawText( QPointF( xOffset, yOffset ), fragment.text() );
 
 1709      else if ( fragment.isImage() )
 
 1711        bool fitsInCache = 
false;
 
 1713        const double imageHeight = metrics.
fragmentFixedHeight( blockIndex, fragmentIndex, mode ) * fontScale;
 
 1716                             QSize( 
static_cast< int >( std::round( imageWidth ) ),
 
 1717                                    static_cast< int >( std::round( imageHeight ) ) ),
 
 1721        const double yOffset = imageBaseline - image.height();
 
 1722        if ( !image.isNull() )
 
 1723          painter->drawImage( QPointF( xOffset, yOffset ), image );
 
 1754      if ( format.
font().underline()
 
 1755           || format.
font().overline()
 
 1756           || format.
font().strikeOut()
 
 1757           || std::any_of( document.begin(), document.end(), []( 
const QgsTextBlock & block )
 
 1759      return std::any_of( block.begin(), block.end(), []( const QgsTextFragment & fragment )
 
 1761        return fragment.characterFormat().underline() == QgsTextCharacterFormat::BooleanValue::SetTrue
 
 1762                 || fragment.characterFormat().overline() == QgsTextCharacterFormat::BooleanValue::SetTrue
 
 1763                 || fragment.characterFormat().strikeOut() == QgsTextCharacterFormat::BooleanValue::SetTrue;
 
 1777  const QStringList textLines = document.
toPlainText();
 
 1781  double labelWidest = 0.0;
 
 1786      labelWidest = documentSize.width();
 
 1792      labelWidest = component.size.width();
 
 1796  double verticalAlignOffset = 0;
 
 1800    const double overallHeight = documentSize.height();
 
 1801    switch ( vAlignment )
 
 1807        verticalAlignOffset = ( component.size.height() - overallHeight ) * 0.5;
 
 1811        verticalAlignOffset = ( component.size.height() - overallHeight );
 
 1817  const bool usePaths = usePathsToRender( context, format, document );
 
 1827                                      || textLines.size() > 1 );
 
 1829    const bool isFinalLineInParagraph = ( blockIndex == document.
size() - 1 )
 
 1830                                        || document.
at( blockIndex + 1 ).
toPlainText().trimmed().isEmpty();
 
 1832    const double blockHeight = metrics.
blockHeight( blockIndex );
 
 1836    context.
painter()->translate( component.origin );
 
 1838      context.
painter()->rotate( rotation );
 
 1843      maskPainter->save();
 
 1844      maskPainter->translate( component.origin );
 
 1846        maskPainter->rotate( rotation );
 
 1850    double xMultiLineOffset = 0.0;
 
 1851    double blockWidth = metrics.
blockWidth( blockIndex );
 
 1852    double extraWordSpace = 0;
 
 1853    double extraLetterSpace = 0;
 
 1854    if ( adjustForAlignment )
 
 1856      double labelWidthDiff = 0;
 
 1857      switch ( blockAlignment )
 
 1860          labelWidthDiff = ( labelWidest - blockWidth ) * 0.5;
 
 1864          labelWidthDiff = labelWidest - blockWidth;
 
 1868          if ( !isFinalLineInParagraph && labelWidest > blockWidth )
 
 1870            calculateExtraSpacingForLineJustification( labelWidest - blockWidth, block, extraWordSpace, extraLetterSpace );
 
 1871            blockWidth = labelWidest;
 
 1885          xMultiLineOffset = labelWidthDiff;
 
 1890          switch ( blockAlignment )
 
 1893              xMultiLineOffset = labelWidthDiff - labelWidest;
 
 1897              xMultiLineOffset = labelWidthDiff - labelWidest / 2.0;
 
 1909    const double baseLineOffset = metrics.
baselineOffset( blockIndex, mode );
 
 1911    context.
painter()->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
 
 1913      maskPainter->translate( QPointF( xMultiLineOffset, baseLineOffset + verticalAlignOffset ) );
 
 1915    Component subComponent;
 
 1916    subComponent.block = block;
 
 1917    subComponent.blockIndex = blockIndex;
 
 1918    subComponent.
size = QSizeF( blockWidth, blockHeight );
 
 1919    subComponent.offset = QPointF( 0.0, -metrics.
ascentOffset() );
 
 1920    subComponent.rotation = -component.rotation * 180 / M_PI;
 
 1921    subComponent.rotationOffset = 0.0;
 
 1922    subComponent.extraWordSpacing = extraWordSpace * fontScale;
 
 1923    subComponent.extraLetterSpacing = extraLetterSpace * fontScale;
 
 1928      QgsTextRenderer::drawMask( context, subComponent, format, metrics, mode );
 
 1933      QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
 
 1941      const bool requiresPicture = drawShadowOnText;
 
 1943      std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
 
 1951      referenceScaleOverride.reset();
 
 1953      std::unique_ptr< QPicture > textPicture;
 
 1954      if ( requiresPicture )
 
 1957        textPicture = std::make_unique< QPicture >();
 
 1958        QPainter picturePainter( textPicture.get() );
 
 1959        picturePainter.setPen( Qt::NoPen );
 
 1960        picturePainter.setBrush( Qt::NoBrush );
 
 1961        picturePainter.scale( 1 / fontScale, 1 / fontScale );
 
 1962        renderBlockHorizontal( block, blockIndex, metrics, context, format, &picturePainter, usePaths,
 
 1963                               fontScale, extraWordSpace, extraLetterSpace, mode );
 
 1964        picturePainter.end();
 
 1967      if ( drawShadowOnText )
 
 1969        subComponent.picture = *textPicture;
 
 1970        subComponent.pictureBuffer = 0.0; 
 
 1971        subComponent.origin = QPointF( 0.0, 0.0 );
 
 1973        QgsTextRenderer::drawShadow( context, subComponent, format );
 
 1983      context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
 
 1988        context.
painter()->drawPicture( 0, 0, *textPicture );
 
 1992        context.
painter()->scale( 1 / fontScale, 1 / fontScale );
 
 1993        context.
painter()->setPen( Qt::NoPen );
 
 1994        context.
painter()->setBrush( Qt::NoBrush );
 
 1995        renderBlockHorizontal( block, blockIndex, metrics, context, format, context.
painter(), usePaths,
 
 1996                               fontScale, extraWordSpace, extraLetterSpace, mode );
 
 2000      maskPainter->restore();
 
 2006void 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 )
 
 2009  const QStringList textLines = document.
toPlainText();
 
 2011  std::optional< QgsScopedRenderContextReferenceScaleOverride > referenceScaleOverride;
 
 2022  referenceScaleOverride.reset();
 
 2025  const double actualTextWidth = documentSize.width();
 
 2026  double textRectWidth = 0.0;
 
 2032      textRectWidth = actualTextWidth;
 
 2038      textRectWidth = component.size.width();
 
 2042  int maxLineLength = 0;
 
 2043  for ( 
const QString &line : std::as_const( textLines ) )
 
 2045    maxLineLength = std::max( maxLineLength, 
static_cast<int>( line.length() ) );
 
 2048  const double actualLabelHeight = documentSize.height();
 
 2058    context.
painter()->translate( component.origin );
 
 2060      context.
painter()->rotate( rotation );
 
 2065      maskPainter->save();
 
 2066      maskPainter->translate( component.origin );
 
 2068        maskPainter->rotate( rotation );
 
 2075    if ( adjustForAlignment )
 
 2077      double hAlignmentOffset = 0;
 
 2078      switch ( hAlignment )
 
 2081          hAlignmentOffset = ( textRectWidth - actualTextWidth ) * 0.5;
 
 2085          hAlignmentOffset = textRectWidth - actualTextWidth;
 
 2099          xOffset += hAlignmentOffset;
 
 2107    double yOffset = 0.0;
 
 2113          if ( rotation >= -405 && rotation < -180 )
 
 2117          else if ( rotation >= 0 && rotation < 45 )
 
 2119            xOffset -= actualTextWidth;
 
 2125          yOffset = -actualLabelHeight;
 
 2130        yOffset = -actualLabelHeight;
 
 2140    context.
painter()->translate( QPointF( xOffset, yOffset ) );
 
 2142    double currentBlockYOffset = 0;
 
 2143    int fragmentIndex = 0;
 
 2151      const QFont fragmentFont = metrics.
fragmentFont( blockIndex, fragmentIndex );
 
 2153      QFontMetricsF fragmentMetrics( fragmentFont );
 
 2155      const double letterSpacing = fragmentFont.letterSpacing() / fontScale;
 
 2156      const double labelHeight = fragmentMetrics.ascent() / fontScale + ( fragmentMetrics.ascent() / fontScale + letterSpacing ) * ( line.length() - 1 );
 
 2158      Component subComponent;
 
 2160      subComponent.blockIndex = blockIndex;
 
 2161      subComponent.firstFragmentIndex = fragmentIndex;
 
 2162      subComponent.size = QSizeF( blockMaximumCharacterWidth, labelHeight + fragmentMetrics.descent() / fontScale );
 
 2163      subComponent.offset = QPointF( 0.0, currentBlockYOffset );
 
 2164      subComponent.rotation = -component.rotation * 180 / M_PI;
 
 2165      subComponent.rotationOffset = 0.0;
 
 2172        QgsTextRenderer::drawMask( context, subComponent, format );
 
 2178        currentBlockYOffset += QgsTextRenderer::drawBuffer( context, subComponent, format, metrics, mode );
 
 2184        path.setFillRule( Qt::WindingFill );
 
 2186        double partYOffset = 0.0;
 
 2187        for ( 
const QString &part : parts )
 
 2189          double partXOffset = ( blockMaximumCharacterWidth - ( fragmentMetrics.horizontalAdvance( part ) / fontScale - letterSpacing ) ) / 2;
 
 2190          partYOffset += fragmentMetrics.ascent() / fontScale;
 
 2191          path.addText( partXOffset * fontScale, partYOffset * fontScale, fragmentFont, part );
 
 2192          partYOffset += letterSpacing;
 
 2198        textp.begin( &textPict );
 
 2199        textp.setPen( Qt::NoPen );
 
 2200        QColor textColor = fragment.characterFormat().textColor().isValid() ? fragment.characterFormat().textColor() : format.
color();
 
 2201        textColor.setAlphaF( fragment.characterFormat().textColor().isValid() ? textColor.alphaF() * format.
opacity() : format.
opacity() );
 
 2202        textp.setBrush( textColor );
 
 2203        textp.scale( 1 / fontScale, 1 / fontScale );
 
 2204        textp.drawPath( path );
 
 2215          subComponent.picture = textPict;
 
 2216          subComponent.pictureBuffer = 0.0; 
 
 2217          subComponent.origin = QPointF( 0.0, currentBlockYOffset );
 
 2218          const double prevY = subComponent.offset.y();
 
 2219          subComponent.offset = QPointF( 0, -subComponent.size.height() );
 
 2220          subComponent.useOrigin = 
true;
 
 2221          QgsTextRenderer::drawShadow( context, subComponent, format );
 
 2222          subComponent.useOrigin = 
false;
 
 2223          subComponent.offset = QPointF( 0, prevY );
 
 2233        context.
painter()->scale( subComponent.dpiRatio, subComponent.dpiRatio );
 
 2237        context.
painter()->translate( 0, currentBlockYOffset );
 
 2239        context.
painter()->drawPicture( 0, 0, textPict );
 
 2240        currentBlockYOffset += partYOffset;
 
 2246      maskPainter->restore();
 
 2264  if ( pixelSize < 50 )
 
 2265    return 200 / pixelSize;
 
 2268  else if ( pixelSize > 200 )
 
 2269    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.
 
@ PreferText
Render text as text objects, unless doing so results in rendering artifacts or poor quality rendering...
 
@ 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.
 
static QgsTextDocumentMetrics calculateMetrics(const QgsTextDocument &document, const QgsTextFormat &format, const QgsRenderContext &context, double scaleFactor=1.0, const QgsTextDocumentRenderContext &documentContext=QgsTextDocumentRenderContext())
Returns precalculated text metrics for a text document, when rendered using the given base format and...
 
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,...
 
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.
 
const QgsTextDocument & document() const
Returns the document associated with the calculated metrics.
 
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.
 
Encapsulates the context in which a text document is to be rendered.
 
void setFlags(Qgis::TextRendererFlags flags)
Sets associated text renderer flags.
 
void setMaximumWidth(double width)
Sets the maximum width (in painter units) for rendered text.
 
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.
 
void append(const QgsTextBlock &block)
Appends a block to the document.
 
static QgsTextDocument fromTextAndFormat(const QStringList &lines, const QgsTextFormat &format)
Constructor for QgsTextDocument consisting of a set of lines, respecting settings from a text format.
 
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.
 
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.
 
QFont font() const
Returns the font used for rendering text.
 
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
 
#define BUILTIN_UNREACHABLE
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
 
QList< QgsSymbolLayer * > QgsSymbolLayerList