Skip to content

Commit

Permalink
Merge pull request #475 from nyalldawson/blend_modes
Browse files Browse the repository at this point in the history
Add support for blending (composition) modes, eg Overlay, Mutiply, etc (Close #5248)
  • Loading branch information
NathanW2 committed Mar 22, 2013
2 parents 9afe76d + 647fbdb commit 8f9ca6f
Show file tree
Hide file tree
Showing 10 changed files with 390 additions and 4 deletions.
5 changes: 5 additions & 0 deletions src/app/qgsrasterlayerproperties.cpp
Expand Up @@ -243,6 +243,9 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv
mMaximumOversamplingSpinBox->setValue( resampleFilter->maxOversampling() );
}

//blend mode
mBlendModeComboBox->setBlendMode( mRasterLayer->blendMode() );

//transparency band
if ( provider )
{
Expand Down Expand Up @@ -798,6 +801,8 @@ void QgsRasterLayerProperties::apply()
resampleFilter->setMaxOversampling( mMaximumOversamplingSpinBox->value() );
}

//set the blend mode for the layer
mRasterLayer->setBlendMode(( QgsMapLayer::BlendMode ) mBlendModeComboBox->blendMode() );

//get the thumbnail for the layer
pixmapThumbnail->setPixmap( mRasterLayer->previewAsPixmap( pixmapThumbnail->size() ) );
Expand Down
6 changes: 6 additions & 0 deletions src/app/qgsvectorlayerproperties.cpp
Expand Up @@ -192,6 +192,9 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
mLayerAbstractTextEdit->setPlainText( layer->abstract() );
}

// Blend mode
mBlendModeComboBox->setBlendMode( layer->blendMode() );

QSettings settings;
restoreGeometry( settings.value( "/Windows/VectorLayerProperties/geometry" ).toByteArray() );
int tabIndex = settings.value( "/Windows/VectorLayerProperties/row", 0 ).toInt();
Expand Down Expand Up @@ -528,6 +531,9 @@ void QgsVectorLayerProperties::apply()
layer->setTitle( mLayerTitleLineEdit->text() );
layer->setAbstract( mLayerAbstractTextEdit->toPlainText() );

// set the blend mode for the layer
layer->setBlendMode(( QgsMapLayer::BlendMode ) mBlendModeComboBox->blendMode() );

// update symbology
emit refreshLegend( layer->id(), QgsLegendItem::DontChange );

Expand Down
71 changes: 70 additions & 1 deletion src/core/qgsmaplayer.cpp
Expand Up @@ -49,7 +49,8 @@ QgsMapLayer::QgsMapLayer( QgsMapLayer::LayerType type,
mDataSource( source ),
mLayerOrigName( lyrname ), // store the original name
mID( "" ),
mLayerType( type )
mLayerType( type ),
mBlendMode( QgsMapLayer::BlendNormal ) // Default to normal blending
{
mCRS = new QgsCoordinateReferenceSystem();

Expand Down Expand Up @@ -133,6 +134,58 @@ QgsRectangle QgsMapLayer::extent()
return mExtent;
}

/** Write blend mode for layer */
void QgsMapLayer::setBlendMode( const QgsMapLayer::BlendMode blendMode )
{
mBlendMode = blendMode;
}

/** Read blend mode for layer */
QgsMapLayer::BlendMode QgsMapLayer::blendMode() const
{
return mBlendMode;
}

/** Returns a QPainter::CompositionMode corresponding to the current
* blend mode for this layer
*/
QPainter::CompositionMode QgsMapLayer::getCompositionMode()
{
// Map QgsMapLayer::BlendNormal to QPainter::CompositionMode
switch ( mBlendMode )
{
case QgsMapLayer::BlendNormal:
return QPainter::CompositionMode_SourceOver;
case QgsMapLayer::BlendLighten:
return QPainter::CompositionMode_Lighten;
case QgsMapLayer::BlendScreen:
return QPainter::CompositionMode_Screen;
case QgsMapLayer::BlendDodge:
return QPainter::CompositionMode_ColorDodge;
case QgsMapLayer::BlendAddition:
return QPainter::CompositionMode_Plus;
case QgsMapLayer::BlendDarken:
return QPainter::CompositionMode_Darken;
case QgsMapLayer::BlendMultiply:
return QPainter::CompositionMode_Multiply;
case QgsMapLayer::BlendBurn:
return QPainter::CompositionMode_ColorBurn;
case QgsMapLayer::BlendOverlay:
return QPainter::CompositionMode_Overlay;
case QgsMapLayer::BlendSoftLight:
return QPainter::CompositionMode_SoftLight;
case QgsMapLayer::BlendHardLight:
return QPainter::CompositionMode_HardLight;
case QgsMapLayer::BlendDifference:
return QPainter::CompositionMode_Difference;
case QgsMapLayer::BlendSubtract:
return QPainter::CompositionMode_Exclusion;
default:
return QPainter::CompositionMode_SourceOver;
}
}


bool QgsMapLayer::draw( QgsRenderContext& rendererContext )
{
Q_UNUSED( rendererContext );
Expand Down Expand Up @@ -358,6 +411,15 @@ bool QgsMapLayer::readXML( const QDomNode& layer_node )
setTransparency( myElement.text().toInt() );
}

//read blend mode
QDomNode blendModeNode = layer_node.namedItem( "blendMode" );
if ( ! blendModeNode.isNull() )
{
// set blend mode if it's specified in project
QDomElement myElement = blendModeNode.toElement();
setBlendMode(( QgsMapLayer::BlendMode )myElement.text().toInt() );
}

readCustomProperties( layer_node );

return true;
Expand Down Expand Up @@ -473,6 +535,13 @@ bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )
QDomText transparencyLevelIntText = document.createTextNode( QString::number( getTransparency() ) );
transparencyLevelIntElement.appendChild( transparencyLevelIntText );
maplayer.appendChild( transparencyLevelIntElement );

// <blendMode>
QDomElement blendModeElement = document.createElement( "blendMode" );
QDomText blendModeText = document.createTextNode( QString::number( blendMode() ) );
blendModeElement.appendChild( blendModeText );
maplayer.appendChild( blendModeElement );

// now append layer node to map layer node

layer_node.appendChild( maplayer );
Expand Down
33 changes: 33 additions & 0 deletions src/core/qgsmaplayer.h
Expand Up @@ -24,6 +24,7 @@
#include <QVariant>
#include <QImage>
#include <QDomNode>
#include <QPainter>

#include "qgis.h"
#include "qgserror.h"
Expand Down Expand Up @@ -52,6 +53,26 @@ class CORE_EXPORT QgsMapLayer : public QObject
RasterLayer,
PluginLayer // added in 1.5
};

/** Blending modes enum defining the available composition modes that can
* be used when rendering a layer
*/
enum BlendMode
{
BlendNormal,
BlendLighten,
BlendScreen,
BlendDodge,
BlendAddition,
BlendDarken,
BlendMultiply,
BlendBurn,
BlendOverlay,
BlendSoftLight,
BlendHardLight,
BlendDifference,
BlendSubtract
};

/** Constructor
* @param type Type of layer as defined in QgsMapLayer::LayerType enum
Expand Down Expand Up @@ -94,6 +115,15 @@ class CORE_EXPORT QgsMapLayer : public QObject
void setAbstract( const QString& abstract ) { mAbstract = abstract; }
const QString& abstract() const { return mAbstract; }

/* Set the blending mode used for rendering a layer */
void setBlendMode( const QgsMapLayer::BlendMode blendMode );
/* Returns the current blending mode for a layer */
QgsMapLayer::BlendMode blendMode() const;
/** Returns a QPainter::CompositionMode corresponding to the
* current blending mode for the layer
*/
QPainter::CompositionMode getCompositionMode();

/**Synchronises with changes in the datasource
@note added in version 1.6*/
virtual void reload() {}
Expand Down Expand Up @@ -462,6 +492,9 @@ class CORE_EXPORT QgsMapLayer : public QObject

/** Type of the layer (eg. vector, raster) */
QgsMapLayer::LayerType mLayerType;

/** Blend mode for the layer */
QgsMapLayer::BlendMode mBlendMode;

/** Tag for embedding additional information */
QString mTag;
Expand Down
7 changes: 6 additions & 1 deletion src/core/qgsmaprenderer.cpp
Expand Up @@ -377,13 +377,18 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
continue;
}

QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5" )
QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" )
.arg( ml->name() )
.arg( ml->minimumScale() )
.arg( ml->maximumScale() )
.arg( ml->hasScaleBasedVisibility() )
.arg( ml->extent().toString() )
.arg( ml->blendMode() )
);

// Set the QPainter composition mode so that this layer is rendered using
// the desired blending mode
mypContextPainter->setCompositionMode(ml->getCompositionMode());

if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview )
{
Expand Down
3 changes: 3 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -48,6 +48,7 @@ qgisinterface.cpp
qgsannotationitem.cpp
qgsattributeeditor.cpp
qgslegendinterface.cpp
qgsblendmodecombobox.cpp
qgscharacterselectdialog.cpp
qgscolorbutton.cpp
qgscomposerview.cpp
Expand Down Expand Up @@ -153,6 +154,7 @@ attributetable/qgsattributetablememorymodel.h
attributetable/qgsattributetabledelegate.h

qgsattributeeditor.h
qgsblendmodecombobox.h
qgscharacterselectdialog.h
qgscomposerview.h
qgsdetaileditemdelegate.h
Expand Down Expand Up @@ -227,6 +229,7 @@ qgsrubberband.h
qgsvertexmarker.h
qgsmaptip.h
qgsscalecombobox.h
qgsblendmodecombobox.h
qgssearchquerybuilder.h
qgsattributeeditor.h
qgsfieldvalidator.h
Expand Down
112 changes: 112 additions & 0 deletions src/gui/qgsblendmodecombobox.cpp
@@ -0,0 +1,112 @@
/***************************************************************************
qgsblendmodecombobox.cpp
------------------------
begin : March 21, 2013
copyright : (C) 2013 by Nyall Dawson
email : nyall.dawson@gmail.com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgis.h"
#include "qgslogger.h"
#include "qgsblendmodecombobox.h"

#include <QAbstractItemView>
#include <QLocale>
#include <QSettings>
#include <QLineEdit>

QgsBlendModeComboBox::QgsBlendModeComboBox( QWidget* parent ) : QComboBox( parent )
{
updateModes();
}

QgsBlendModeComboBox::~QgsBlendModeComboBox()
{
}

/* Returns a QStringList of the translated blend modes
* "-" is used to indicate the position of a seperator in the list
* This list is designed to emulate GIMP's layer modes, where
* blending modes are grouped by their effect (lightening, darkening, etc)
*/
QStringList QgsBlendModeComboBox::blendModesList() const
{
return QStringList() << tr( "Normal" )
<< "-"
<< tr( "Lighten" )
<< tr( "Screen" )
<< tr( "Dodge" )
<< tr( "Addition" )
<< "-"
<< tr( "Darken" )
<< tr( "Multiply" )
<< tr( "Burn" )
<< "-"
<< tr( "Overlay" )
<< tr( "Soft light" )
<< tr( "Hard light" )
<< "-"
<< tr( "Difference" )
<< tr( "Subtract" );
}

/* Populates the blend mode combo box, and sets up mapping for
* blend modes to combo box indexes
*/
void QgsBlendModeComboBox::updateModes()
{
blockSignals( true );
clear();

QStringList myBlendModesList = blendModesList();
QStringList::const_iterator blendModeIt = myBlendModesList.constBegin();

mBlendModeToListIndex.resize( myBlendModesList.count() );
mListIndexToBlendMode.resize( myBlendModesList.count() );

// Loop through blend modes
int index = 0;
int blendModeIndex = 0;
for ( ; blendModeIt != myBlendModesList.constEnd(); ++blendModeIt )
{
if ( *blendModeIt == "-" )
{
// Add seperator
insertSeparator( index );
}
else
{
// Not a seperator, so store indexes for translation
// between blend modes and combo box item index
addItem( *blendModeIt );
mListIndexToBlendMode[ index ] = blendModeIndex;
mBlendModeToListIndex[ blendModeIndex ] = index;
blendModeIndex++;
}
index++;
}

blockSignals( false );
}

//! Function to read the selected blend mode as int
int QgsBlendModeComboBox::blendMode()
{
return mListIndexToBlendMode[ currentIndex()];
}

//! Function to set the selected blend mode from int
void QgsBlendModeComboBox::setBlendMode( int blendMode )
{
setCurrentIndex( mBlendModeToListIndex[ blendMode ] );
}

0 comments on commit 8f9ca6f

Please sign in to comment.