LCOV - code coverage report
Current view: top level - core/symbology - qgssymbollayer.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 206 510 40.4 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :  qgssymbollayer.cpp
       3                 :            :  ---------------------
       4                 :            :  begin                : November 2009
       5                 :            :  copyright            : (C) 2009 by Martin Dobias
       6                 :            :  email                : wonder dot sk at gmail dot com
       7                 :            :  ***************************************************************************
       8                 :            :  *                                                                         *
       9                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      10                 :            :  *   it under the terms of the GNU General Public License as published by  *
      11                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      12                 :            :  *   (at your option) any later version.                                   *
      13                 :            :  *                                                                         *
      14                 :            :  ***************************************************************************/
      15                 :            : 
      16                 :            : #include "qgssymbollayer.h"
      17                 :            : #include "qgsclipper.h"
      18                 :            : #include "qgsexpression.h"
      19                 :            : #include "qgsrendercontext.h"
      20                 :            : #include "qgsvectorlayer.h"
      21                 :            : #include "qgsdxfexport.h"
      22                 :            : #include "qgsgeometrysimplifier.h"
      23                 :            : #include "qgspainteffect.h"
      24                 :            : #include "qgseffectstack.h"
      25                 :            : #include "qgspainteffectregistry.h"
      26                 :            : #include "qgsproperty.h"
      27                 :            : #include "qgsexpressioncontext.h"
      28                 :            : #include "qgssymbollayerutils.h"
      29                 :            : #include "qgsapplication.h"
      30                 :            : #include "qgsmultipoint.h"
      31                 :            : #include "qgslegendpatchshape.h"
      32                 :            : #include "qgsstyle.h"
      33                 :            : 
      34                 :            : #include <QSize>
      35                 :            : #include <QPainter>
      36                 :            : #include <QPointF>
      37                 :            : #include <QPolygonF>
      38                 :            : 
      39                 :          5 : QgsPropertiesDefinition QgsSymbolLayer::sPropertyDefinitions;
      40                 :            : 
      41                 :        990 : void QgsSymbolLayer::initPropertyDefinitions()
      42                 :            : {
      43                 :        990 :   if ( !sPropertyDefinitions.isEmpty() )
      44                 :        985 :     return;
      45                 :            : 
      46                 :         10 :   QString origin = QStringLiteral( "symbol" );
      47                 :            : 
      48                 :        310 :   sPropertyDefinitions = QgsPropertiesDefinition
      49                 :        315 :   {
      50                 :          5 :     { QgsSymbolLayer::PropertySize, QgsPropertyDefinition( "size", QObject::tr( "Symbol size" ), QgsPropertyDefinition::Size, origin ) },
      51                 :          5 :     { QgsSymbolLayer::PropertyAngle, QgsPropertyDefinition( "angle", QObject::tr( "Rotation angle" ), QgsPropertyDefinition::Rotation, origin ) },
      52                 :          5 :     { QgsSymbolLayer::PropertyName, QgsPropertyDefinition( "name", QObject::tr( "Symbol name" ), QgsPropertyDefinition::String, origin ) },
      53                 :          5 :     { QgsSymbolLayer::PropertyFillColor, QgsPropertyDefinition( "fillColor", QObject::tr( "Symbol fill color" ), QgsPropertyDefinition::ColorWithAlpha, origin ) },
      54                 :          5 :     { QgsSymbolLayer::PropertyStrokeColor, QgsPropertyDefinition( "outlineColor", QObject::tr( "Symbol stroke color" ), QgsPropertyDefinition::ColorWithAlpha, origin ) },
      55                 :          5 :     { QgsSymbolLayer::PropertyStrokeWidth, QgsPropertyDefinition( "outlineWidth", QObject::tr( "Symbol stroke width" ), QgsPropertyDefinition::StrokeWidth, origin ) },
      56                 :          5 :     { QgsSymbolLayer::PropertyStrokeStyle, QgsPropertyDefinition( "outlineStyle", QObject::tr( "Symbol stroke style" ), QgsPropertyDefinition::LineStyle, origin )},
      57                 :          5 :     { QgsSymbolLayer::PropertyOffset, QgsPropertyDefinition( "offset", QObject::tr( "Symbol offset" ), QgsPropertyDefinition::Offset, origin )},
      58                 :          5 :     { QgsSymbolLayer::PropertyCharacter, QgsPropertyDefinition( "char", QObject::tr( "Marker character(s)" ), QgsPropertyDefinition::String, origin )},
      59                 :          5 :     { QgsSymbolLayer::PropertyFontFamily, QgsPropertyDefinition( "fontFamily", QObject::tr( "Font family" ), QgsPropertyDefinition::String, origin )},
      60                 :          5 :     { QgsSymbolLayer::PropertyFontStyle, QgsPropertyDefinition( "fontStyle", QObject::tr( "Font style" ), QgsPropertyDefinition::String, origin )},
      61                 :          5 :     { QgsSymbolLayer::PropertyWidth, QgsPropertyDefinition( "width", QObject::tr( "Symbol width" ), QgsPropertyDefinition::DoublePositive, origin )},
      62                 :          5 :     { QgsSymbolLayer::PropertyHeight, QgsPropertyDefinition( "height", QObject::tr( "Symbol height" ), QgsPropertyDefinition::DoublePositive, origin )},
      63                 :          5 :     { QgsSymbolLayer::PropertyPreserveAspectRatio, QgsPropertyDefinition( "preserveAspectRatio", QObject::tr( "Preserve aspect ratio between width and height" ), QgsPropertyDefinition::Boolean, origin )},
      64                 :          5 :     { QgsSymbolLayer::PropertyFillStyle, QgsPropertyDefinition( "fillStyle", QObject::tr( "Symbol fill style" ), QgsPropertyDefinition::FillStyle, origin )},
      65                 :          5 :     { QgsSymbolLayer::PropertyJoinStyle, QgsPropertyDefinition( "joinStyle", QObject::tr( "Outline join style" ), QgsPropertyDefinition::PenJoinStyle, origin )},
      66                 :          5 :     { QgsSymbolLayer::PropertySecondaryColor, QgsPropertyDefinition( "color2", QObject::tr( "Secondary fill color" ), QgsPropertyDefinition::ColorWithAlpha, origin )},
      67                 :          5 :     { QgsSymbolLayer::PropertyLineAngle, QgsPropertyDefinition( "lineAngle", QObject::tr( "Angle for line fills" ), QgsPropertyDefinition::Rotation, origin )},
      68                 :          5 :     { QgsSymbolLayer::PropertyGradientType, QgsPropertyDefinition( "gradientType", QgsPropertyDefinition::DataTypeString, QObject::tr( "Gradient type" ),  QObject::tr( "string " ) + QLatin1String( "[<b>linear</b>|<b>radial</b>|<b>conical</b>]" ), origin )},
      69                 :          5 :     { QgsSymbolLayer::PropertyCoordinateMode, QgsPropertyDefinition( "gradientMode", QgsPropertyDefinition::DataTypeString, QObject::tr( "Gradient mode" ), QObject::tr( "string " ) + QLatin1String( "[<b>feature</b>|<b>viewport</b>]" ), origin )},
      70                 :          5 :     { QgsSymbolLayer::PropertyGradientSpread, QgsPropertyDefinition( "gradientSpread", QgsPropertyDefinition::DataTypeString, QObject::tr( "Gradient spread" ), QObject::tr( "string " ) + QLatin1String( "[<b>pad</b>|<b>repeat</b>|<b>reflect</b>]" ), origin )},
      71                 :          5 :     { QgsSymbolLayer::PropertyGradientReference1X, QgsPropertyDefinition( "gradientRef1X", QObject::tr( "Reference point 1 (X)" ), QgsPropertyDefinition::Double0To1, origin )},
      72                 :          5 :     { QgsSymbolLayer::PropertyGradientReference1Y, QgsPropertyDefinition( "gradientRef1Y", QObject::tr( "Reference point 1 (Y)" ), QgsPropertyDefinition::Double0To1, origin )},
      73                 :          5 :     { QgsSymbolLayer::PropertyGradientReference2X, QgsPropertyDefinition( "gradientRef2X", QObject::tr( "Reference point 2 (X)" ), QgsPropertyDefinition::Double0To1, origin )},
      74                 :          5 :     { QgsSymbolLayer::PropertyGradientReference2Y, QgsPropertyDefinition( "gradientRef2Y", QObject::tr( "Reference point 2 (Y)" ), QgsPropertyDefinition::Double0To1, origin )},
      75                 :          5 :     { QgsSymbolLayer::PropertyGradientReference1IsCentroid, QgsPropertyDefinition( "gradientRef1Centroid", QObject::tr( "Reference point 1 follows feature centroid" ), QgsPropertyDefinition::Boolean, origin )},
      76                 :          5 :     { QgsSymbolLayer::PropertyGradientReference2IsCentroid, QgsPropertyDefinition( "gradientRef2Centroid", QObject::tr( "Reference point 2 follows feature centroid" ), QgsPropertyDefinition::Boolean, origin )},
      77                 :          5 :     { QgsSymbolLayer::PropertyBlurRadius, QgsPropertyDefinition( "blurRadius", QgsPropertyDefinition::DataTypeNumeric, QObject::tr( "Blur radius" ), QObject::tr( "Integer between 0 and 18" ), origin )},
      78                 :          5 :     { QgsSymbolLayer::PropertyLineDistance, QgsPropertyDefinition( "lineDistance", QObject::tr( "Distance between lines" ), QgsPropertyDefinition::DoublePositive, origin )},
      79                 :          5 :     { QgsSymbolLayer::PropertyShapeburstUseWholeShape, QgsPropertyDefinition( "shapeburstWholeShape", QObject::tr( "Shade whole shape" ), QgsPropertyDefinition::Boolean, origin )},
      80                 :          5 :     { QgsSymbolLayer::PropertyShapeburstMaxDistance, QgsPropertyDefinition( "shapeburstMaxDist", QObject::tr( "Maximum distance for shapeburst fill" ), QgsPropertyDefinition::DoublePositive, origin )},
      81                 :          5 :     { QgsSymbolLayer::PropertyShapeburstIgnoreRings, QgsPropertyDefinition( "shapeburstIgnoreRings", QObject::tr( "Ignore rings in feature" ), QgsPropertyDefinition::Boolean, origin )},
      82                 :          5 :     { QgsSymbolLayer::PropertyFile, QgsPropertyDefinition( "file", QObject::tr( "Symbol file path" ), QgsPropertyDefinition::String, origin )},
      83                 :          5 :     { QgsSymbolLayer::PropertyDistanceX, QgsPropertyDefinition( "distanceX", QObject::tr( "Horizontal distance between markers" ), QgsPropertyDefinition::DoublePositive, origin )},
      84                 :          5 :     { QgsSymbolLayer::PropertyDistanceY, QgsPropertyDefinition( "distanceY", QObject::tr( "Vertical distance between markers" ), QgsPropertyDefinition::DoublePositive, origin )},
      85                 :          5 :     { QgsSymbolLayer::PropertyDisplacementX, QgsPropertyDefinition( "displacementX", QObject::tr( "Horizontal displacement between rows" ), QgsPropertyDefinition::DoublePositive, origin )},
      86                 :          5 :     { QgsSymbolLayer::PropertyDisplacementY, QgsPropertyDefinition( "displacementY", QObject::tr( "Vertical displacement between columns" ), QgsPropertyDefinition::DoublePositive, origin )},
      87                 :          5 :     { QgsSymbolLayer::PropertyOffsetX, QgsPropertyDefinition( "offsetX", QObject::tr( "Horizontal offset" ), QgsPropertyDefinition::Double, origin )},
      88                 :          5 :     { QgsSymbolLayer::PropertyOffsetY, QgsPropertyDefinition( "offsetY", QObject::tr( "Vertical offset" ), QgsPropertyDefinition::Double, origin )},
      89                 :          5 :     { QgsSymbolLayer::PropertyOpacity, QgsPropertyDefinition( "alpha", QObject::tr( "Opacity" ), QgsPropertyDefinition::Opacity, origin )},
      90                 :          5 :     { QgsSymbolLayer::PropertyCustomDash, QgsPropertyDefinition( "customDash", QgsPropertyDefinition::DataTypeString, QObject::tr( "Custom dash pattern" ), QObject::tr( "[<b><dash>;<space></b>] e.g. '8;2;1;2'" ), origin )},
      91                 :          5 :     { QgsSymbolLayer::PropertyCapStyle, QgsPropertyDefinition( "capStyle", QObject::tr( "Line cap style" ), QgsPropertyDefinition::CapStyle, origin )},
      92                 :          5 :     { QgsSymbolLayer::PropertyPlacement, QgsPropertyDefinition( "placement", QgsPropertyDefinition::DataTypeString, QObject::tr( "Marker placement" ), QObject::tr( "string " ) + "[<b>interval</b>|<b>vertex</b>|<b>lastvertex</b>|<b>firstvertex</b>|<b>centerpoint</b>|<b>curvepoint</b>|<b>segmentcenter</b>]", origin )},
      93                 :          5 :     { QgsSymbolLayer::PropertyInterval, QgsPropertyDefinition( "interval", QObject::tr( "Marker interval" ), QgsPropertyDefinition::DoublePositive, origin )},
      94                 :          5 :     { QgsSymbolLayer::PropertyOffsetAlongLine, QgsPropertyDefinition( "offsetAlongLine", QObject::tr( "Offset along line" ), QgsPropertyDefinition::DoublePositive, origin )},
      95                 :          5 :     { QgsSymbolLayer::PropertyAverageAngleLength, QgsPropertyDefinition( "averageAngleLength", QObject::tr( "Average line angles over" ), QgsPropertyDefinition::DoublePositive, origin )},
      96                 :          5 :     { QgsSymbolLayer::PropertyHorizontalAnchor, QgsPropertyDefinition( "hAnchor", QObject::tr( "Horizontal anchor point" ), QgsPropertyDefinition::HorizontalAnchor, origin )},
      97                 :          5 :     { QgsSymbolLayer::PropertyVerticalAnchor, QgsPropertyDefinition( "vAnchor", QObject::tr( "Vertical anchor point" ), QgsPropertyDefinition::VerticalAnchor, origin )},
      98                 :          5 :     { QgsSymbolLayer::PropertyLayerEnabled, QgsPropertyDefinition( "enabled", QObject::tr( "Layer enabled" ), QgsPropertyDefinition::Boolean, origin )},
      99                 :          5 :     { QgsSymbolLayer::PropertyArrowWidth, QgsPropertyDefinition( "arrowWidth", QObject::tr( "Arrow line width" ), QgsPropertyDefinition::StrokeWidth, origin )},
     100                 :          5 :     { QgsSymbolLayer::PropertyArrowStartWidth, QgsPropertyDefinition( "arrowStartWidth", QObject::tr( "Arrow line start width" ), QgsPropertyDefinition::StrokeWidth, origin )},
     101                 :          5 :     { QgsSymbolLayer::PropertyArrowHeadLength, QgsPropertyDefinition( "arrowHeadLength", QObject::tr( "Arrow head length" ), QgsPropertyDefinition::DoublePositive, origin )},
     102                 :          5 :     { QgsSymbolLayer::PropertyArrowHeadThickness, QgsPropertyDefinition( "arrowHeadThickness", QObject::tr( "Arrow head thickness" ), QgsPropertyDefinition::DoublePositive, origin )},
     103                 :          5 :     { QgsSymbolLayer::PropertyArrowHeadType, QgsPropertyDefinition( "arrowHeadType", QgsPropertyDefinition::DataTypeString, QObject::tr( "Arrow head type" ), QObject::tr( "string " ) + QLatin1String( "[<b>single</b>|<b>reversed</b>|<b>double</b>]" ), origin )},
     104                 :          5 :     { QgsSymbolLayer::PropertyArrowType, QgsPropertyDefinition( "arrowType", QgsPropertyDefinition::DataTypeString, QObject::tr( "Arrow type" ), QObject::tr( "string " ) + QLatin1String( "[<b>plain</b>|<b>lefthalf</b>|<b>righthalf</b>]" ), origin )},
     105                 :          5 :     { QgsSymbolLayer::PropertyPointCount, QgsPropertyDefinition( "pointCount", QObject::tr( "Point count" ), QgsPropertyDefinition::IntegerPositive, origin )},
     106                 :          5 :     { QgsSymbolLayer::PropertyRandomSeed, QgsPropertyDefinition( "randomSeed", QgsPropertyDefinition::DataTypeNumeric, QObject::tr( "Random number seed" ), QObject::tr( "integer > 0, or 0 for completely random sequence" ), origin )},
     107                 :          5 :     { QgsSymbolLayer::PropertyClipPoints, QgsPropertyDefinition( "clipPoints", QObject::tr( "Clip markers" ), QgsPropertyDefinition::Boolean, origin )},
     108                 :          5 :     { QgsSymbolLayer::PropertyClipPoints, QgsPropertyDefinition( "densityArea", QObject::tr( "Density area" ), QgsPropertyDefinition::DoublePositive, origin )},
     109                 :          5 :     { QgsSymbolLayer::PropertyDashPatternOffset, QgsPropertyDefinition( "dashPatternOffset", QObject::tr( "Dash pattern offset" ), QgsPropertyDefinition::DoublePositive, origin )},
     110                 :          5 :     { QgsSymbolLayer::PropertyTrimStart, QgsPropertyDefinition( "trimStart", QObject::tr( "Start trim distance" ), QgsPropertyDefinition::DoublePositive, origin )},
     111                 :          5 :     { QgsSymbolLayer::PropertyTrimEnd, QgsPropertyDefinition( "trimEnd", QObject::tr( "End trim distance" ), QgsPropertyDefinition::DoublePositive, origin )},
     112                 :            :   };
     113                 :        990 : }
     114                 :            : 
     115                 :          0 : void QgsSymbolLayer::setDataDefinedProperty( QgsSymbolLayer::Property key, const QgsProperty &property )
     116                 :            : {
     117                 :          0 :   dataDefinedProperties().setProperty( key, property );
     118                 :          0 : }
     119                 :            : 
     120                 :          0 : void QgsSymbolLayer::startFeatureRender( const QgsFeature &, QgsRenderContext & )
     121                 :            : {
     122                 :            : 
     123                 :          0 : }
     124                 :            : 
     125                 :          0 : void QgsSymbolLayer::stopFeatureRender( const QgsFeature &, QgsRenderContext & )
     126                 :            : {
     127                 :            : 
     128                 :          0 : }
     129                 :            : 
     130                 :          0 : bool QgsSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
     131                 :            : {
     132                 :          0 :   Q_UNUSED( e )
     133                 :            :   Q_UNUSED( mmMapUnitScaleFactor )
     134                 :          0 :   Q_UNUSED( layerName )
     135                 :          0 :   Q_UNUSED( context )
     136                 :            :   Q_UNUSED( shift )
     137                 :          0 :   return false;
     138                 :            : }
     139                 :            : 
     140                 :          0 : double QgsSymbolLayer::dxfWidth( const QgsDxfExport &e, QgsSymbolRenderContext &context ) const
     141                 :            : {
     142                 :          0 :   Q_UNUSED( e )
     143                 :          0 :   Q_UNUSED( context )
     144                 :          0 :   return 1.0;
     145                 :            : }
     146                 :            : 
     147                 :          0 : double QgsSymbolLayer::dxfOffset( const QgsDxfExport &e, QgsSymbolRenderContext &context ) const
     148                 :            : {
     149                 :          0 :   Q_UNUSED( e )
     150                 :          0 :   Q_UNUSED( context )
     151                 :          0 :   return 0.0;
     152                 :            : }
     153                 :            : 
     154                 :          0 : QColor QgsSymbolLayer::dxfColor( QgsSymbolRenderContext &context ) const
     155                 :            : {
     156                 :          0 :   Q_UNUSED( context )
     157                 :          0 :   return color();
     158                 :            : }
     159                 :            : 
     160                 :          0 : double QgsSymbolLayer::dxfAngle( QgsSymbolRenderContext &context ) const
     161                 :            : {
     162                 :          0 :   Q_UNUSED( context )
     163                 :          0 :   return 0.0;
     164                 :            : }
     165                 :            : 
     166                 :          0 : QVector<qreal> QgsSymbolLayer::dxfCustomDashPattern( QgsUnitTypes::RenderUnit &unit ) const
     167                 :            : {
     168                 :          0 :   Q_UNUSED( unit )
     169                 :          0 :   return QVector<qreal>();
     170                 :            : }
     171                 :            : 
     172                 :          0 : Qt::PenStyle QgsSymbolLayer::dxfPenStyle() const
     173                 :            : {
     174                 :          0 :   return Qt::SolidLine;
     175                 :            : }
     176                 :            : 
     177                 :          0 : QColor QgsSymbolLayer::dxfBrushColor( QgsSymbolRenderContext &context ) const
     178                 :            : {
     179                 :          0 :   Q_UNUSED( context )
     180                 :          0 :   return color();
     181                 :            : }
     182                 :            : 
     183                 :          0 : Qt::BrushStyle QgsSymbolLayer::dxfBrushStyle() const
     184                 :            : {
     185                 :          0 :   return Qt::NoBrush;
     186                 :            : }
     187                 :            : 
     188                 :          0 : QgsPaintEffect *QgsSymbolLayer::paintEffect() const
     189                 :            : {
     190                 :          0 :   return mPaintEffect.get();
     191                 :            : }
     192                 :            : 
     193                 :         50 : void QgsSymbolLayer::setPaintEffect( QgsPaintEffect *effect )
     194                 :            : {
     195                 :         50 :   if ( effect == mPaintEffect.get() )
     196                 :          0 :     return;
     197                 :            : 
     198                 :         50 :   mPaintEffect.reset( effect );
     199                 :         50 : }
     200                 :            : 
     201                 :       1343 : QgsSymbolLayer::QgsSymbolLayer( QgsSymbol::SymbolType type, bool locked )
     202                 :       1343 :   : mType( type )
     203                 :       1343 :   , mLocked( locked )
     204                 :       1343 : {
     205                 :       1343 : }
     206                 :            : 
     207                 :          0 : void QgsSymbolLayer::prepareExpressions( const QgsSymbolRenderContext &context )
     208                 :            : {
     209                 :          0 :   mDataDefinedProperties.prepare( context.renderContext().expressionContext() );
     210                 :            : 
     211                 :          0 :   if ( !context.fields().isEmpty() )
     212                 :            :   {
     213                 :            :     //QgsFields is implicitly shared, so it's cheap to make a copy
     214                 :          0 :     mFields = context.fields();
     215                 :          0 :   }
     216                 :          0 : }
     217                 :            : 
     218                 :          0 : bool QgsSymbolLayer::hasDataDefinedProperties() const
     219                 :            : {
     220                 :          0 :   return mDataDefinedProperties.hasActiveProperties();
     221                 :            : }
     222                 :            : 
     223                 :        990 : const QgsPropertiesDefinition &QgsSymbolLayer::propertyDefinitions()
     224                 :            : {
     225                 :        990 :   QgsSymbolLayer::initPropertyDefinitions();
     226                 :        990 :   return sPropertyDefinitions;
     227                 :            : }
     228                 :            : 
     229                 :        923 : QgsSymbolLayer::~QgsSymbolLayer() = default;
     230                 :            : 
     231                 :       1020 : bool QgsSymbolLayer::isCompatibleWithSymbol( QgsSymbol *symbol ) const
     232                 :            : {
     233                 :       1020 :   if ( symbol->type() == QgsSymbol::Fill && mType == QgsSymbol::Line )
     234                 :        125 :     return true;
     235                 :            : 
     236                 :        895 :   return symbol->type() == mType;
     237                 :       1020 : }
     238                 :            : 
     239                 :          0 : bool QgsSymbolLayer::canCauseArtifactsBetweenAdjacentTiles() const
     240                 :            : {
     241                 :          0 :   return false;
     242                 :            : }
     243                 :            : 
     244                 :          0 : bool QgsSymbolLayer::usesMapUnits() const
     245                 :            : {
     246                 :          0 :   return false;
     247                 :            : }
     248                 :            : 
     249                 :        990 : void QgsSymbolLayer::setRenderingPass( int renderingPass )
     250                 :            : {
     251                 :        990 :   mRenderingPass = renderingPass;
     252                 :        990 : }
     253                 :            : 
     254                 :          0 : int QgsSymbolLayer::renderingPass() const
     255                 :            : {
     256                 :          0 :   return mRenderingPass;
     257                 :            : }
     258                 :            : 
     259                 :          0 : QSet<QString> QgsSymbolLayer::usedAttributes( const QgsRenderContext &context ) const
     260                 :            : {
     261                 :            :   // calling referencedFields() with ignoreContext=true because in our expression context
     262                 :            :   // we do not have valid QgsFields yet - because of that the field names from expressions
     263                 :            :   // wouldn't get reported
     264                 :          0 :   QSet<QString> columns = mDataDefinedProperties.referencedFields( context.expressionContext(), true );
     265                 :          0 :   return columns;
     266                 :          0 : }
     267                 :            : 
     268                 :          0 : QgsProperty propertyFromMap( const QVariantMap &map, const QString &baseName )
     269                 :            : {
     270                 :          0 :   QString prefix;
     271                 :          0 :   if ( !baseName.isEmpty() )
     272                 :            :   {
     273                 :          0 :     prefix.append( QStringLiteral( "%1_dd_" ).arg( baseName ) );
     274                 :          0 :   }
     275                 :            : 
     276                 :          0 :   if ( !map.contains( QStringLiteral( "%1expression" ).arg( prefix ) ) )
     277                 :            :   {
     278                 :            :     //requires at least the expression value
     279                 :          0 :     return QgsProperty();
     280                 :            :   }
     281                 :            : 
     282                 :          0 :   bool active = ( map.value( QStringLiteral( "%1active" ).arg( prefix ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
     283                 :          0 :   QString expression = map.value( QStringLiteral( "%1expression" ).arg( prefix ) ).toString();
     284                 :          0 :   bool useExpression = ( map.value( QStringLiteral( "%1useexpr" ).arg( prefix ), QStringLiteral( "1" ) ) != QLatin1String( "0" ) );
     285                 :          0 :   QString field = map.value( QStringLiteral( "%1field" ).arg( prefix ), QString() ).toString();
     286                 :            : 
     287                 :          0 :   if ( useExpression )
     288                 :          0 :     return QgsProperty::fromExpression( expression, active );
     289                 :            :   else
     290                 :          0 :     return QgsProperty::fromField( field, active );
     291                 :          0 : }
     292                 :            : 
     293                 :       1000 : void QgsSymbolLayer::restoreOldDataDefinedProperties( const QVariantMap &stringMap )
     294                 :            : {
     295                 :            :   // property string to type upgrade map
     296                 :       1355 :   static const QMap< QString, QgsSymbolLayer::Property > OLD_PROPS
     297                 :          5 :   {
     298                 :          5 :     { "color", QgsSymbolLayer::PropertyFillColor },
     299                 :          5 :     { "arrow_width", QgsSymbolLayer::PropertyArrowWidth },
     300                 :          5 :     { "arrow_start_width", QgsSymbolLayer::PropertyArrowStartWidth },
     301                 :          5 :     { "head_length", QgsSymbolLayer::PropertyArrowHeadLength },
     302                 :          5 :     { "head_thickness", QgsSymbolLayer::PropertyArrowHeadThickness },
     303                 :          5 :     { "offset", QgsSymbolLayer::PropertyOffset },
     304                 :          5 :     { "head_type", QgsSymbolLayer::PropertyArrowHeadType },
     305                 :          5 :     { "arrow_type", QgsSymbolLayer::PropertyArrowType },
     306                 :          5 :     { "width_field", QgsSymbolLayer::PropertyWidth },
     307                 :          5 :     { "height_field", QgsSymbolLayer::PropertyHeight },
     308                 :          5 :     { "rotation_field", QgsSymbolLayer::PropertyAngle },
     309                 :          5 :     { "outline_width_field", QgsSymbolLayer::PropertyStrokeWidth },
     310                 :          5 :     { "fill_color_field", QgsSymbolLayer::PropertyFillColor },
     311                 :          5 :     { "outline_color_field", QgsSymbolLayer::PropertyStrokeColor },
     312                 :          5 :     { "symbol_name_field", QgsSymbolLayer::PropertyName },
     313                 :          5 :     { "outline_width", QgsSymbolLayer::PropertyStrokeWidth },
     314                 :          5 :     { "outline_style", QgsSymbolLayer::PropertyStrokeStyle },
     315                 :          5 :     { "join_style", QgsSymbolLayer::PropertyJoinStyle },
     316                 :          5 :     { "fill_color", QgsSymbolLayer::PropertyFillColor },
     317                 :          5 :     { "outline_color", QgsSymbolLayer::PropertyStrokeColor },
     318                 :          5 :     { "width", QgsSymbolLayer::PropertyWidth },
     319                 :          5 :     { "height", QgsSymbolLayer::PropertyHeight },
     320                 :          5 :     { "symbol_name", QgsSymbolLayer::PropertyName },
     321                 :          5 :     { "angle", QgsSymbolLayer::PropertyAngle },
     322                 :          5 :     { "fill_style", QgsSymbolLayer::PropertyFillStyle },
     323                 :          5 :     { "color_border", QgsSymbolLayer::PropertyStrokeColor },
     324                 :          5 :     { "width_border", QgsSymbolLayer::PropertyStrokeWidth },
     325                 :          5 :     { "border_color", QgsSymbolLayer::PropertyStrokeColor },
     326                 :          5 :     { "border_style", QgsSymbolLayer::PropertyStrokeStyle },
     327                 :          5 :     { "color2", QgsSymbolLayer::PropertySecondaryColor },
     328                 :          5 :     { "gradient_type", QgsSymbolLayer::PropertyGradientType },
     329                 :          5 :     { "coordinate_mode", QgsSymbolLayer::PropertyCoordinateMode },
     330                 :          5 :     { "spread", QgsSymbolLayer::PropertyGradientSpread },
     331                 :          5 :     { "reference1_x", QgsSymbolLayer::PropertyGradientReference1X },
     332                 :          5 :     { "reference1_y", QgsSymbolLayer::PropertyGradientReference1Y },
     333                 :          5 :     { "reference2_x", QgsSymbolLayer::PropertyGradientReference2X },
     334                 :          5 :     { "reference2_y", QgsSymbolLayer::PropertyGradientReference2Y },
     335                 :          5 :     { "reference1_iscentroid", QgsSymbolLayer::PropertyGradientReference1IsCentroid },
     336                 :          5 :     { "reference2_iscentroid", QgsSymbolLayer::PropertyGradientReference2IsCentroid },
     337                 :          5 :     { "blur_radius", QgsSymbolLayer::PropertyBlurRadius },
     338                 :          5 :     { "use_whole_shape", QgsSymbolLayer::PropertyShapeburstUseWholeShape },
     339                 :          5 :     { "max_distance", QgsSymbolLayer::PropertyShapeburstMaxDistance },
     340                 :          5 :     { "ignore_rings", QgsSymbolLayer::PropertyShapeburstIgnoreRings },
     341                 :          5 :     { "svgFillColor", QgsSymbolLayer::PropertyFillColor },
     342                 :          5 :     { "svgOutlineColor", QgsSymbolLayer::PropertyStrokeColor },
     343                 :          5 :     { "svgOutlineWidth", QgsSymbolLayer::PropertyStrokeWidth },
     344                 :          5 :     { "svgFile", QgsSymbolLayer::PropertyFile },
     345                 :          5 :     { "lineangle", QgsSymbolLayer::PropertyLineAngle },
     346                 :          5 :     { "distance", QgsSymbolLayer::PropertyLineDistance },
     347                 :          5 :     { "distance_x", QgsSymbolLayer::PropertyDistanceX },
     348                 :          5 :     { "distance_y", QgsSymbolLayer::PropertyDistanceY },
     349                 :          5 :     { "displacement_x", QgsSymbolLayer::PropertyDisplacementX },
     350                 :          5 :     { "displacement_y", QgsSymbolLayer::PropertyDisplacementY },
     351                 :          5 :     { "file", QgsSymbolLayer::PropertyFile },
     352                 :          5 :     { "alpha", QgsSymbolLayer::PropertyOpacity },
     353                 :          5 :     { "customdash", QgsSymbolLayer::PropertyCustomDash },
     354                 :          5 :     { "line_style", QgsSymbolLayer::PropertyStrokeStyle },
     355                 :          5 :     { "joinstyle", QgsSymbolLayer::PropertyJoinStyle },
     356                 :          5 :     { "capstyle", QgsSymbolLayer::PropertyCapStyle },
     357                 :          5 :     { "placement", QgsSymbolLayer::PropertyPlacement },
     358                 :          5 :     { "interval", QgsSymbolLayer::PropertyInterval },
     359                 :          5 :     { "offset_along_line", QgsSymbolLayer::PropertyOffsetAlongLine },
     360                 :          5 :     { "name", QgsSymbolLayer::PropertyName },
     361                 :          5 :     { "size", QgsSymbolLayer::PropertySize },
     362                 :          5 :     { "fill", QgsSymbolLayer::PropertyFillColor },
     363                 :          5 :     { "outline", QgsSymbolLayer::PropertyStrokeColor },
     364                 :          5 :     { "char", QgsSymbolLayer::PropertyCharacter },
     365                 :          5 :     { "enabled", QgsSymbolLayer::PropertyLayerEnabled },
     366                 :          5 :     { "rotation", QgsSymbolLayer::PropertyAngle },
     367                 :          5 :     { "horizontal_anchor_point", QgsSymbolLayer::PropertyHorizontalAnchor },
     368                 :          5 :     { "vertical_anchor_point", QgsSymbolLayer::PropertyVerticalAnchor },
     369                 :            :   };
     370                 :            : 
     371                 :       1000 :   QVariantMap::const_iterator propIt = stringMap.constBegin();
     372                 :      19820 :   for ( ; propIt != stringMap.constEnd(); ++propIt )
     373                 :            :   {
     374                 :      18820 :     std::unique_ptr<QgsProperty> prop;
     375                 :      18820 :     QString propertyName;
     376                 :            : 
     377                 :      18820 :     if ( propIt.key().endsWith( QLatin1String( "_dd_expression" ) ) )
     378                 :            :     {
     379                 :            :       //found a data defined property
     380                 :            : 
     381                 :            :       //get data defined property name by stripping "_dd_expression" from property key
     382                 :          0 :       propertyName = propIt.key().left( propIt.key().length() - 14 );
     383                 :            : 
     384                 :          0 :       prop = std::make_unique<QgsProperty>( propertyFromMap( stringMap, propertyName ) );
     385                 :          0 :     }
     386                 :      18820 :     else if ( propIt.key().endsWith( QLatin1String( "_expression" ) ) )
     387                 :            :     {
     388                 :            :       //old style data defined property, upgrade
     389                 :            : 
     390                 :            :       //get data defined property name by stripping "_expression" from property key
     391                 :          0 :       propertyName = propIt.key().left( propIt.key().length() - 11 );
     392                 :            : 
     393                 :          0 :       prop = std::make_unique<QgsProperty>( QgsProperty::fromExpression( propIt.value().toString() ) );
     394                 :          0 :     }
     395                 :            : 
     396                 :      18820 :     if ( !prop || !OLD_PROPS.contains( propertyName ) )
     397                 :      18820 :       continue;
     398                 :            : 
     399                 :          0 :     QgsSymbolLayer::Property key = static_cast< QgsSymbolLayer::Property >( OLD_PROPS.value( propertyName ) );
     400                 :            : 
     401                 :          0 :     if ( type() == QgsSymbol::Line )
     402                 :            :     {
     403                 :            :       //these keys had different meaning for line symbol layers
     404                 :          0 :       if ( propertyName == QLatin1String( "width" ) )
     405                 :          0 :         key = QgsSymbolLayer::PropertyStrokeWidth;
     406                 :          0 :       else if ( propertyName == QLatin1String( "color" ) )
     407                 :          0 :         key = QgsSymbolLayer::PropertyStrokeColor;
     408                 :          0 :     }
     409                 :            : 
     410                 :          0 :     setDataDefinedProperty( key, QgsProperty( *prop.get() ) );
     411                 :      18820 :   }
     412                 :       1000 : }
     413                 :            : 
     414                 :          0 : void QgsSymbolLayer::copyDataDefinedProperties( QgsSymbolLayer *destLayer ) const
     415                 :            : {
     416                 :          0 :   if ( !destLayer )
     417                 :          0 :     return;
     418                 :            : 
     419                 :          0 :   destLayer->setDataDefinedProperties( mDataDefinedProperties );
     420                 :          0 : }
     421                 :            : 
     422                 :          0 : void QgsSymbolLayer::copyPaintEffect( QgsSymbolLayer *destLayer ) const
     423                 :            : {
     424                 :          0 :   if ( !destLayer || !mPaintEffect )
     425                 :          0 :     return;
     426                 :            : 
     427                 :          0 :   if ( !QgsPaintEffectRegistry::isDefaultStack( mPaintEffect.get() ) )
     428                 :          0 :     destLayer->setPaintEffect( mPaintEffect->clone() );
     429                 :            :   else
     430                 :          0 :     destLayer->setPaintEffect( nullptr );
     431                 :          0 : }
     432                 :            : 
     433                 :        372 : QgsMarkerSymbolLayer::QgsMarkerSymbolLayer( bool locked )
     434                 :        372 :   : QgsSymbolLayer( QgsSymbol::Marker, locked )
     435                 :        744 : {
     436                 :            : 
     437                 :        372 : }
     438                 :            : 
     439                 :        610 : QgsLineSymbolLayer::QgsLineSymbolLayer( bool locked )
     440                 :        610 :   : QgsSymbolLayer( QgsSymbol::Line, locked )
     441                 :       1220 : {
     442                 :        610 : }
     443                 :            : 
     444                 :          0 : QgsLineSymbolLayer::RenderRingFilter QgsLineSymbolLayer::ringFilter() const
     445                 :            : {
     446                 :          0 :   return mRingFilter;
     447                 :            : }
     448                 :            : 
     449                 :        405 : void QgsLineSymbolLayer::setRingFilter( const RenderRingFilter filter )
     450                 :            : {
     451                 :        405 :   mRingFilter = filter;
     452                 :        405 : }
     453                 :            : 
     454                 :        361 : QgsFillSymbolLayer::QgsFillSymbolLayer( bool locked )
     455                 :        361 :   : QgsSymbolLayer( QgsSymbol::Fill, locked )
     456                 :        722 : {
     457                 :        361 : }
     458                 :            : 
     459                 :          0 : void QgsMarkerSymbolLayer::startRender( QgsSymbolRenderContext &context )
     460                 :            : {
     461                 :          0 :   Q_UNUSED( context )
     462                 :          0 : }
     463                 :            : 
     464                 :          0 : void QgsMarkerSymbolLayer::stopRender( QgsSymbolRenderContext &context )
     465                 :            : {
     466                 :          0 :   Q_UNUSED( context )
     467                 :          0 : }
     468                 :            : 
     469                 :          0 : void QgsMarkerSymbolLayer::drawPreviewIcon( QgsSymbolRenderContext &context, QSize size )
     470                 :            : {
     471                 :          0 :   startRender( context );
     472                 :          0 :   QgsPaintEffect *effect = paintEffect();
     473                 :            : 
     474                 :          0 :   QPolygonF points = context.patchShape() ? context.patchShape()->toQPolygonF( QgsSymbol::Marker, size ).value( 0 ).value( 0 )
     475                 :          0 :                      : QgsStyle::defaultStyle()->defaultPatchAsQPolygonF( QgsSymbol::Marker, size ).value( 0 ).value( 0 );
     476                 :            : 
     477                 :          0 :   std::unique_ptr< QgsEffectPainter > effectPainter;
     478                 :          0 :   if ( effect && effect->enabled() )
     479                 :          0 :     effectPainter = std::make_unique< QgsEffectPainter >( context.renderContext(), effect );
     480                 :            : 
     481                 :          0 :   for ( QPointF point : std::as_const( points ) )
     482                 :          0 :     renderPoint( point, context );
     483                 :            : 
     484                 :          0 :   effectPainter.reset();
     485                 :            : 
     486                 :          0 :   stopRender( context );
     487                 :          0 : }
     488                 :            : 
     489                 :          0 : void QgsMarkerSymbolLayer::markerOffset( QgsSymbolRenderContext &context, double &offsetX, double &offsetY ) const
     490                 :            : {
     491                 :          0 :   markerOffset( context, mSize, mSize, mSizeUnit, mSizeUnit, offsetX, offsetY, mSizeMapUnitScale, mSizeMapUnitScale );
     492                 :          0 : }
     493                 :            : 
     494                 :          0 : void QgsMarkerSymbolLayer::markerOffset( QgsSymbolRenderContext &context, double width, double height, double &offsetX, double &offsetY ) const
     495                 :            : {
     496                 :          0 :   markerOffset( context, width, height, mSizeUnit, mSizeUnit, offsetX, offsetY, mSizeMapUnitScale, mSizeMapUnitScale );
     497                 :          0 : }
     498                 :            : 
     499                 :          0 : void QgsMarkerSymbolLayer::markerOffset( QgsSymbolRenderContext &context, double width, double height,
     500                 :            :     QgsUnitTypes::RenderUnit widthUnit, QgsUnitTypes::RenderUnit heightUnit,
     501                 :            :     double &offsetX, double &offsetY, const QgsMapUnitScale &widthMapUnitScale, const QgsMapUnitScale &heightMapUnitScale ) const
     502                 :            : {
     503                 :          0 :   offsetX = mOffset.x();
     504                 :          0 :   offsetY = mOffset.y();
     505                 :            : 
     506                 :          0 :   if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyOffset ) )
     507                 :            :   {
     508                 :          0 :     context.setOriginalValueVariable( QgsSymbolLayerUtils::encodePoint( mOffset ) );
     509                 :          0 :     QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyOffset, context.renderContext().expressionContext() );
     510                 :          0 :     bool ok = false;
     511                 :          0 :     const QPointF offset = QgsSymbolLayerUtils::toPoint( exprVal, &ok );
     512                 :          0 :     if ( ok )
     513                 :            :     {
     514                 :          0 :       offsetX = offset.x();
     515                 :          0 :       offsetY = offset.y();
     516                 :          0 :     }
     517                 :          0 :   }
     518                 :            : 
     519                 :          0 :   offsetX = context.renderContext().convertToPainterUnits( offsetX, mOffsetUnit, mOffsetMapUnitScale );
     520                 :          0 :   offsetY = context.renderContext().convertToPainterUnits( offsetY, mOffsetUnit, mOffsetMapUnitScale );
     521                 :            : 
     522                 :          0 :   HorizontalAnchorPoint horizontalAnchorPoint = mHorizontalAnchorPoint;
     523                 :          0 :   VerticalAnchorPoint verticalAnchorPoint = mVerticalAnchorPoint;
     524                 :          0 :   if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHorizontalAnchor ) )
     525                 :            :   {
     526                 :          0 :     QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyHorizontalAnchor, context.renderContext().expressionContext() );
     527                 :          0 :     if ( exprVal.isValid() )
     528                 :            :     {
     529                 :          0 :       horizontalAnchorPoint = decodeHorizontalAnchorPoint( exprVal.toString() );
     530                 :          0 :     }
     531                 :          0 :   }
     532                 :          0 :   if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyVerticalAnchor ) )
     533                 :            :   {
     534                 :          0 :     QVariant exprVal = mDataDefinedProperties.value( QgsSymbolLayer::PropertyVerticalAnchor, context.renderContext().expressionContext() );
     535                 :          0 :     if ( exprVal.isValid() )
     536                 :            :     {
     537                 :          0 :       verticalAnchorPoint = decodeVerticalAnchorPoint( exprVal.toString() );
     538                 :          0 :     }
     539                 :          0 :   }
     540                 :            : 
     541                 :            :   //correct horizontal position according to anchor point
     542                 :          0 :   if ( horizontalAnchorPoint == HCenter && verticalAnchorPoint == VCenter )
     543                 :            :   {
     544                 :       1343 :     return;
     545                 :            :   }
     546                 :            : 
     547                 :          0 :   double anchorPointCorrectionX = context.renderContext().convertToPainterUnits( width, widthUnit, widthMapUnitScale ) / 2.0;
     548                 :       1343 :   if ( widthUnit == QgsUnitTypes::RenderMetersInMapUnits && context.renderContext().flags() & QgsRenderContext::RenderSymbolPreview )
     549                 :            :   {
     550                 :            :     // rendering for symbol previews -- an size in meters in map units can't be calculated, so treat the size as millimeters
     551                 :            :     // and clamp it to a reasonable range. It's the best we can do in this situation!
     552                 :          0 :     anchorPointCorrectionX = std::min( std::max( context.renderContext().convertToPainterUnits( width, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 ) / 2.0;
     553                 :          0 :   }
     554                 :            : 
     555                 :          0 :   double anchorPointCorrectionY = context.renderContext().convertToPainterUnits( height, heightUnit, heightMapUnitScale ) / 2.0;
     556                 :          0 :   if ( heightUnit == QgsUnitTypes::RenderMetersInMapUnits && context.renderContext().flags() & QgsRenderContext::RenderSymbolPreview )
     557                 :            :   {
     558                 :            :     // rendering for symbol previews -- an size in meters in map units can't be calculated, so treat the size as millimeters
     559                 :            :     // and clamp it to a reasonable range. It's the best we can do in this situation!
     560                 :          0 :     anchorPointCorrectionY = std::min( std::max( context.renderContext().convertToPainterUnits( height, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 ) / 2.0;
     561                 :          0 :   }
     562                 :            : 
     563                 :          0 :   if ( horizontalAnchorPoint == Left )
     564                 :            :   {
     565                 :          0 :     offsetX += anchorPointCorrectionX;
     566                 :          0 :   }
     567                 :          0 :   else if ( horizontalAnchorPoint == Right )
     568                 :            :   {
     569                 :          0 :     offsetX -= anchorPointCorrectionX;
     570                 :          0 :   }
     571                 :            : 
     572                 :            :   //correct vertical position according to anchor point
     573                 :          0 :   if ( verticalAnchorPoint == Top )
     574                 :            :   {
     575                 :          0 :     offsetY += anchorPointCorrectionY;
     576                 :          0 :   }
     577                 :          0 :   else if ( verticalAnchorPoint == Bottom )
     578                 :            :   {
     579                 :          0 :     offsetY -= anchorPointCorrectionY;
     580                 :          0 :   }
     581                 :          0 : }
     582                 :            : 
     583                 :          0 : QPointF QgsMarkerSymbolLayer::_rotatedOffset( QPointF offset, double angle )
     584                 :            : {
     585                 :          0 :   angle = DEG2RAD( angle );
     586                 :          0 :   double c = std::cos( angle ), s = std::sin( angle );
     587                 :          0 :   return QPointF( offset.x() * c - offset.y() * s, offset.x() * s + offset.y() * c );
     588                 :            : }
     589                 :            : 
     590                 :          0 : QgsMarkerSymbolLayer::HorizontalAnchorPoint QgsMarkerSymbolLayer::decodeHorizontalAnchorPoint( const QString &str )
     591                 :            : {
     592                 :          0 :   if ( str.compare( QLatin1String( "left" ), Qt::CaseInsensitive ) == 0 )
     593                 :            :   {
     594                 :          0 :     return QgsMarkerSymbolLayer::Left;
     595                 :            :   }
     596                 :          0 :   else if ( str.compare( QLatin1String( "right" ), Qt::CaseInsensitive ) == 0 )
     597                 :            :   {
     598                 :          0 :     return QgsMarkerSymbolLayer::Right;
     599                 :            :   }
     600                 :            :   else
     601                 :            :   {
     602                 :          0 :     return QgsMarkerSymbolLayer::HCenter;
     603                 :            :   }
     604                 :          0 : }
     605                 :            : 
     606                 :          0 : QgsMarkerSymbolLayer::VerticalAnchorPoint QgsMarkerSymbolLayer::decodeVerticalAnchorPoint( const QString &str )
     607                 :            : {
     608                 :          0 :   if ( str.compare( QLatin1String( "top" ), Qt::CaseInsensitive ) == 0 )
     609                 :            :   {
     610                 :          0 :     return QgsMarkerSymbolLayer::Top;
     611                 :            :   }
     612                 :          0 :   else if ( str.compare( QLatin1String( "bottom" ), Qt::CaseInsensitive ) == 0 )
     613                 :            :   {
     614                 :          0 :     return QgsMarkerSymbolLayer::Bottom;
     615                 :            :   }
     616                 :            :   else
     617                 :            :   {
     618                 :          0 :     return QgsMarkerSymbolLayer::VCenter;
     619                 :            :   }
     620                 :          0 : }
     621                 :            : 
     622                 :          0 : void QgsMarkerSymbolLayer::setOutputUnit( QgsUnitTypes::RenderUnit unit )
     623                 :            : {
     624                 :          0 :   mSizeUnit = unit;
     625                 :          0 :   mOffsetUnit = unit;
     626                 :          0 : }
     627                 :            : 
     628                 :          0 : QgsUnitTypes::RenderUnit QgsMarkerSymbolLayer::outputUnit() const
     629                 :            : {
     630                 :          0 :   if ( mOffsetUnit != mSizeUnit )
     631                 :            :   {
     632                 :          0 :     return QgsUnitTypes::RenderUnknownUnit;
     633                 :            :   }
     634                 :          0 :   return mOffsetUnit;
     635                 :          0 : }
     636                 :            : 
     637                 :          0 : void QgsMarkerSymbolLayer::setMapUnitScale( const QgsMapUnitScale &scale )
     638                 :            : {
     639                 :          0 :   mSizeMapUnitScale = scale;
     640                 :          0 :   mOffsetMapUnitScale = scale;
     641                 :          0 : }
     642                 :            : 
     643                 :          0 : QgsMapUnitScale QgsMarkerSymbolLayer::mapUnitScale() const
     644                 :            : {
     645                 :          0 :   if ( mSizeMapUnitScale == mOffsetMapUnitScale )
     646                 :            :   {
     647                 :          0 :     return mSizeMapUnitScale;
     648                 :            :   }
     649                 :          0 :   return QgsMapUnitScale();
     650                 :          0 : }
     651                 :            : 
     652                 :          0 : void QgsLineSymbolLayer::setOutputUnit( QgsUnitTypes::RenderUnit unit )
     653                 :            : {
     654                 :          0 :   mWidthUnit = unit;
     655                 :          0 : }
     656                 :            : 
     657                 :          0 : QgsUnitTypes::RenderUnit QgsLineSymbolLayer::outputUnit() const
     658                 :            : {
     659                 :          0 :   return mWidthUnit;
     660                 :            : }
     661                 :            : 
     662                 :          0 : void QgsLineSymbolLayer::setMapUnitScale( const QgsMapUnitScale &scale )
     663                 :            : {
     664                 :          0 :   mWidthMapUnitScale = scale;
     665                 :          0 : }
     666                 :            : 
     667                 :          0 : QgsMapUnitScale QgsLineSymbolLayer::mapUnitScale() const
     668                 :            : {
     669                 :          0 :   return mWidthMapUnitScale;
     670                 :            : }
     671                 :            : 
     672                 :            : 
     673                 :          0 : void QgsLineSymbolLayer::drawPreviewIcon( QgsSymbolRenderContext &context, QSize size )
     674                 :            : {
     675                 :          0 :   const QList< QList< QPolygonF > > points = context.patchShape() ? context.patchShape()->toQPolygonF( QgsSymbol::Line, size )
     676                 :          0 :       : QgsStyle::defaultStyle()->defaultPatchAsQPolygonF( QgsSymbol::Line, size );
     677                 :          0 :   startRender( context );
     678                 :          0 :   QgsPaintEffect *effect = paintEffect();
     679                 :            : 
     680                 :          0 :   std::unique_ptr< QgsEffectPainter > effectPainter;
     681                 :          0 :   if ( effect && effect->enabled() )
     682                 :          0 :     effectPainter = std::make_unique< QgsEffectPainter >( context.renderContext(), effect );
     683                 :            : 
     684                 :          0 :   for ( const QList< QPolygonF > &line : points )
     685                 :          0 :     renderPolyline( line.value( 0 ), context );
     686                 :            : 
     687                 :          0 :   effectPainter.reset();
     688                 :            : 
     689                 :          0 :   stopRender( context );
     690                 :          0 : }
     691                 :            : 
     692                 :          0 : void QgsLineSymbolLayer::renderPolygonStroke( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context )
     693                 :            : {
     694                 :          0 :   switch ( mRingFilter )
     695                 :            :   {
     696                 :            :     case AllRings:
     697                 :            :     case ExteriorRingOnly:
     698                 :          0 :       renderPolyline( points, context );
     699                 :          0 :       break;
     700                 :            :     case InteriorRingsOnly:
     701                 :          0 :       break;
     702                 :            :   }
     703                 :            : 
     704                 :          0 :   if ( rings )
     705                 :            :   {
     706                 :          0 :     switch ( mRingFilter )
     707                 :            :     {
     708                 :            :       case AllRings:
     709                 :            :       case InteriorRingsOnly:
     710                 :            :       {
     711                 :          0 :         for ( const QPolygonF &ring : std::as_const( *rings ) )
     712                 :          0 :           renderPolyline( ring, context );
     713                 :            :       }
     714                 :          0 :       break;
     715                 :            :       case ExteriorRingOnly:
     716                 :          0 :         break;
     717                 :            :     }
     718                 :          0 :   }
     719                 :          0 : }
     720                 :            : 
     721                 :          0 : double QgsLineSymbolLayer::width( const QgsRenderContext &context ) const
     722                 :            : {
     723                 :          0 :   return context.convertToPainterUnits( mWidth, mWidthUnit, mWidthMapUnitScale );
     724                 :            : }
     725                 :            : 
     726                 :          0 : double QgsLineSymbolLayer::dxfWidth( const QgsDxfExport &e, QgsSymbolRenderContext &context ) const
     727                 :            : {
     728                 :          0 :   Q_UNUSED( context )
     729                 :          0 :   return width() * e.mapUnitScaleFactor( e.symbologyScale(), widthUnit(), e.mapUnits(), context.renderContext().mapToPixel().mapUnitsPerPixel() );
     730                 :            : }
     731                 :            : 
     732                 :            : 
     733                 :          0 : void QgsFillSymbolLayer::drawPreviewIcon( QgsSymbolRenderContext &context, QSize size )
     734                 :            : {
     735                 :          0 :   const QList< QList< QPolygonF > > polys = context.patchShape() ? context.patchShape()->toQPolygonF( QgsSymbol::Fill, size )
     736                 :          0 :       : QgsStyle::defaultStyle()->defaultPatchAsQPolygonF( QgsSymbol::Fill, size );
     737                 :            : 
     738                 :          0 :   startRender( context );
     739                 :          0 :   QgsPaintEffect *effect = paintEffect();
     740                 :            : 
     741                 :          0 :   std::unique_ptr< QgsEffectPainter > effectPainter;
     742                 :          0 :   if ( effect && effect->enabled() )
     743                 :          0 :     effectPainter = std::make_unique< QgsEffectPainter >( context.renderContext(), effect );
     744                 :            : 
     745                 :          0 :   for ( const QList< QPolygonF > &poly : polys )
     746                 :            :   {
     747                 :          0 :     QVector< QPolygonF > rings;
     748                 :          0 :     for ( int i = 1; i < poly.size(); ++i )
     749                 :          0 :       rings << poly.at( i );
     750                 :          0 :     renderPolygon( poly.value( 0 ), &rings, context );
     751                 :          0 :   }
     752                 :            : 
     753                 :          0 :   effectPainter.reset();
     754                 :            : 
     755                 :          0 :   stopRender( context );
     756                 :          0 : }
     757                 :            : 
     758                 :          0 : void QgsFillSymbolLayer::_renderPolygon( QPainter *p, const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context )
     759                 :            : {
     760                 :          0 :   if ( !p )
     761                 :            :   {
     762                 :          0 :     return;
     763                 :            :   }
     764                 :            : 
     765                 :            :   // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #5 points).
     766                 :          0 :   if ( points.size() <= 5 &&
     767                 :          0 :        ( context.renderContext().vectorSimplifyMethod().simplifyHints() & QgsVectorSimplifyMethod::AntialiasingSimplification ) &&
     768                 :          0 :        QgsAbstractGeometrySimplifier::isGeneralizableByDeviceBoundingBox( points, context.renderContext().vectorSimplifyMethod().threshold() ) &&
     769                 :          0 :        ( p->renderHints() & QPainter::Antialiasing ) )
     770                 :            :   {
     771                 :          0 :     p->setRenderHint( QPainter::Antialiasing, false );
     772                 :          0 :     p->drawRect( points.boundingRect() );
     773                 :          0 :     p->setRenderHint( QPainter::Antialiasing, true );
     774                 :          0 :     return;
     775                 :            :   }
     776                 :            : 
     777                 :            :   // polygons outlines are sometimes rendered wrongly with drawPolygon, when
     778                 :            :   // clipped (see #13343), so use drawPath instead.
     779                 :          0 :   if ( !rings && p->pen().style() == Qt::NoPen )
     780                 :            :   {
     781                 :            :     // simple polygon without holes
     782                 :          0 :     p->drawPolygon( points );
     783                 :          0 :   }
     784                 :            :   else
     785                 :            :   {
     786                 :            :     // polygon with holes must be drawn using painter path
     787                 :          0 :     QPainterPath path;
     788                 :          0 :     path.addPolygon( points );
     789                 :            : 
     790                 :          0 :     if ( rings )
     791                 :            :     {
     792                 :          0 :       for ( auto it = rings->constBegin(); it != rings->constEnd(); ++it )
     793                 :            :       {
     794                 :          0 :         QPolygonF ring = *it;
     795                 :          0 :         path.addPolygon( ring );
     796                 :          0 :       }
     797                 :          0 :     }
     798                 :            : 
     799                 :          0 :     p->drawPath( path );
     800                 :          0 :   }
     801                 :          0 : }
     802                 :            : 
     803                 :          0 : void QgsMarkerSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
     804                 :            : {
     805                 :          0 :   QDomElement symbolizerElem = doc.createElement( QStringLiteral( "se:PointSymbolizer" ) );
     806                 :          0 :   if ( !props.value( QStringLiteral( "uom" ), QString() ).toString().isEmpty() )
     807                 :          0 :     symbolizerElem.setAttribute( QStringLiteral( "uom" ), props.value( QStringLiteral( "uom" ), QString() ).toString() );
     808                 :          0 :   element.appendChild( symbolizerElem );
     809                 :            : 
     810                 :            :   // <Geometry>
     811                 :          0 :   QgsSymbolLayerUtils::createGeometryElement( doc, symbolizerElem, props.value( QStringLiteral( "geom" ), QString() ).toString() );
     812                 :            : 
     813                 :          0 :   writeSldMarker( doc, symbolizerElem, props );
     814                 :          0 : }
     815                 :            : 
     816                 :          0 : QgsSymbolLayerReferenceList QgsSymbolLayer::masks() const
     817                 :            : {
     818                 :          0 :   return {};
     819                 :            : }
     820                 :            : 

Generated by: LCOV version 1.14