QgsLayerTreeModelLegendNode::ItemMetrics QgsDataDefinedSizeLegendNode::draw( const QgsLegendSettings &settings, QgsLayerTreeModelLegendNode::ItemContext *ctx ) { // setup temporary render context QgsRenderContext context; context.setScaleFactor( settings.dpi() / 25.4 ); context.setRendererScale( settings.mapScale() ); context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) ); context.setForceVectorOutput( true ); if ( ctx && ctx->painter ) { context.setPainter( ctx->painter ); ctx->painter->save(); ctx->painter->setRenderHint( QPainter::Antialiasing ); ctx->painter->translate( ctx->point ); ctx->painter->scale( 1 / context.scaleFactor(), 1 / context.scaleFactor() ); } QgsDataDefinedSizeLegend ddsLegend( *mSettings ); ddsLegend.setFont( settings.style( QgsLegendStyle::SymbolLabel ).font() ); ddsLegend.setTextColor( settings.fontColor() ); QSize contentSize; int labelXOffset; ddsLegend.drawCollapsedLegend( context, &contentSize, &labelXOffset ); if ( ctx && ctx->painter ) ctx->painter->restore(); ItemMetrics im; im.symbolSize = QSizeF( ( contentSize.width() - labelXOffset ) / context.scaleFactor(), contentSize.height() / context.scaleFactor() ); im.labelSize = QSizeF( labelXOffset / context.scaleFactor(), contentSize.height() / context.scaleFactor() ); return im; }
QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const { QIcon symbolIcon = data( Qt::DecorationRole ).value<QIcon>(); if ( symbolIcon.isNull() ) return QSizeF(); if ( ctx ) symbolIcon.paint( ctx->painter, ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2, settings.symbolSize().width(), settings.symbolSize().height() ); return settings.symbolSize(); }
QSizeF QgsImageLegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const { Q_UNUSED( itemHeight ); if ( ctx ) { ctx->painter->drawImage( QRectF( ctx->point.x(), ctx->point.y(), settings.wmsLegendSize().width(), settings.wmsLegendSize().height() ), mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) ); } return settings.wmsLegendSize(); }
QSizeF QgsWmsLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const { Q_UNUSED( itemHeight ); if ( ctx && ctx->painter ) { ctx->painter->drawImage( QRectF( ctx->point, settings.wmsLegendSize() ), mImage, QRectF( QPointF( 0, 0 ), mImage.size() ) ); } return settings.wmsLegendSize(); }
static void _setStandardTestFont( QgsLegendSettings& settings, const QString& style = "Roman" ) { QList< QgsComposerLegendStyle::Style> styles; styles << QgsComposerLegendStyle::Title << QgsComposerLegendStyle::Group << QgsComposerLegendStyle::Subgroup << QgsComposerLegendStyle::SymbolLabel; Q_FOREACH ( QgsComposerLegendStyle::Style st, styles ) { QFont font( QgsFontUtils::getStandardTestFont( style ) ); font.setPointSizeF( settings.style( st ).font().pointSizeF() ); settings.rstyle( st ).setFont( font ); }
static void _setStandardTestFont( QgsLegendSettings& settings ) { QList< QgsComposerLegendStyle::Style> styles; styles << QgsComposerLegendStyle::Title << QgsComposerLegendStyle::Group << QgsComposerLegendStyle::Subgroup << QgsComposerLegendStyle::SymbolLabel; foreach ( QgsComposerLegendStyle::Style st, styles ) { QFont font( QgsFontUtils::getStandardTestFont() ); font.setPointSizeF( settings.style( st ).font().pointSizeF() ); settings.rstyle( st ).setFont( font ); }
void QgsLayerTreeModelLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &, QJsonObject &json ) const { const QIcon icon = data( Qt::DecorationRole ).value<QIcon>(); if ( icon.isNull() ) return; const QImage image( icon.pixmap( settings.symbolSize().width(), settings.symbolSize().height() ).toImage() ); QByteArray byteArray; QBuffer buffer( &byteArray ); image.save( &buffer, "PNG" ); const QString base64 = QString::fromLatin1( byteArray.toBase64().data() ); json[ "icon" ] = base64; }
QgsLayerTreeModelLegendNode::ItemMetrics QgsLayerTreeModelLegendNode::draw( const QgsLegendSettings& settings, ItemContext* ctx ) { QFont symbolLabelFont = settings.style( QgsComposerLegendStyle::SymbolLabel ).font(); double textHeight = settings.fontHeightCharacterMM( symbolLabelFont, QChar( '0' ) ); // itemHeight here is not realy item height, it is only for symbol // vertical alignment purpose, i.e. ok take single line height // if there are more lines, thos run under the symbol double itemHeight = qMax(( double ) settings.symbolSize().height(), textHeight ); ItemMetrics im; im.symbolSize = drawSymbol( settings, ctx, itemHeight ); im.labelSize = drawSymbolText( settings, ctx, im.symbolSize ); return im; }
QSizeF QgsRasterSymbolLegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const { if ( ctx ) { QColor itemColor = mColor; if ( QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( layerNode()->layer() ) ) { if ( QgsRasterRenderer* rasterRenderer = rasterLayer->renderer() ) itemColor.setAlpha( rasterRenderer->opacity() * 255.0 ); } ctx->painter->setBrush( itemColor ); ctx->painter->drawRect( QRectF( ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2, settings.symbolSize().width(), settings.symbolSize().height() ) ); } return settings.symbolSize(); }
QSizeF QgsRasterSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const { if ( ctx && ctx->painter ) { QColor itemColor = mColor; if ( QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layerNode()->layer() ) ) { if ( QgsRasterRenderer *rasterRenderer = rasterLayer->renderer() ) itemColor.setAlpha( rasterRenderer->opacity() * 255.0 ); } ctx->painter->setBrush( itemColor ); if ( settings.drawRasterStroke() ) { QPen pen; pen.setColor( settings.rasterStrokeColor() ); pen.setWidthF( settings.rasterStrokeWidth() ); pen.setJoinStyle( Qt::MiterJoin ); ctx->painter->setPen( pen ); } else { ctx->painter->setPen( Qt::NoPen ); } ctx->painter->drawRect( QRectF( ctx->point.x(), ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2, settings.symbolSize().width(), settings.symbolSize().height() ) ); } return settings.symbolSize(); }
void QgsSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const { const QgsSymbol *s = mItem.symbol(); if ( !s ) { return; } QgsRenderContext ctx; ctx.setScaleFactor( settings.dpi() / 25.4 ); ctx.setRendererScale( settings.mapScale() ); ctx.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * ctx.scaleFactor() ) ) ); ctx.setForceVectorOutput( true ); // ensure that a minimal expression context is available QgsExpressionContext expContext = context.expressionContext(); expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); ctx.setExpressionContext( expContext ); const QPixmap pix = QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), minimumIconSize(), 0, &ctx ); QImage img( pix.toImage().convertToFormat( QImage::Format_ARGB32_Premultiplied ) ); int opacity = 255; if ( QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layerNode()->layer() ) ) opacity = ( 255 * vectorLayer->opacity() ); if ( opacity != 255 ) { QPainter painter; painter.begin( &img ); painter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); painter.fillRect( pix.rect(), QColor( 0, 0, 0, opacity ) ); painter.end(); } QByteArray byteArray; QBuffer buffer( &byteArray ); img.save( &buffer, "PNG" ); const QString base64 = QString::fromLatin1( byteArray.toBase64().data() ); json[ "icon" ] = base64; }
QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &settings, ItemContext *ctx, QSizeF symbolSize ) const { QSizeF labelSize( 0, 0 ); QFont symbolLabelFont = settings.style( QgsLegendStyle::SymbolLabel ).font(); double textHeight = settings.fontHeightCharacterMM( symbolLabelFont, QChar( '0' ) ); double textDescent = settings.fontDescentMillimeters( symbolLabelFont ); QgsExpressionContext tempContext; const QStringList lines = settings.evaluateItemText( data( Qt::DisplayRole ).toString(), ctx && ctx->context ? ctx->context->expressionContext() : tempContext ); labelSize.rheight() = lines.count() * textHeight + ( lines.count() - 1 ) * ( settings.lineSpacing() + textDescent ); double labelX = 0.0, labelY = 0.0; if ( ctx && ctx->painter ) { ctx->painter->setPen( settings.fontColor() ); labelX = ctx->point.x() + std::max( static_cast< double >( symbolSize.width() ), ctx->labelXOffset ); labelY = ctx->point.y(); // Vertical alignment of label with symbol if ( labelSize.height() < symbolSize.height() ) labelY += symbolSize.height() / 2 - labelSize.height() / 2; // label centered with symbol labelY += textHeight; } for ( QStringList::ConstIterator itemPart = lines.constBegin(); itemPart != lines.constEnd(); ++itemPart ) { labelSize.rwidth() = std::max( settings.textWidthMillimeters( symbolLabelFont, *itemPart ), double( labelSize.width() ) ); if ( ctx && ctx->painter ) { settings.drawText( ctx->painter, labelX, labelY, *itemPart, symbolLabelFont ); if ( itemPart != ( lines.end() - 1 ) ) labelY += textDescent + settings.lineSpacing() + textHeight; } } return labelSize; }
QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings& settings, ItemContext* ctx, const QSizeF& symbolSize ) const { QSizeF labelSize( 0, 0 ); QFont symbolLabelFont = settings.style( QgsComposerLegendStyle::SymbolLabel ).font(); double textHeight = settings.fontHeightCharacterMM( symbolLabelFont, QChar( '0' ) ); QStringList lines = settings.splitStringForWrapping( data( Qt::DisplayRole ).toString() ); labelSize.rheight() = lines.count() * textHeight + ( lines.count() - 1 ) * settings.lineSpacing(); double labelX = 0.0, labelY = 0.0; if ( ctx ) { ctx->painter->setPen( settings.fontColor() ); labelX = ctx->point.x() + qMax(( double ) symbolSize.width(), ctx->labelXOffset ); labelY = ctx->point.y(); // Vertical alignment of label with symbol if ( labelSize.height() < symbolSize.height() ) labelY += symbolSize.height() / 2 + textHeight / 2; // label centered with symbol else labelY += textHeight; // label starts at top and runs under symbol } for ( QStringList::Iterator itemPart = lines.begin(); itemPart != lines.end(); ++itemPart ) { labelSize.rwidth() = qMax( settings.textWidthMillimeters( symbolLabelFont, *itemPart ), double( labelSize.width() ) ); if ( ctx ) { settings.drawText( ctx->painter, labelX, labelY, *itemPart, symbolLabelFont ); if ( itemPart != lines.end() ) labelY += settings.lineSpacing() + textHeight; } } return labelSize; }
void QgsRasterSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &, QJsonObject &json ) const { QImage img = QImage( settings.symbolSize().toSize(), QImage::Format_ARGB32 ); img.fill( Qt::transparent ); QPainter painter( &img ); painter.setRenderHint( QPainter::Antialiasing ); QColor itemColor = mColor; if ( QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layerNode()->layer() ) ) { if ( QgsRasterRenderer *rasterRenderer = rasterLayer->renderer() ) itemColor.setAlpha( rasterRenderer->opacity() * 255.0 ); } painter.setBrush( itemColor ); if ( settings.drawRasterStroke() ) { QPen pen; pen.setColor( settings.rasterStrokeColor() ); pen.setWidthF( settings.rasterStrokeWidth() ); pen.setJoinStyle( Qt::MiterJoin ); painter.setPen( pen ); } else { painter.setPen( Qt::NoPen ); } painter.drawRect( QRectF( 0, 0, settings.symbolSize().width(), settings.symbolSize().height() ) ); QByteArray byteArray; QBuffer buffer( &byteArray ); img.save( &buffer, "PNG" ); const QString base64 = QString::fromLatin1( byteArray.toBase64().data() ); json[ "icon" ] = base64; }
QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const { QgsSymbolV2* s = mItem.symbol(); if ( !s ) { return QSizeF(); } // setup temporary render context QgsRenderContext context; context.setScaleFactor( settings.dpi() / 25.4 ); context.setRendererScale( settings.mapScale() ); context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) ); context.setForceVectorOutput( true ); context.setPainter( ctx ? ctx->painter : 0 ); //Consider symbol size for point markers double height = settings.symbolSize().height(); double width = settings.symbolSize().width(); double size = 0; //Center small marker symbols double widthOffset = 0; double heightOffset = 0; if ( QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( s ) ) { // allow marker symbol to occupy bigger area if necessary size = markerSymbol->size() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context, s->outputUnit(), s->mapUnitScale() ) / context.scaleFactor(); height = size; width = size; if ( width < settings.symbolSize().width() ) { widthOffset = ( settings.symbolSize().width() - width ) / 2.0; } if ( height < settings.symbolSize().height() ) { heightOffset = ( settings.symbolSize().height() - height ) / 2.0; } } if ( ctx ) { double currentXPosition = ctx->point.x(); double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2; QPainter* p = ctx->painter; //setup painter scaling to dots so that raster symbology is drawn to scale double dotsPerMM = context.scaleFactor(); int opacity = 255; if ( QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( layerNode()->layer() ) ) opacity = 255 - ( 255 * vectorLayer->layerTransparency() / 100 ); p->save(); p->setRenderHint( QPainter::Antialiasing ); p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset ); p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM ); if ( opacity != 255 && settings.useAdvancedEffects() ) { //semi transparent layer, so need to draw symbol to an image (to flatten it first) //create image which is same size as legend rect, in case symbol bleeds outside its alloted space QSize tempImageSize( width * dotsPerMM, height * dotsPerMM ); QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 ); tempImage.fill( Qt::transparent ); QPainter imagePainter( &tempImage ); context.setPainter( &imagePainter ); s->drawPreviewIcon( &imagePainter, tempImageSize, &context ); context.setPainter( ctx->painter ); //reduce opacity of image imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) ); imagePainter.end(); //draw rendered symbol image p->drawImage( 0, 0, tempImage ); } else { s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context ); } p->restore(); } return QSizeF( qMax( width + 2 * widthOffset, ( double ) settings.symbolSize().width() ), qMax( height + 2 * heightOffset, ( double ) settings.symbolSize().height() ) ); }
QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const { QgsSymbol *s = mItem.symbol(); if ( !s ) { return QSizeF(); } // setup temporary render context QgsRenderContext context; context.setScaleFactor( settings.dpi() / 25.4 ); context.setRendererScale( settings.mapScale() ); context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) ); context.setForceVectorOutput( true ); context.setPainter( ctx ? ctx->painter : nullptr ); if ( ctx && ctx->context ) { context.setExpressionContext( ctx->context->expressionContext() ); } else { // setup a minimal expression context QgsExpressionContext expContext; expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); context.setExpressionContext( expContext ); } //Consider symbol size for point markers double height = settings.symbolSize().height(); double width = settings.symbolSize().width(); //Center small marker symbols double widthOffset = 0; double heightOffset = 0; if ( QgsMarkerSymbol *markerSymbol = dynamic_cast<QgsMarkerSymbol *>( s ) ) { // allow marker symbol to occupy bigger area if necessary double size = markerSymbol->size( context ) / context.scaleFactor(); height = size; width = size; if ( width < settings.symbolSize().width() ) { widthOffset = ( settings.symbolSize().width() - width ) / 2.0; } if ( height < settings.symbolSize().height() ) { heightOffset = ( settings.symbolSize().height() - height ) / 2.0; } } if ( ctx && ctx->painter ) { double currentXPosition = ctx->point.x(); double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2; QPainter *p = ctx->painter; //setup painter scaling to dots so that raster symbology is drawn to scale double dotsPerMM = context.scaleFactor(); int opacity = 255; if ( QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layerNode()->layer() ) ) opacity = ( 255 * vectorLayer->opacity() ); p->save(); p->setRenderHint( QPainter::Antialiasing ); p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset ); p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM ); if ( opacity != 255 && settings.useAdvancedEffects() ) { //semi transparent layer, so need to draw symbol to an image (to flatten it first) //create image which is same size as legend rect, in case symbol bleeds outside its alloted space QSize tempImageSize( width * dotsPerMM, height * dotsPerMM ); QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 ); tempImage.fill( Qt::transparent ); QPainter imagePainter( &tempImage ); context.setPainter( &imagePainter ); s->drawPreviewIcon( &imagePainter, tempImageSize, &context ); context.setPainter( ctx->painter ); //reduce opacity of image imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) ); imagePainter.end(); //draw rendered symbol image p->drawImage( 0, 0, tempImage ); } else { s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context ); } if ( !mTextOnSymbolLabel.isEmpty() ) { QFontMetricsF fm( mTextOnSymbolTextFormat.scaledFont( context ) ); qreal yBaselineVCenter = ( height * dotsPerMM + fm.ascent() - fm.descent() ) / 2; QgsTextRenderer::drawText( QPointF( width * dotsPerMM / 2, yBaselineVCenter ), 0, QgsTextRenderer::AlignCenter, QStringList() << mTextOnSymbolLabel, context, mTextOnSymbolTextFormat ); } p->restore(); } return QSizeF( std::max( width + 2 * widthOffset, static_cast< double >( settings.symbolSize().width() ) ), std::max( height + 2 * heightOffset, static_cast< double >( settings.symbolSize().height() ) ) ); }