Merge pull request #590 from nyalldawson/advanced_composition

FFE? some blending fixes & composition feature requests
This commit is contained in:
Nathan Woodrow 2013-05-13 20:27:58 -07:00
commit db619edcb4
21 changed files with 490 additions and 59 deletions

View File

@ -208,6 +208,11 @@ class QgsComposerMap : QgsComposerItem
@note this function was added in version 1.4*/
void setGridAnnotationFont( const QFont& f );
QFont gridAnnotationFont() const;
/**Sets font color for grid annotations
@note this function was added in version 2.0*/
void setAnnotationFontColor( const QColor& c );
QColor annotationFontColor() const;
/**Sets coordinate precision for grid annotations
@note this function was added in version 1.4*/
@ -242,6 +247,13 @@ class QgsComposerMap : QgsComposerItem
@note: this function was added in version 1.9*/
void setGridFrameWidth( double w );
double gridFrameWidth() const;
/** Returns the grid's blending mode
@note added in version 2.0*/
const QPainter::CompositionMode gridBlendMode() const;
/** Sets the grid's blending mode
@note added in version 2.0*/
void setGridBlendMode( const QPainter::CompositionMode blendMode );
/**In case of annotations, the bounding rectangle can be larger than the map item rectangle
@note this function was added in version 1.4*/

View File

@ -755,7 +755,25 @@ class QgsVectorLayer : QgsMapLayer
@note this method was added in version 1.1
*/
QgsVectorOverlay* findOverlayByType( const QString& typeName );
/* Set the blending mode used for rendering each feature
* @note added in 2.0
*/
void setFeatureBlendMode( const QPainter::CompositionMode blendMode );
/* Returns the current blending mode for features
* @note added in 2.0
*/
const QPainter::CompositionMode featureBlendMode() const;
/* Set the transparency for the vector layer
* @note added in 2.0
*/
void setLayerTransparency( const int layerTransparency );
/* Returns the current transparency for the vector layer
* @note added in 2.0
*/
const int layerTransparency() const;
//! Buffer with uncommitted editing operations. Only valid after editing has been turned on.
QgsVectorLayerEditBuffer* editBuffer();

View File

@ -632,9 +632,9 @@ void QgsComposer::on_mActionExportAsPDF_triggered()
showWMSPrintingWarning();
}
if ( containsBlendModes() )
if ( containsAdvancedEffects() )
{
showBlendModePrintingWarning();
showAdvancedEffectsWarning();
}
// If we are not printing as raster, temporarily disable advanced effects
@ -828,9 +828,9 @@ void QgsComposer::on_mActionPrint_triggered()
showWMSPrintingWarning();
}
if ( containsBlendModes() )
if ( containsAdvancedEffects() )
{
showBlendModePrintingWarning();
showAdvancedEffectsWarning();
}
// If we are not printing as raster, temporarily disable advanced effects
@ -2056,9 +2056,9 @@ bool QgsComposer::containsWMSLayer() const
return false;
}
bool QgsComposer::containsBlendModes() const
bool QgsComposer::containsAdvancedEffects() const
{
// Check if composer contains any blend modes
// Check if composer contains any blend modes or flattened layers for transparency
QMap<QgsComposerItem*, QWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
QgsComposerItem* currentItem = 0;
QgsComposerMap* currentMap = 0;
@ -2071,11 +2071,11 @@ bool QgsComposer::containsBlendModes() const
{
return true;
}
// If item is a composer map, check if it contains any blended layers
// If item is a composer map, check if it contains any advanced effects
currentMap = dynamic_cast<QgsComposerMap *>( currentItem );
if ( currentMap )
{
if ( currentMap->containsBlendModes() )
if ( currentMap->containsAdvancedEffects() )
{
return true;
}
@ -2087,6 +2087,14 @@ bool QgsComposer::containsBlendModes() const
return true;
}
}
if ( currentMap->gridEnabled() )
{
// map contains an grid, check its blend mode
if ( currentMap->gridBlendMode() != QPainter::CompositionMode_SourceOver )
{
return true;
}
}
}
}
return false;
@ -2111,13 +2119,13 @@ void QgsComposer::showWMSPrintingWarning()
}
}
void QgsComposer::showBlendModePrintingWarning()
void QgsComposer::showAdvancedEffectsWarning()
{
if ( ! mComposition->printAsRaster() )
{
QgsMessageViewer* m = new QgsMessageViewer( this, QgisGui::ModalDialogFlags, false );
m->setWindowTitle( tr( "Project contains blend modes" ) );
m->setMessage( tr( "Blend modes are enabled in this project, which cannot be printed as vectors. Printing as a raster is recommended." ), QgsMessageOutput::MessageText );
m->setWindowTitle( tr( "Project contains composition effects" ) );
m->setMessage( tr( "Advanced composition effects such as blend modes or vector layer transparency are enabled in this project, which cannot be printed as vectors. Printing as a raster is recommended." ), QgsMessageOutput::MessageText );
m->setCheckBoxText( tr( "Print as raster" ) );
m->setCheckBoxState( Qt::Checked );
m->setCheckBoxVisible( true );

View File

@ -309,14 +309,14 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
//! True if a composer map contains a WMS layer
bool containsWMSLayer() const;
//! True if a composer contains blend modes
bool containsBlendModes() const;
//! True if a composer contains advanced effects, such as blend modes
bool containsAdvancedEffects() const;
//! Displays a warning because of possible min/max size in WMS
void showWMSPrintingWarning();
//! Displays a warning because of incompatibility between blend modes and QPrinter
void showBlendModePrintingWarning();
void showAdvancedEffectsWarning();
//! Changes elements that are not suitable for this project
void cleanupAfterTemplateRead();

View File

@ -343,6 +343,9 @@ void QgsComposerMapWidget::updateGuiElements()
mFrameStyleComboBox->setCurrentIndex( mFrameStyleComboBox->findText( tr( "No frame" ) ) );
}
//grid blend mode
mGridBlendComboBox->setBlendMode( mComposerMap->gridBlendMode() );
//grid annotation format
QgsComposerMap::GridAnnotationFormat gf = mComposerMap->gridAnnotationFormat();
mAnnotationFormatComboBox->setCurrentIndex(( int )gf );
@ -359,6 +362,10 @@ void QgsComposerMapWidget::updateGuiElements()
initAnnotationDirectionBox( mAnnotationDirectionComboBoxTop, mComposerMap->gridAnnotationDirection( QgsComposerMap::Top ) );
initAnnotationDirectionBox( mAnnotationDirectionComboBoxBottom, mComposerMap->gridAnnotationDirection( QgsComposerMap::Bottom ) );
mAnnotationFontColorButton->setColor( mComposerMap->annotationFontColor() );
mAnnotationFontColorButton->setColorDialogTitle( tr( "Select font color" ) );
mAnnotationFontColorButton->setColorDialogOptions( QColorDialog::ShowAlphaChannel );
mDistanceToMapFrameSpinBox->setValue( mComposerMap->annotationFrameDistance() );
if ( mComposerMap->showGridAnnotation() )
@ -423,6 +430,7 @@ void QgsComposerMapWidget::blockAllSignals( bool b )
mSetToMapCanvasExtentButton->blockSignals( b );
mUpdatePreviewButton->blockSignals( b );
mGridLineStyleButton->blockSignals( b );
mGridBlendComboBox->blockSignals( b );
mDrawAnnotationCheckableGroupBox->blockSignals( b );
mAnnotationFontButton->blockSignals( b );
mAnnotationFormatComboBox->blockSignals( b );
@ -436,6 +444,7 @@ void QgsComposerMapWidget::blockAllSignals( bool b )
mAnnotationDirectionComboBoxTop->blockSignals( b );
mAnnotationDirectionComboBoxBottom->blockSignals( b );
mCoordinatePrecisionSpinBox->blockSignals( b );
mAnnotationFontColorButton->blockSignals( b );
mDrawCanvasItemsCheckBox->blockSignals( b );
mFrameStyleComboBox->blockSignals( b );
mFrameWidthSpinBox->blockSignals( b );
@ -705,6 +714,16 @@ void QgsComposerMapWidget::on_mCrossWidthSpinBox_valueChanged( double d )
mComposerMap->endCommand();
}
void QgsComposerMapWidget::on_mGridBlendComboBox_currentIndexChanged( int index )
{
Q_UNUSED( index );
if ( mComposerMap )
{
mComposerMap->setGridBlendMode( mGridBlendComboBox->blendMode() );
}
}
void QgsComposerMapWidget::on_mAnnotationFontButton_clicked()
{
if ( !mComposerMap )
@ -729,6 +748,18 @@ void QgsComposerMapWidget::on_mAnnotationFontButton_clicked()
}
}
void QgsComposerMapWidget::on_mAnnotationFontColorButton_colorChanged( const QColor& newFontColor )
{
if ( !mComposerMap )
{
return;
}
mComposerMap->beginCommand( tr( "Label font changed" ) );
mComposerMap->setAnnotationFontColor( newFontColor );
mComposerMap->update();
mComposerMap->endCommand();
}
void QgsComposerMapWidget::on_mDistanceToMapFrameSpinBox_valueChanged( double d )
{
if ( !mComposerMap )

View File

@ -60,7 +60,9 @@ class QgsComposerMapWidget: public QWidget, private Ui::QgsComposerMapWidgetBase
void on_mGridLineStyleButton_clicked();
void on_mGridTypeComboBox_currentIndexChanged( const QString& text );
void on_mCrossWidthSpinBox_valueChanged( double d );
void on_mGridBlendComboBox_currentIndexChanged( int index );
void on_mAnnotationFontButton_clicked();
void on_mAnnotationFontColorButton_colorChanged( const QColor& newFontColor );
void on_mDistanceToMapFrameSpinBox_valueChanged( double d );
void on_mAnnotationFormatComboBox_currentIndexChanged( int index );

View File

@ -42,10 +42,12 @@
QgsComposerMap::QgsComposerMap( QgsComposition *composition, int x, int y, int width, int height )
: QgsComposerItem( x, y, width, height, composition ), mKeepLayerSet( false ),
mOverviewFrameMapId( -1 ), mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mGridEnabled( false ), mGridStyle( Solid ),
mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ),
mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame ), mTopGridAnnotationPosition( OutsideMapFrame ),
mBottomGridAnnotationPosition( OutsideMapFrame ), mAnnotationFrameDistance( 1.0 ), mLeftGridAnnotationDirection( Horizontal ), mRightGridAnnotationDirection( Horizontal ),
mTopGridAnnotationDirection( Horizontal ), mBottomGridAnnotationDirection( Horizontal ), mGridFrameStyle( NoGridFrame ), mGridFrameWidth( 2.0 ),
mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationFontColor( QColor( 0, 0, 0 ) ),
mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ), mGridBlendMode( QPainter::CompositionMode_SourceOver ),
mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame ),
mTopGridAnnotationPosition( OutsideMapFrame ), mBottomGridAnnotationPosition( OutsideMapFrame ), mAnnotationFrameDistance( 1.0 ),
mLeftGridAnnotationDirection( Horizontal ), mRightGridAnnotationDirection( Horizontal ), mTopGridAnnotationDirection( Horizontal ),
mBottomGridAnnotationDirection( Horizontal ), mGridFrameStyle( NoGridFrame ), mGridFrameWidth( 2.0 ),
mCrossLength( 3 ), mMapCanvas( 0 ), mDrawCanvasItems( true )
{
mComposition = composition;
@ -85,10 +87,12 @@ QgsComposerMap::QgsComposerMap( QgsComposition *composition, int x, int y, int w
QgsComposerMap::QgsComposerMap( QgsComposition *composition )
: QgsComposerItem( 0, 0, 10, 10, composition ), mKeepLayerSet( false ), mOverviewFrameMapId( -1 ),
mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mGridEnabled( false ), mGridStyle( Solid ),
mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ),
mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame ), mTopGridAnnotationPosition( OutsideMapFrame ),
mBottomGridAnnotationPosition( OutsideMapFrame ), mAnnotationFrameDistance( 1.0 ), mLeftGridAnnotationDirection( Horizontal ), mRightGridAnnotationDirection( Horizontal ),
mTopGridAnnotationDirection( Horizontal ), mBottomGridAnnotationDirection( Horizontal ), mGridFrameStyle( NoGridFrame ), mGridFrameWidth( 2.0 ), mCrossLength( 3 ),
mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationFontColor( QColor( 0, 0, 0 ) ),
mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ), mGridBlendMode( QPainter::CompositionMode_SourceOver ),
mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame ),
mTopGridAnnotationPosition( OutsideMapFrame ), mBottomGridAnnotationPosition( OutsideMapFrame ), mAnnotationFrameDistance( 1.0 ),
mLeftGridAnnotationDirection( Horizontal ), mRightGridAnnotationDirection( Horizontal ), mTopGridAnnotationDirection( Horizontal ),
mBottomGridAnnotationDirection( Horizontal ), mGridFrameStyle( NoGridFrame ), mGridFrameWidth( 2.0 ), mCrossLength( 3 ),
mMapCanvas( 0 ), mDrawCanvasItems( true )
{
mOverviewFrameMapSymbol = 0;
@ -631,8 +635,9 @@ bool QgsComposerMap::containsWMSLayer() const
return false;
}
bool QgsComposerMap::containsBlendModes() const
bool QgsComposerMap::containsAdvancedEffects() const
{
// check if map contains advanced effects like blend modes, or flattened layers for transparency
if ( !mMapRenderer )
{
return false;
@ -655,10 +660,19 @@ bool QgsComposerMap::containsBlendModes() const
{
return true;
}
// if vector layer and has labels, check label blend modes
// if vector layer, check labels and feature blend mode
QgsVectorLayer* currentVectorLayer = qobject_cast<QgsVectorLayer *>( currentLayer );
if ( currentVectorLayer )
{
if ( currentVectorLayer->layerTransparency() != 0 )
{
return true;
}
if ( currentVectorLayer->featureBlendMode() != QPainter::CompositionMode_SourceOver )
{
return true;
}
// check label blend modes
if ( lbl->willUseLayer( currentVectorLayer ) )
{
// Check all label blending properties
@ -782,6 +796,7 @@ bool QgsComposerMap::writeXML( QDomElement& elem, QDomDocument & doc ) const
gridElem.setAttribute( "crossLength", QString::number( mCrossLength ) );
gridElem.setAttribute( "gridFrameStyle", mGridFrameStyle );
gridElem.setAttribute( "gridFrameWidth", QString::number( mGridFrameWidth ) );
gridElem.setAttribute( "gridBlendMode", QgsMapRenderer::getBlendModeEnum( mGridBlendMode ) );
QDomElement gridLineStyleElem = QgsSymbolLayerV2Utils::saveSymbol( QString(), mGridLineSymbol, doc );
gridElem.appendChild( gridLineStyleElem );
@ -800,6 +815,12 @@ bool QgsComposerMap::writeXML( QDomElement& elem, QDomDocument & doc ) const
annotationElem.setAttribute( "frameDistance", QString::number( mAnnotationFrameDistance ) );
annotationElem.setAttribute( "font", mGridAnnotationFont.toString() );
annotationElem.setAttribute( "precision", mGridAnnotationPrecision );
//annotation font color
QDomElement annotationFontColorElem = doc.createElement( "fontColor" );
annotationFontColorElem.setAttribute( "red", mGridAnnotationFontColor.red() );
annotationFontColorElem.setAttribute( "green", mGridAnnotationFontColor.green() );
annotationFontColorElem.setAttribute( "blue", mGridAnnotationFontColor.blue() );
annotationElem.appendChild( annotationFontColorElem );
gridElem.appendChild( annotationElem );
composerMapElem.appendChild( gridElem );
@ -928,6 +949,7 @@ bool QgsComposerMap::readXML( const QDomElement& itemElem, const QDomDocument& d
mCrossLength = gridElem.attribute( "crossLength", "3" ).toDouble();
mGridFrameStyle = ( QgsComposerMap::GridFrameStyle )gridElem.attribute( "gridFrameStyle", "0" ).toInt();
mGridFrameWidth = gridElem.attribute( "gridFrameWidth", "2.0" ).toDouble();
setGridBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) gridElem.attribute( "gridBlendMode", "0" ).toUInt() ) );
QDomElement gridSymbolElem = gridElem.firstChildElement( "symbol" );
delete mGridLineSymbol;
@ -961,6 +983,22 @@ bool QgsComposerMap::readXML( const QDomElement& itemElem, const QDomDocument& d
mBottomGridAnnotationDirection = QgsComposerMap::GridAnnotationDirection( annotationElem.attribute( "bottomDirection", "0" ).toInt() );
mAnnotationFrameDistance = annotationElem.attribute( "frameDistance", "0" ).toDouble();
mGridAnnotationFont.fromString( annotationElem.attribute( "font", "" ) );
//annotation font color
QDomNodeList annotationFontColorList = annotationElem.elementsByTagName( "fontColor" );
if ( annotationFontColorList.size() > 0 )
{
QDomElement fontColorElem = annotationFontColorList.at( 0 ).toElement();
int red = fontColorElem.attribute( "red", "0" ).toInt();
int green = fontColorElem.attribute( "green", "0" ).toInt();
int blue = fontColorElem.attribute( "blue", "0" ).toInt();
mGridAnnotationFontColor = QColor( red, green, blue );
}
else
{
mGridAnnotationFontColor = QColor( 0, 0, 0 );
}
mGridAnnotationPrecision = annotationElem.attribute( "precision", "3" ).toInt();
}
}
@ -1025,6 +1063,10 @@ void QgsComposerMap::drawGrid( QPainter* p )
QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
p->setClipRect( thisPaintRect );
// set the blend mode for drawing grid lines
p->save();
p->setCompositionMode( mGridBlendMode );
//simpler approach: draw vertical lines first, then horizontal ones
if ( mGridStyle == QgsComposerMap::Solid )
{
@ -1085,6 +1127,8 @@ void QgsComposerMap::drawGrid( QPainter* p )
drawGridLine( QLineF( hIt->second.p2(), crossEnd1 ), p );
}
}
// reset composition mode
p->restore();
p->setClipRect( thisPaintRect , Qt::NoClip );
@ -1097,6 +1141,7 @@ void QgsComposerMap::drawGrid( QPainter* p )
{
drawCoordinateAnnotations( p, horizontalLines, verticalLines );
}
}
void QgsComposerMap::drawGridFrame( QPainter* p, const QList< QPair< double, QLineF > >& hLines, const QList< QPair< double, QLineF > >& vLines )
@ -1377,7 +1422,7 @@ void QgsComposerMap::drawAnnotation( QPainter* p, const QPointF& pos, int rotati
p->save();
p->translate( pos );
p->rotate( rotation );
p->setPen( QColor( 0, 0, 0 ) );
p->setPen( QPen( QColor( mGridAnnotationFontColor ) ) );
drawText( p, 0, 0, annotationText, mGridAnnotationFont );
p->restore();
}
@ -1587,6 +1632,12 @@ QPen QgsComposerMap::gridPen() const
return p;
}
void QgsComposerMap::setGridBlendMode( QPainter::CompositionMode blendMode )
{
mGridBlendMode = blendMode;
update();
}
QRectF QgsComposerMap::boundingRect() const
{
return mCurrentRectangle;

View File

@ -183,8 +183,8 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
/**True if composer map renders a WMS layer*/
bool containsWMSLayer() const;
/**True if composer map contains layers with blend modes*/
bool containsBlendModes() const;
/**True if composer map contains layers with blend modes or flattened layers for vectors */
bool containsAdvancedEffects() const;
/** stores state in Dom node
* @param elem is Dom element corresponding to 'Composer' tag
@ -246,6 +246,13 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
void setGridAnnotationFont( const QFont& f ) { mGridAnnotationFont = f; }
QFont gridAnnotationFont() const { return mGridAnnotationFont; }
/**Sets font color for grid annotations
@note: this function was added in version 2.0*/
void setAnnotationFontColor( const QColor& c ) {mGridAnnotationFontColor = c;}
/**Get font color for grid annotations
@note: this function was added in version 2.0*/
QColor annotationFontColor() const {return mGridAnnotationFontColor;}
/**Sets coordinate precision for grid annotations
@note this function was added in version 1.4*/
void setGridAnnotationPrecision( int p ) {mGridAnnotationPrecision = p;}
@ -328,6 +335,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
void setGridLineSymbol( QgsLineSymbolV2* symbol );
QgsLineSymbolV2* gridLineSymbol() { return mGridLineSymbol; }
/** Returns the grid's blending mode */
QPainter::CompositionMode gridBlendMode() const {return mGridBlendMode;}
/** Sets the grid's blending mode*/
void setGridBlendMode( QPainter::CompositionMode blendMode );
/**Sets mId to a number not yet used in the composition. mId is kept if it is not in use.
Usually, this function is called before adding the composer map to the composition*/
void assignFreeId();
@ -417,10 +429,14 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
double mGridOffsetY;
/**Font for grid line annotation*/
QFont mGridAnnotationFont;
/**Font color for grid line annotation*/
QColor mGridAnnotationFontColor;
/**Digits after the dot*/
int mGridAnnotationPrecision;
/**True if coordinate values should be drawn*/
bool mShowGridAnnotation;
/**Blend mode for grid*/
QPainter::CompositionMode mGridBlendMode;
/**Annotation position for left map side (inside / outside / not shown)*/
GridAnnotationPosition mLeftGridAnnotationPosition;

View File

@ -518,20 +518,30 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
// before compositing this on the map. This effectively flattens the layer and prevents
// blending occuring between objects on the layer
// (this is not required for raster layers or when layer caching is enabled, since that has the same effect)
if (( mRenderContext.useAdvancedEffects() ) && ( ml->blendMode() != QPainter::CompositionMode_SourceOver ) &&
( ml->type() != QgsMapLayer::RasterLayer ) &&
( split || !mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) )
bool flattenedLayer = false;
if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) )
{
mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(),
mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
mypFlattenedImage->fill( 0 );
QPainter * mypPainter = new QPainter( mypFlattenedImage );
if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() )
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
if (( vl->blendMode() != QPainter::CompositionMode_SourceOver && ( split || !mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) )
|| ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
|| ( vl->layerTransparency() != 0 ) )
{
mypPainter->setRenderHint( QPainter::Antialiasing );
flattenedLayer = true;
mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(),
mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
mypFlattenedImage->fill( 0 );
QPainter * mypPainter = new QPainter( mypFlattenedImage );
if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() )
{
mypPainter->setRenderHint( QPainter::Antialiasing );
}
mypPainter->scale( rasterScaleFactor, rasterScaleFactor );
mRenderContext.setPainter( mypPainter );
// set the painter to the feature blend mode
mypPainter->setCompositionMode( vl->featureBlendMode() );
}
mypPainter->scale( rasterScaleFactor, rasterScaleFactor );
mRenderContext.setPainter( mypPainter );
}
if ( scaleRaster )
@ -584,10 +594,19 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
}
// If we flattened this layer for alternate blend modes, composite it now
if (( mRenderContext.useAdvancedEffects() ) && ( ml->blendMode() != QPainter::CompositionMode_SourceOver ) &&
( ml->type() != QgsMapLayer::RasterLayer ) &&
( split || !mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) )
if ( flattenedLayer )
{
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
if ( vl->layerTransparency() != 0 )
{
// a layer transparency has been set, so update the alpha for the flattened layer
// by combining it with the layer transparency
QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) );
// use destination in composition mode to merge source's alpha with destination
mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
mRenderContext.painter()->fillRect( mypFlattenedImage->rect(), transparentFillColor );
}
delete mRenderContext.painter();
mRenderContext.setPainter( mypContextPainter );
mypContextPainter->save();

View File

@ -122,6 +122,8 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
, mRendererV2( NULL )
, mLabel( 0 )
, mLabelOn( false )
, mFeatureBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal feature blending
, mLayerTransparency( 0 )
, mVertexMarkerOnlyForSelection( false )
, mCache( new QgsGeometryCache( this ) )
, mEditBuffer( 0 )
@ -1759,6 +1761,22 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
setBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) e.text().toInt() ) );
}
// get and set the feature blend mode if it exists
QDomNode featureBlendModeNode = node.namedItem( "featureBlendMode" );
if ( !featureBlendModeNode.isNull() )
{
QDomElement e = featureBlendModeNode.toElement();
setFeatureBlendMode( QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode ) e.text().toInt() ) );
}
// get and set the layer transparency if it exists
QDomNode layerTransparencyNode = node.namedItem( "layerTransparency" );
if ( !layerTransparencyNode.isNull() )
{
QDomElement e = layerTransparencyNode.toElement();
setLayerTransparency( e.text().toInt() );
}
// use scale dependent visibility flag
QDomElement e = node.toElement();
mLabel->setScaleBasedVisibility( e.attribute( "scaleBasedLabelVisibilityFlag", "0" ) == "1" );
@ -2084,6 +2102,18 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
blendModeElem.appendChild( blendModeText );
node.appendChild( blendModeElem );
// add the feature blend mode field
QDomElement featureBlendModeElem = doc.createElement( "featureBlendMode" );
QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsMapRenderer::getBlendModeEnum( featureBlendMode() ) ) );
featureBlendModeElem.appendChild( featureBlendModeText );
node.appendChild( featureBlendModeElem );
// add the layer transparency
QDomElement layerTransparencyElem = doc.createElement( "layerTransparency" );
QDomText layerTransparencyText = doc.createTextNode( QString::number( layerTransparency() ) );
layerTransparencyElem.appendChild( layerTransparencyText );
node.appendChild( layerTransparencyElem );
// add the display field
QDomElement dField = doc.createElement( "displayfield" );
QDomText dFieldText = doc.createTextNode( displayField() );
@ -3340,6 +3370,30 @@ QVariant QgsVectorLayer::maximumValue( int index )
return QVariant();
}
/** Write blend mode for features */
void QgsVectorLayer::setFeatureBlendMode( const QPainter::CompositionMode featureBlendMode )
{
mFeatureBlendMode = featureBlendMode;
}
/** Read blend mode for layer */
QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
{
return mFeatureBlendMode;
}
/** Write transparency for layer */
void QgsVectorLayer::setLayerTransparency( int layerTransparency )
{
mLayerTransparency = layerTransparency;
}
/** Read transparency for layer */
int QgsVectorLayer::layerTransparency() const
{
return mLayerTransparency;
}
void QgsVectorLayer::stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer )
{
mRendererV2->stopRender( rendererContext );

View File

@ -1226,6 +1226,24 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
@note added in 1.7*/
QVariant maximumValue( int index );
/* Set the blending mode used for rendering each feature
* @note added in 2.0
*/
void setFeatureBlendMode( const QPainter::CompositionMode blendMode );
/* Returns the current blending mode for features
* @note added in 2.0
*/
QPainter::CompositionMode featureBlendMode() const;
/* Set the transparency for the vector layer
* @note added in 2.0
*/
void setLayerTransparency( int layerTransparency );
/* Returns the current transparency for the vector layer
* @note added in 2.0
*/
int layerTransparency() const;
public slots:
/**
* Select feature by its ID
@ -1480,6 +1498,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Display labels */
bool mLabelOn;
/** Blend mode for features */
QPainter::CompositionMode mFeatureBlendMode;
/** Layer transparency */
int mLayerTransparency;
/**The current type of editing marker*/
QgsVectorLayer::VertexMarkerType mCurrentVertexMarkerType;

View File

@ -89,6 +89,17 @@ QgsRendererV2PropertiesDialog::QgsRendererV2PropertiesDialog( QgsVectorLayer* la
// Blend mode
mBlendModeComboBox->setBlendMode( mLayer->blendMode() );
// Feature blend mode
mFeatureBlendComboBox->setBlendMode( mLayer->featureBlendMode() );
// Layer transparency
mLayerTransparencySlider->setValue( mLayer->layerTransparency() );
mLayerTransparencySpnBx->setValue( mLayer->layerTransparency() );
// connect layer transparency slider and spin box
connect( mLayerTransparencySlider, SIGNAL( valueChanged( int ) ), mLayerTransparencySpnBx, SLOT( setValue( int ) ) );
connect( mLayerTransparencySpnBx, SIGNAL( valueChanged( int ) ), mLayerTransparencySlider, SLOT( setValue( int ) ) );
QPixmap pix;
QgsRendererV2Registry* reg = QgsRendererV2Registry::instance();
QStringList renderers = reg->renderersList();
@ -173,8 +184,12 @@ void QgsRendererV2PropertiesDialog::apply()
mLayer->setRendererV2( renderer->clone() );
}
// set the blend mode for the layer
// set the blend modes for the layer
mLayer->setBlendMode( mBlendModeComboBox->blendMode() );
mLayer->setFeatureBlendMode( mFeatureBlendComboBox->blendMode() );
// set transparency for the layer
mLayer->setLayerTransparency( mLayerTransparencySlider->value() );
}
void QgsRendererV2PropertiesDialog::onOK()

View File

@ -56,7 +56,7 @@
<x>0</x>
<y>-202</y>
<width>440</width>
<height>1310</height>
<height>1380</height>
</rect>
</property>
<property name="sizePolicy">
@ -448,6 +448,16 @@
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QgsBlendModeComboBox" name="mGridBlendComboBox"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="mGridBlendLabel">
<property name="text">
<string>Blend mode</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -583,7 +593,7 @@
</property>
</widget>
</item>
<item row="10" column="0">
<item row="11" column="0">
<widget class="QLabel" name="mDistanceToFrameLabel">
<property name="text">
<string>Distance to map frame</string>
@ -596,10 +606,10 @@
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<widget class="QDoubleSpinBox" name="mDistanceToMapFrameSpinBox"/>
</item>
<item row="11" column="0">
<item row="12" column="0">
<widget class="QLabel" name="mCoordinatePrecisionLabel">
<property name="text">
<string>Coordinate precision</string>
@ -612,9 +622,16 @@
</property>
</widget>
</item>
<item row="11" column="1">
<item row="12" column="1">
<widget class="QSpinBox" name="mCoordinatePrecisionSpinBox"/>
</item>
<item row="10" column="1">
<widget class="QgsColorButton" name="mAnnotationFontColorButton">
<property name="text">
<string>Font color...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -702,6 +719,11 @@
<extends>QComboBox</extends>
<header>qgsblendmodecombobox.h</header>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QPushButton</extends>
<header>qgscolorbutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -14,6 +14,69 @@
<string>Renderer settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QgsCollapsibleGroupBox" name="groupBox">
<property name="title">
<string>Layer rendering</string>
</property>
<property name="collapsed" stdset="0">
<bool>false</bool>
</property>
<property name="saveCollapsedState" stdset="0">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSlider" name="mLayerTransparencySlider">
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mLayerTransparencySpnBx">
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblTransparency">
<property name="text">
<string>Layer transparency</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QgsBlendModeComboBox" name="mFeatureBlendComboBox"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="lblFeatureBlend">
<property name="text">
<string>Feature blending mode</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblLayerBlend">
<property name="text">
<string>Layer blending mode</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsBlendModeComboBox" name="mBlendModeComboBox"/>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@ -32,16 +95,6 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Blending mode</string>
</property>
</widget>
</item>
<item>
<widget class="QgsBlendModeComboBox" name="mBlendModeComboBox"/>
</item>
</layout>
</item>
<item>
@ -89,6 +142,12 @@
<extends>QComboBox</extends>
<header>qgsblendmodecombobox.h</header>
</customwidget>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>cboRenderers</tabstop>

View File

@ -45,12 +45,15 @@ class TestQgsBlendModes: public QObject
void cleanup() {};// will be called after every testfunction.
void vectorBlending();
void featureBlending();
void vectorLayerTransparency();
void rasterBlending();
private:
bool imageCheck( QString theType ); //as above
QgsMapRenderer * mpMapRenderer;
QgsMapLayer * mpPointsLayer;
QgsMapLayer * mpPolysLayer;
QgsVectorLayer * mpLinesLayer;
QgsRasterLayer* mRasterLayer1;
QgsRasterLayer* mRasterLayer2;
QString mTestDataDir;
@ -85,6 +88,14 @@ void TestQgsBlendModes::initTestCase()
QgsMapLayerRegistry::instance()->addMapLayers(
QList<QgsMapLayer *>() << mpPolysLayer );
//create a line layer that will be used in tests
QString myLinesFileName = mTestDataDir + "lines.shp";
QFileInfo myLineFileInfo( myLinesFileName );
mpLinesLayer = new QgsVectorLayer( myLineFileInfo.filePath(),
myLineFileInfo.completeBaseName(), "ogr" );
QgsMapLayerRegistry::instance()->addMapLayers(
QList<QgsMapLayer *>() << mpLinesLayer );
//create two raster layers
QFileInfo rasterFileInfo( mTestDataDir + "landsat.tif" );
mRasterLayer1 = new QgsRasterLayer( rasterFileInfo.filePath(),
@ -121,6 +132,35 @@ void TestQgsBlendModes::vectorBlending()
QVERIFY( imageCheck( "vector_blendmodes" ) );
}
void TestQgsBlendModes::featureBlending()
{
//Add two vector layers
QStringList myLayers;
myLayers << mpLinesLayer->id();
myLayers << mpPolysLayer->id();
mpMapRenderer->setLayerSet( myLayers );
//Set feature blending modes for point layer
mpLinesLayer->setFeatureBlendMode( QPainter::CompositionMode_Plus );
mpMapRenderer->setExtent( mpPointsLayer->extent() );
QVERIFY( imageCheck( "vector_featureblendmodes" ) );
}
void TestQgsBlendModes::vectorLayerTransparency()
{
//Add two vector layers
QStringList myLayers;
myLayers << mpLinesLayer->id();
myLayers << mpPolysLayer->id();
mpMapRenderer->setLayerSet( myLayers );
mpLinesLayer->setFeatureBlendMode( QPainter::CompositionMode_SourceOver );
//Set feature blending modes for point layer
mpLinesLayer->setLayerTransparency( 50 );
mpMapRenderer->setExtent( mpPointsLayer->extent() );
QVERIFY( imageCheck( "vector_layertransparency" ) );
}
void TestQgsBlendModes::rasterBlending()
{
//Add two raster layers to map renderer

View File

@ -107,6 +107,7 @@ void TestQgsComposerMap::grid()
mComposerMap->setGridIntervalY( 2000 );
mComposerMap->setShowGridAnnotation( true );
mComposerMap->setGridPenWidth( 0.5 );
mComposerMap->setGridPenColor( QColor( 0, 255, 0 ) );
mComposerMap->setGridAnnotationPrecision( 0 );
mComposerMap->setGridAnnotationPosition( QgsComposerMap::Disabled, QgsComposerMap::Left );
mComposerMap->setGridAnnotationPosition( QgsComposerMap::OutsideMapFrame, QgsComposerMap::Right );
@ -114,6 +115,8 @@ void TestQgsComposerMap::grid()
mComposerMap->setGridAnnotationPosition( QgsComposerMap::OutsideMapFrame, QgsComposerMap::Bottom );
mComposerMap->setGridAnnotationDirection( QgsComposerMap::Horizontal, QgsComposerMap::Right );
mComposerMap->setGridAnnotationDirection( QgsComposerMap::Horizontal, QgsComposerMap::Bottom );
mComposerMap->setAnnotationFontColor( QColor( 255, 0, 0, 150 ) );
mComposerMap->setGridBlendMode( QPainter::CompositionMode_Overlay );
QgsCompositionChecker checker( "Composer map grid", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() +
"control_images" + QDir::separator() + "expected_composermap" + QDir::separator() + "composermap_landsat_grid.png" ) );
bool testResult = checker.testComposition();
@ -200,6 +203,10 @@ void TestQgsComposerMap::uniqueId()
void TestQgsComposerMap::zebraStyle()
{
mComposerMap->setGridPenColor( QColor( 0, 0, 0 ) );
mComposerMap->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) );
mComposerMap->setGridBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->setGridFrameStyle( QgsComposerMap::Zebra );
mComposerMap->setGridEnabled( true );

View File

@ -67,6 +67,11 @@ class TestQgsBlendModes(TestCase):
self.mPolygonLayer = QgsVectorLayer(myShpFile, 'Polygons', 'ogr')
self.mMapRegistry.addMapLayer(self.mPolygonLayer)
# create line layer
myShpFile = os.path.join(TEST_DATA_DIR, 'lines.shp')
self.mLineLayer = QgsVectorLayer(myShpFile, 'Lines', 'ogr')
self.mMapRegistry.addMapLayer(self.mLineLayer)
# create two raster layers
myRasterFile = os.path.join(TEST_DATA_DIR, 'landsat.tif')
self.mRasterLayer1 = QgsRasterLayer(myRasterFile, "raster1")
@ -108,6 +113,50 @@ class TestQgsBlendModes(TestCase):
myMessage = ('vector blending failed')
assert myResult, myMessage
def testVectorFeatureBlending(self):
"""Test that feature blend modes work for vector layers."""
#Add vector layers to map
myLayers = QStringList()
myLayers.append(self.mLineLayer.id())
myLayers.append(self.mPolygonLayer.id())
self.mMapRenderer.setLayerSet(myLayers)
self.mMapRenderer.setExtent(self.mPointLayer.extent())
self.mPolygonLayer.setBlendMode(QPainter.CompositionMode_Multiply)
#Set feature blending for line layer
self.mLineLayer.setFeatureBlendMode(QPainter.CompositionMode_Plus)
checker = QgsRenderChecker()
checker.setControlName("expected_vector_featureblendmodes")
checker.setMapRenderer(self.mMapRenderer)
myResult = checker.runTest("vector_featureblendmodes");
myMessage = ('vector feature blending failed')
assert myResult, myMessage
def testVectorLayerTransparency(self):
"""Test that layer transparency works for vector layers."""
#Add vector layers to map
myLayers = QStringList()
myLayers.append(self.mLineLayer.id())
myLayers.append(self.mPolygonLayer.id())
self.mMapRenderer.setLayerSet(myLayers)
self.mMapRenderer.setExtent(self.mPointLayer.extent())
self.mPolygonLayer.setBlendMode(QPainter.CompositionMode_Multiply)
#Set feature blending for line layer
self.mLineLayer.setLayerTransparency( 50 )
checker = QgsRenderChecker()
checker.setControlName("expected_vector_layertransparency")
checker.setMapRenderer(self.mMapRenderer)
myResult = checker.runTest("vector_layertransparency");
myMessage = ('vector layer transparency failed')
assert myResult, myMessage
def testRasterBlending(self):
"""Test that blend modes work for raster layers."""
#Add raster layers to map

View File

@ -16,7 +16,8 @@ import os
from PyQt4.QtCore import (QStringList,
QFileInfo)
from PyQt4.QtXml import QDomDocument
from PyQt4.QtGui import QPainter
from PyQt4.QtGui import (QPainter,
QColor)
from qgis.core import (QgsComposerMap,
QgsRectangle,
@ -76,6 +77,7 @@ class TestQgsComposerMap(TestCase):
self.mComposerMap.setGridIntervalY(2000)
self.mComposerMap.setShowGridAnnotation(True)
self.mComposerMap.setGridPenWidth(0.5)
self.mComposerMap.setGridPenColor(QColor(0,255,0))
self.mComposerMap.setGridAnnotationPrecision(0)
self.mComposerMap.setGridAnnotationPosition(QgsComposerMap.Disabled,
QgsComposerMap.Left)
@ -91,6 +93,8 @@ class TestQgsComposerMap(TestCase):
QgsComposerMap.Right)
self.mComposerMap.setGridAnnotationDirection(QgsComposerMap.Horizontal,
QgsComposerMap.Bottom)
self.mComposerMap.setAnnotationFontColor(QColor(255,0,0,150))
self.mComposerMap.setGridBlendMode(QPainter.CompositionMode_Overlay)
checker = QgsCompositionChecker()
myPath = os.path.join(TEST_DATA_DIR,
'control_images',

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 KiB