Skip to content

Commit

Permalink
Port item blend mode support to layouts
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 7, 2017
1 parent 0143d0b commit 4e8878d
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 9 deletions.
3 changes: 2 additions & 1 deletion python/core/core_auto.sip
Expand Up @@ -158,7 +158,6 @@
%Include composer/qgscomposertexttable.sip
%Include composer/qgspaperitem.sip
%Include layout/qgslayoutaligner.sip
%Include layout/qgslayoutcontext.sip
%Include layout/qgslayoutgridsettings.sip
%Include layout/qgslayoutmeasurement.sip
%Include layout/qgslayoutmeasurementconverter.sip
Expand Down Expand Up @@ -403,6 +402,8 @@
%Include gps/qgsnmeaconnection.sip
%Include gps/qgsgpsdconnection.sip
%Include layout/qgslayout.sip
%Include layout/qgslayoutcontext.sip
%Include layout/qgslayouteffect.sip
%Include layout/qgslayoutguidecollection.sip
%Include layout/qgslayoutitem.sip
%Include layout/qgslayoutitemgroup.sip
Expand Down
18 changes: 18 additions & 0 deletions python/core/layout/qgslayoutitem.sip
Expand Up @@ -412,6 +412,19 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
Sets the background ``color`` for this item.
.. seealso:: backgroundColor()
.. seealso:: setBackgroundEnabled()
%End

QPainter::CompositionMode blendMode() const;
%Docstring
Returns the item's composition blending mode.
.. seealso:: setBlendMode()
:rtype: QPainter.CompositionMode
%End

void setBlendMode( const QPainter::CompositionMode mode );
%Docstring
Sets the item's composition blending ``mode``.
.. seealso:: blendMode()
%End

virtual double estimatedFrameBleed() const;
Expand Down Expand Up @@ -579,6 +592,11 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
after the frame color is set and a later call to update() must be made.
%End

void refreshBlendMode();
%Docstring
Refresh item's blend mode, considering data defined blend mode.
%End

QPointF adjustPointForReferencePosition( const QPointF &point, const QSizeF &size, const ReferencePoint &reference ) const;
%Docstring
Adjusts the specified ``point`` at which a ``reference`` position of the item
Expand Down
3 changes: 3 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -362,6 +362,7 @@ SET(QGIS_CORE_SRCS
layout/qgslayout.cpp
layout/qgslayoutaligner.cpp
layout/qgslayoutcontext.cpp
layout/qgslayouteffect.cpp
layout/qgslayoutgridsettings.cpp
layout/qgslayoutguidecollection.cpp
layout/qgslayoutitem.cpp
Expand Down Expand Up @@ -713,6 +714,8 @@ SET(QGIS_CORE_MOC_HDRS
gps/qgsgpsdconnection.h

layout/qgslayout.h
layout/qgslayoutcontext.h
layout/qgslayouteffect.h
layout/qgslayoutguidecollection.h
layout/qgslayoutitem.h
layout/qgslayoutitemgroup.h
Expand Down
62 changes: 62 additions & 0 deletions src/core/layout/qgslayouteffect.cpp
@@ -0,0 +1,62 @@
/***************************************************************************
qgslayouteffect.cpp
-------------------
begin : October 2017
copyright : (C) 2017 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 <QPainter>

#include "qgslayouteffect.h"

void QgsLayoutEffect::draw( QPainter *painter )
{
QPoint offset;
QPixmap pixmap;

// Set desired composition mode then draw source
painter->setCompositionMode( mCompositionMode );

if ( mCompositionMode == QPainter::CompositionMode_SourceOver )
{
// Normal (sourceover) blending, do faster drawSource operation
drawSource( painter );
return;
}

// Otherwise, draw using pixmap so QPrinter output works as expected
if ( sourceIsPixmap() )
{
// No point in drawing in device coordinates (pixmap will be scaled anyways).
pixmap = sourcePixmap( Qt::LogicalCoordinates, &offset );
}
else
{
// Draw pixmap in device coordinates to avoid pixmap scaling;
pixmap = sourcePixmap( Qt::DeviceCoordinates, &offset );
painter->setWorldTransform( QTransform() );
}

painter->drawPixmap( offset, pixmap );
}

void QgsLayoutEffect::setCompositionMode( QPainter::CompositionMode compositionMode )
{
mCompositionMode = compositionMode;

// force redraw with new composition mode
update();
}



70 changes: 70 additions & 0 deletions src/core/layout/qgslayouteffect.h
@@ -0,0 +1,70 @@
/***************************************************************************
qgslayouteffect.h
-------------------
begin : October 2017
copyright : (C) 2017 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. *
* *
***************************************************************************/

#ifndef QGSLAYOUTEFFECT_H
#define QGSLAYOUTEFFECT_H

#include <QGraphicsEffect>
#include <QPainter>

#include "qgis_core.h"

/**
* \ingroup core
* \class QgsLayoutEffect
*
* A QGraphicsEffect subclass used for rendering layout items
* onto a scene with custom composition modes.
*
* \since QGIS 3.0
*/
class CORE_EXPORT QgsLayoutEffect : public QGraphicsEffect
{
Q_OBJECT

public:

/**
* Constructor for QgsLayoutEffect.
*/
QgsLayoutEffect() = default;

/**
* Sets the composition (blending) \a mode used for rendering
* the item.
* \see compositionMode()
*/
void setCompositionMode( QPainter::CompositionMode mode );

/**
* Returns the composition (blending) mode used for rendering
* the item.
* \see setCompositionMode()
*/
QPainter::CompositionMode compositionMode() const { return mCompositionMode; }

protected:

virtual void draw( QPainter *painter ) override;

private:

QPainter::CompositionMode mCompositionMode = QPainter::CompositionMode_SourceOver;
};

#endif // QGSLAYOUTEFFECT_H

54 changes: 49 additions & 5 deletions src/core/layout/qgslayoutitem.cpp
Expand Up @@ -22,6 +22,8 @@
#include "qgslayoutmodel.h"
#include "qgssymbollayerutils.h"
#include "qgslayoutitemgroup.h"
#include "qgspainting.h"
#include "qgslayouteffect.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QUuid>
Expand Down Expand Up @@ -61,6 +63,18 @@ QgsLayoutItem::QgsLayoutItem( QgsLayout *layout, bool manageZValue )
{
mLayoutManagesZValue = false;
}

// Setup layout effect
mEffect.reset( new QgsLayoutEffect() );
if ( mLayout )
{
mEffect->setEnabled( mLayout->context().flags() & QgsLayoutContext::FlagUseAdvancedEffects );
connect( &mLayout->context(), &QgsLayoutContext::flagsChanged, this, [ = ]( QgsLayoutContext::Flags flags )
{
mEffect->setEnabled( flags & QgsLayoutContext::FlagUseAdvancedEffects );
} );
}
setGraphicsEffect( mEffect.get() );
}

QgsLayoutItem::~QgsLayoutItem()
Expand Down Expand Up @@ -497,6 +511,13 @@ void QgsLayoutItem::setBackgroundColor( const QColor &color )
refreshBackgroundColor( true );
}

void QgsLayoutItem::setBlendMode( const QPainter::CompositionMode mode )
{
mBlendMode = mode;
// Update the item effect to use the new blend mode
refreshBlendMode();
}

double QgsLayoutItem::estimatedFrameBleed() const
{
if ( !hasFrame() )
Expand Down Expand Up @@ -592,6 +613,10 @@ void QgsLayoutItem::refreshDataDefinedProperty( const QgsLayoutObject::DataDefin
{
refreshBackgroundColor( false );
}
if ( property == QgsLayoutObject::BlendMode || property == QgsLayoutObject::AllProperties )
{
refreshBlendMode();
}
}

void QgsLayoutItem::setItemRotation( const double angle )
Expand Down Expand Up @@ -810,11 +835,11 @@ bool QgsLayoutItem::writePropertiesToElement( QDomElement &element, QDomDocument
bgColorElem.setAttribute( QStringLiteral( "alpha" ), QString::number( mBackgroundColor.alpha() ) );
element.appendChild( bgColorElem );

//TODO
#if 0
//blend mode
// composerItemElem.setAttribute( "blendMode", QgsMapRenderer::getBlendModeEnum( mBlendMode ) );
element.setAttribute( "blendMode", QgsPainting::getBlendModeEnum( mBlendMode ) );

//TODO
#if 0
//transparency
// composerItemElem.setAttribute( "transparency", QString::number( mTransparency ) );

Expand Down Expand Up @@ -937,9 +962,10 @@ bool QgsLayoutItem::readPropertiesFromElement( const QDomElement &element, const
refreshBackgroundColor( false );
}

#if 0 //TODO
//blend mode
setBlendMode( QgsMapRenderer::getCompositionMode( ( QgsMapRenderer::BlendMode ) itemElem.attribute( "blendMode", "0" ).toUInt() ) );
setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( element.attribute( QStringLiteral( "blendMode" ), QStringLiteral( "0" ) ).toUInt() ) ) );

#if 0 //TODO
//transparency
setTransparency( itemElem.attribute( "transparency", "0" ).toInt() );
mExcludeFromExports = itemElem.attribute( "excludeFromExports", "0" ).toInt();
Expand Down Expand Up @@ -1059,3 +1085,21 @@ void QgsLayoutItem::refreshBackgroundColor( bool updateItem )
update();
}
}

void QgsLayoutItem::refreshBlendMode()
{
QPainter::CompositionMode blendMode = mBlendMode;

//data defined blend mode set?
bool ok = false;
QString blendStr = mDataDefinedProperties.valueAsString( QgsLayoutObject::BlendMode, createExpressionContext(), QString(), &ok );
if ( ok && !blendStr.isEmpty() )
{
QString blendstr = blendStr.trimmed();
QPainter::CompositionMode blendModeD = QgsSymbolLayerUtils::decodeBlendMode( blendstr );
blendMode = blendModeD;
}

// Update the item effect to use the new blend mode
mEffect->setCompositionMode( blendMode );
}
23 changes: 23 additions & 0 deletions src/core/layout/qgslayoutitem.h
Expand Up @@ -25,10 +25,12 @@
#include "qgslayoutundocommand.h"
#include "qgslayoutmeasurement.h"
#include <QGraphicsRectItem>
#include <QPainter>

class QgsLayout;
class QPainter;
class QgsLayoutItemGroup;
class QgsLayoutEffect;

/**
* \ingroup core
Expand Down Expand Up @@ -415,6 +417,18 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
void setBackgroundColor( const QColor &color );

/**
* Returns the item's composition blending mode.
* \see setBlendMode()
*/
QPainter::CompositionMode blendMode() const { return mBlendMode; }

/**
* Sets the item's composition blending \a mode.
* \see blendMode()
*/
void setBlendMode( const QPainter::CompositionMode mode );

/**
* Returns the estimated amount the item's frame bleeds outside the item's
* actual rectangle. For instance, if the item has a 2mm frame stroke, then
Expand Down Expand Up @@ -577,6 +591,11 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
void refreshBackgroundColor( bool updateItem = true );

/**
* Refresh item's blend mode, considering data defined blend mode.
*/
void refreshBlendMode();

/**
* Adjusts the specified \a point at which a \a reference position of the item
* sits and returns the top left corner of the item, if reference point were placed at the specified position.
Expand Down Expand Up @@ -638,6 +657,10 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
QgsLayoutPoint mItemPosition;
double mItemRotation = 0.0;

//! Composition blend mode for item
QPainter::CompositionMode mBlendMode = QPainter::CompositionMode_SourceOver;
std::unique_ptr< QgsLayoutEffect > mEffect;

QImage mItemCachedImage;
double mItemCacheDpi = -1;

Expand Down
4 changes: 1 addition & 3 deletions src/gui/layout/qgslayoutitemwidget.cpp
Expand Up @@ -640,8 +640,8 @@ void QgsLayoutItemPropertiesWidget::setValuesForGuiNonPositionElements()
mItemIdLineEdit->setText( mItem->id() );
mFrameGroupBox->setChecked( mItem->hasFrame() );
mBackgroundGroupBox->setChecked( mItem->hasBackground() );
#if 0//TODO
mBlendModeCombo->setBlendMode( mItem->blendMode() );
#if 0//TODO
mOpacityWidget->setOpacity( mItem->itemOpacity() );
mItemRotationSpinBox->setValue( mItem->itemRotation( QgsComposerObject::OriginalValue ) );
mExcludeFromPrintsCheckBox->setChecked( mItem->excludeFromExports( QgsComposerObject::OriginalValue ) );
Expand Down Expand Up @@ -698,9 +698,7 @@ void QgsLayoutItemPropertiesWidget::mBlendModeCombo_currentIndexChanged( int ind
if ( mItem )
{
mItem->layout()->undoStack()->beginCommand( mItem, tr( "Change Blend Mode" ) );
#if 0 //TODO
mItem->setBlendMode( mBlendModeCombo->blendMode() );
#endif
mItem->layout()->undoStack()->endCommand();
}
}
Expand Down

0 comments on commit 4e8878d

Please sign in to comment.