LCOV - code coverage report
Current view: top level - core/effects - qgsgloweffect.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 68 174 39.1 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                               qgsgloweffect.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 "qgsgloweffect.h"
      19                 :            : #include "qgssymbollayerutils.h"
      20                 :            : #include "qgsimageoperation.h"
      21                 :            : #include "qgscolorramp.h"
      22                 :            : #include "qgsunittypes.h"
      23                 :            : 
      24                 :        226 : QgsGlowEffect::QgsGlowEffect()
      25                 :        226 :   : mColor( Qt::white )
      26                 :        452 : {
      27                 :            : 
      28                 :        226 : }
      29                 :            : 
      30                 :          0 : QgsGlowEffect::QgsGlowEffect( const QgsGlowEffect &other )
      31                 :          0 :   : QgsPaintEffect( other )
      32                 :          0 : {
      33                 :          0 :   operator=( other );
      34                 :          0 : }
      35                 :            : 
      36                 :        166 : QgsGlowEffect::~QgsGlowEffect()
      37                 :        166 : {
      38                 :        166 :   delete mRamp;
      39                 :        166 : }
      40                 :            : 
      41                 :          0 : void QgsGlowEffect::draw( QgsRenderContext &context )
      42                 :            : {
      43                 :          0 :   if ( !source() || !enabled() || !context.painter() )
      44                 :          0 :     return;
      45                 :            : 
      46                 :          0 :   QImage im = sourceAsImage( context )->copy();
      47                 :            : 
      48                 :          0 :   QgsColorRamp *ramp = nullptr;
      49                 :          0 :   std::unique_ptr< QgsGradientColorRamp > tempRamp;
      50                 :          0 :   if ( mColorType == ColorRamp && mRamp )
      51                 :            :   {
      52                 :          0 :     ramp = mRamp;
      53                 :          0 :   }
      54                 :            :   else
      55                 :            :   {
      56                 :            :     //create a temporary ramp
      57                 :          0 :     QColor transparentColor = mColor;
      58                 :          0 :     transparentColor.setAlpha( 0 );
      59                 :          0 :     tempRamp.reset( new QgsGradientColorRamp( mColor, transparentColor ) );
      60                 :          0 :     ramp = tempRamp.get();
      61                 :            :   }
      62                 :            : 
      63                 :          0 :   QgsImageOperation::DistanceTransformProperties dtProps;
      64                 :          0 :   dtProps.spread = context.convertToPainterUnits( mSpread, mSpreadUnit, mSpreadMapUnitScale );
      65                 :          0 :   dtProps.useMaxDistance = false;
      66                 :          0 :   dtProps.shadeExterior = shadeExterior();
      67                 :          0 :   dtProps.ramp = ramp;
      68                 :          0 :   QgsImageOperation::distanceTransform( im, dtProps );
      69                 :            : 
      70                 :          0 :   int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
      71                 :          0 :   if ( blurLevel <= 16 )
      72                 :            :   {
      73                 :          0 :     QgsImageOperation::stackBlur( im, blurLevel );
      74                 :          0 :   }
      75                 :            :   else
      76                 :            :   {
      77                 :          0 :     QImage *imb = QgsImageOperation::gaussianBlur( im, blurLevel );
      78                 :          0 :     im = QImage( *imb );
      79                 :          0 :     delete imb;
      80                 :            :   }
      81                 :            : 
      82                 :          0 :   QgsImageOperation::multiplyOpacity( im, mOpacity );
      83                 :            : 
      84                 :          0 :   if ( !shadeExterior() )
      85                 :            :   {
      86                 :            :     //only keep interior portion
      87                 :          0 :     QPainter p( &im );
      88                 :          0 :     p.setRenderHint( QPainter::Antialiasing );
      89                 :          0 :     p.setCompositionMode( QPainter::CompositionMode_DestinationIn );
      90                 :          0 :     p.drawImage( 0, 0, *sourceAsImage( context ) );
      91                 :          0 :     p.end();
      92                 :          0 :   }
      93                 :            : 
      94                 :          0 :   QPainter *painter = context.painter();
      95                 :          0 :   QgsScopedQPainterState painterState( painter );
      96                 :          0 :   painter->setCompositionMode( mBlendMode );
      97                 :          0 :   painter->drawImage( imageOffset( context ), im );
      98                 :          0 : }
      99                 :            : 
     100                 :          0 : QVariantMap QgsGlowEffect::properties() const
     101                 :            : {
     102                 :          0 :   QVariantMap props;
     103                 :          0 :   props.insert( QStringLiteral( "enabled" ), mEnabled ? "1" : "0" );
     104                 :          0 :   props.insert( QStringLiteral( "draw_mode" ), QString::number( int( mDrawMode ) ) );
     105                 :          0 :   props.insert( QStringLiteral( "blend_mode" ), QString::number( int( mBlendMode ) ) );
     106                 :          0 :   props.insert( QStringLiteral( "opacity" ), QString::number( mOpacity ) );
     107                 :          0 :   props.insert( QStringLiteral( "blur_level" ), QString::number( mBlurLevel ) );
     108                 :          0 :   props.insert( QStringLiteral( "blur_unit" ), QgsUnitTypes::encodeUnit( mBlurUnit ) );
     109                 :          0 :   props.insert( QStringLiteral( "blur_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mBlurMapUnitScale ) );
     110                 :          0 :   props.insert( QStringLiteral( "spread" ), QString::number( mSpread ) );
     111                 :          0 :   props.insert( QStringLiteral( "spread_unit" ), QgsUnitTypes::encodeUnit( mSpreadUnit ) );
     112                 :          0 :   props.insert( QStringLiteral( "spread_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mSpreadMapUnitScale ) );
     113                 :          0 :   props.insert( QStringLiteral( "color_type" ), QString::number( static_cast< int >( mColorType ) ) );
     114                 :          0 :   props.insert( QStringLiteral( "single_color" ), QgsSymbolLayerUtils::encodeColor( mColor ) );
     115                 :            : 
     116                 :          0 :   if ( mRamp )
     117                 :            :   {
     118                 :            : #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
     119                 :            :     props.unite( mRamp->properties() );
     120                 :            : #else
     121                 :          0 :     props.insert( mRamp->properties() );
     122                 :            : #endif
     123                 :          0 :   }
     124                 :            : 
     125                 :          0 :   return props;
     126                 :          0 : }
     127                 :            : 
     128                 :        140 : void QgsGlowEffect::readProperties( const QVariantMap &props )
     129                 :            : {
     130                 :            :   bool ok;
     131                 :        280 :   QPainter::CompositionMode mode = static_cast< QPainter::CompositionMode >( props.value( QStringLiteral( "blend_mode" ) ).toInt( &ok ) );
     132                 :        140 :   if ( ok )
     133                 :            :   {
     134                 :         70 :     mBlendMode = mode;
     135                 :         70 :   }
     136                 :        280 :   if ( props.contains( QStringLiteral( "transparency" ) ) )
     137                 :            :   {
     138                 :          0 :     double transparency = props.value( QStringLiteral( "transparency" ) ).toDouble( &ok );
     139                 :          0 :     if ( ok )
     140                 :            :     {
     141                 :          0 :       mOpacity = 1.0 - transparency;
     142                 :          0 :     }
     143                 :          0 :   }
     144                 :            :   else
     145                 :            :   {
     146                 :        280 :     double opacity = props.value( QStringLiteral( "opacity" ) ).toDouble( &ok );
     147                 :        140 :     if ( ok )
     148                 :            :     {
     149                 :         70 :       mOpacity = opacity;
     150                 :         70 :     }
     151                 :            :   }
     152                 :        420 :   mEnabled = props.value( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt();
     153                 :        420 :   mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( QStringLiteral( "draw_mode" ), QStringLiteral( "2" ) ).toInt() );
     154                 :        280 :   double level = props.value( QStringLiteral( "blur_level" ) ).toDouble( &ok );
     155                 :        140 :   if ( ok )
     156                 :            :   {
     157                 :         70 :     mBlurLevel = level;
     158                 :        140 :     if ( !props.contains( QStringLiteral( "blur_unit" ) ) )
     159                 :            :     {
     160                 :            :       // deal with pre blur unit era by assuming 96 dpi and converting pixel values as millimeters
     161                 :          0 :       mBlurLevel *= 0.2645;
     162                 :          0 :     }
     163                 :         70 :   }
     164                 :        280 :   mBlurUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "blur_unit" ) ).toString() );
     165                 :        280 :   mBlurMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "blur_unit_scale" ) ).toString() );
     166                 :        280 :   double spread = props.value( QStringLiteral( "spread" ) ).toDouble( &ok );
     167                 :        140 :   if ( ok )
     168                 :            :   {
     169                 :         70 :     mSpread = spread;
     170                 :         70 :   }
     171                 :        280 :   mSpreadUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "spread_unit" ) ).toString() );
     172                 :        280 :   mSpreadMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "spread_unit_scale" ) ).toString() );
     173                 :        280 :   QgsGlowEffect::GlowColorType type = static_cast< QgsGlowEffect::GlowColorType >( props.value( QStringLiteral( "color_type" ) ).toInt( &ok ) );
     174                 :        140 :   if ( ok )
     175                 :            :   {
     176                 :         70 :     mColorType = type;
     177                 :         70 :   }
     178                 :        280 :   if ( props.contains( QStringLiteral( "single_color" ) ) )
     179                 :            :   {
     180                 :        140 :     mColor = QgsSymbolLayerUtils::decodeColor( props.value( QStringLiteral( "single_color" ) ).toString() );
     181                 :         70 :   }
     182                 :            : 
     183                 :            :   //attempt to create color ramp from props
     184                 :        140 :   delete mRamp;
     185                 :        420 :   if ( props.contains( QStringLiteral( "rampType" ) ) && props[QStringLiteral( "rampType" )] == QgsCptCityColorRamp::typeString() )
     186                 :            :   {
     187                 :          0 :     mRamp = QgsCptCityColorRamp::create( props );
     188                 :          0 :   }
     189                 :            :   else
     190                 :            :   {
     191                 :        140 :     mRamp = QgsGradientColorRamp::create( props );
     192                 :            :   }
     193                 :        140 : }
     194                 :            : 
     195                 :          0 : void QgsGlowEffect::setRamp( QgsColorRamp *ramp )
     196                 :            : {
     197                 :          0 :   delete mRamp;
     198                 :          0 :   mRamp = ramp;
     199                 :          0 : }
     200                 :            : 
     201                 :          0 : QgsGlowEffect &QgsGlowEffect::operator=( const QgsGlowEffect &rhs )
     202                 :            : {
     203                 :          0 :   if ( &rhs == this )
     204                 :          0 :     return *this;
     205                 :            : 
     206                 :          0 :   delete mRamp;
     207                 :            : 
     208                 :          0 :   mSpread = rhs.spread();
     209                 :          0 :   mSpreadUnit = rhs.spreadUnit();
     210                 :          0 :   mSpreadMapUnitScale = rhs.spreadMapUnitScale();
     211                 :          0 :   mRamp = rhs.ramp() ? rhs.ramp()->clone() : nullptr;
     212                 :          0 :   mBlurLevel = rhs.blurLevel();
     213                 :          0 :   mBlurUnit = rhs.mBlurUnit;
     214                 :          0 :   mBlurMapUnitScale = rhs.mBlurMapUnitScale;
     215                 :          0 :   mOpacity = rhs.opacity();
     216                 :          0 :   mColor = rhs.color();
     217                 :          0 :   mBlendMode = rhs.blendMode();
     218                 :          0 :   mColorType = rhs.colorType();
     219                 :            : 
     220                 :          0 :   return *this;
     221                 :          0 : }
     222                 :            : 
     223                 :          0 : QRectF QgsGlowEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
     224                 :            : {
     225                 :            :   //blur radius and spread size
     226                 :          0 :   int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
     227                 :          0 :   double spread = context.convertToPainterUnits( mSpread, mSpreadUnit, mSpreadMapUnitScale );
     228                 :            :   //plus possible extension due to blur, with a couple of extra pixels thrown in for safety
     229                 :          0 :   spread += blurLevel * 2 + 10;
     230                 :          0 :   return rect.adjusted( -spread, -spread, spread, spread );
     231                 :            : }
     232                 :            : 
     233                 :            : 
     234                 :            : //
     235                 :            : // QgsOuterGlowEffect
     236                 :            : //
     237                 :            : 
     238                 :        113 : QgsOuterGlowEffect::QgsOuterGlowEffect()
     239                 :        113 :   : QgsGlowEffect()
     240                 :        226 : {
     241                 :            : 
     242                 :        113 : }
     243                 :            : 
     244                 :         35 : QgsPaintEffect *QgsOuterGlowEffect::create( const QVariantMap &map )
     245                 :            : {
     246                 :         35 :   QgsOuterGlowEffect *effect = new QgsOuterGlowEffect();
     247                 :         35 :   effect->readProperties( map );
     248                 :         35 :   return effect;
     249                 :          0 : }
     250                 :            : 
     251                 :          0 : QgsOuterGlowEffect *QgsOuterGlowEffect::clone() const
     252                 :            : {
     253                 :          0 :   QgsOuterGlowEffect *newEffect = new QgsOuterGlowEffect( *this );
     254                 :          0 :   return newEffect;
     255                 :          0 : }
     256                 :            : 
     257                 :            : 
     258                 :            : //
     259                 :            : // QgsInnerGlowEffect
     260                 :            : //
     261                 :            : 
     262                 :        113 : QgsInnerGlowEffect::QgsInnerGlowEffect()
     263                 :        113 :   : QgsGlowEffect()
     264                 :        226 : {
     265                 :            : 
     266                 :        113 : }
     267                 :            : 
     268                 :         35 : QgsPaintEffect *QgsInnerGlowEffect::create( const QVariantMap &map )
     269                 :            : {
     270                 :         35 :   QgsInnerGlowEffect *effect = new QgsInnerGlowEffect();
     271                 :         35 :   effect->readProperties( map );
     272                 :         35 :   return effect;
     273                 :          0 : }
     274                 :            : 
     275                 :          0 : QgsInnerGlowEffect *QgsInnerGlowEffect::clone() const
     276                 :        226 : {
     277                 :        226 :   QgsInnerGlowEffect *newEffect = new QgsInnerGlowEffect( *this );
     278                 :          0 :   return newEffect;
     279                 :        226 : }

Generated by: LCOV version 1.14