Skip to content

Commit

Permalink
[composer] Respect layer transparency when drawing legend items (fix #…
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 17, 2014
1 parent 4bb5aae commit da5215d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 15 deletions.
51 changes: 38 additions & 13 deletions src/core/composer/qgscomposerlegend.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgscomposition.h"
#include "qgslogger.h"
#include "qgsmaplayer.h"
#include "qgsvectorlayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaprenderer.h"
#include "qgssymbolv2.h"
Expand Down Expand Up @@ -346,7 +347,6 @@ QgsComposerLegend::Nucleon QgsComposerLegend::drawSymbolItem( QgsComposerLegendI
//real symbol height. Can be different from standard height in case of point symbols
double realSymbolHeight;

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

int opacity = 255;
Expand All @@ -355,10 +355,14 @@ QgsComposerLegend::Nucleon QgsComposerLegend::drawSymbolItem( QgsComposerLegendI
QgsMapLayer* currentLayer = QgsMapLayerRegistry::instance()->mapLayer( layerItem->layerID() );
if ( currentLayer )
{
opacity = currentLayer->getTransparency();
//vector layer
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
if ( vectorLayer )
{
opacity = 255 - ( 255 * vectorLayer->layerTransparency() / 100 );
}
}
}
#endif

QString text = symbolItem->text();

Expand All @@ -376,7 +380,7 @@ QgsComposerLegend::Nucleon QgsComposerLegend::drawSymbolItem( QgsComposerLegendI
if ( symbolNg ) //item with symbol NG?
{
// must be called also with painter=0 to get real size
drawSymbolV2( painter, symbolNg, point.y() + ( itemHeight - mSymbolHeight ) / 2, x, realSymbolHeight );
drawSymbolV2( painter, symbolNg, point.y() + ( itemHeight - mSymbolHeight ) / 2, x, realSymbolHeight, opacity );
symbolSize.rwidth() = qMax( x - point.x(), mSymbolWidth );
symbolSize.rheight() = qMax( realSymbolHeight, mSymbolHeight );
}
Expand Down Expand Up @@ -472,22 +476,23 @@ QgsComposerLegend::Nucleon QgsComposerLegend::drawSymbolItem( QgsComposerLegendI
}


void QgsComposerLegend::drawSymbolV2( QPainter* p, QgsSymbolV2* s, double currentYCoord, double& currentXPosition, double& symbolHeight ) const
void QgsComposerLegend::drawSymbolV2( QPainter* p, QgsSymbolV2* s, double currentYCoord, double& currentXPosition, double& symbolHeight, int opacity ) const
{
if ( !s )
{
return;
}

double rasterScaleFactor = 1.0;
//setup painter scaling to dots so that raster symbology is drawn to scale
double dotsPerMM = 1.0;
if ( p )
{
QPaintDevice* paintDevice = p->device();
if ( !paintDevice )
{
return;
}
rasterScaleFactor = ( paintDevice->logicalDpiX() + paintDevice->logicalDpiY() ) / 2.0 / 25.4;
dotsPerMM = ( paintDevice->logicalDpiX() + paintDevice->logicalDpiY() ) / 2.0 / 25.4;
}

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

if ( p )
{
p->save();
p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
p->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );

if ( markerSymbol && sizeInMapUnits )
{
s->setOutputUnit( QgsSymbolV2::MM );
}

s->drawPreviewIcon( p, QSize( width * rasterScaleFactor, height * rasterScaleFactor ) );
p->save();
p->setRenderHint( QPainter::Antialiasing );
if ( opacity != 255 && mComposition && mComposition->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
QImage tempImage = QImage( QSize( rect().width() * dotsPerMM, rect().height() * dotsPerMM ), QImage::Format_ARGB32 );
QPainter imagePainter( &tempImage );
tempImage.fill( Qt::transparent );
imagePainter.translate( dotsPerMM * ( currentXPosition + widthOffset ),
dotsPerMM * ( currentYCoord + heightOffset ) );
s->drawPreviewIcon( &imagePainter, QSize( width * dotsPerMM, height * dotsPerMM ) );
//reduce opacity of image
imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) );
//draw rendered symbol image
p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
p->drawImage( 0, 0, tempImage );
}
else
{
p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ) );
}
p->restore();

if ( markerSymbol && sizeInMapUnits )
{
s->setOutputUnit( QgsSymbolV2::MapUnit );
markerSymbol->setSize( size );
}
p->restore();
}
currentXPosition += width;
currentXPosition += 2 * widthOffset;
Expand Down
2 changes: 1 addition & 1 deletion src/core/composer/qgscomposerlegend.h
Expand Up @@ -246,7 +246,7 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem

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

/** Draw atom and return its actual size, the atom is drawn with the space above it
* so that first atoms in column are all aligned to the same line regardles their
Expand Down
15 changes: 14 additions & 1 deletion src/core/composer/qgslegendmodel.cpp
Expand Up @@ -281,7 +281,20 @@ int QgsLegendModel::addRasterLayerItems( QStandardItem* layerItem, QgsMapLayer*
currentSymbolItem->setIcon( QIcon( itemPixmap ) );
}
currentSymbolItem->setLayerID( rasterLayer->id() );
currentSymbolItem->setColor( itemIt->second );

QColor itemColor = itemIt->second;

//determine raster layer opacity, and adjust item color opacity to match
QgsRasterRenderer* rasterRenderer = rasterLayer->renderer();
int opacity = 255;
if ( rasterRenderer )
{
opacity = rasterRenderer->opacity() * 255.0;
}
itemColor.setAlpha( opacity );

currentSymbolItem->setColor( itemColor );

int currentRowCount = layerItem->rowCount();
layerItem->setChild( currentRowCount, 0, currentSymbolItem );
row++;
Expand Down

0 comments on commit da5215d

Please sign in to comment.