48 #include <QDomDocument> 
   50 #include <QDomElement> 
   58 #include <QRegularExpression> 
   60 #define POINTS_TO_MM 2.83464567 
   64   return QStringLiteral( 
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
 
   69   const QStringList lst = 
str.split( 
',' );
 
   70   if ( lst.count() < 3 )
 
   74   int red, green, blue, alpha;
 
   76   green = lst[1].toInt();
 
   77   blue = lst[2].toInt();
 
   79   if ( lst.count() > 3 )
 
   81     alpha = lst[3].toInt();
 
   83   return QColor( red, green, blue, alpha );
 
   88   return QString::number( alpha / 255.0, 
'g', 2 );
 
   94   double alpha = 
str.toDouble( &ok );
 
   95   if ( !ok || alpha > 1 )
 
  106     case QFont::StyleNormal:
 
  107       return QStringLiteral( 
"normal" );
 
  108     case QFont::StyleItalic:
 
  109       return QStringLiteral( 
"italic" );
 
  110     case QFont::StyleOblique:
 
  111       return QStringLiteral( 
"oblique" );
 
  119   if ( 
str == QLatin1String( 
"normal" ) ) 
return QFont::StyleNormal;
 
  120   if ( 
str == QLatin1String( 
"italic" ) ) 
return QFont::StyleItalic;
 
  121   if ( 
str == QLatin1String( 
"oblique" ) ) 
return QFont::StyleOblique;
 
  122   return QFont::StyleNormal;
 
  127   if ( weight == 50 ) 
return QStringLiteral( 
"normal" );
 
  128   if ( weight == 75 ) 
return QStringLiteral( 
"bold" );
 
  132   if ( weight < 0 ) 
return QStringLiteral( 
"100" );
 
  133   if ( weight > 99 ) 
return QStringLiteral( 
"900" );
 
  134   return QString::number( weight * 800 / 99 + 100 );
 
  140   const int weight = 
str.toInt( &ok );
 
  142     return static_cast< int >( QFont::Normal );
 
  146   if ( weight > 900 ) 
return 99;
 
  147   if ( weight < 100 ) 
return 0;
 
  148   return ( weight - 100 ) * 99 / 800;
 
  156       return QStringLiteral( 
"no" );
 
  158       return QStringLiteral( 
"solid" );
 
  160       return QStringLiteral( 
"dash" );
 
  162       return QStringLiteral( 
"dot" );
 
  163     case Qt::DashDotLine:
 
  164       return QStringLiteral( 
"dash dot" );
 
  165     case Qt::DashDotDotLine:
 
  166       return QStringLiteral( 
"dash dot dot" );
 
  168       return QStringLiteral( 
"???" );
 
  174   if ( 
str == QLatin1String( 
"no" ) ) 
return Qt::NoPen;
 
  175   if ( 
str == QLatin1String( 
"solid" ) ) 
return Qt::SolidLine;
 
  176   if ( 
str == QLatin1String( 
"dash" ) ) 
return Qt::DashLine;
 
  177   if ( 
str == QLatin1String( 
"dot" ) ) 
return Qt::DotLine;
 
  178   if ( 
str == QLatin1String( 
"dash dot" ) ) 
return Qt::DashDotLine;
 
  179   if ( 
str == QLatin1String( 
"dash dot dot" ) ) 
return Qt::DashDotDotLine;
 
  180   return Qt::SolidLine;
 
  188       return QStringLiteral( 
"bevel" );
 
  190       return QStringLiteral( 
"miter" );
 
  192       return QStringLiteral( 
"round" );
 
  194       return QStringLiteral( 
"???" );
 
  200   const QString cleaned = 
str.toLower().trimmed();
 
  201   if ( cleaned == QLatin1String( 
"bevel" ) )
 
  202     return Qt::BevelJoin;
 
  203   if ( cleaned == QLatin1String( 
"miter" ) )
 
  204     return Qt::MiterJoin;
 
  205   if ( cleaned == QLatin1String( 
"round" ) )
 
  206     return Qt::RoundJoin;
 
  207   return Qt::BevelJoin;
 
  215       return QStringLiteral( 
"bevel" );
 
  217       return QStringLiteral( 
"mitre" );  
 
  219       return QStringLiteral( 
"round" );
 
  227   if ( 
str == QLatin1String( 
"bevel" ) ) 
return Qt::BevelJoin;
 
  228   if ( 
str == QLatin1String( 
"mitre" ) ) 
return Qt::MiterJoin;  
 
  229   if ( 
str == QLatin1String( 
"round" ) ) 
return Qt::RoundJoin;
 
  230   return Qt::BevelJoin;
 
  238       return QStringLiteral( 
"square" );
 
  240       return QStringLiteral( 
"flat" );
 
  242       return QStringLiteral( 
"round" );
 
  244       return QStringLiteral( 
"???" );
 
  250   if ( 
str == QLatin1String( 
"square" ) ) 
return Qt::SquareCap;
 
  251   if ( 
str == QLatin1String( 
"flat" ) ) 
return Qt::FlatCap;
 
  252   if ( 
str == QLatin1String( 
"round" ) ) 
return Qt::RoundCap;
 
  253   return Qt::SquareCap;
 
  261       return QStringLiteral( 
"square" );
 
  263       return QStringLiteral( 
"butt" );
 
  265       return QStringLiteral( 
"round" );
 
  273   if ( 
str == QLatin1String( 
"square" ) ) 
return Qt::SquareCap;
 
  274   if ( 
str == QLatin1String( 
"butt" ) ) 
return Qt::FlatCap;
 
  275   if ( 
str == QLatin1String( 
"round" ) ) 
return Qt::RoundCap;
 
  276   return Qt::SquareCap;
 
  283     case Qt::SolidPattern :
 
  284       return QStringLiteral( 
"solid" );
 
  285     case Qt::HorPattern :
 
  286       return QStringLiteral( 
"horizontal" );
 
  287     case Qt::VerPattern :
 
  288       return QStringLiteral( 
"vertical" );
 
  289     case Qt::CrossPattern :
 
  290       return QStringLiteral( 
"cross" );
 
  291     case Qt::BDiagPattern :
 
  292       return QStringLiteral( 
"b_diagonal" );
 
  293     case Qt::FDiagPattern :
 
  294       return  QStringLiteral( 
"f_diagonal" );
 
  295     case Qt::DiagCrossPattern :
 
  296       return QStringLiteral( 
"diagonal_x" );
 
  297     case Qt::Dense1Pattern  :
 
  298       return QStringLiteral( 
"dense1" );
 
  299     case Qt::Dense2Pattern  :
 
  300       return QStringLiteral( 
"dense2" );
 
  301     case Qt::Dense3Pattern  :
 
  302       return QStringLiteral( 
"dense3" );
 
  303     case Qt::Dense4Pattern  :
 
  304       return QStringLiteral( 
"dense4" );
 
  305     case Qt::Dense5Pattern  :
 
  306       return QStringLiteral( 
"dense5" );
 
  307     case Qt::Dense6Pattern  :
 
  308       return QStringLiteral( 
"dense6" );
 
  309     case Qt::Dense7Pattern  :
 
  310       return QStringLiteral( 
"dense7" );
 
  312       return QStringLiteral( 
"no" );
 
  314       return QStringLiteral( 
"???" );
 
  320   if ( 
str == QLatin1String( 
"solid" ) ) 
return Qt::SolidPattern;
 
  321   if ( 
str == QLatin1String( 
"horizontal" ) ) 
return Qt::HorPattern;
 
  322   if ( 
str == QLatin1String( 
"vertical" ) ) 
return Qt::VerPattern;
 
  323   if ( 
str == QLatin1String( 
"cross" ) ) 
return Qt::CrossPattern;
 
  324   if ( 
str == QLatin1String( 
"b_diagonal" ) ) 
return Qt::BDiagPattern;
 
  325   if ( 
str == QLatin1String( 
"f_diagonal" ) ) 
return Qt::FDiagPattern;
 
  326   if ( 
str == QLatin1String( 
"diagonal_x" ) ) 
return Qt::DiagCrossPattern;
 
  327   if ( 
str == QLatin1String( 
"dense1" ) ) 
return Qt::Dense1Pattern;
 
  328   if ( 
str == QLatin1String( 
"dense2" ) ) 
return Qt::Dense2Pattern;
 
  329   if ( 
str == QLatin1String( 
"dense3" ) ) 
return Qt::Dense3Pattern;
 
  330   if ( 
str == QLatin1String( 
"dense4" ) ) 
return Qt::Dense4Pattern;
 
  331   if ( 
str == QLatin1String( 
"dense5" ) ) 
return Qt::Dense5Pattern;
 
  332   if ( 
str == QLatin1String( 
"dense6" ) ) 
return Qt::Dense6Pattern;
 
  333   if ( 
str == QLatin1String( 
"dense7" ) ) 
return Qt::Dense7Pattern;
 
  334   if ( 
str == QLatin1String( 
"no" ) ) 
return Qt::NoBrush;
 
  335   return Qt::SolidPattern;
 
  342     case Qt::CrossPattern:
 
  343       return QStringLiteral( 
"cross" );
 
  344     case Qt::DiagCrossPattern:
 
  345       return QStringLiteral( 
"x" );
 
  352       return QStringLiteral( 
"horline" );
 
  354       return QStringLiteral( 
"line" );
 
  355     case Qt::BDiagPattern:
 
  356       return QStringLiteral( 
"slash" );
 
  357     case Qt::FDiagPattern:
 
  358       return QStringLiteral( 
"backslash" );
 
  361     case Qt::Dense1Pattern:
 
  362     case Qt::Dense2Pattern:
 
  363     case Qt::Dense3Pattern:
 
  364     case Qt::Dense4Pattern:
 
  365     case Qt::Dense5Pattern:
 
  366     case Qt::Dense6Pattern:
 
  367     case Qt::Dense7Pattern:
 
  377   if ( 
str == QLatin1String( 
"horline" ) ) 
return Qt::HorPattern;
 
  378   if ( 
str == QLatin1String( 
"line" ) ) 
return Qt::VerPattern;
 
  379   if ( 
str == QLatin1String( 
"cross" ) ) 
return Qt::CrossPattern;
 
  380   if ( 
str == QLatin1String( 
"slash" ) ) 
return Qt::BDiagPattern;
 
  381   if ( 
str == QLatin1String( 
"backshash" ) ) 
return Qt::FDiagPattern;
 
  382   if ( 
str == QLatin1String( 
"x" ) ) 
return Qt::DiagCrossPattern;
 
  384   if ( 
str.startsWith( QLatin1String( 
"brush://" ) ) )
 
  396   const QString s = value.toString().toLower().trimmed();
 
  397   if ( s == QLatin1String( 
"single" ) )
 
  399   else if ( s == QLatin1String( 
"reversed" ) )
 
  401   else if ( s == QLatin1String( 
"double" ) )
 
  403   else if ( value.toInt() == 1 )
 
  405   else if ( value.toInt() == 2 )
 
  407   else if ( value.toInt( &intOk ) == 0 && intOk )
 
  421   const QString s = value.toString().toLower().trimmed();
 
  422   if ( s == QLatin1String( 
"plain" ) )
 
  424   else if ( s == QLatin1String( 
"lefthalf" ) )
 
  426   else if ( s == QLatin1String( 
"righthalf" ) )
 
  428   else if ( value.toInt() == 1 )
 
  430   else if ( value.toInt() == 2 )
 
  432   else if ( value.toInt( &intOk ) == 0 && intOk )
 
  447   QStringList lst = 
str.split( 
',' );
 
  448   if ( lst.count() != 2 )
 
  449     return QPointF( 0, 0 );
 
  450   return QPointF( lst[0].toDouble(), lst[1].toDouble() );
 
  458   if ( value.isNull() )
 
  461   if ( value.type() == QVariant::List )
 
  463     const QVariantList list = value.toList();
 
  464     if ( list.size() != 2 )
 
  468     bool convertOk = 
false;
 
  469     const double x = list.at( 0 ).toDouble( &convertOk );
 
  472       const double y = list.at( 1 ).toDouble( &convertOk );
 
  477         return QPointF( x, y );
 
  485     const QStringList list = value.toString().trimmed().split( 
',' );
 
  486     if ( list.count() != 2 )
 
  488     bool convertOk = 
false;
 
  489     const double x = list.at( 0 ).toDouble( &convertOk );
 
  492       const double y = list.at( 1 ).toDouble( &convertOk );
 
  497         return QPointF( x, y );
 
  511   QStringList lst = 
string.split( 
',' );
 
  512   if ( lst.count() != 2 )
 
  513     return QSizeF( 0, 0 );
 
  514   return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
 
  522   if ( value.isNull() )
 
  525   if ( value.type() == QVariant::List )
 
  527     const QVariantList list = value.toList();
 
  528     if ( list.size() != 2 )
 
  532     bool convertOk = 
false;
 
  533     const double x = list.at( 0 ).toDouble( &convertOk );
 
  536       const double y = list.at( 1 ).toDouble( &convertOk );
 
  541         return QSizeF( x, y );
 
  549     const QStringList list = value.toString().trimmed().split( 
',' );
 
  550     if ( list.count() != 2 )
 
  552     bool convertOk = 
false;
 
  553     const double x = list.at( 0 ).toDouble( &convertOk );
 
  556       const double y = list.at( 1 ).toDouble( &convertOk );
 
  561         return QSizeF( x, y );
 
  582   if ( 
str.startsWith( QLatin1String( 
"3x:" ) ) )
 
  585     const QString chopped = 
str.mid( 3 );
 
  586     lst = chopped.split( 
',' );
 
  590     lst = 
str.split( 
',' );
 
  592   if ( lst.count() < 2 )
 
  595   double minScale = lst[0].toDouble();
 
  597     minScale = minScale != 0 ? 1.0 / minScale : 0;
 
  598   double maxScale = lst[1].toDouble();
 
  600     maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
 
  602   if ( lst.count() < 6 )
 
  622         *scaleFactor = 0.001; 
 
  623       return QStringLiteral( 
"http://www.opengeospatial.org/se/units/metre" );
 
  630         *scaleFactor = 1 / 0.28;  
 
  639   if ( 
str == QLatin1String( 
"http://www.opengeospatial.org/se/units/metre" ) )
 
  642       *scaleFactor = 1000.0;  
 
  645   else if ( 
str == QLatin1String( 
"http://www.opengeospatial.org/se/units/foot" ) )
 
  648       *scaleFactor = 304.8; 
 
  651   else if ( 
str == QLatin1String( 
"http://www.opengeospatial.org/se/units/pixel" ) )
 
  661     *scaleFactor = 1 / 0.00028; 
 
  667   QString vectorString;
 
  668   QVector<qreal>::const_iterator it = v.constBegin();
 
  669   for ( ; it != v.constEnd(); ++it )
 
  671     if ( it != v.constBegin() )
 
  673       vectorString.append( 
';' );
 
  675     vectorString.append( QString::number( *it ) );
 
  682   QVector<qreal> resultVector;
 
  684   const QStringList realList = s.split( 
';' );
 
  685   QStringList::const_iterator it = realList.constBegin();
 
  686   for ( ; it != realList.constEnd(); ++it )
 
  688     resultVector.append( it->toDouble() );
 
  696   QString vectorString;
 
  697   QVector<qreal>::const_iterator it = v.constBegin();
 
  698   for ( ; it != v.constEnd(); ++it )
 
  700     if ( it != v.constBegin() )
 
  702       vectorString.append( 
' ' );
 
  704     vectorString.append( QString::number( *it ) );
 
  711   QVector<qreal> resultVector;
 
  713   const QStringList realList = s.split( 
' ' );
 
  714   QStringList::const_iterator it = realList.constBegin();
 
  715   for ( ; it != realList.constEnd(); ++it )
 
  717     resultVector.append( it->toDouble() );
 
  725   QString encodedValue;
 
  727   switch ( scaleMethod )
 
  730       encodedValue = QStringLiteral( 
"diameter" );
 
  733       encodedValue = QStringLiteral( 
"area" );
 
  743   if ( 
str == QLatin1String( 
"diameter" ) )
 
  757   if ( s.compare( QLatin1String( 
"Lighten" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_Lighten;
 
  758   if ( s.compare( QLatin1String( 
"Screen" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_Screen;
 
  759   if ( s.compare( QLatin1String( 
"Dodge" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_ColorDodge;
 
  760   if ( s.compare( QLatin1String( 
"Addition" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_Plus;
 
  761   if ( s.compare( QLatin1String( 
"Darken" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_Darken;
 
  762   if ( s.compare( QLatin1String( 
"Multiply" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_Multiply;
 
  763   if ( s.compare( QLatin1String( 
"Burn" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_ColorBurn;
 
  764   if ( s.compare( QLatin1String( 
"Overlay" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_Overlay;
 
  765   if ( s.compare( QLatin1String( 
"SoftLight" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_SoftLight;
 
  766   if ( s.compare( QLatin1String( 
"HardLight" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_HardLight;
 
  767   if ( s.compare( QLatin1String( 
"Difference" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_Difference;
 
  768   if ( s.compare( QLatin1String( 
"Subtract" ), Qt::CaseInsensitive ) == 0 ) 
return QPainter::CompositionMode_Exclusion;
 
  769   return QPainter::CompositionMode_SourceOver; 
 
  774   return QIcon( 
symbolPreviewPixmap( symbol, size, padding, 
nullptr, 
false, 
nullptr, shape ) );
 
  780   QPixmap pixmap( size );
 
  781   pixmap.fill( Qt::transparent );
 
  783   painter.begin( &pixmap );
 
  787     painter.setRenderHint( QPainter::Antialiasing );
 
  796     size.setWidth( size.rwidth() - ( padding * 2 ) );
 
  797     size.setHeight( size.rheight() - ( padding * 2 ) );
 
  798     painter.translate( padding, padding );
 
  808     std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
 
  810     for ( 
const auto &layer : layers )
 
  812       for ( 
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
 
  814         QgsProperty &prop = layer->dataDefinedProperties().property( i );
 
  820     symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
 
  824     std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
 
  825     symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
 
  839     maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
 
  849   painter.begin( &picture );
 
  850   painter.setRenderHint( QPainter::Antialiasing );
 
  854   QgsSymbolRenderContext symbolContext( renderContext, units, 1.0, 
false, Qgis::SymbolRenderHints(), 
nullptr );
 
  856   switch ( parentSymbolType )
 
  871   std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
 
  872   layerClone->drawPreviewIcon( symbolContext, size );
 
  879   QPixmap pixmap( size );
 
  880   pixmap.fill( Qt::transparent );
 
  882   painter.begin( &pixmap );
 
  883   painter.setRenderHint( QPainter::Antialiasing );
 
  893   switch ( parentSymbolType )
 
  908   std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
 
  909   layerClone->drawPreviewIcon( symbolContext, size );
 
  911   return QIcon( pixmap );
 
  921   QPixmap pixmap( size );
 
  922   pixmap.fill( Qt::transparent );
 
  925   painter.begin( &pixmap );
 
  928   if ( drawTransparentBackground )
 
  929     drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding  * 2 ) );
 
  937       for ( 
int i = 0; i < size.width(); i++ )
 
  939         const QPen pen( ramp->
color( 
static_cast< double >( i ) / size.width() ) );
 
  940         painter.setPen( pen );
 
  941         const int x = flipDirection ? size.width() - i - 1 : i;
 
  942         painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
 
  949       for ( 
int i = 0; i < size.height(); i++ )
 
  951         const QPen pen( ramp->
color( 
static_cast< double >( i ) / size.height() ) );
 
  952         painter.setPen( pen );
 
  953         const int y = flipDirection ? size.height() - i - 1 : i;
 
  954         painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
 
  967   uchar pixDataRGB[] = { 255, 255, 255, 255,
 
  972   const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
 
  974   const int width = ( rect.width() < rect.height() ) ?
 
  975                     rect.width() / 2.5 : rect.height() / 2.5;
 
  976   const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
 
  979   brush.setTexture( pix );
 
  980   painter->fillRect( rect, brush );
 
  985   const qreal s = ( markerSize - 1 ) / 2.0;
 
  990       p.setPen( QColor( 50, 100, 120, 200 ) );
 
  991       p.setBrush( QColor( 200, 200, 210, 120 ) );
 
  992       p.drawEllipse( x - s, y - s, s * 2, s * 2 );
 
  995       p.setPen( QColor( 255, 0, 0 ) );
 
  996       p.drawLine( x - s, y + s, x + s, y - s );
 
  997       p.drawLine( x - s, y - s, x + s, y + s );
 
 1004 #include <QPolygonF> 
 1009 static QPolygonF makeOffsetGeometry( 
const QgsPolylineXY &polyline )
 
 1011   int i, pointCount = polyline.count();
 
 1013   QPolygonF resultLine;
 
 1014   resultLine.resize( pointCount );
 
 1018   for ( i = 0; i < pointCount; ++i, tempPtr++ )
 
 1019     resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
 
 1023 static QList<QPolygonF> makeOffsetGeometry( 
const QgsPolygonXY &polygon )
 
 1025   QList<QPolygonF> resultGeom;
 
 1026   resultGeom.reserve( polygon.size() );
 
 1027   for ( 
int ring = 0; ring < polygon.size(); ++ring )
 
 1028     resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
 
 1034   QList<QPolygonF> resultLine;
 
 1036   if ( polyline.count() < 2 )
 
 1038     resultLine.append( polyline );
 
 1042   unsigned int i, pointCount = polyline.count();
 
 1045   QPointF *tempPtr = polyline.data();
 
 1046   for ( i = 0; i < pointCount; ++i, tempPtr++ )
 
 1047     tempPolyline[i] = 
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
 
 1050   if ( !tempGeometry.
isNull() )
 
 1052     const int quadSegments = 0; 
 
 1053     const double miterLimit = 2.0; 
 
 1056       offsetGeom = tempGeometry.
buffer( -dist, quadSegments, Qgis::EndCapStyle::Flat,
 
 1057                                         Qgis::JoinStyle::Miter, miterLimit );
 
 1059       offsetGeom = tempGeometry.
offsetCurve( dist, quadSegments, Qgis::JoinStyle::Miter, miterLimit );
 
 1061     if ( !offsetGeom.
isNull() )
 
 1063       tempGeometry = offsetGeom;
 
 1068         resultLine.append( makeOffsetGeometry( line ) );
 
 1073         resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
 
 1079         resultLine.reserve( tempMPolyline.count() );
 
 1080         for ( 
int part = 0; part < tempMPolyline.count(); ++part )
 
 1082           resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
 
 1089         resultLine.reserve( tempMPolygon.count() );
 
 1090         for ( 
int part = 0; part < tempMPolygon.count(); ++part )
 
 1092           resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
 
 1100   resultLine.append( polyline );
 
 1110   QDomNode layerNode = element.firstChild();
 
 1112   while ( !layerNode.isNull() )
 
 1114     QDomElement e = layerNode.toElement();
 
 1115     if ( !e.isNull() && e.tagName() != QLatin1String( 
"data_defined_properties" ) )
 
 1117       if ( e.tagName() != QLatin1String( 
"layer" ) )
 
 1128           const QDomElement s = e.firstChildElement( QStringLiteral( 
"symbol" ) );
 
 1135               QgsDebugMsg( 
"symbol layer refused subsymbol: " + s.attribute( 
"name" ) );
 
 1138           layers.append( layer );
 
 1142     layerNode = layerNode.nextSibling();
 
 1145   if ( layers.isEmpty() )
 
 1147     QgsDebugMsg( QStringLiteral( 
"no layers for symbol" ) );
 
 1151   const QString symbolType = element.attribute( QStringLiteral( 
"type" ) );
 
 1154   if ( symbolType == QLatin1String( 
"line" ) )
 
 1156   else if ( symbolType == QLatin1String( 
"fill" ) )
 
 1158   else if ( symbolType == QLatin1String( 
"marker" ) )
 
 1162     QgsDebugMsg( 
"unknown symbol type " + symbolType );
 
 1166   if ( element.hasAttribute( QStringLiteral( 
"outputUnit" ) ) )
 
 1170   if ( element.hasAttribute( ( QStringLiteral( 
"mapUnitScale" ) ) ) )
 
 1173     const double oldMin = element.attribute( QStringLiteral( 
"mapUnitMinScale" ), QStringLiteral( 
"0.0" ) ).toDouble();
 
 1174     mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
 
 1175     const double oldMax = element.attribute( QStringLiteral( 
"mapUnitMaxScale" ), QStringLiteral( 
"0.0" ) ).toDouble();
 
 1176     mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
 
 1179   symbol->
setOpacity( element.attribute( QStringLiteral( 
"alpha" ), QStringLiteral( 
"1.0" ) ).toDouble() );
 
 1180   symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral( 
"clip_to_extent" ), QStringLiteral( 
"1" ) ).toInt() );
 
 1181   symbol->
setForceRHR( element.attribute( QStringLiteral( 
"force_rhr" ), QStringLiteral( 
"0" ) ).toInt() );
 
 1182   Qgis::SymbolFlags flags;
 
 1183   if ( element.attribute( QStringLiteral( 
"renderer_should_use_levels" ), QStringLiteral( 
"0" ) ).toInt() )
 
 1187   const QDomElement ddProps = element.firstChildElement( QStringLiteral( 
"data_defined_properties" ) );
 
 1188   if ( !ddProps.isNull() )
 
 1198   const QString layerClass = element.attribute( QStringLiteral( 
"class" ) );
 
 1199   const bool locked = element.attribute( QStringLiteral( 
"locked" ) ).toInt();
 
 1200   const bool enabled = element.attribute( QStringLiteral( 
"enabled" ), QStringLiteral( 
"1" ) ).toInt();
 
 1201   const int pass = element.attribute( QStringLiteral( 
"pass" ) ).toInt();
 
 1220     const QDomElement effectElem = element.firstChildElement( QStringLiteral( 
"effect" ) );
 
 1221     if ( !effectElem.isNull() )
 
 1229     const QDomElement ddProps = element.firstChildElement( QStringLiteral( 
"data_defined_properties" ) );
 
 1230     if ( !ddProps.isNull() )
 
 1237       const QSet< int > oldKeys = prevProperties.
propertyKeys();
 
 1238       for ( 
int key : oldKeys )
 
 1259       return QStringLiteral( 
"line" );
 
 1261       return QStringLiteral( 
"marker" );
 
 1263       return QStringLiteral( 
"fill" );
 
 1272   QDomElement symEl = doc.createElement( QStringLiteral( 
"symbol" ) );
 
 1273   symEl.setAttribute( QStringLiteral( 
"type" ), _nameForSymbolType( symbol->
type() ) );
 
 1274   symEl.setAttribute( QStringLiteral( 
"name" ), name );
 
 1275   symEl.setAttribute( QStringLiteral( 
"alpha" ), QString::number( symbol->
opacity() ) );
 
 1276   symEl.setAttribute( QStringLiteral( 
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
 1277   symEl.setAttribute( QStringLiteral( 
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral( 
"1" ) : QStringLiteral( 
"0" ) );
 
 1279     symEl.setAttribute( QStringLiteral( 
"renderer_should_use_levels" ), QStringLiteral( 
"1" ) );
 
 1283   QDomElement ddProps = doc.createElement( QStringLiteral( 
"data_defined_properties" ) );
 
 1285   symEl.appendChild( ddProps );
 
 1291     QDomElement layerEl = doc.createElement( QStringLiteral( 
"layer" ) );
 
 1292     layerEl.setAttribute( QStringLiteral( 
"class" ), layer->
layerType() );
 
 1293     layerEl.setAttribute( QStringLiteral( 
"enabled" ), layer->
enabled() );
 
 1294     layerEl.setAttribute( QStringLiteral( 
"locked" ), layer->
isLocked() );
 
 1295     layerEl.setAttribute( QStringLiteral( 
"pass" ), layer->
renderingPass() );
 
 1307     QDomElement ddProps = doc.createElement( QStringLiteral( 
"data_defined_properties" ) );
 
 1309     layerEl.appendChild( ddProps );
 
 1313       const QString subname = QStringLiteral( 
"@%1@%2" ).arg( name ).arg( i );
 
 1314       const QDomElement subEl = 
saveSymbol( subname, subSymbol, doc, context );
 
 1315       layerEl.appendChild( subEl );
 
 1317     symEl.appendChild( layerEl );
 
 1325   QDomDocument doc( QStringLiteral( 
"qgis-symbol-definition" ) );
 
 1328   QTextStream stream( &props );
 
 1329   symbolElem.save( stream, -1 );
 
 1335     QList<QgsSymbolLayer *> &layers )
 
 1339   if ( element.isNull() )
 
 1344   const QString symbolizerName = element.localName();
 
 1346   if ( symbolizerName == QLatin1String( 
"PointSymbolizer" ) )
 
 1349     const QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1350     if ( graphicElem.isNull() )
 
 1352       QgsDebugMsg( QStringLiteral( 
"Graphic element not found in PointSymbolizer" ) );
 
 1388   if ( symbolizerName == QLatin1String( 
"LineSymbolizer" ) )
 
 1391     const QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 1392     if ( strokeElem.isNull() )
 
 1394       QgsDebugMsg( QStringLiteral( 
"Stroke element not found in LineSymbolizer" ) );
 
 1424   if ( symbolizerName == QLatin1String( 
"PolygonSymbolizer" ) )
 
 1427     const QDomElement fillElem = element.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 1428     const QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 1429     if ( fillElem.isNull() && strokeElem.isNull() )
 
 1431       QgsDebugMsg( QStringLiteral( 
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
 
 1449             if ( l->
layerType() == QLatin1String( 
"SimpleFill" ) || l->
layerType() == QLatin1String( 
"SVGFill" ) )
 
 1485   const QDomElement fillElem = element.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 1486   if ( fillElem.isNull() )
 
 1488     QgsDebugMsg( QStringLiteral( 
"Fill element not found" ) );
 
 1508   const QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 1509   if ( strokeElem.isNull() )
 
 1511     QgsDebugMsg( QStringLiteral( 
"Stroke element not found" ) );
 
 1527   const QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1528   if ( graphicElem.isNull() )
 
 1530     QgsDebugMsg( QStringLiteral( 
"Graphic element not found" ) );
 
 1550   const QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1551   if ( graphicElem.isNull() )
 
 1554   const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral( 
"ExternalGraphic" ) );
 
 1555   if ( externalGraphicElem.isNull() )
 
 1559   const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral( 
"Format" ) );
 
 1560   if ( formatElem.isNull() )
 
 1563   const QString format = formatElem.firstChild().nodeValue();
 
 1564   if ( format != QLatin1String( 
"image/svg+xml" ) )
 
 1566     QgsDebugMsg( 
"unsupported External Graphic format found: " + format );
 
 1571   const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral( 
"OnlineResource" ) );
 
 1572   const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral( 
"InlineContent" ) );
 
 1573   if ( !onlineResourceElem.isNull() )
 
 1578   else if ( !inlineContentElem.isNull() )
 
 1591   const QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1592   if ( graphicElem.isNull() )
 
 1595   const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral( 
"Mark" ) );
 
 1596   if ( markElem.isNull() )
 
 1599   const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral( 
"WellKnownName" ) );
 
 1600   return !wellKnownNameElem.isNull();
 
 1606   const QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1607   if ( graphicElem.isNull() )
 
 1610   const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral( 
"Mark" ) );
 
 1611   if ( markElem.isNull() )
 
 1615   const QDomElement formatElem = markElem.firstChildElement( QStringLiteral( 
"Format" ) );
 
 1616   if ( formatElem.isNull() )
 
 1619   const QString format = formatElem.firstChild().nodeValue();
 
 1620   if ( format != QLatin1String( 
"ttf" ) )
 
 1622     QgsDebugMsg( 
"unsupported Graphic Mark format found: " + format );
 
 1627   const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral( 
"OnlineResource" ) );
 
 1628   const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral( 
"InlineContent" ) );
 
 1629   if ( !onlineResourceElem.isNull() )
 
 1632     const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral( 
"MarkIndex" ) );
 
 1633     if ( !markIndexElem.isNull() )
 
 1636   else if ( !inlineContentElem.isNull() )
 
 1651   QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1652   if ( graphicElem.isNull() )
 
 1656   for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
 
 1658     if ( it.key() == QLatin1String( 
"widthHeightFactor" ) )
 
 1669   const QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 1670   if ( strokeElem.isNull() )
 
 1673   QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral( 
"GraphicStroke" ) );
 
 1674   if ( graphicStrokeElem.isNull() )
 
 1682   const QDomElement fillElem = element.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 1683   if ( fillElem.isNull() )
 
 1686   const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral( 
"GraphicFill" ) );
 
 1687   if ( graphicFillElem.isNull() )
 
 1690   QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1691   if ( graphicElem.isNull() )
 
 1697   QColor fillColor, strokeColor;
 
 1698   double size, strokeWidth;
 
 1699   Qt::PenStyle strokeStyle;
 
 1700   if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
 
 1703   if ( name != QLatin1String( 
"horline" ) )
 
 1711   const double angle = angleFunc.toDouble( &ok );
 
 1723   const QDomElement fillElem = element.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 1724   if ( fillElem.isNull() )
 
 1727   QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral( 
"GraphicFill" ) );
 
 1728   if ( graphicFillElem.isNull() )
 
 1748   QDomElement fillElem = element.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 1749   QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 1753     bool validFill = 
false, validStroke = 
false;
 
 1758     Qt::BrushStyle fillStyle;
 
 1760     if ( 
fillFromSld( fillElem, fillStyle, fillColor ) )
 
 1766     Qt::PenStyle strokeStyle;
 
 1767     double strokeWidth = 1.0, dashOffset = 0.0;
 
 1768     QVector<qreal> customDashPattern;
 
 1770     if ( 
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
 
 1771                       nullptr, 
nullptr, &customDashPattern, &dashOffset ) )
 
 1774     if ( validFill || validStroke )
 
 1777       map[QStringLiteral( 
"name" )] = QStringLiteral( 
"square" );
 
 1778       map[QStringLiteral( 
"color" )] = 
encodeColor( validFill ? fillColor : Qt::transparent );
 
 1779       map[QStringLiteral( 
"color_border" )] = 
encodeColor( validStroke ? strokeColor : Qt::transparent );
 
 1780       map[QStringLiteral( 
"size" )] = QString::number( 6 );
 
 1781       map[QStringLiteral( 
"angle" )] = QString::number( 0 );
 
 1782       map[QStringLiteral( 
"offset" )] = 
encodePoint( QPointF( 0, 0 ) );
 
 1789     bool validFill = 
false, validStroke = 
false;
 
 1792     QString name, format;
 
 1794     QColor fillColor, strokeColor;
 
 1795     double strokeWidth = 1.0, size = 0.0, 
angle = 0.0;
 
 1799     const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral( 
"GraphicFill" ) );
 
 1800     if ( !graphicFillElem.isNull() )
 
 1803       QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1804       if ( !graphicElem.isNull() )
 
 1810         const QDomElement graphicChildElem = graphicElem.firstChildElement();
 
 1811         while ( !graphicChildElem.isNull() )
 
 1813           if ( graphicChildElem.localName() == QLatin1String( 
"Mark" ) )
 
 1816             const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral( 
"WellKnownName" ) );
 
 1817             if ( !wellKnownNameElem.isNull() )
 
 1819               name = wellKnownNameElem.firstChild().nodeValue();
 
 1825           if ( graphicChildElem.localName() == QLatin1String( 
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String( 
"Mark" ) )
 
 1828             const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral( 
"Format" ) );
 
 1829             if ( formatElem.isNull() )
 
 1832             format = formatElem.firstChild().nodeValue();
 
 1836             if ( graphicChildElem.localName() == QLatin1String( 
"ExternalGraphic" ) && format != QLatin1String( 
"image/svg+xml" ) )
 
 1841             if ( graphicChildElem.localName() == QLatin1String( 
"Mark" ) && format != QLatin1String( 
"ttf" ) )
 
 1845             const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral( 
"OnlineResource" ) );
 
 1846             const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral( 
"InlineContent" ) );
 
 1848             if ( !onlineResourceElem.isNull() )
 
 1850               name = onlineResourceElem.attributeNS( QStringLiteral( 
"http://www.w3.org/1999/xlink" ), QStringLiteral( 
"href" ) );
 
 1852               if ( graphicChildElem.localName() == QLatin1String( 
"Mark" ) && format == QLatin1String( 
"ttf" ) )
 
 1855                 if ( name.startsWith( QLatin1String( 
"ttf://" ) ) )
 
 1856                   name = name.mid( 6 );
 
 1859                 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral( 
"MarkIndex" ) );
 
 1860                 if ( markIndexElem.isNull() )
 
 1864                 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
 
 1875             else if ( !inlineContentElem.isNull() )
 
 1885           if ( graphicChildElem.localName() == QLatin1String( 
"Mark" ) )
 
 1887             name = QStringLiteral( 
"square" );
 
 1894         if ( found && graphicChildElem.localName() == QLatin1String( 
"Mark" ) )
 
 1901           Qt::BrushStyle markFillStyle;
 
 1903           QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 1904           if ( 
fillFromSld( markFillElem, markFillStyle, fillColor ) )
 
 1909           Qt::PenStyle strokeStyle;
 
 1910           double strokeWidth = 1.0, dashOffset = 0.0;
 
 1911           QVector<qreal> customDashPattern;
 
 1913           QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 1914           if ( 
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
 
 1915                             nullptr, 
nullptr, &customDashPattern, &dashOffset ) )
 
 1922           const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral( 
"Opacity" ) );
 
 1923           if ( !opacityElem.isNull() )
 
 1924             fillColor.setAlpha( 
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
 
 1926           const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral( 
"Size" ) );
 
 1927           if ( !sizeElem.isNull() )
 
 1930             const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
 
 1939             const double v = angleFunc.toDouble( &ok );
 
 1949     if ( validFill || validStroke )
 
 1951       if ( format == QLatin1String( 
"image/svg+xml" ) )
 
 1954         map[QStringLiteral( 
"name" )] = name;
 
 1955         map[QStringLiteral( 
"fill" )] = fillColor.name();
 
 1956         map[QStringLiteral( 
"outline" )] = strokeColor.name();
 
 1957         map[QStringLiteral( 
"outline-width" )] = QString::number( strokeWidth );
 
 1959           map[QStringLiteral( 
"size" )] = QString::number( size );
 
 1961           map[QStringLiteral( 
"angle" )] = QString::number( 
angle );
 
 1962         if ( !offset.isNull() )
 
 1963           map[QStringLiteral( 
"offset" )] = 
encodePoint( offset );
 
 1966       else if ( format == QLatin1String( 
"ttf" ) )
 
 1969         map[QStringLiteral( 
"font" )] = name;
 
 1970         map[QStringLiteral( 
"chr" )] = markIndex;
 
 1971         map[QStringLiteral( 
"color" )] = 
encodeColor( validFill ? fillColor : Qt::transparent );
 
 1973           map[QStringLiteral( 
"size" )] = QString::number( size );
 
 1975           map[QStringLiteral( 
"angle" )] = QString::number( 
angle );
 
 1976         if ( !offset.isNull() )
 
 1977           map[QStringLiteral( 
"offset" )] = 
encodePoint( offset );
 
 1983   if ( layers.isEmpty() )
 
 1986   layerList << layers;
 
 1993   QString patternName;
 
 1994   switch ( brushStyle )
 
 1999     case Qt::SolidPattern:
 
 2000       if ( color.isValid() )
 
 2003         if ( color.alpha() < 255 )
 
 2008     case Qt::CrossPattern:
 
 2009     case Qt::DiagCrossPattern:
 
 2010     case Qt::HorPattern:
 
 2011     case Qt::VerPattern:
 
 2012     case Qt::BDiagPattern:
 
 2013     case Qt::FDiagPattern:
 
 2014     case Qt::Dense1Pattern:
 
 2015     case Qt::Dense2Pattern:
 
 2016     case Qt::Dense3Pattern:
 
 2017     case Qt::Dense4Pattern:
 
 2018     case Qt::Dense5Pattern:
 
 2019     case Qt::Dense6Pattern:
 
 2020     case Qt::Dense7Pattern:
 
 2025       element.appendChild( doc.createComment( QStringLiteral( 
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
 
 2029   QDomElement graphicFillElem = doc.createElement( QStringLiteral( 
"se:GraphicFill" ) );
 
 2030   element.appendChild( graphicFillElem );
 
 2032   QDomElement graphicElem = doc.createElement( QStringLiteral( 
"se:Graphic" ) );
 
 2033   graphicFillElem.appendChild( graphicElem );
 
 2035   const QColor fillColor = patternName.startsWith( QLatin1String( 
"brush://" ) ) ? color : QColor();
 
 2036   const QColor strokeColor = !patternName.startsWith( QLatin1String( 
"brush://" ) ) ? color : QColor();
 
 2039   wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
 
 2046   brushStyle = Qt::SolidPattern;
 
 2047   color = QColor( 128, 128, 128 );
 
 2049   if ( element.isNull() )
 
 2051     brushStyle = Qt::NoBrush;
 
 2056   const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral( 
"GraphicFill" ) );
 
 2058   if ( graphicFillElem.isNull() )
 
 2061     for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
 
 2063       QgsDebugMsg( QStringLiteral( 
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
 
 2065       if ( it.key() == QLatin1String( 
"fill" ) )
 
 2066         color = QColor( it.value() );
 
 2067       else if ( it.key() == QLatin1String( 
"fill-opacity" ) )
 
 2073     QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 2074     if ( graphicElem.isNull() )
 
 2077     QString patternName = QStringLiteral( 
"square" );
 
 2078     QColor fillColor, strokeColor;
 
 2079     double strokeWidth, size;
 
 2080     Qt::PenStyle strokeStyle;
 
 2081     if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
 
 2085     if ( brushStyle == Qt::NoBrush )
 
 2088     const QColor 
c = patternName.startsWith( QLatin1String( 
"brush://" ) ) ? fillColor : strokeColor;
 
 2097                                      Qt::PenStyle penStyle, 
const QColor &color, 
double width,
 
 2098                                      const Qt::PenJoinStyle *penJoinStyle, 
const Qt::PenCapStyle *penCapStyle,
 
 2099                                      const QVector<qreal> *customDashPattern, 
double dashOffset )
 
 2101   QVector<qreal> dashPattern;
 
 2102   const QVector<qreal> *pattern = &dashPattern;
 
 2104   if ( penStyle == Qt::CustomDashLine && !customDashPattern )
 
 2106     element.appendChild( doc.createComment( QStringLiteral( 
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
 
 2107     penStyle = Qt::DashLine;
 
 2119       dashPattern.push_back( 4.0 );
 
 2120       dashPattern.push_back( 2.0 );
 
 2123       dashPattern.push_back( 1.0 );
 
 2124       dashPattern.push_back( 2.0 );
 
 2126     case Qt::DashDotLine:
 
 2127       dashPattern.push_back( 4.0 );
 
 2128       dashPattern.push_back( 2.0 );
 
 2129       dashPattern.push_back( 1.0 );
 
 2130       dashPattern.push_back( 2.0 );
 
 2132     case Qt::DashDotDotLine:
 
 2133       dashPattern.push_back( 4.0 );
 
 2134       dashPattern.push_back( 2.0 );
 
 2135       dashPattern.push_back( 1.0 );
 
 2136       dashPattern.push_back( 2.0 );
 
 2137       dashPattern.push_back( 1.0 );
 
 2138       dashPattern.push_back( 2.0 );
 
 2141     case Qt::CustomDashLine:
 
 2142       Q_ASSERT( customDashPattern );
 
 2143       pattern = customDashPattern;
 
 2147       element.appendChild( doc.createComment( QStringLiteral( 
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
 
 2151   if ( color.isValid() )
 
 2154     if ( color.alpha() < 255 )
 
 2161   else if ( width == 0 )
 
 2171   if ( !pattern->isEmpty() )
 
 2181                                        Qt::PenStyle &penStyle, QColor &color, 
double &width,
 
 2182                                        Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
 
 2183                                        QVector<qreal> *customDashPattern, 
double *dashOffset )
 
 2187   penStyle = Qt::SolidLine;
 
 2188   color = QColor( 0, 0, 0 );
 
 2191     *penJoinStyle = Qt::BevelJoin;
 
 2193     *penCapStyle = Qt::SquareCap;
 
 2194   if ( customDashPattern )
 
 2195     customDashPattern->clear();
 
 2199   if ( element.isNull() )
 
 2201     penStyle = Qt::NoPen;
 
 2207   for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
 
 2209     QgsDebugMsg( QStringLiteral( 
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
 
 2211     if ( it.key() == QLatin1String( 
"stroke" ) )
 
 2213       color = QColor( it.value() );
 
 2215     else if ( it.key() == QLatin1String( 
"stroke-opacity" ) )
 
 2219     else if ( it.key() == QLatin1String( 
"stroke-width" ) )
 
 2222       const double w = it.value().toDouble( &ok );
 
 2226     else if ( it.key() == QLatin1String( 
"stroke-linejoin" ) && penJoinStyle )
 
 2230     else if ( it.key() == QLatin1String( 
"stroke-linecap" ) && penCapStyle )
 
 2234     else if ( it.key() == QLatin1String( 
"stroke-dasharray" ) )
 
 2237       if ( !dashPattern.isEmpty() )
 
 2241         bool dashPatternFound = 
false;
 
 2243         if ( dashPattern.count() == 2 )
 
 2245           if ( dashPattern.at( 0 ) == 4.0 &&
 
 2246                dashPattern.at( 1 ) == 2.0 )
 
 2248             penStyle = Qt::DashLine;
 
 2249             dashPatternFound = 
true;
 
 2251           else if ( dashPattern.at( 0 ) == 1.0 &&
 
 2252                     dashPattern.at( 1 ) == 2.0 )
 
 2254             penStyle = Qt::DotLine;
 
 2255             dashPatternFound = 
true;
 
 2258         else if ( dashPattern.count() == 4 )
 
 2260           if ( dashPattern.at( 0 ) == 4.0 &&
 
 2261                dashPattern.at( 1 ) == 2.0 &&
 
 2262                dashPattern.at( 2 ) == 1.0 &&
 
 2263                dashPattern.at( 3 ) == 2.0 )
 
 2265             penStyle = Qt::DashDotLine;
 
 2266             dashPatternFound = 
true;
 
 2269         else if ( dashPattern.count() == 6 )
 
 2271           if ( dashPattern.at( 0 ) == 4.0 &&
 
 2272                dashPattern.at( 1 ) == 2.0 &&
 
 2273                dashPattern.at( 2 ) == 1.0 &&
 
 2274                dashPattern.at( 3 ) == 2.0 &&
 
 2275                dashPattern.at( 4 ) == 1.0 &&
 
 2276                dashPattern.at( 5 ) == 2.0 )
 
 2278             penStyle = Qt::DashDotDotLine;
 
 2279             dashPatternFound = 
true;
 
 2284         if ( !dashPatternFound )
 
 2286           if ( customDashPattern )
 
 2288             penStyle = Qt::CustomDashLine;
 
 2289             *customDashPattern = dashPattern;
 
 2293             QgsDebugMsg( QStringLiteral( 
"custom dash pattern required but not provided. Using default dash pattern." ) );
 
 2294             penStyle = Qt::DashLine;
 
 2299     else if ( it.key() == QLatin1String( 
"stroke-dashoffset" ) && dashOffset )
 
 2302       const double d = it.value().toDouble( &ok );
 
 2312     const QString &path, 
const QString &mime,
 
 2313     const QColor &color, 
double size )
 
 2315   QDomElement externalGraphicElem = doc.createElement( QStringLiteral( 
"se:ExternalGraphic" ) );
 
 2316   element.appendChild( externalGraphicElem );
 
 2325     QDomElement sizeElem = doc.createElement( QStringLiteral( 
"se:Size" ) );
 
 2327     element.appendChild( sizeElem );
 
 2332     const QString &path, 
const QColor &fillColor, 
double size, 
const QColor &strokeColor, 
double strokeWidth )
 
 2339   graphicElem.appendChild( doc.createComment( QStringLiteral( 
"Parametric SVG" ) ) );
 
 2340   const QString parametricPath = 
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
 
 2343   graphicElem.appendChild( doc.createComment( QStringLiteral( 
"Plain SVG fallback, no parameters" ) ) );
 
 2346   graphicElem.appendChild( doc.createComment( QStringLiteral( 
"Well known marker fallback" ) ) );
 
 2352     QDomElement sizeElem = doc.createElement( QStringLiteral( 
"se:Size" ) );
 
 2354     graphicElem.appendChild( sizeElem );
 
 2362   if ( fillColor.isValid() )
 
 2364     url.addQueryItem( QStringLiteral( 
"fill" ), fillColor.name() );
 
 2365     url.addQueryItem( QStringLiteral( 
"fill-opacity" ), 
encodeSldAlpha( fillColor.alpha() ) );
 
 2369     url.addQueryItem( QStringLiteral( 
"fill" ), QStringLiteral( 
"#000000" ) );
 
 2370     url.addQueryItem( QStringLiteral( 
"fill-opacity" ), QStringLiteral( 
"1" ) );
 
 2372   if ( strokeColor.isValid() )
 
 2374     url.addQueryItem( QStringLiteral( 
"outline" ), strokeColor.name() );
 
 2375     url.addQueryItem( QStringLiteral( 
"outline-opacity" ), 
encodeSldAlpha( strokeColor.alpha() ) );
 
 2379     url.addQueryItem( QStringLiteral( 
"outline" ), QStringLiteral( 
"#000000" ) );
 
 2380     url.addQueryItem( QStringLiteral( 
"outline-opacity" ), QStringLiteral( 
"1" ) );
 
 2382   url.addQueryItem( QStringLiteral( 
"outline-width" ), QString::number( strokeWidth ) );
 
 2383   const QString params = url.toString( QUrl::FullyEncoded );
 
 2384   if ( params.isEmpty() )
 
 2390     return basePath + 
"?" + params;
 
 2395     QString &path, QString &mime,
 
 2396     QColor &color, 
double &size )
 
 2401   QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral( 
"ExternalGraphic" ) );
 
 2402   if ( externalGraphicElem.isNull() )
 
 2407   const QDomElement sizeElem = element.firstChildElement( QStringLiteral( 
"Size" ) );
 
 2408   if ( !sizeElem.isNull() )
 
 2411     const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
 
 2420     const QString &path, 
const QString &format, 
int *markIndex,
 
 2421     const QColor &color, 
double size )
 
 2423   QDomElement markElem = doc.createElement( QStringLiteral( 
"se:Mark" ) );
 
 2424   element.appendChild( markElem );
 
 2430     QDomElement markIndexElem = doc.createElement( QStringLiteral( 
"se:MarkIndex" ) );
 
 2431     markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
 
 2432     markElem.appendChild( markIndexElem );
 
 2436   QDomElement fillElem = doc.createElement( QStringLiteral( 
"se:Fill" ) );
 
 2437   fillToSld( doc, fillElem, Qt::SolidPattern, color );
 
 2438   markElem.appendChild( fillElem );
 
 2443     QDomElement sizeElem = doc.createElement( QStringLiteral( 
"se:Size" ) );
 
 2445     element.appendChild( sizeElem );
 
 2450     QString &path, QString &format, 
int &markIndex,
 
 2451     QColor &color, 
double &size )
 
 2459   QDomElement markElem = element.firstChildElement( QStringLiteral( 
"Mark" ) );
 
 2460   if ( markElem.isNull() )
 
 2465   const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral( 
"MarkIndex" ) );
 
 2466   if ( !markIndexElem.isNull() )
 
 2469     const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
 
 2475   QDomElement fillElem = markElem.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 2476   Qt::BrushStyle b = Qt::SolidPattern;
 
 2481   const QDomElement sizeElem = element.firstChildElement( QStringLiteral( 
"Size" ) );
 
 2482   if ( !sizeElem.isNull() )
 
 2485     const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
 
 2494     const QString &name, 
const QColor &color, 
const QColor &strokeColor, Qt::PenStyle strokeStyle,
 
 2495     double strokeWidth, 
double size )
 
 2497   QDomElement markElem = doc.createElement( QStringLiteral( 
"se:Mark" ) );
 
 2498   element.appendChild( markElem );
 
 2500   QDomElement wellKnownNameElem = doc.createElement( QStringLiteral( 
"se:WellKnownName" ) );
 
 2501   wellKnownNameElem.appendChild( doc.createTextNode( name ) );
 
 2502   markElem.appendChild( wellKnownNameElem );
 
 2505   if ( color.isValid() )
 
 2507     QDomElement fillElem = doc.createElement( QStringLiteral( 
"se:Fill" ) );
 
 2508     fillToSld( doc, fillElem, Qt::SolidPattern, color );
 
 2509     markElem.appendChild( fillElem );
 
 2513   if ( strokeColor.isValid() )
 
 2515     QDomElement strokeElem = doc.createElement( QStringLiteral( 
"se:Stroke" ) );
 
 2516     lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
 
 2517     markElem.appendChild( strokeElem );
 
 2523     QDomElement sizeElem = doc.createElement( QStringLiteral( 
"se:Size" ) );
 
 2525     element.appendChild( sizeElem );
 
 2530     QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
 
 2531     double &strokeWidth, 
double &size )
 
 2535   name = QStringLiteral( 
"square" );
 
 2537   strokeColor = QColor( 0, 0, 0 );
 
 2541   const QDomElement markElem = element.firstChildElement( QStringLiteral( 
"Mark" ) );
 
 2542   if ( markElem.isNull() )
 
 2545   const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral( 
"WellKnownName" ) );
 
 2546   if ( !wellKnownNameElem.isNull() )
 
 2548     name = wellKnownNameElem.firstChild().nodeValue();
 
 2549     QgsDebugMsg( 
"found Mark with well known name: " + name );
 
 2553   QDomElement fillElem = markElem.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 2554   Qt::BrushStyle b = Qt::SolidPattern;
 
 2559   QDomElement strokeElem = markElem.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 2560   lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
 
 2564   const QDomElement sizeElem = element.firstChildElement( QStringLiteral( 
"Size" ) );
 
 2565   if ( !sizeElem.isNull() )
 
 2568     const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
 
 2578   if ( !rotationFunc.isEmpty() )
 
 2580     QDomElement rotationElem = doc.createElement( QStringLiteral( 
"se:Rotation" ) );
 
 2582     element.appendChild( rotationElem );
 
 2588   QDomElement rotationElem = element.firstChildElement( QStringLiteral( 
"Rotation" ) );
 
 2589   if ( !rotationElem.isNull() )
 
 2599   if ( !alphaFunc.isEmpty() )
 
 2601     QDomElement opacityElem = doc.createElement( QStringLiteral( 
"se:Opacity" ) );
 
 2603     element.appendChild( opacityElem );
 
 2609   QDomElement opacityElem = element.firstChildElement( QStringLiteral( 
"Opacity" ) );
 
 2610   if ( !opacityElem.isNull() )
 
 2619   if ( offset.isNull() )
 
 2622   QDomElement displacementElem = doc.createElement( QStringLiteral( 
"se:Displacement" ) );
 
 2623   element.appendChild( displacementElem );
 
 2625   QDomElement dispXElem = doc.createElement( QStringLiteral( 
"se:DisplacementX" ) );
 
 2626   dispXElem.appendChild( doc.createTextNode( 
qgsDoubleToString( offset.x(), 2 ) ) );
 
 2628   QDomElement dispYElem = doc.createElement( QStringLiteral( 
"se:DisplacementY" ) );
 
 2629   dispYElem.appendChild( doc.createTextNode( 
qgsDoubleToString( offset.y(), 2 ) ) );
 
 2631   displacementElem.appendChild( dispXElem );
 
 2632   displacementElem.appendChild( dispYElem );
 
 2639   QDomElement anchorElem = doc.createElement( QStringLiteral( 
"se:AnchorPoint" ) );
 
 2640   element.appendChild( anchorElem );
 
 2642   QDomElement anchorXElem = doc.createElement( QStringLiteral( 
"se:AnchorPointX" ) );
 
 2643   anchorXElem.appendChild( doc.createTextNode( 
qgsDoubleToString( anchor.x() ) ) );
 
 2645   QDomElement anchorYElem = doc.createElement( QStringLiteral( 
"se:AnchorPointY" ) );
 
 2646   anchorYElem.appendChild( doc.createTextNode( 
qgsDoubleToString( anchor.y() ) ) );
 
 2648   anchorElem.appendChild( anchorXElem );
 
 2649   anchorElem.appendChild( anchorYElem );
 
 2654   offset = QPointF( 0, 0 );
 
 2656   const QDomElement displacementElem = element.firstChildElement( QStringLiteral( 
"Displacement" ) );
 
 2657   if ( displacementElem.isNull() )
 
 2660   const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral( 
"DisplacementX" ) );
 
 2661   if ( !dispXElem.isNull() )
 
 2664     const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
 
 2666       offset.setX( offsetX );
 
 2669   const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral( 
"DisplacementY" ) );
 
 2670   if ( !dispYElem.isNull() )
 
 2673     const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
 
 2675       offset.setY( offsetY );
 
 2682     const QString &label, 
const QFont &font,
 
 2683     const QColor &color, 
double size )
 
 2685   QDomElement labelElem = doc.createElement( QStringLiteral( 
"se:Label" ) );
 
 2686   labelElem.appendChild( doc.createTextNode( label ) );
 
 2687   element.appendChild( labelElem );
 
 2689   QDomElement fontElem = doc.createElement( QStringLiteral( 
"se:Font" ) );
 
 2690   element.appendChild( fontElem );
 
 2694   fontElem.appendChild( createSldParameterElement( doc, 
"font-style", 
encodeSldFontStyle( font.style() ) ) );
 
 2695   fontElem.appendChild( createSldParameterElement( doc, 
"font-weight", 
encodeSldFontWeight( font.weight() ) ) );
 
 2700   if ( color.isValid() )
 
 2702     QDomElement fillElem = doc.createElement( QStringLiteral( 
"Fill" ) );
 
 2703     fillToSld( doc, fillElem, Qt::SolidPattern, color );
 
 2704     element.appendChild( fillElem );
 
 2709     Qt::PenJoinStyle joinStyle,
 
 2710     Qt::PenCapStyle capStyle,
 
 2712     const QVector<qreal> *dashPattern )
 
 2715   penStyle.append( 
"PEN(" );
 
 2716   penStyle.append( 
"c:" );
 
 2717   penStyle.append( 
c.name() );
 
 2718   penStyle.append( 
",w:" );
 
 2720   penStyle.append( QString::number( width * mmScaleFactor ) );
 
 2721   penStyle.append( 
"mm" );
 
 2724   if ( dashPattern && !dashPattern->isEmpty() )
 
 2726     penStyle.append( 
",p:\"" );
 
 2727     QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
 
 2728     for ( ; pIt != dashPattern->constEnd(); ++pIt )
 
 2730       if ( pIt != dashPattern->constBegin() )
 
 2732         penStyle.append( 
' ' );
 
 2734       penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
 
 2735       penStyle.append( 
'g' );
 
 2737     penStyle.append( 
'\"' );
 
 2741   penStyle.append( 
",cap:" );
 
 2745       penStyle.append( 
'p' );
 
 2748       penStyle.append( 
'r' );
 
 2752       penStyle.append( 
'b' );
 
 2756   penStyle.append( 
",j:" );
 
 2757   switch ( joinStyle )
 
 2760       penStyle.append( 
'b' );
 
 2763       penStyle.append( 
'r' );
 
 2767       penStyle.append( 
'm' );
 
 2773     penStyle.append( 
",dp:" );
 
 2774     penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
 
 2775     penStyle.append( 
'g' );
 
 2778   penStyle.append( 
')' );
 
 2785   brushStyle.append( 
"BRUSH(" );
 
 2786   brushStyle.append( 
"fc:" );
 
 2787   brushStyle.append( fillColor.name() );
 
 2788   brushStyle.append( 
')' );
 
 2794   if ( geomFunc.isEmpty() )
 
 2797   QDomElement geometryElem = doc.createElement( QStringLiteral( 
"Geometry" ) );
 
 2798   element.appendChild( geometryElem );
 
 2828   QDomElement geometryElem = element.firstChildElement( QStringLiteral( 
"Geometry" ) );
 
 2829   if ( geometryElem.isNull() )
 
 2841     element.appendChild( doc.createComment( 
"Parser Error: " + expr.
parserErrorString() + 
" - Expression was: " + 
function ) );
 
 2845   if ( !filterElem.isNull() )
 
 2846     element.appendChild( filterElem );
 
 2857     element.appendChild( doc.createComment( 
"Parser Error: " + expr.
parserErrorString() + 
" - Expression was: " + 
function ) );
 
 2861   if ( !filterElem.isNull() )
 
 2862     element.appendChild( filterElem );
 
 2869   QDomElement elem = element;
 
 2870   if ( element.tagName() != QLatin1String( 
"Filter" ) )
 
 2872     const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral( 
"Filter" ) );
 
 2873     if ( !filterNodes.isEmpty() )
 
 2875       elem = filterNodes.at( 0 ).toElement();
 
 2879   if ( elem.isNull() )
 
 2904     const QString &path, 
const QString &format )
 
 2908   QDomElement onlineResourceElem = doc.createElement( QStringLiteral( 
"se:OnlineResource" ) );
 
 2909   onlineResourceElem.setAttribute( QStringLiteral( 
"xlink:type" ), QStringLiteral( 
"simple" ) );
 
 2910   onlineResourceElem.setAttribute( QStringLiteral( 
"xlink:href" ), url );
 
 2911   element.appendChild( onlineResourceElem );
 
 2913   QDomElement formatElem = doc.createElement( QStringLiteral( 
"se:Format" ) );
 
 2914   formatElem.appendChild( doc.createTextNode( format ) );
 
 2915   element.appendChild( formatElem );
 
 2922   const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral( 
"OnlineResource" ) );
 
 2923   if ( onlineResourceElem.isNull() )
 
 2926   path = onlineResourceElem.attributeNS( QStringLiteral( 
"http://www.w3.org/1999/xlink" ), QStringLiteral( 
"href" ) );
 
 2928   const QDomElement formatElem = element.firstChildElement( QStringLiteral( 
"Format" ) );
 
 2929   if ( formatElem.isNull() )
 
 2932   format = formatElem.firstChild().nodeValue();
 
 2939   QDomElement nodeElem = doc.createElement( QStringLiteral( 
"se:SvgParameter" ) );
 
 2940   nodeElem.setAttribute( QStringLiteral( 
"name" ), name );
 
 2941   nodeElem.appendChild( doc.createTextNode( value ) );
 
 2950   QDomElement paramElem = element.firstChildElement();
 
 2951   while ( !paramElem.isNull() )
 
 2953     if ( paramElem.localName() == QLatin1String( 
"SvgParameter" ) || paramElem.localName() == QLatin1String( 
"CssParameter" ) )
 
 2955       const QString name = paramElem.attribute( QStringLiteral( 
"name" ) );
 
 2956       if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
 
 2958         value = paramElem.firstChild().nodeValue();
 
 2962         if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
 
 2963              paramElem.firstChild().localName() == QLatin1String( 
"Literal" ) )
 
 2965           QgsDebugMsg( paramElem.firstChild().localName() );
 
 2966           value = paramElem.firstChild().firstChild().nodeValue();
 
 2970           QgsDebugMsg( QStringLiteral( 
"unexpected child of %1" ).arg( paramElem.localName() ) );
 
 2974       if ( !name.isEmpty() && !value.isEmpty() )
 
 2975         params[ name ] = value;
 
 2978     paramElem = paramElem.nextSiblingElement();
 
 2986   QDomElement nodeElem = doc.createElement( QStringLiteral( 
"se:VendorOption" ) );
 
 2987   nodeElem.setAttribute( QStringLiteral( 
"name" ), name );
 
 2988   nodeElem.appendChild( doc.createTextNode( value ) );
 
 2996   QDomElement paramElem = element.firstChildElement( QStringLiteral( 
"VendorOption" ) );
 
 2997   while ( !paramElem.isNull() )
 
 2999     const QString name = paramElem.attribute( QStringLiteral( 
"name" ) );
 
 3000     const QString value = paramElem.firstChild().nodeValue();
 
 3002     if ( !name.isEmpty() && !value.isEmpty() )
 
 3003       params[ name ] = value;
 
 3005     paramElem = paramElem.nextSiblingElement( QStringLiteral( 
"VendorOption" ) );
 
 3015   if ( newSymbols.type() == QVariant::Map )
 
 3017     return newSymbols.toMap();
 
 3024     QDomElement e = element.firstChildElement();
 
 3025     while ( !e.isNull() )
 
 3027       if ( e.tagName() == QLatin1String( 
"prop" ) )
 
 3029         const QString propKey = e.attribute( QStringLiteral( 
"k" ) );
 
 3030         const QString propValue = e.attribute( QStringLiteral( 
"v" ) );
 
 3031         props[propKey] = propValue;
 
 3033       e = e.nextSiblingElement();
 
 3048   for ( QVariantMap::iterator it = props.begin(); it != props.end(); ++it )
 
 3050     QDomElement propEl = doc.createElement( QStringLiteral( 
"prop" ) );
 
 3051     propEl.setAttribute( QStringLiteral( 
"k" ), it.key() );
 
 3052     propEl.setAttribute( QStringLiteral( 
"v" ), it.value().toString() );
 
 3053     element.appendChild( propEl );
 
 3063   QDomElement e = element.firstChildElement();
 
 3065   while ( !e.isNull() )
 
 3067     if ( e.tagName() == QLatin1String( 
"symbol" ) )
 
 3071         symbols.insert( e.attribute( QStringLiteral( 
"name" ) ), symbol );
 
 3077     e = e.nextSiblingElement();
 
 3084   QStringList subsymbols;
 
 3086   for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
 
 3088     if ( it.key()[0] != 
'@' )
 
 3092     subsymbols.append( it.key() );
 
 3094     QStringList parts = it.key().split( 
'@' );
 
 3095     if ( parts.count() < 3 )
 
 3097       QgsDebugMsg( 
"found subsymbol with invalid name: " + it.key() );
 
 3101     const QString symname = parts[1];
 
 3102     const int symlayer = parts[2].toInt();
 
 3104     if ( !symbols.contains( symname ) )
 
 3106       QgsDebugMsg( 
"subsymbol references invalid symbol: " + symname );
 
 3114       QgsDebugMsg( 
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
 
 3123       QgsDebugMsg( 
"symbol layer refused subsymbol: " + it.key() );
 
 3130   for ( 
int i = 0; i < subsymbols.count(); i++ )
 
 3131     symbols.take( subsymbols[i] );
 
 3138   QDomElement symbolsElem = doc.createElement( tagName );
 
 3141   for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
 
 3143     const QDomElement symEl = 
saveSymbol( its.key(), its.value(), doc, context );
 
 3144     symbolsElem.appendChild( symEl );
 
 3152   qDeleteAll( symbols );
 
 3161   std::unique_ptr< QMimeData >mimeData( 
new QMimeData );
 
 3163   QDomDocument symbolDoc;
 
 3165   symbolDoc.appendChild( symbolElem );
 
 3166   mimeData->setText( symbolDoc.toString() );
 
 3169   mimeData->setColorData( symbol->
color() );
 
 3171   return mimeData.release();
 
 3179   const QString text = data->text();
 
 3180   if ( !text.isEmpty() )
 
 3185     if ( doc.setContent( text ) )
 
 3187       elem = doc.documentElement();
 
 3189       if ( elem.nodeName() != QLatin1String( 
"symbol" ) )
 
 3190         elem = elem.firstChildElement( QStringLiteral( 
"symbol" ) );
 
 3201   const QString rampType = element.attribute( QStringLiteral( 
"type" ) );
 
 3218     QgsDebugMsg( 
"unknown colorramp type " + rampType );
 
 3226   QDomElement rampEl = doc.createElement( QStringLiteral( 
"colorramp" ) );
 
 3227   rampEl.setAttribute( QStringLiteral( 
"type" ), ramp->
type() );
 
 3228   rampEl.setAttribute( QStringLiteral( 
"name" ), name );
 
 3236   QVariantMap rampMap;
 
 3238   rampMap.insert( QStringLiteral( 
"type" ), ramp->
type() );
 
 3239   rampMap.insert( QStringLiteral( 
"name" ), name );
 
 3241   const QVariantMap properties = ramp->
properties();
 
 3243   QVariantMap propertyMap;
 
 3244   for ( 
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
 
 3246     propertyMap.insert( property.key(), property.value() );
 
 3249   rampMap.insert( QStringLiteral( 
"properties" ), propertyMap );
 
 3255   const QVariantMap rampMap = value.toMap();
 
 3257   const QString rampType = rampMap.
value( QStringLiteral( 
"type" ) ).toString();
 
 3260   const QVariantMap propertyMap = rampMap.value( QStringLiteral( 
"properties" ) ).toMap();
 
 3263   for ( 
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
 
 3265     props.insert( property.key(), property.value().toString() );
 
 3280     QgsDebugMsg( 
"unknown colorramp type " + rampType );
 
 3287   if ( !color.isValid() )
 
 3294   return color.name();
 
 3299   QList<QColor> colors;
 
 3302   const thread_local QRegularExpression sepCommaSpaceRegExp( 
"(,|\\s)" );
 
 3303   QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
 
 3304   QStringList::iterator it = components.begin();
 
 3305   for ( ; it != components.end(); ++it )
 
 3307     const QColor result = 
parseColor( *it, 
true );
 
 3308     if ( result.isValid() )
 
 3313   if ( colors.length() > 0 )
 
 3319   const thread_local QRegularExpression sepCommaRegExp( 
"(,|\n)" );
 
 3320   components = colorStr.split( sepCommaRegExp );
 
 3321   it = components.begin();
 
 3322   for ( ; it != components.end(); ++it )
 
 3324     const QColor result = 
parseColor( *it, 
true );
 
 3325     if ( result.isValid() )
 
 3330   if ( colors.length() > 0 )
 
 3336   components = colorStr.simplified().split( QString( 
' ' ) );
 
 3337   it = components.begin();
 
 3338   for ( ; it != components.end(); ++it )
 
 3340     const QColor result = 
parseColor( *it, 
true );
 
 3341     if ( result.isValid() )
 
 3346   if ( colors.length() > 0 )
 
 3352   components = colorStr.split( 
'\n' );
 
 3353   it = components.begin();
 
 3354   for ( ; it != components.end(); ++it )
 
 3356     const QColor result = 
parseColor( *it, 
true );
 
 3357     if ( result.isValid() )
 
 3370   QMimeData *mimeData = 
new QMimeData;
 
 3371   mimeData->setColorData( QVariant( color ) );
 
 3372   mimeData->setText( color.name() );
 
 3379   if ( mimeData->hasColor() )
 
 3381     QColor mimeColor = mimeData->colorData().value<QColor>();
 
 3382     if ( mimeColor.isValid() )
 
 3390   if ( mimeData->hasText() )
 
 3394     if ( textColor.isValid() )
 
 3409   if ( data->hasFormat( QStringLiteral( 
"text/xml" ) ) )
 
 3412     const QByteArray encodedData = data->data( QStringLiteral( 
"text/xml" ) );
 
 3413     QDomDocument xmlDoc;
 
 3414     xmlDoc.setContent( encodedData );
 
 3416     const QDomElement dragDataElem = xmlDoc.documentElement();
 
 3417     if ( dragDataElem.tagName() == QLatin1String( 
"ColorSchemeModelDragData" ) )
 
 3419       const QDomNodeList nodeList = dragDataElem.childNodes();
 
 3420       const int nChildNodes = nodeList.size();
 
 3421       QDomElement currentElem;
 
 3423       for ( 
int i = 0; i < nChildNodes; ++i )
 
 3425         currentElem = nodeList.at( i ).toElement();
 
 3426         if ( currentElem.isNull() )
 
 3431         QPair< QColor, QString> namedColor;
 
 3433         namedColor.second = currentElem.attribute( QStringLiteral( 
"label" ), QString() );
 
 3435         mimeColors << namedColor;
 
 3440   if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral( 
"application/x-colorobject-list" ) ) )
 
 3443     const QByteArray encodedData = data->data( QStringLiteral( 
"application/x-colorobject-list" ) );
 
 3444     QDomDocument xmlDoc;
 
 3445     xmlDoc.setContent( encodedData );
 
 3447     const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral( 
"colors" ) );
 
 3448     if ( colorsNodes.length() > 0 )
 
 3450       const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
 
 3451       const QDomNodeList colorNodeList = colorsElem.childNodes();
 
 3452       const int nChildNodes = colorNodeList.size();
 
 3453       QDomElement currentElem;
 
 3455       for ( 
int i = 0; i < nChildNodes; ++i )
 
 3458         currentElem = colorNodeList.at( i ).toElement();
 
 3459         if ( currentElem.isNull() )
 
 3464         const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral( 
"color" ) );
 
 3465         const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral( 
"name" ) );
 
 3467         if ( colorNodes.length() > 0 )
 
 3469           const QDomElement colorElem = colorNodes.at( 0 ).toElement();
 
 3471           const QStringList colorParts = colorElem.text().simplified().split( 
' ' );
 
 3472           if ( colorParts.length() < 3 )
 
 3477           const int red = colorParts.at( 0 ).toDouble() * 255;
 
 3478           const int green = colorParts.at( 1 ).toDouble() * 255;
 
 3479           const int blue = colorParts.at( 2 ).toDouble() * 255;
 
 3480           QPair< QColor, QString> namedColor;
 
 3481           namedColor.first = QColor( red, green, blue );
 
 3482           if ( nameNodes.length() > 0 )
 
 3484             const QDomElement nameElem = nameNodes.at( 0 ).toElement();
 
 3485             namedColor.second = nameElem.text();
 
 3487           mimeColors << namedColor;
 
 3493   if ( mimeColors.length() == 0 && data->hasText() )
 
 3497     QList< QColor >::iterator it = parsedColors.begin();
 
 3498     for ( ; it != parsedColors.end(); ++it )
 
 3500       mimeColors << qMakePair( *it, QString() );
 
 3504   if ( mimeColors.length() == 0 && data->hasColor() )
 
 3507     const QColor mimeColor = data->colorData().value<QColor>();
 
 3508     if ( mimeColor.isValid() )
 
 3510       mimeColors << qMakePair( mimeColor, QString() );
 
 3520   QMimeData *mimeData = 
new QMimeData();
 
 3521   QDomDocument xmlDoc;
 
 3522   QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral( 
"ColorSchemeModelDragData" ) );
 
 3523   xmlDoc.appendChild( xmlRootElement );
 
 3525   QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
 
 3526   for ( ; colorIt != colorList.constEnd(); ++colorIt )
 
 3528     QDomElement namedColor = xmlDoc.createElement( QStringLiteral( 
"NamedColor" ) );
 
 3530     namedColor.setAttribute( QStringLiteral( 
"label" ), ( *colorIt ).second );
 
 3531     xmlRootElement.appendChild( namedColor );
 
 3533   mimeData->setData( QStringLiteral( 
"text/xml" ), xmlDoc.toByteArray() );
 
 3541   colorIt = colorList.constBegin();
 
 3542   QStringList colorListString;
 
 3543   for ( ; colorIt != colorList.constEnd(); ++colorIt )
 
 3545     colorListString << ( *colorIt ).first.name();
 
 3547   mimeData->setText( colorListString.join( QLatin1Char( 
'\n' ) ) );
 
 3550   if ( colorList.length() > 0 )
 
 3552     mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
 
 3560   if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
 
 3565   QTextStream stream( &file );
 
 3566 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
 3567   stream << 
"GIMP Palette" << endl;
 
 3569   stream << 
"GIMP Palette" << Qt::endl;
 
 3571   if ( paletteName.isEmpty() )
 
 3573 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
 3574     stream << 
"Name: QGIS Palette" << endl;
 
 3576     stream << 
"Name: QGIS Palette" << Qt::endl;
 
 3581 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
 3582     stream << 
"Name: " << paletteName << endl;
 
 3584     stream << 
"Name: " << paletteName << Qt::endl;
 
 3587 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
 3588   stream << 
"Columns: 4" << endl;
 
 3589   stream << 
'#' << endl;
 
 3591   stream << 
"Columns: 4" << Qt::endl;
 
 3592   stream << 
'#' << Qt::endl;
 
 3595   for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
 
 3597     const QColor color = ( *colorIt ).first;
 
 3598     if ( !color.isValid() )
 
 3602     stream << QStringLiteral( 
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
 
 3603 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 
 3604     stream << 
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << endl;
 
 3606     stream << 
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
 
 3618   if ( !file.open( QIODevice::ReadOnly ) )
 
 3621     return importedColors;
 
 3624   QTextStream in( &file );
 
 3626   QString line = in.readLine();
 
 3627   if ( !line.startsWith( QLatin1String( 
"GIMP Palette" ) ) )
 
 3630     return importedColors;
 
 3634   while ( !in.atEnd() && !line.startsWith( QLatin1String( 
"Name:" ) ) && !line.startsWith( 
'#' ) )
 
 3636     line = in.readLine();
 
 3638   if ( line.startsWith( QLatin1String( 
"Name:" ) ) )
 
 3640     const thread_local QRegularExpression nameRx( 
"Name:\\s*(\\S.*)$" );
 
 3641     const QRegularExpressionMatch match = nameRx.match( line );
 
 3642     if ( match.hasMatch() )
 
 3644       name = match.captured( 1 );
 
 3649   while ( !in.atEnd() && !line.startsWith( 
'#' ) )
 
 3651     line = in.readLine();
 
 3656     return importedColors;
 
 3660   const thread_local QRegularExpression rx( 
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
 
 3661   while ( !in.atEnd() )
 
 3663     line = in.readLine();
 
 3664     const QRegularExpressionMatch match = rx.match( line );
 
 3665     if ( !match.hasMatch() )
 
 3669     const int red = match.captured( 1 ).toInt();
 
 3670     const int green = match.captured( 2 ).toInt();
 
 3671     const int blue = match.captured( 3 ).toInt();
 
 3672     const QColor color = QColor( red, green, blue );
 
 3673     if ( !color.isValid() )
 
 3680     if ( rx.captureCount() > 3 )
 
 3682       label = match.captured( 4 ).simplified();
 
 3689     importedColors << qMakePair( color, label );
 
 3694   return importedColors;
 
 3707   const thread_local QRegularExpression hexColorAlphaRx( 
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
 
 3708   QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
 
 3711   if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
 
 3714     parsedColor.setNamedColor( colorStr );
 
 3715     if ( parsedColor.isValid() )
 
 3717       containsAlpha = 
false;
 
 3723   if ( match.hasMatch() )
 
 3725     const QString hexColor = match.captured( 1 );
 
 3726     parsedColor.setNamedColor( QStringLiteral( 
"#" ) + hexColor );
 
 3728     const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
 
 3730     if ( parsedColor.isValid() && alphaOk )
 
 3732       parsedColor.setAlpha( alphaHex );
 
 3733       containsAlpha = 
true;
 
 3741     const thread_local QRegularExpression hexColorRx2( 
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
 
 3742     if ( colorStr.indexOf( hexColorRx2 ) != -1 )
 
 3745       parsedColor.setNamedColor( QStringLiteral( 
"#" ) + colorStr );
 
 3746       if ( parsedColor.isValid() )
 
 3748         containsAlpha = 
false;
 
 3755   const thread_local QRegularExpression rgbFormatRx( 
"^\\s*(?:rgb)?\\(?\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*\\)?\\s*;?\\s*$" );
 
 3756   match = rgbFormatRx.match( colorStr );
 
 3757   if ( match.hasMatch() )
 
 3759     const int r = match.captured( 1 ).toInt();
 
 3760     const int g = match.captured( 2 ).toInt();
 
 3761     const int b = match.captured( 3 ).toInt();
 
 3762     parsedColor.setRgb( r, g, b );
 
 3763     if ( parsedColor.isValid() )
 
 3765       containsAlpha = 
false;
 
 3771   const thread_local QRegularExpression hslFormatRx( 
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
 
 3772   match = hslFormatRx.match( colorStr );
 
 3773   if ( match.hasMatch() )
 
 3775     const int h = match.captured( 1 ).toInt();
 
 3776     const int s = match.captured( 2 ).toInt();
 
 3777     const int l = match.captured( 3 ).toInt();
 
 3778     parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
 
 3779     if ( parsedColor.isValid() )
 
 3781       containsAlpha = 
false;
 
 3787   const thread_local QRegularExpression rgbPercentFormatRx( 
"^\\s*(?:rgb)?\\(?\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(100|0*\\d{1,2})\\s*%\\s*\\)?\\s*;?\\s*$" );
 
 3788   match = rgbPercentFormatRx.match( colorStr );
 
 3789   if ( match.hasMatch() )
 
 3791     const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
 
 3792     const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
 
 3793     const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
 
 3794     parsedColor.setRgb( r, g, b );
 
 3795     if ( parsedColor.isValid() )
 
 3797       containsAlpha = 
false;
 
 3803   const thread_local QRegularExpression rgbaFormatRx( 
"^\\s*(?:rgba)?\\(?\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$" );
 
 3804   match = rgbaFormatRx.match( colorStr );
 
 3805   if ( match.hasMatch() )
 
 3807     const int r = match.captured( 1 ).toInt();
 
 3808     const int g = match.captured( 2 ).toInt();
 
 3809     const int b = match.captured( 3 ).toInt();
 
 3810     const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
 
 3811     parsedColor.setRgb( r, g, b, a );
 
 3812     if ( parsedColor.isValid() )
 
 3814       containsAlpha = 
true;
 
 3820   const thread_local QRegularExpression rgbaPercentFormatRx( 
"^\\s*(?:rgba)?\\(?\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$" );
 
 3821   match = rgbaPercentFormatRx.match( colorStr );
 
 3822   if ( match.hasMatch() )
 
 3824     const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
 
 3825     const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
 
 3826     const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
 
 3827     const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
 
 3828     parsedColor.setRgb( r, g, b, a );
 
 3829     if ( parsedColor.isValid() )
 
 3831       containsAlpha = 
true;
 
 3837   const thread_local QRegularExpression hslaPercentFormatRx( 
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
 
 3838   match = hslaPercentFormatRx.match( colorStr );
 
 3839   if ( match.hasMatch() )
 
 3841     const int h = match.captured( 1 ).toInt();
 
 3842     const int s = match.captured( 2 ).toInt();
 
 3843     const int l = match.captured( 3 ).toInt();
 
 3844     const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
 
 3845     parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
 
 3846     if ( parsedColor.isValid() )
 
 3848       containsAlpha = 
true;
 
 3865   const QImage::Format format = image->format();
 
 3866   if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
 
 3868     QgsDebugMsg( QStringLiteral( 
"no alpha channel." ) );
 
 3873   for ( 
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
 
 3875     QRgb *scanLine = 
reinterpret_cast< QRgb * 
>( image->scanLine( heightIndex ) );
 
 3876     for ( 
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
 
 3878       myRgb = scanLine[widthIndex];
 
 3879       if ( format == QImage::Format_ARGB32_Premultiplied )
 
 3880         scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
 
 3882         scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
 
 3890   const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
 
 3891   const int alpha = ( radius < 1 )  ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
 
 3893   if ( image.format() != QImage::Format_ARGB32_Premultiplied
 
 3894        && image.format() != QImage::Format_RGB32 )
 
 3896     image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
 
 3899   const int r1 = rect.top();
 
 3900   const int r2 = rect.bottom();
 
 3901   const int c1 = rect.left();
 
 3902   const int c2 = rect.right();
 
 3904   const int bpl = image.bytesPerLine();
 
 3912     i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
 
 3914   for ( 
int col = c1; col <= c2; col++ )
 
 3916     p = image.scanLine( r1 ) + col * 4;
 
 3917     for ( 
int i = i1; i <= i2; i++ )
 
 3918       rgba[i] = p[i] << 4;
 
 3921     for ( 
int j = r1; j < r2; j++, p += bpl )
 
 3922       for ( 
int i = i1; i <= i2; i++ )
 
 3923         p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
 
 3926   for ( 
int row = r1; row <= r2; row++ )
 
 3928     p = image.scanLine( row ) + c1 * 4;
 
 3929     for ( 
int i = i1; i <= i2; i++ )
 
 3930       rgba[i] = p[i] << 4;
 
 3933     for ( 
int j = c1; j < c2; j++, p += 4 )
 
 3934       for ( 
int i = i1; i <= i2; i++ )
 
 3935         p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
 
 3938   for ( 
int col = c1; col <= c2; col++ )
 
 3940     p = image.scanLine( r2 ) + col * 4;
 
 3941     for ( 
int i = i1; i <= i2; i++ )
 
 3942       rgba[i] = p[i] << 4;
 
 3945     for ( 
int j = r1; j < r2; j++, p -= bpl )
 
 3946       for ( 
int i = i1; i <= i2; i++ )
 
 3947         p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
 
 3950   for ( 
int row = r1; row <= r2; row++ )
 
 3952     p = image.scanLine( row ) + c2 * 4;
 
 3953     for ( 
int i = i1; i <= i2; i++ )
 
 3954       rgba[i] = p[i] << 4;
 
 3957     for ( 
int j = c1; j < c2; j++, p -= 4 )
 
 3958       for ( 
int i = i1; i <= i2; i++ )
 
 3959         p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
 
 3965   if ( alpha != 255 && alpha > 0 )
 
 3969     const double alphaFactor = alpha / 255.;
 
 3970     int r = 0, g = 0, b = 0;
 
 3971     rgb.getRgb( &r, &g, &b );
 
 3976     rgb.setRgb( r, g, b, alpha );
 
 3978   else if ( alpha == 0 )
 
 3980     rgb.setRgb( 0, 0, 0, 0 );
 
 3989   if ( !simpleFill || !simpleLine )
 
 4013   if ( simpleLine->
offset() )
 
 4031   if ( order == Qt::AscendingOrder )
 
 4045   const double dx = directionPoint.x() - startPoint.x();
 
 4046   const double dy = directionPoint.y() - startPoint.y();
 
 4047   const double length = std::sqrt( dx * dx + dy * dy );
 
 4048   const double scaleFactor = distance / length;
 
 4049   return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
 
 4059   for ( 
int i = 0; i < svgPaths.size(); i++ )
 
 4061     const QDir dir( svgPaths[i] );
 
 4062     const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
 
 4063     for ( 
const QString &item : svgSubPaths )
 
 4065       svgPaths.insert( i + 1, dir.path() + 
'/' + item );
 
 4068     const auto svgFiles = dir.entryList( QStringList( 
"*.svg" ), QDir::Files );
 
 4069     for ( 
const QString &item : svgFiles )
 
 4072       list.append( dir.path() + 
'/' + item );
 
 4084   QStringList svgPaths;
 
 4085   svgPaths.append( directory );
 
 4087   for ( 
int i = 0; i < svgPaths.size(); i++ )
 
 4089     const QDir dir( svgPaths[i] );
 
 4090     const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
 
 4091     for ( 
const QString &item : svgSubPaths )
 
 4093       svgPaths.insert( i + 1, dir.path() + 
'/' + item );
 
 4096     const auto svgFiles = dir.entryList( QStringList( 
"*.svg" ), QDir::Files );
 
 4097     for ( 
const QString &item : svgFiles )
 
 4099       list.append( dir.path() + 
'/' + item );
 
 4111   if ( n.startsWith( QLatin1String( 
"base64:" ) ) )
 
 4115   if ( QFileInfo::exists( n ) )
 
 4116     return QFileInfo( n ).canonicalFilePath();
 
 4120   if ( name.contains( QLatin1String( 
"://" ) ) )
 
 4122     const QUrl url( name );
 
 4123     if ( url.isValid() && !url.scheme().isEmpty() )
 
 4125       if ( url.scheme().compare( QLatin1String( 
"file" ), Qt::CaseInsensitive ) == 0 )
 
 4128         name = url.toLocalFile();
 
 4129         if ( QFile( name ).exists() )
 
 4131           return QFileInfo( name ).canonicalFilePath();
 
 4145   for ( 
int i = 0; i < svgPaths.size(); i++ )
 
 4147     QString svgPath = svgPaths[i];
 
 4148     if ( svgPath.endsWith( QChar( 
'/' ) ) )
 
 4159     const QString myLocalPath = svgPath + QDir::separator() + name;
 
 4162     if ( QFile( myLocalPath ).exists() )
 
 4165       return QFileInfo( myLocalPath ).canonicalFilePath();
 
 4169   return pathResolver.
readPath( name );
 
 4177   if ( p.startsWith( QLatin1String( 
"base64:" ) ) )
 
 4180   if ( !QFileInfo::exists( p ) )
 
 4183   QString path = QFileInfo( p ).canonicalFilePath();
 
 4187   bool isInSvgPaths = 
false;
 
 4188   for ( 
int i = 0; i < svgPaths.size(); i++ )
 
 4190     const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
 
 4192     if ( !dir.isEmpty() && path.startsWith( dir ) )
 
 4194       path = path.mid( dir.size() + 1 );
 
 4195       isInSvgPaths = 
true;
 
 4210   double cx = 0, cy = 0;
 
 4211   double area, sum = 0;
 
 4212   for ( 
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
 
 4214     const QPointF &p1 = points[i];
 
 4215     const QPointF &p2 = points[j];
 
 4216     area = p1.x() * p2.y() - p1.y() * p2.x();
 
 4218     cx += ( p1.x() + p2.x() ) * area;
 
 4219     cy += ( p1.y() + p2.y() ) * area;
 
 4226     if ( points.count() >= 2 )
 
 4227       return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
 
 4228     else if ( points.count() == 1 )
 
 4236   return QPointF( cx, cy );
 
 4245     unsigned int i, pointCount = points.count();
 
 4247     for ( i = 0; i < pointCount; ++i ) polyline[i] = 
QgsPointXY( points[i].x(), points[i].y() );
 
 4253         for ( 
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
 
 4255           pointCount = ( *ringIt ).count();
 
 4257           for ( i = 0; i < pointCount; ++i ) polyline[i] = 
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
 
 4263       if ( !pointOnSurfaceGeom.
isNull() )
 
 4277   bool inside = 
false;
 
 4279   const double x = point.x();
 
 4280   const double y = point.y();
 
 4282   for ( 
int i = 0, j = points.count() - 1; i < points.count(); i++ )
 
 4284     const QPointF &p1 = points[i];
 
 4285     const QPointF &p2 = points[j];
 
 4290     if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
 
 4292       if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
 
 4303   if ( polyline.size() < 2 )
 
 4306   double totalLength = 0;
 
 4307   auto it = polyline.begin();
 
 4309   for ( ; it != polyline.end(); ++it )
 
 4311     const QPointF p2 = *it;
 
 4312     const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
 
 4313     totalLength += segmentLength;
 
 4321   if ( polyline.size() < 2 )
 
 4324   double totalLength = 0;
 
 4325   auto it = polyline.begin();
 
 4327   std::vector< double > segmentLengths( polyline.size() - 1 );
 
 4328   auto segmentLengthIt = segmentLengths.begin();
 
 4329   for ( ; it != polyline.end(); ++it )
 
 4331     const QPointF p2 = *it;
 
 4332     *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
 
 4333     totalLength += *segmentLengthIt;
 
 4339   if ( startOffset >= 0 && totalLength <= startOffset )
 
 4341   if ( endOffset < 0 && totalLength <= -endOffset )
 
 4344   const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
 
 4345   const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
 
 4346   QPolygonF substringPoints;
 
 4347   substringPoints.reserve( polyline.size() );
 
 4349   it = polyline.begin();
 
 4350   segmentLengthIt = segmentLengths.begin();
 
 4353   bool foundStart = 
false;
 
 4354   if ( 
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
 
 4356     substringPoints << p1;
 
 4360   double distanceTraversed = 0;
 
 4361   for ( ; it != polyline.end(); ++it )
 
 4363     const QPointF p2 = *it;
 
 4364     if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
 
 4367       const double distanceToStart = startDistance - distanceTraversed;
 
 4368       double startX, startY;
 
 4370       substringPoints << QPointF( startX, startY );
 
 4373     if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
 
 4376       const double distanceToEnd = endDistance - distanceTraversed;
 
 4379       if ( substringPoints.last() != QPointF( endX, endY ) )
 
 4380         substringPoints << QPointF( endX, endY );
 
 4382     else if ( foundStart )
 
 4384       if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
 
 4385         substringPoints << QPointF( p2.x(), p2.y() );
 
 4388     distanceTraversed += *segmentLengthIt;
 
 4389     if ( distanceTraversed > endDistance )
 
 4396   if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
 
 4399   return substringPoints;
 
 4404   double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
 
 4408   return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
 
 4413   target.reserve( target.size() + line.size() );
 
 4414   for ( 
const QPointF &pt : line )
 
 4416     if ( !target.empty() && target.last() == pt )
 
 4425   if ( fieldOrExpression.isEmpty() )
 
 4460   QList<double> breaks;
 
 4463     breaks.append( maximum );
 
 4467   const int minimumCount = 
static_cast< int >( classes ) / 3;
 
 4468   const double shrink = 0.75;
 
 4469   const double highBias = 1.5;
 
 4470   const double adjustBias = 0.5 + 1.5 * highBias;
 
 4471   const int divisions = classes;
 
 4472   const double h = highBias;
 
 4475   const double dx = maximum - minimum;
 
 4485     cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
 
 4486     if ( adjustBias >= 1.5 * h + 0.5 )
 
 4488       U = 1 + ( 1.0 / ( 1 + h ) );
 
 4492       U = 1 + ( 1.5 / ( 1 + adjustBias ) );
 
 4494     small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
 
 4501       cell = 9 + cell / 10;
 
 4502       cell = cell * shrink;
 
 4504     if ( minimumCount > 1 )
 
 4506       cell = cell / minimumCount;
 
 4512     if ( divisions > 1 )
 
 4514       cell = cell / divisions;
 
 4517   if ( cell < 20 * 1e-07 )
 
 4522   const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
 
 4524   if ( ( 2 * base ) - cell < h * ( cell - unit ) )
 
 4527     if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
 
 4530       if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
 
 4537   int start = std::floor( minimum / unit + 1e-07 );
 
 4538   int end = std::ceil( maximum / unit - 1e-07 );
 
 4541   while ( start * unit > minimum + ( 1e-07 * unit ) )
 
 4545   while ( end * unit < maximum - ( 1e-07 * unit ) )
 
 4549   QgsDebugMsg( QStringLiteral( 
"pretty classes: %1" ).arg( end ) );
 
 4553   int k = std::floor( 0.5 + end - start );
 
 4554   if ( k < minimumCount )
 
 4556     k = minimumCount - k;
 
 4560       start = start - k / 2 + k % 2;
 
 4564       start = start - k / 2;
 
 4565       end = end + k / 2 + k % 2;
 
 4568   const double minimumBreak = start * unit;
 
 4570   const int count = end - start;
 
 4572   breaks.reserve( count );
 
 4573   for ( 
int i = 1; i < count + 1; i++ )
 
 4575     breaks.append( minimumBreak + i * unit );
 
 4578   if ( breaks.isEmpty() )
 
 4581   if ( breaks.first() < minimum )
 
 4583     breaks[0] = minimum;
 
 4585   if ( breaks.last() > maximum )
 
 4587     breaks[breaks.count() - 1] = maximum;
 
 4592   if ( minimum < 0.0 && maximum > 0.0 ) 
 
 4594     QList<double> breaksMinusZero; 
 
 4595     for ( 
int i = 0; i < breaks.count(); i++ )
 
 4597       breaksMinusZero.append( breaks[i] - 0.0 );
 
 4600     for ( 
int i = 1; i < breaks.count(); i++ ) 
 
 4602       if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
 
 4605     breaks[posOfMin] = 0.0;
 
 4614   bool roundToUnit = 
false;
 
 4617     if ( props.contains( QStringLiteral( 
"uomScale" ) ) )
 
 4620       scale = props.value( QStringLiteral( 
"uomScale" ) ).toDouble( &ok );
 
 4629     if ( props.value( QStringLiteral( 
"uom" ) ) == QLatin1String( 
"http://www.opengeospatial.org/se/units/metre" ) )
 
 4654           scale = 1 / 0.28 * 25.4;
 
 4678   double rescaled = size * scale;
 
 4683     rescaled = std::round( rescaled );
 
 4690   const double x = 
rescaleUom( point.x(), unit, props );
 
 4691   const double y = 
rescaleUom( point.y(), unit, props );
 
 4692   return QPointF( x, y );
 
 4697   QVector<qreal> result;
 
 4698   QVector<qreal>::const_iterator it = array.constBegin();
 
 4699   for ( ; it != array.constEnd(); ++it )
 
 4701     result.append( 
rescaleUom( *it, unit, props ) );
 
 4708   if ( !props.value( QStringLiteral( 
"scaleMinDenom" ), QString() ).toString().isEmpty() )
 
 4710     QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral( 
"se:MinScaleDenominator" ) );
 
 4711     scaleMinDenomElem.appendChild( doc.createTextNode( 
qgsDoubleToString( props.value( QStringLiteral( 
"scaleMinDenom" ) ).toString().toDouble() ) ) );
 
 4712     ruleElem.appendChild( scaleMinDenomElem );
 
 4715   if ( !props.value( QStringLiteral( 
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
 
 4717     QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral( 
"se:MaxScaleDenominator" ) );
 
 4718     scaleMaxDenomElem.appendChild( doc.createTextNode( 
qgsDoubleToString( props.value( QStringLiteral( 
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
 
 4719     ruleElem.appendChild( scaleMaxDenomElem );
 
 4728     const double parentScaleMinDenom = props.value( QStringLiteral( 
"scaleMinDenom" ), QStringLiteral( 
"0" ) ).toString().toDouble( &ok );
 
 4729     if ( !ok || parentScaleMinDenom <= 0 )
 
 4730       props[ QStringLiteral( 
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
 
 4732       props[ QStringLiteral( 
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
 
 4738     const double parentScaleMaxDenom = props.value( QStringLiteral( 
"scaleMaxDenom" ), QStringLiteral( 
"0" ) ).toString().toDouble( &ok );
 
 4739     if ( !ok || parentScaleMaxDenom <= 0 )
 
 4740       props[ QStringLiteral( 
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
 
 4742       props[ QStringLiteral( 
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
 
 4750   if ( uom == QLatin1String( 
"http://www.opengeospatial.org/se/units/metre" ) )
 
 4752     scale = 1.0 / 0.00028; 
 
 4754   else if ( uom == QLatin1String( 
"http://www.opengeospatial.org/se/units/foot" ) )
 
 4756     scale = 304.8 / 0.28; 
 
 4763   return size * scale;
 
 4771       SymbolLayerVisitor( 
const QSet<QgsSymbolLayerId> &layerIds )
 
 4772         : mSymbolLayerIds( layerIds )
 
 4785       void visitSymbol( 
const QgsSymbol *symbol, 
const QString &identifier, QVector<int> rootPath )
 
 4789           QVector<int> indexPath = rootPath;
 
 4790           indexPath.append( idx );
 
 4792           if ( mSymbolLayerIds.contains( 
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
 
 4794             mSymbolLayers.insert( sl );
 
 4799             visitSymbol( subSymbol, identifier, indexPath );
 
 4808           if ( symbolEntity->symbol() )
 
 4810             visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
 
 4816       QString mCurrentRuleKey;
 
 4817       const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
 
 4818       QSet<const QgsSymbolLayer *> mSymbolLayers;
 
 4821   SymbolLayerVisitor visitor( symbolLayerIds );
 
 4822   renderer->
accept( &visitor );
 
 4823   return visitor.mSymbolLayers;
 
 4828   if ( !s || !context )
 
 4838     size = markerSymbol->
size( *context );
 
 4840   else if ( lineSymbol )
 
 4842     size = lineSymbol->
width( *context );
 
 4851   if ( minSize > 0 && size < minSize )
 
 4855   else if ( maxSize > 0 && size > maxSize )
 
 4873   else if ( lineSymbol )
 
 4887   QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
 
 4888   for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
 
 4890     properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
 
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
@ SemiTransparentCircle
Semi-transparent circle marker.
@ RendererShouldUseSymbolLevels
If present, indicates that a QgsFeatureRenderer using the symbol should use symbol levels for best re...
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QStringList svgPaths()
Returns the paths to svg directories.
HeadType
Possible head types.
ArrowType
Possible arrow types.
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string map...
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
virtual QString type() const =0
Returns a string representing the color ramp type.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
An expression node which takes it value from a feature's field.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
Class for parsing and evaluation of expressions (formerly called "search strings").
QString expression() const
Returns the original, unmodified expression string.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString parserErrorString() const
Returns parser error.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static double normalizedAngle(double angle) SIP_HOLDGIL
Ensures that an angle is in the range 0 <= angle < 2 pi.
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance) SIP_HOLDGIL
Returns a point a specified distance toward a second point.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Represents a patch shape for use in map legends.
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsLimitedRandomColorRamp color ramp created using the properties encoded in a string m...
@ AllRings
Render both exterior and interior rings.
RenderRingFilter ringFilter() const
Returns the line symbol layer's ring filter, which controls which rings are rendered when the line sy...
QgsUnitTypes::RenderUnit widthUnit() const
Returns the units for the line's width.
virtual double width() const
Returns the estimated width for the line symbol layer.
double offset() const
Returns the line's offset.
const QgsMapUnitScale & widthMapUnitScale() const
A line symbol type, for rendering LineString and MultiLineString geometries.
void setWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the width units for the whole symbol (including all symbol layers).
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
void setWidth(double width)
Sets the width for the whole line symbol.
Struct for storing maximum and minimum scales for measurements in map units.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
double maxScale
The maximum scale, or 0.0 if unset.
double minScale
The minimum scale, or 0.0 if unset.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
bool maxSizeMMEnabled
Whether the maximum size in mm should be respected.
double minSizeMM
The minimum size in millimeters, or 0.0 if unset.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setSize(double size)
Sets the size for the whole symbol.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the size units for the whole symbol (including all symbol layers).
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates an OGC expression XML element.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
A class to represent a 2D point.
void setX(double x) SIP_HOLDGIL
Sets the point's x-coordinate.
void setY(double y) SIP_HOLDGIL
Sets the point's y-coordinate.
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string ma...
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
QSet< int > propertyKeys() const override
Returns a list of property keys contained within the collection.
A store for object properties.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
Contains information about the context of a rendering operation.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setPenJoinStyle(Qt::PenJoinStyle style)
void setStrokeWidth(double strokeWidth)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setStrokeColor(const QColor &strokeColor) override
Set stroke color.
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the width of the fill's stroke.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
double trimDistanceStart() const
Returns the trim distance for the start of the line, which dictates a length from the start of the li...
double trimDistanceEnd() const
Returns the trim distance for the end of the line, which dictates a length from the end of the line a...
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
double dashPatternOffset() const
Returns the dash pattern offset, which dictates how far along the dash pattern the pattern should sta...
bool drawInsidePolygon() const
Returns true if the line should only be drawn inside polygons, and any portion of the line which fall...
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A symbol entity for QgsStyle databases.
We may need stable references to symbol layers, when pointers to symbol layers is not usable (when a ...
QgsSymbolLayer * createSymbolLayerFromSld(const QString &name, QDomElement &element) const
create a new instance of symbol layer given symbol layer name and SLD
QgsSymbolLayer * createSymbolLayer(const QString &name, const QVariantMap &properties=QVariantMap()) const
create a new instance of symbol layer given symbol layer name and properties
void resolvePaths(const QString &name, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving) const
Resolve paths in properties of a particular symbol layer.
void resolveFonts(const QString &name, QVariantMap &properties, const QgsReadWriteContext &context) const
Resolve fonts from the properties of a particular symbol layer.
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
static QColor parseColor(const QString &colorStr, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
static void createAnchorPointElement(QDomDocument &doc, QDomElement &element, QPointF anchor)
Creates a SE 1.1 anchor point element as a child of the specified element.
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
static bool hasExternalGraphic(QDomElement &element)
static QString encodePenStyle(Qt::PenStyle style)
static bool needMarkerLine(QDomElement &element)
static QVector< qreal > decodeSldRealVector(const QString &s)
static bool needLinePatternFill(QDomElement &element)
static QString encodeSldBrushStyle(Qt::BrushStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QgsArrowSymbolLayer::HeadType decodeArrowHeadType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow head type.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
static QgsSymbol * symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
static QgsStringMap evaluatePropertiesMap(const QMap< QString, QgsProperty > &propertiesMap, const QgsExpressionContext &context)
Evaluates a map of properties using the given context and returns a variant map with evaluated expres...
static void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
static bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
static bool hasWellKnownMark(QDomElement &element)
static QString getSvgParametricPath(const QString &basePath, const QColor &fillColor, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into a path with parameters according to the SVG Parameters s...
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
static QColor decodeColor(const QString &str)
static bool onlineResourceFromSldElement(QDomElement &element, QString &path, QString &format)
static QPointF polygonCentroid(const QPolygonF &points)
Calculate the centroid point of a QPolygonF.
static QIcon colorRampPreviewIcon(QgsColorRamp *ramp, QSize size, int padding=0)
Returns an icon preview for a color ramp.
static QString encodeBrushStyle(Qt::BrushStyle style)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QPixmap colorRampPreviewPixmap(QgsColorRamp *ramp, QSize size, int padding=0, Qt::Orientation direction=Qt::Horizontal, bool flipDirection=false, bool drawTransparentBackground=true)
Returns a pixmap preview for a color ramp.
static QString encodeSldAlpha(int alpha)
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &mime, const QColor &color, double size=-1)
static QPointF polygonPointOnSurface(const QPolygonF &points, const QVector< QPolygonF > *rings=nullptr)
Calculate a point on the surface of a QPolygonF.
static void blurImageInPlace(QImage &image, QRect rect, int radius, bool alphaOnly)
Blurs an image in place, e.g. creating Qt-independent drop shadows.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static double rescaleUom(double size, QgsUnitTypes::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static void premultiplyColor(QColor &rgb, int alpha)
Converts a QColor into a premultiplied ARGB QColor value using a specified alpha value.
static void saveProperties(QVariantMap props, QDomDocument &doc, QDomElement &element)
Saves the map of properties to XML.
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
static bool functionFromSldElement(QDomElement &element, QString &function)
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr)
Returns a pixmap preview for a color ramp.
static QColor parseColorWithAlpha(const QString &colorStr, bool &containsAlpha, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static QString encodeSldUom(QgsUnitTypes::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QSizeF toSize(const QVariant &value, bool *ok=nullptr)
Converts a value to a size.
static bool needEllipseMarker(QDomElement &element)
static QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static QgsUnitTypes::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static QgsStringMap getSvgParameterList(QDomElement &element)
static bool needSvgFill(QDomElement &element)
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static void parametricSvgToSld(QDomDocument &doc, QDomElement &graphicElem, const QString &path, const QColor &fillColor, double size, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into SLD, as a succession of parametric SVG using URL paramet...
static QString encodeSldLineCapStyle(Qt::PenCapStyle style)
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
static void createOpacityElement(QDomDocument &doc, QDomElement &element, const QString &alphaFunc)
static QSet< const QgsSymbolLayer * > toSymbolLayerPointers(QgsFeatureRenderer *renderer, const QSet< QgsSymbolLayerId > &symbolLayerIds)
Converts a set of symbol layer id to a set of pointers to actual symbol layers carried by the feature...
static QString ogrFeatureStyleBrush(const QColor &fillColr)
Create ogr feature style string for brush.
static bool pointInPolygon(const QPolygonF &points, QPointF point)
Calculate whether a point is within of a QPolygonF.
static QStringList listSvgFiles()
Returns a list of all available svg files.
static QgsSymbol * restrictedSizeSymbol(const QgsSymbol *s, double minSize, double maxSize, QgsRenderContext *context, double &width, double &height)
Creates a new symbol with size restricted to min/max size if original size is out of min/max range.
static bool convertPolygonSymbolizerToPointMarker(QDomElement &element, QList< QgsSymbolLayer * > &layerList)
Converts a polygon symbolizer element to a list of marker symbol layers.
static QStringList listSvgFilesAt(const QString &directory)
Returns a list of svg files at the specified directory.
static bool needFontMarker(QDomElement &element)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QFont::Style decodeSldFontStyle(const QString &str)
static QString fieldOrExpressionFromExpression(QgsExpression *expression)
Returns a field name if the whole expression is just a name of the field .
static bool createSymbolLayerListFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType, QList< QgsSymbolLayer * > &layers)
Creates a symbol layer list from a DOM element.
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static bool opacityFromSldElement(QDomElement &element, QString &alphaFunc)
static QString encodeSldFontWeight(int weight)
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
static QMimeData * colorListToMimeData(const QgsNamedColorList &colorList, bool allFormats=true)
Creates mime data from a list of named colors.
static Qt::BrushStyle decodeBrushStyle(const QString &str)
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static Qt::PenCapStyle decodeSldLineCapStyle(const QString &str)
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
static QString encodeSize(QSizeF size)
Encodes a QSizeF to a string.
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static double sizeInPixelsFromSldUom(const QString &uom, double size)
Returns the size scaled in pixels according to the uom attribute.
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static QgsSymbol * loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
static int decodeSldAlpha(const QString &str)
static QString encodeSldLineJoinStyle(Qt::PenJoinStyle style)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static void drawStippledBackground(QPainter *painter, QRect rect)
static QList< QColor > parseColorList(const QString &colorStr)
Attempts to parse a string as a list of colors using a variety of common formats, including hex codes...
static QString encodeColor(const QColor &color)
static QgsSymbolLayer * loadSymbolLayer(QDomElement &element, const QgsReadWriteContext &context)
Reads and returns symbol layer from XML. Caller is responsible for deleting the returned object.
static Qt::PenJoinStyle decodeSldLineJoinStyle(const QString &str)
static QVariantMap parseProperties(const QDomElement &element)
Parses the properties from XML and returns a map.
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QString encodeSldFontStyle(QFont::Style style)
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static int decodeSldFontWeight(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static QPicture symbolLayerPreviewPicture(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to a QPicture.
static void fillToSld(QDomDocument &doc, QDomElement &element, Qt::BrushStyle brushStyle, const QColor &color=QColor())
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr)
Returns an icon preview for a color ramp.
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
static QgsArrowSymbolLayer::ArrowType decodeArrowType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow type.
static bool needSvgMarker(QDomElement &element)
static void clearSymbolMap(QgsSymbolMap &symbols)
static Qt::BrushStyle decodeSldBrushStyle(const QString &str)
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
static bool geometryFromSldElement(QDomElement &element, QString &geomFunc)
static QString encodeScaleMethod(Qgis::ScaleMethod scaleMethod)
Encodes a symbol scale method to a string.
static void createOnlineResourceElement(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format)
static Qt::PenStyle decodePenStyle(const QString &str)
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static void labelTextToSld(QDomDocument &doc, QDomElement &element, const QString &label, const QFont &font, const QColor &color=QColor(), double size=-1)
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static QgsSymbolLayer * createLineLayerFromSld(QDomElement &element)
static bool needPointPatternFill(QDomElement &element)
static QString encodeSldRealVector(const QVector< qreal > &v)
static QgsSymbolLayer * createFillLayerFromSld(QDomElement &element)
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
static QgsExpression * fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to an icon.
static QString encodeRealVector(const QVector< qreal > &v)
Property
Data definable properties.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
virtual QColor color() const
The fill color.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
void setRenderingPass(int renderingPass)
Specifies the rendering pass in which this symbol layer should be rendered.
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
void setEnabled(bool enabled)
Sets whether symbol layer is enabled and should be drawn.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
void setLocked(bool locked)
Sets whether the layer's colors are locked.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setOriginalGeometryType(QgsWkbTypes::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
void setOutputUnit(QgsUnitTypes::RenderUnit unit)
Sets the units to use for sizes and widths within the symbol.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
void setFlags(Qgis::SymbolFlags flags)
Sets flags for the symbol.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
void setMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context's extent.
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
RenderUnit
Rendering size units.
@ RenderUnknownUnit
Mixed or unknown units.
@ RenderMetersInMapUnits
Meters value as Map units.
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
@ RenderPoints
Points (e.g., for font sizes)
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
QMap< QString, QgsSymbol * > QgsSymbolMap
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, QgsWkbTypes::GeometryType geometryType)
calculate geometry shifted by a specified distance
Contains information relating to a node (i.e.
QString identifier
A string identifying the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.
QString identifier
A string identifying the style entity.