Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix #11006 (wrong size of symbols in print composer legend if map uni…
…ts are used)
  • Loading branch information
wonder-sk committed Sep 1, 2014
1 parent d3e24c7 commit d994e0a
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 35 deletions.
6 changes: 6 additions & 0 deletions python/core/qgslegendsettings.sip
Expand Up @@ -71,6 +71,12 @@ class QgsLegendSettings
bool useAdvancedEffects() const;
void setUseAdvancedEffects( bool use );

double mapScale() const;
void setMapScale( double scale );

int dpi() const;
void setDpi( int dpi );

// utility functions

/** Splits a string using the wrap char taking into account handling empty
Expand Down
5 changes: 4 additions & 1 deletion python/core/symbology-ng/qgssymbolv2.sip
Expand Up @@ -80,7 +80,10 @@ class QgsSymbolV2
void setColor( const QColor& color );
QColor color() const;

void drawPreviewIcon( QPainter* painter, QSize size );
//! Draw icon of the symbol that occupyies area given by size using the painter.
//! Optionally custom context may be given in order to get rendering of symbols that use map units right.
//! @note customContext parameter added in 2.6
void drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext = 0 );

QImage bigSymbolPreviewImage();

Expand Down
4 changes: 4 additions & 0 deletions src/core/composer/qgscomposerlegend.cpp
Expand Up @@ -65,7 +65,11 @@ void QgsComposerLegend::paint( QPainter* painter, const QStyleOptionGraphicsItem


if ( mComposition )
{
mSettings.setUseAdvancedEffects( mComposition->useAdvancedEffects() );
mSettings.setMapScale( mComposition->mapSettings().scale() );
mSettings.setDpi( painter->device()->logicalDpiX() );
}
if ( mComposerMap )
mSettings.setMmPerMapUnit( mComposerMap->mapUnitsToMM() );

Expand Down
44 changes: 13 additions & 31 deletions src/core/layertree/qgslayertreemodellegendnode.cpp
Expand Up @@ -207,9 +207,13 @@ QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, Ite
return QSizeF();
}

//consider relation to composer map for symbol sizes in mm
bool sizeInMapUnits = s->outputUnit() == QgsSymbolV2::MapUnit;
QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( s );
// setup temporary render context
QgsRenderContext context;
context.setScaleFactor( settings.dpi() / 25.4 );
context.setRendererScale( settings.mapScale() );
context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) ); // hope it's ok to leave out other params
context.setForceVectorOutput( true );
context.setPainter( ctx ? ctx->painter : 0 );

//Consider symbol size for point markers
double height = settings.symbolSize().height();
Expand All @@ -219,17 +223,12 @@ QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, Ite
double widthOffset = 0;
double heightOffset = 0;

if ( markerSymbol )
if ( QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( s ) )
{
size = markerSymbol->size();
// 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 ( sizeInMapUnits )
{
height *= settings.mmPerMapUnit();
width *= settings.mmPerMapUnit();
markerSymbol->setSize( width );
}
if ( width < settings.symbolSize().width() )
{
widthOffset = ( settings.symbolSize().width() - width ) / 2.0;
Expand All @@ -247,18 +246,7 @@ QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, Ite
QPainter* p = ctx->painter;

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

if ( markerSymbol && sizeInMapUnits )
{
s->setOutputUnit( QgsSymbolV2::MM );
}
double dotsPerMM = context.scaleFactor();

int opacity = 255;
if ( QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( parent()->layer() ) )
Expand All @@ -275,7 +263,7 @@ QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, Ite
tempImage.fill( Qt::transparent );
imagePainter.translate( dotsPerMM * ( currentXPosition + widthOffset ),
dotsPerMM * ( currentYCoord + heightOffset ) );
s->drawPreviewIcon( &imagePainter, QSize( width * dotsPerMM, height * dotsPerMM ) );
s->drawPreviewIcon( &imagePainter, QSize( width * dotsPerMM, height * dotsPerMM ), &context );
//reduce opacity of image
imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) );
Expand All @@ -287,15 +275,9 @@ QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, Ite
{
p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset );
p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ) );
s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context );
}
p->restore();

if ( markerSymbol && sizeInMapUnits )
{
s->setOutputUnit( QgsSymbolV2::MapUnit );
markerSymbol->setSize( size );
}
}

return QSizeF( qMax( width + 2 * widthOffset, settings.symbolSize().width() ),
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgslegendsettings.cpp
Expand Up @@ -32,6 +32,8 @@ QgsLegendSettings::QgsLegendSettings()
, mEqualColumnWidth( false )
, mMmPerMapUnit( 1 )
, mUseAdvancedEffects( true )
, mMapScale( 1 )
, mDpi( 96 ) // based on QImage's default DPI
{
rstyle( QgsComposerLegendStyle::Title ).setMargin( QgsComposerLegendStyle::Bottom, 2 );
rstyle( QgsComposerLegendStyle::Group ).setMargin( QgsComposerLegendStyle::Top, 2 );
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgslegendsettings.h
Expand Up @@ -94,6 +94,12 @@ class CORE_EXPORT QgsLegendSettings
bool useAdvancedEffects() const { return mUseAdvancedEffects; }
void setUseAdvancedEffects( bool use ) { mUseAdvancedEffects = use; }

double mapScale() const { return mMapScale; }
void setMapScale( double scale ) { mMapScale = scale; }

int dpi() const { return mDpi; }
void setDpi( int dpi ) { mDpi = dpi; }

// utility functions

/** Splits a string using the wrap char taking into account handling empty
Expand Down Expand Up @@ -175,6 +181,12 @@ class CORE_EXPORT QgsLegendSettings

/** Whether to use advanced effects like transparency for symbols - may require their rasterization */
bool mUseAdvancedEffects;

/** Denominator of map's scale */
double mMapScale;

/** DPI to be used when rendering legend */
int mDpi;
};


Expand Down
4 changes: 2 additions & 2 deletions src/core/symbology-ng/qgssymbolv2.cpp
Expand Up @@ -283,9 +283,9 @@ QColor QgsSymbolV2::color() const
return QColor( 0, 0, 0 );
}

void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size )
void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext )
{
QgsRenderContext context = QgsSymbolLayerV2Utils::createRenderContext( painter );
QgsRenderContext context = customContext ? *customContext : QgsSymbolLayerV2Utils::createRenderContext( painter );
context.setForceVectorOutput( true );
QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, 0, 0, mapUnitScale() );

Expand Down
5 changes: 4 additions & 1 deletion src/core/symbology-ng/qgssymbolv2.h
Expand Up @@ -105,7 +105,10 @@ class CORE_EXPORT QgsSymbolV2
void setColor( const QColor& color );
QColor color() const;

void drawPreviewIcon( QPainter* painter, QSize size );
//! Draw icon of the symbol that occupyies area given by size using the painter.
//! Optionally custom context may be given in order to get rendering of symbols that use map units right.
//! @note customContext parameter added in 2.6
void drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext = 0 );

QImage bigSymbolPreviewImage();

Expand Down

0 comments on commit d994e0a

Please sign in to comment.