Skip to content

Commit da5215d

Browse files
committed
[composer] Respect layer transparency when drawing legend items (fix #7890)
1 parent 4bb5aae commit da5215d

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

src/core/composer/qgscomposerlegend.cpp

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "qgscomposition.h"
2424
#include "qgslogger.h"
2525
#include "qgsmaplayer.h"
26+
#include "qgsvectorlayer.h"
2627
#include "qgsmaplayerregistry.h"
2728
#include "qgsmaprenderer.h"
2829
#include "qgssymbolv2.h"
@@ -346,7 +347,6 @@ QgsComposerLegend::Nucleon QgsComposerLegend::drawSymbolItem( QgsComposerLegendI
346347
//real symbol height. Can be different from standard height in case of point symbols
347348
double realSymbolHeight;
348349

349-
#if 0
350350
QgsComposerLayerItem* layerItem = dynamic_cast<QgsComposerLayerItem*>( symbolItem->parent() );
351351

352352
int opacity = 255;
@@ -355,10 +355,14 @@ QgsComposerLegend::Nucleon QgsComposerLegend::drawSymbolItem( QgsComposerLegendI
355355
QgsMapLayer* currentLayer = QgsMapLayerRegistry::instance()->mapLayer( layerItem->layerID() );
356356
if ( currentLayer )
357357
{
358-
opacity = currentLayer->getTransparency();
358+
//vector layer
359+
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
360+
if ( vectorLayer )
361+
{
362+
opacity = 255 - ( 255 * vectorLayer->layerTransparency() / 100 );
363+
}
359364
}
360365
}
361-
#endif
362366

363367
QString text = symbolItem->text();
364368

@@ -376,7 +380,7 @@ QgsComposerLegend::Nucleon QgsComposerLegend::drawSymbolItem( QgsComposerLegendI
376380
if ( symbolNg ) //item with symbol NG?
377381
{
378382
// must be called also with painter=0 to get real size
379-
drawSymbolV2( painter, symbolNg, point.y() + ( itemHeight - mSymbolHeight ) / 2, x, realSymbolHeight );
383+
drawSymbolV2( painter, symbolNg, point.y() + ( itemHeight - mSymbolHeight ) / 2, x, realSymbolHeight, opacity );
380384
symbolSize.rwidth() = qMax( x - point.x(), mSymbolWidth );
381385
symbolSize.rheight() = qMax( realSymbolHeight, mSymbolHeight );
382386
}
@@ -472,22 +476,23 @@ QgsComposerLegend::Nucleon QgsComposerLegend::drawSymbolItem( QgsComposerLegendI
472476
}
473477

474478

475-
void QgsComposerLegend::drawSymbolV2( QPainter* p, QgsSymbolV2* s, double currentYCoord, double& currentXPosition, double& symbolHeight ) const
479+
void QgsComposerLegend::drawSymbolV2( QPainter* p, QgsSymbolV2* s, double currentYCoord, double& currentXPosition, double& symbolHeight, int opacity ) const
476480
{
477481
if ( !s )
478482
{
479483
return;
480484
}
481485

482-
double rasterScaleFactor = 1.0;
486+
//setup painter scaling to dots so that raster symbology is drawn to scale
487+
double dotsPerMM = 1.0;
483488
if ( p )
484489
{
485490
QPaintDevice* paintDevice = p->device();
486491
if ( !paintDevice )
487492
{
488493
return;
489494
}
490-
rasterScaleFactor = ( paintDevice->logicalDpiX() + paintDevice->logicalDpiY() ) / 2.0 / 25.4;
495+
dotsPerMM = ( paintDevice->logicalDpiX() + paintDevice->logicalDpiY() ) / 2.0 / 25.4;
491496
}
492497

493498
//consider relation to composer map for symbol sizes in mm
@@ -530,23 +535,43 @@ void QgsComposerLegend::drawSymbolV2( QPainter* p, QgsSymbolV2* s, double curren
530535

531536
if ( p )
532537
{
533-
p->save();
534-
p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
535-
p->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
536-
537538
if ( markerSymbol && sizeInMapUnits )
538539
{
539540
s->setOutputUnit( QgsSymbolV2::MM );
540541
}
541542

542-
s->drawPreviewIcon( p, QSize( width * rasterScaleFactor, height * rasterScaleFactor ) );
543+
p->save();
544+
p->setRenderHint( QPainter::Antialiasing );
545+
if ( opacity != 255 && mComposition && mComposition->useAdvancedEffects() )
546+
{
547+
//semi transparent layer, so need to draw symbol to an image (to flatten it first)
548+
//create image which is same size as legend rect, in case symbol bleeds outside its alloted space
549+
QImage tempImage = QImage( QSize( rect().width() * dotsPerMM, rect().height() * dotsPerMM ), QImage::Format_ARGB32 );
550+
QPainter imagePainter( &tempImage );
551+
tempImage.fill( Qt::transparent );
552+
imagePainter.translate( dotsPerMM * ( currentXPosition + widthOffset ),
553+
dotsPerMM * ( currentYCoord + heightOffset ) );
554+
s->drawPreviewIcon( &imagePainter, QSize( width * dotsPerMM, height * dotsPerMM ) );
555+
//reduce opacity of image
556+
imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
557+
imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) );
558+
//draw rendered symbol image
559+
p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
560+
p->drawImage( 0, 0, tempImage );
561+
}
562+
else
563+
{
564+
p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
565+
p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
566+
s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ) );
567+
}
568+
p->restore();
543569

544570
if ( markerSymbol && sizeInMapUnits )
545571
{
546572
s->setOutputUnit( QgsSymbolV2::MapUnit );
547573
markerSymbol->setSize( size );
548574
}
549-
p->restore();
550575
}
551576
currentXPosition += width;
552577
currentXPosition += 2 * widthOffset;

src/core/composer/qgscomposerlegend.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
246246

247247
/**Draws a symbol at the current y position and returns the new x position. Returns real symbol height, because for points,
248248
it is possible that it differs from mSymbolHeight*/
249-
void drawSymbolV2( QPainter* p, QgsSymbolV2* s, double currentYCoord, double& currentXPosition, double& symbolHeight ) const;
249+
void drawSymbolV2( QPainter* p, QgsSymbolV2* s, double currentYCoord, double& currentXPosition, double& symbolHeight, int opacity = 255 ) const;
250250

251251
/** Draw atom and return its actual size, the atom is drawn with the space above it
252252
* so that first atoms in column are all aligned to the same line regardles their

src/core/composer/qgslegendmodel.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,20 @@ int QgsLegendModel::addRasterLayerItems( QStandardItem* layerItem, QgsMapLayer*
281281
currentSymbolItem->setIcon( QIcon( itemPixmap ) );
282282
}
283283
currentSymbolItem->setLayerID( rasterLayer->id() );
284-
currentSymbolItem->setColor( itemIt->second );
284+
285+
QColor itemColor = itemIt->second;
286+
287+
//determine raster layer opacity, and adjust item color opacity to match
288+
QgsRasterRenderer* rasterRenderer = rasterLayer->renderer();
289+
int opacity = 255;
290+
if ( rasterRenderer )
291+
{
292+
opacity = rasterRenderer->opacity() * 255.0;
293+
}
294+
itemColor.setAlpha( opacity );
295+
296+
currentSymbolItem->setColor( itemColor );
297+
285298
int currentRowCount = layerItem->rowCount();
286299
layerItem->setChild( currentRowCount, 0, currentSymbolItem );
287300
row++;

0 commit comments

Comments
 (0)