LCOV - code coverage report
Current view: top level - core/effects - qgseffectstack.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 35 152 23.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                             qgseffectstack.cpp
       3                 :            :                              -------------------
       4                 :            :     begin                : December 2014
       5                 :            :     copyright            : (C) 2014 Nyall Dawson
       6                 :            :     email                : nyall dot dawson at gmail dot com
       7                 :            :  ***************************************************************************/
       8                 :            : 
       9                 :            : /***************************************************************************
      10                 :            :  *                                                                         *
      11                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      12                 :            :  *   it under the terms of the GNU General Public License as published by  *
      13                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      14                 :            :  *   (at your option) any later version.                                   *
      15                 :            :  *                                                                         *
      16                 :            :  ***************************************************************************/
      17                 :            : 
      18                 :            : #include "qgseffectstack.h"
      19                 :            : #include "qgspainteffectregistry.h"
      20                 :            : #include "qgsrendercontext.h"
      21                 :            : #include "qgsapplication.h"
      22                 :            : #include <QPicture>
      23                 :            : 
      24                 :          0 : QgsEffectStack::QgsEffectStack( const QgsEffectStack &other )
      25                 :          0 :   : QgsPaintEffect( other )
      26                 :          0 : {
      27                 :            :   //deep copy
      28                 :          0 :   for ( int i = 0; i < other.count(); ++i )
      29                 :            :   {
      30                 :          0 :     appendEffect( other.effect( i )->clone() );
      31                 :          0 :   }
      32                 :          0 : }
      33                 :            : 
      34                 :          0 : QgsEffectStack::QgsEffectStack( QgsEffectStack &&other )
      35                 :          0 :   : QgsPaintEffect( other )
      36                 :          0 : {
      37                 :          0 :   std::swap( mEffectList, other.mEffectList );
      38                 :          0 : }
      39                 :            : 
      40                 :          0 : QgsEffectStack::QgsEffectStack( const QgsPaintEffect &effect )
      41                 :          0 : {
      42                 :          0 :   appendEffect( effect.clone() );
      43                 :          0 : }
      44                 :            : 
      45                 :        184 : QgsEffectStack::~QgsEffectStack()
      46                 :        184 : {
      47                 :         92 :   clearStack();
      48                 :        184 : }
      49                 :            : 
      50                 :          0 : QgsEffectStack &QgsEffectStack::operator=( const QgsEffectStack &rhs )
      51                 :            : {
      52                 :          0 :   if ( &rhs == this )
      53                 :          0 :     return *this;
      54                 :            : 
      55                 :            :   //deep copy
      56                 :          0 :   clearStack();
      57                 :          0 :   for ( int i = 0; i < rhs.count(); ++i )
      58                 :            :   {
      59                 :          0 :     appendEffect( rhs.effect( i )->clone() );
      60                 :          0 :   }
      61                 :          0 :   mEnabled = rhs.enabled();
      62                 :          0 :   return *this;
      63                 :          0 : }
      64                 :            : 
      65                 :          0 : QgsEffectStack &QgsEffectStack::operator=( QgsEffectStack &&other )
      66                 :            : {
      67                 :          0 :   std::swap( mEffectList, other.mEffectList );
      68                 :          0 :   mEnabled = other.enabled();
      69                 :          0 :   return *this;
      70                 :            : }
      71                 :            : 
      72                 :         50 : QgsPaintEffect *QgsEffectStack::create( const QVariantMap &map )
      73                 :            : {
      74                 :         50 :   QgsEffectStack *effect = new QgsEffectStack();
      75                 :         50 :   effect->readProperties( map );
      76                 :         50 :   return effect;
      77                 :            : }
      78                 :            : 
      79                 :          0 : void QgsEffectStack::draw( QgsRenderContext &context )
      80                 :            : {
      81                 :          0 :   QPainter *destPainter = context.painter();
      82                 :            : 
      83                 :            :   //first, we build up a list of rendered effects
      84                 :            :   //we do this moving backwards through the stack, so that each effect's results
      85                 :            :   //becomes the source of the previous effect
      86                 :          0 :   QPicture *sourcePic = new QPicture( *source() );
      87                 :          0 :   QPicture *currentPic = sourcePic;
      88                 :          0 :   QList< QPicture * > results;
      89                 :          0 :   for ( int i = mEffectList.count() - 1; i >= 0; --i )
      90                 :            :   {
      91                 :          0 :     QgsPaintEffect *effect = mEffectList.at( i );
      92                 :          0 :     if ( !effect->enabled() )
      93                 :            :     {
      94                 :          0 :       continue;
      95                 :            :     }
      96                 :            : 
      97                 :          0 :     QPicture *pic = nullptr;
      98                 :          0 :     if ( effect->type() == QLatin1String( "drawSource" ) )
      99                 :            :     {
     100                 :            :       //draw source is always the original source, regardless of previous effect results
     101                 :          0 :       pic = sourcePic;
     102                 :          0 :     }
     103                 :            :     else
     104                 :            :     {
     105                 :          0 :       pic = currentPic;
     106                 :            :     }
     107                 :            : 
     108                 :          0 :     QPicture *resultPic = new QPicture();
     109                 :          0 :     QPainter p( resultPic );
     110                 :          0 :     context.setPainter( &p );
     111                 :            :     //effect stack has it's own handling of the QPicture DPI issue, so
     112                 :            :     //we disable QgsPaintEffect's internal workaround
     113                 :          0 :     effect->requiresQPainterDpiFix = false;
     114                 :          0 :     effect->render( *pic, context );
     115                 :          0 :     effect->requiresQPainterDpiFix = true;
     116                 :          0 :     p.end();
     117                 :            : 
     118                 :          0 :     results << resultPic;
     119                 :          0 :     if ( mEffectList.at( i )->drawMode() != QgsPaintEffect::Render )
     120                 :            :     {
     121                 :          0 :       currentPic = resultPic;
     122                 :          0 :     }
     123                 :          0 :   }
     124                 :          0 :   delete sourcePic;
     125                 :          0 :   sourcePic = nullptr;
     126                 :            : 
     127                 :          0 :   context.setPainter( destPainter );
     128                 :            :   //then, we render all the results in the opposite order
     129                 :          0 :   for ( int i = 0; i < mEffectList.count(); ++i )
     130                 :            :   {
     131                 :          0 :     if ( !mEffectList[i]->enabled() )
     132                 :            :     {
     133                 :          0 :       continue;
     134                 :            :     }
     135                 :            : 
     136                 :          0 :     QPicture *pic = results.takeLast();
     137                 :          0 :     if ( mEffectList.at( i )->drawMode() != QgsPaintEffect::Modifier )
     138                 :            :     {
     139                 :          0 :       QgsScopedQPainterState painterState( context.painter() );
     140                 :          0 :       fixQPictureDpi( context.painter() );
     141                 :          0 :       context.painter()->drawPicture( 0, 0, *pic );
     142                 :          0 :     }
     143                 :          0 :     delete pic;
     144                 :          0 :   }
     145                 :          0 : }
     146                 :            : 
     147                 :          0 : QgsEffectStack *QgsEffectStack::clone() const
     148                 :            : {
     149                 :          0 :   return new QgsEffectStack( *this );
     150                 :          0 : }
     151                 :            : 
     152                 :          0 : bool QgsEffectStack::saveProperties( QDomDocument &doc, QDomElement &element ) const
     153                 :            : {
     154                 :            :   //effect stack needs to save all child effects
     155                 :          0 :   if ( element.isNull() )
     156                 :            :   {
     157                 :          0 :     return false;
     158                 :            :   }
     159                 :            : 
     160                 :          0 :   QDomElement effectElement = doc.createElement( QStringLiteral( "effect" ) );
     161                 :          0 :   effectElement.setAttribute( QStringLiteral( "type" ), type() );
     162                 :          0 :   effectElement.setAttribute( QStringLiteral( "enabled" ), mEnabled );
     163                 :            : 
     164                 :          0 :   bool ok = true;
     165                 :          0 :   for ( QgsPaintEffect *effect : mEffectList )
     166                 :            :   {
     167                 :          0 :     if ( effect )
     168                 :          0 :       ok = ok && effect->saveProperties( doc, effectElement );
     169                 :            :   }
     170                 :            : 
     171                 :          0 :   element.appendChild( effectElement );
     172                 :          0 :   return ok;
     173                 :          0 : }
     174                 :            : 
     175                 :         50 : bool QgsEffectStack::readProperties( const QDomElement &element )
     176                 :            : {
     177                 :         50 :   if ( element.isNull() )
     178                 :            :   {
     179                 :          0 :     return false;
     180                 :            :   }
     181                 :            : 
     182                 :        150 :   mEnabled = ( element.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
     183                 :            : 
     184                 :         50 :   clearStack();
     185                 :            : 
     186                 :            :   //restore all child effects
     187                 :         50 :   QDomNodeList childNodes = element.childNodes();
     188                 :        245 :   for ( int i = 0; i < childNodes.size(); ++i )
     189                 :            :   {
     190                 :        195 :     QDomElement childElement = childNodes.at( i ).toElement();
     191                 :        195 :     QgsPaintEffect *effect = QgsApplication::paintEffectRegistry()->createEffect( childElement );
     192                 :        195 :     if ( effect )
     193                 :        195 :       mEffectList << effect;
     194                 :        195 :   }
     195                 :         50 :   return true;
     196                 :         50 : }
     197                 :            : 
     198                 :          0 : QVariantMap QgsEffectStack::properties() const
     199                 :            : {
     200                 :          0 :   QVariantMap props;
     201                 :          0 :   return props;
     202                 :          0 : }
     203                 :            : 
     204                 :         50 : void QgsEffectStack::readProperties( const QVariantMap &props )
     205                 :            : {
     206                 :         50 :   Q_UNUSED( props )
     207                 :         50 : }
     208                 :            : 
     209                 :        142 : void QgsEffectStack::clearStack()
     210                 :            : {
     211                 :        142 :   qDeleteAll( mEffectList );
     212                 :        142 :   mEffectList.clear();
     213                 :        142 : }
     214                 :            : 
     215                 :        390 : void QgsEffectStack::appendEffect( QgsPaintEffect *effect )
     216                 :            : {
     217                 :        390 :   mEffectList.append( effect );
     218                 :        390 : }
     219                 :            : 
     220                 :          0 : bool QgsEffectStack::insertEffect( const int index, QgsPaintEffect *effect )
     221                 :            : {
     222                 :          0 :   if ( index < 0 || index > mEffectList.count() )
     223                 :          0 :     return false;
     224                 :          0 :   if ( !effect )
     225                 :          0 :     return false;
     226                 :            : 
     227                 :          0 :   mEffectList.insert( index, effect );
     228                 :          0 :   return true;
     229                 :          0 : }
     230                 :            : 
     231                 :          0 : bool QgsEffectStack::changeEffect( const int index, QgsPaintEffect *effect )
     232                 :            : {
     233                 :          0 :   if ( index < 0 || index >= mEffectList.count() )
     234                 :          0 :     return false;
     235                 :          0 :   if ( !effect )
     236                 :          0 :     return false;
     237                 :            : 
     238                 :          0 :   delete mEffectList.at( index );
     239                 :          0 :   mEffectList[index] = effect;
     240                 :          0 :   return true;
     241                 :          0 : }
     242                 :            : 
     243                 :          0 : QgsPaintEffect *QgsEffectStack::takeEffect( const int index )
     244                 :            : {
     245                 :          0 :   if ( index < 0 || index >= mEffectList.count() )
     246                 :          0 :     return nullptr;
     247                 :            : 
     248                 :          0 :   return mEffectList.takeAt( index );
     249                 :          0 : }
     250                 :            : 
     251                 :          0 : QList<QgsPaintEffect *> *QgsEffectStack::effectList()
     252                 :            : {
     253                 :          0 :   return &mEffectList;
     254                 :            : }
     255                 :            : 
     256                 :        130 : QgsPaintEffect *QgsEffectStack::effect( int index ) const
     257                 :            : {
     258                 :        130 :   if ( index >= 0 && index < mEffectList.count() )
     259                 :            :   {
     260                 :        130 :     return mEffectList.at( index );
     261                 :            :   }
     262                 :            :   else
     263                 :            :   {
     264                 :          0 :     return nullptr;
     265                 :            :   }
     266                 :        130 : }

Generated by: LCOV version 1.14