Skip to content
Permalink
Browse files

[layouts] Avoid rasterizing the whole layout when only a single item …

…has opacity set

Instead, only rasterize that one item and pre-apply it's opacity
to the rasterized version. This keeps all the rest of the layout
content as vectors/text.

(cherry picked from commit d08ecc2)
  • Loading branch information
nyalldawson committed Dec 5, 2018
1 parent 856486a commit 03e226404e94f159ec3d42b309354d3be5a36598
@@ -238,6 +238,13 @@ Base class for graphical items within a :py:class:`QgsLayout`.
UndoCustomCommand,
};

enum Flag
{
FlagOverridesPaint,
};
typedef QFlags<QgsLayoutItem::Flag> Flags;


explicit QgsLayoutItem( QgsLayout *layout, bool manageZValue = true );
%Docstring
Constructor for QgsLayoutItem, with the specified parent ``layout``.
@@ -279,6 +286,13 @@ upon creation.
.. seealso:: :py:func:`id`

.. seealso:: :py:func:`setId`
%End

virtual Flags itemFlags() const;
%Docstring
Returns the item's flags, which indicate how the item behaves.

.. versionadded:: 3.4.3
%End

QString id() const;
@@ -1166,6 +1180,9 @@ Applies any present data defined size overrides to the specified layout ``size``

};

QFlags<QgsLayoutItem::Flag> operator|(QgsLayoutItem::Flag f1, QFlags<QgsLayoutItem::Flag> f2);





@@ -67,6 +67,8 @@ The caller takes responsibility for deleting the returned object.

virtual QIcon icon() const;

virtual QgsLayoutItem::Flags itemFlags() const;

virtual QString displayName() const;


@@ -41,6 +41,8 @@ Constructor for QgsLayoutItemMap, with the specified parent ``layout``.

virtual QIcon icon() const;

virtual QgsLayoutItem::Flags itemFlags() const;


void assignFreeId();
%Docstring
@@ -286,8 +286,6 @@ Forces a recalculation of the picture's frame size

virtual void refreshDataDefinedProperty( QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties );

virtual bool containsAdvancedEffects() const;


signals:
void pictureRotationChanged( double newRotation );
@@ -27,6 +27,7 @@
#include "qgslayoutundostack.h"
#include "qgslayoutpagecollection.h"
#include "qgslayoutitempage.h"
#include "qgsimageoperation.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QUuid>
@@ -123,6 +124,11 @@ int QgsLayoutItem::type() const
return QgsLayoutItemRegistry::LayoutItem;
}

QgsLayoutItem::Flags QgsLayoutItem::itemFlags() const
{
return nullptr;
}

void QgsLayoutItem::setId( const QString &id )
{
if ( id == mId )
@@ -326,6 +332,8 @@ void QgsLayoutItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *it
drawFrame( context );
p.end();

QgsImageOperation::multiplyOpacity( image, mEvaluatedOpacity );

painter->save();
// scale painter from mm to dots
painter->scale( 1.0 / context.scaleFactor(), 1.0 / context.scaleFactor() );
@@ -854,7 +862,9 @@ void QgsLayoutItem::setBlendMode( const QPainter::CompositionMode mode )
void QgsLayoutItem::setItemOpacity( double opacity )
{
mOpacity = opacity;
refreshOpacity( true );
refreshOpacity( mItemCachedImage.isNull() );
if ( !mItemCachedImage.isNull() )
invalidateCache();
}

bool QgsLayoutItem::excludeFromExports() const
@@ -870,12 +880,13 @@ void QgsLayoutItem::setExcludeFromExports( bool exclude )

bool QgsLayoutItem::containsAdvancedEffects() const
{
return false;
return itemFlags() & Flag::FlagOverridesPaint ? false : mEvaluatedOpacity < 1.0;
}

bool QgsLayoutItem::requiresRasterization() const
{
return itemOpacity() < 1.0 || blendMode() != QPainter::CompositionMode_SourceOver;
return ( itemFlags() & Flag::FlagOverridesPaint && itemOpacity() < 1.0 ) ||
blendMode() != QPainter::CompositionMode_SourceOver;
}

double QgsLayoutItem::estimatedFrameBleed() const
@@ -1360,7 +1371,14 @@ void QgsLayoutItem::refreshOpacity( bool updateItem )
double opacity = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::Opacity, createExpressionContext(), mOpacity * 100.0 );

// Set the QGraphicItem's opacity
setOpacity( opacity / 100.0 );
mEvaluatedOpacity = opacity / 100.0;

if ( itemFlags() & QgsLayoutItem::FlagOverridesPaint )
{
// item handles it's own painting, so it won't use the built-in opacity handling in QgsLayoutItem::paint, and
// we have to rely on QGraphicsItem opacity to handle this
setOpacity( mEvaluatedOpacity );
}

if ( updateItem )
{
@@ -287,6 +287,16 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
UndoCustomCommand, //!< Base id for plugin based item undo commands
};

/**
* Flags for controlling how an item behaves.
* \since QGIS 3.4.3
*/
enum Flag
{
FlagOverridesPaint = 1 << 1, //!< Item overrides the default layout item painting method
};
Q_DECLARE_FLAGS( Flags, Flag )

/**
* Constructor for QgsLayoutItem, with the specified parent \a layout.
*
@@ -324,6 +334,12 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
*/
virtual QString uuid() const { return mUuid; }

/**
* Returns the item's flags, which indicate how the item behaves.
* \since QGIS 3.4.3
*/
virtual Flags itemFlags() const;

/**
* Returns the item's ID name. This is not necessarily unique, and duplicate ID names may exist
* for a layout.
@@ -1109,6 +1125,7 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt

//! Item opacity, between 0 and 1
double mOpacity = 1.0;
double mEvaluatedOpacity = 1.0;

QImage mItemCachedImage;
double mItemCacheDpi = -1;
@@ -1137,7 +1154,6 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
void preparePainter( QPainter *painter );
bool shouldDrawAntialiased() const;
bool shouldDrawDebugRect() const;

QSizeF applyMinimumSize( QSizeF targetSize );
QSizeF applyFixedSize( QSizeF targetSize );
QgsLayoutPoint applyDataDefinedPosition( const QgsLayoutPoint &position );
@@ -1157,6 +1173,8 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
friend class QgsCompositionConverter;
};

Q_DECLARE_OPERATORS_FOR_FLAGS( QgsLayoutItem::Flags )

#endif //QGSLAYOUTITEM_H


@@ -64,6 +64,11 @@ QIcon QgsLayoutItemLegend::icon() const
return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemLegend.svg" ) );
}

QgsLayoutItem::Flags QgsLayoutItemLegend::itemFlags() const
{
return QgsLayoutItem::FlagOverridesPaint;
}

void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget )
{
if ( !painter )
@@ -78,6 +78,7 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem

int type() const override;
QIcon icon() const override;
QgsLayoutItem::Flags itemFlags() const override;
//Overridden to show legend title
QString displayName() const override;

@@ -77,6 +77,11 @@ QIcon QgsLayoutItemMap::icon() const
return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemMap.svg" ) );
}

QgsLayoutItem::Flags QgsLayoutItemMap::itemFlags() const
{
return QgsLayoutItem::FlagOverridesPaint;
}

void QgsLayoutItemMap::assignFreeId()
{
if ( !mLayout )
@@ -71,6 +71,7 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem

int type() const override;
QIcon icon() const override;
QgsLayoutItem::Flags itemFlags() const override;

/**
* Sets the map id() to a number not yet used in the layout. The existing id() is kept if it is not in use.
@@ -669,14 +669,6 @@ void QgsLayoutItemPicture::refreshDataDefinedProperty( const QgsLayoutObject::Da
QgsLayoutItem::refreshDataDefinedProperty( property );
}

bool QgsLayoutItemPicture::containsAdvancedEffects() const
{
if ( QgsLayoutItem::containsAdvancedEffects() )
return true;

return mMode == FormatSVG && itemOpacity() < 1.0;
}

void QgsLayoutItemPicture::setPicturePath( const QString &path )
{
mSourcePath = path;
@@ -259,7 +259,6 @@ class CORE_EXPORT QgsLayoutItemPicture: public QgsLayoutItem
void recalculateSize();

void refreshDataDefinedProperty( QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties ) override;
bool containsAdvancedEffects() const override;

signals:
//! Is emitted on picture rotation change
@@ -27,6 +27,11 @@ QgsResidualPlotItem::QgsResidualPlotItem( QgsLayout *layout )
setBackgroundEnabled( false );
}

QgsLayoutItem::Flags QgsResidualPlotItem::itemFlags() const
{
return QgsLayoutItem::FlagOverridesPaint;
}

void QgsResidualPlotItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget )
{
Q_UNUSED( itemStyle );
@@ -30,6 +30,8 @@ class QgsResidualPlotItem: public QgsLayoutItem
public:
explicit QgsResidualPlotItem( QgsLayout *layout );

QgsLayoutItem::Flags itemFlags() const override;

//! \brief Reimplementation of QCanvasItem::paint
void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget ) override;

0 comments on commit 03e2264

Please sign in to comment.
You can’t perform that action at this time.