Skip to content

Commit 7daca21

Browse files
committed
Ignore bounds for generated geometries
And guard many other static_casts to avoid crashes.
1 parent d021100 commit 7daca21

File tree

1 file changed

+103
-78
lines changed

1 file changed

+103
-78
lines changed

src/core/symbology-ng/qgssymbolv2.cpp

Lines changed: 103 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -949,24 +949,24 @@ void QgsMarkerSymbolV2::setAngle( double ang )
949949

950950
double QgsMarkerSymbolV2::angle() const
951951
{
952-
QgsSymbolLayerV2List::const_iterator it = mLayers.begin();
953-
954-
if ( it == mLayers.end() )
955-
return 0;
956-
957-
// return angle of the first symbol layer
958-
const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
959-
return layer->angle();
952+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
953+
{
954+
if ( layer->type() != QgsSymbolV2::Marker )
955+
continue;
956+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
957+
return markerLayer->angle();
958+
}
959+
return 0;
960960
}
961961

962962
void QgsMarkerSymbolV2::setLineAngle( double lineAng )
963963
{
964964
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
965965
{
966-
QgsMarkerSymbolLayerV2* markerLayer = dynamic_cast<QgsMarkerSymbolLayerV2*>( layer );
967-
968-
if ( markerLayer )
969-
markerLayer->setLineAngle( lineAng );
966+
if ( layer->type() != QgsSymbolV2::Marker )
967+
continue;
968+
QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
969+
markerLayer->setLineAngle( lineAng );
970970
}
971971
}
972972

@@ -976,25 +976,23 @@ void QgsMarkerSymbolV2::setDataDefinedAngle( const QgsDataDefined& dd )
976976

977977
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
978978
{
979-
QgsMarkerSymbolLayerV2* markerLayer = dynamic_cast<QgsMarkerSymbolLayerV2*>( layer );
980-
981-
if ( markerLayer )
979+
if ( layer->type() != QgsSymbolV2::Marker )
980+
continue;
981+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
982+
if ( dd.hasDefaultValues() )
982983
{
983-
if ( dd.hasDefaultValues() )
984+
layer->removeDataDefinedProperty( "angle" );
985+
}
986+
else
987+
{
988+
if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
984989
{
985-
layer->removeDataDefinedProperty( "angle" );
990+
layer->setDataDefinedProperty( "angle", new QgsDataDefined( dd ) );
986991
}
987992
else
988993
{
989-
if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
990-
{
991-
layer->setDataDefinedProperty( "angle", new QgsDataDefined( dd ) );
992-
}
993-
else
994-
{
995-
QgsDataDefined* rotatedDD = rotateWholeSymbol( markerLayer->angle() - symbolRotation, dd );
996-
layer->setDataDefinedProperty( "angle", rotatedDD );
997-
}
994+
QgsDataDefined* rotatedDD = rotateWholeSymbol( markerLayer->angle() - symbolRotation, dd );
995+
layer->setDataDefinedProperty( "angle", rotatedDD );
998996
}
999997
}
1000998
}
@@ -1006,12 +1004,14 @@ QgsDataDefined QgsMarkerSymbolV2::dataDefinedAngle() const
10061004
QgsDataDefined* symbolDD = 0;
10071005

10081006
// find the base of the "en masse" pattern
1009-
for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1007+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
10101008
{
1011-
const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
1012-
if ( layer->angle() == symbolRotation && layer->getDataDefinedProperty( "angle" ) )
1009+
if ( layer->type() != QgsSymbolV2::Marker )
1010+
continue;
1011+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1012+
if ( markerLayer->angle() == symbolRotation && markerLayer->getDataDefinedProperty( "angle" ) )
10131013
{
1014-
symbolDD = layer->getDataDefinedProperty( "angle" );
1014+
symbolDD = markerLayer->getDataDefinedProperty( "angle" );
10151015
break;
10161016
}
10171017
}
@@ -1020,20 +1020,21 @@ QgsDataDefined QgsMarkerSymbolV2::dataDefinedAngle() const
10201020
return QgsDataDefined();
10211021

10221022
// check that all layer's angle expressions match the "en masse" pattern
1023-
for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1023+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
10241024
{
1025-
const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
1026-
1027-
QgsDataDefined* layerAngleDD = layer->getDataDefinedProperty( "angle" );
1025+
if ( layer->type() != QgsSymbolV2::Marker )
1026+
continue;
1027+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1028+
QgsDataDefined* layerAngleDD = markerLayer->getDataDefinedProperty( "angle" );
10281029

1029-
if ( qgsDoubleNear( layer->angle(), symbolRotation ) )
1030+
if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
10301031
{
10311032
if ( !layerAngleDD || *layerAngleDD != *symbolDD )
10321033
return QgsDataDefined();
10331034
}
10341035
else
10351036
{
1036-
QScopedPointer< QgsDataDefined > rotatedDD( rotateWholeSymbol( layer->angle() - symbolRotation, *symbolDD ) );
1037+
QScopedPointer< QgsDataDefined > rotatedDD( rotateWholeSymbol( markerLayer->angle() - symbolRotation, *symbolDD ) );
10371038
if ( !layerAngleDD || *layerAngleDD != *( rotatedDD.data() ) )
10381039
return QgsDataDefined();
10391040
}
@@ -1048,7 +1049,9 @@ void QgsMarkerSymbolV2::setSize( double s )
10481049

10491050
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
10501051
{
1051-
QgsMarkerSymbolLayerV2* markerLayer = dynamic_cast<QgsMarkerSymbolLayerV2*>( layer );
1052+
if ( layer->type() != QgsSymbolV2::Marker )
1053+
continue;
1054+
QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
10521055
if ( markerLayer->size() == origSize )
10531056
markerLayer->setSize( s );
10541057
else if ( origSize != 0 )
@@ -1067,10 +1070,12 @@ double QgsMarkerSymbolV2::size() const
10671070
{
10681071
// return size of the largest symbol
10691072
double maxSize = 0;
1070-
for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1073+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
10711074
{
1072-
const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
1073-
double lsize = layer->size();
1075+
if ( layer->type() != QgsSymbolV2::Marker )
1076+
continue;
1077+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1078+
double lsize = markerLayer->size();
10741079
if ( lsize > maxSize )
10751080
maxSize = lsize;
10761081
}
@@ -1083,7 +1088,9 @@ void QgsMarkerSymbolV2::setDataDefinedSize( const QgsDataDefined &dd )
10831088

10841089
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
10851090
{
1086-
QgsMarkerSymbolLayerV2* markerLayer = dynamic_cast<QgsMarkerSymbolLayerV2 *>( layer );
1091+
if ( layer->type() != QgsSymbolV2::Marker )
1092+
continue;
1093+
QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
10871094

10881095
if ( dd.hasDefaultValues() )
10891096
{
@@ -1118,12 +1125,14 @@ QgsDataDefined QgsMarkerSymbolV2::dataDefinedSize() const
11181125
QgsDataDefined* symbolDD = 0;
11191126

11201127
// find the base of the "en masse" pattern
1121-
for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1128+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
11221129
{
1123-
const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
1124-
if ( layer->size() == symbolSize && layer->getDataDefinedProperty( "size" ) )
1130+
if ( layer->type() != QgsSymbolV2::Marker )
1131+
continue;
1132+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1133+
if ( markerLayer->size() == symbolSize && markerLayer->getDataDefinedProperty( "size" ) )
11251134
{
1126-
symbolDD = layer->getDataDefinedProperty( "size" );
1135+
symbolDD = markerLayer->getDataDefinedProperty( "size" );
11271136
break;
11281137
}
11291138
}
@@ -1132,14 +1141,16 @@ QgsDataDefined QgsMarkerSymbolV2::dataDefinedSize() const
11321141
return QgsDataDefined();
11331142

11341143
// check that all layers size expressions match the "en masse" pattern
1135-
for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1144+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
11361145
{
1137-
const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
1146+
if ( layer->type() != QgsSymbolV2::Marker )
1147+
continue;
1148+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
11381149

1139-
QgsDataDefined* layerSizeDD = layer->getDataDefinedProperty( "size" );
1140-
QgsDataDefined* layerOffsetDD = layer->getDataDefinedProperty( "offset" );
1150+
QgsDataDefined* layerSizeDD = markerLayer->getDataDefinedProperty( "size" );
1151+
QgsDataDefined* layerOffsetDD = markerLayer->getDataDefinedProperty( "offset" );
11411152

1142-
if ( qgsDoubleNear( layer->size(), symbolSize ) )
1153+
if ( qgsDoubleNear( markerLayer->size(), symbolSize ) )
11431154
{
11441155
if ( !layerSizeDD || *layerSizeDD != *symbolDD )
11451156
return QgsDataDefined();
@@ -1149,12 +1160,12 @@ QgsDataDefined QgsMarkerSymbolV2::dataDefinedSize() const
11491160
if ( symbolSize == 0 )
11501161
return QgsDataDefined();
11511162

1152-
QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( layer->size() / symbolSize, *symbolDD ) );
1163+
QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( markerLayer->size() / symbolSize, *symbolDD ) );
11531164
if ( !layerSizeDD || *layerSizeDD != *( scaledDD.data() ) )
11541165
return QgsDataDefined();
11551166
}
11561167

1157-
QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( layer->offset().x() / symbolSize, layer->offset().y() / symbolSize, *symbolDD ) );
1168+
QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( markerLayer->offset().x() / symbolSize, markerLayer->offset().y() / symbolSize, *symbolDD ) );
11581169
if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
11591170
return QgsDataDefined();
11601171
}
@@ -1166,22 +1177,25 @@ void QgsMarkerSymbolV2::setScaleMethod( QgsSymbolV2::ScaleMethod scaleMethod )
11661177
{
11671178
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
11681179
{
1169-
QgsMarkerSymbolLayerV2* markerLayer = dynamic_cast<QgsMarkerSymbolLayerV2*>( layer );
1170-
if ( markerLayer )
1171-
markerLayer->setScaleMethod( scaleMethod );
1180+
if ( layer->type() != QgsSymbolV2::Marker )
1181+
continue;
1182+
QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1183+
markerLayer->setScaleMethod( scaleMethod );
11721184
}
11731185
}
11741186

11751187
QgsSymbolV2::ScaleMethod QgsMarkerSymbolV2::scaleMethod()
11761188
{
1177-
QgsSymbolLayerV2List::const_iterator it = mLayers.begin();
1178-
1179-
if ( it == mLayers.end() )
1180-
return DEFAULT_SCALE_METHOD;
1189+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1190+
{
1191+
if ( layer->type() != QgsSymbolV2::Marker )
1192+
continue;
1193+
const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1194+
// return scale method of the first symbol layer
1195+
return markerLayer->scaleMethod();
1196+
}
11811197

1182-
// return scale method of the first symbol layer
1183-
const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
1184-
return layer->scaleMethod();
1198+
return DEFAULT_SCALE_METHOD;
11851199
}
11861200

11871201
void QgsMarkerSymbolV2::renderPointUsingLayer( QgsMarkerSymbolLayerV2* layer, const QPointF& point, QgsSymbolV2RenderContext& context )
@@ -1241,12 +1255,16 @@ QRectF QgsMarkerSymbolV2::bounds( const QPointF& point, QgsRenderContext& contex
12411255
QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, 0, 0, mapUnitScale() );
12421256

12431257
QRectF bound;
1244-
for ( QgsSymbolLayerV2List::const_iterator it = mLayers.constBegin(); it != mLayers.constEnd(); ++it )
1258+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
12451259
{
1246-
if ( bound.isNull() )
1247-
bound = static_cast< QgsMarkerSymbolLayerV2* >( *it )->bounds( point, symbolContext );
1248-
else
1249-
bound = bound.united( static_cast< QgsMarkerSymbolLayerV2* >( *it )->bounds( point, symbolContext ) );
1260+
if ( layer->type() == QgsSymbolV2::Marker )
1261+
{
1262+
QgsMarkerSymbolLayerV2* symbolLayer = static_cast< QgsMarkerSymbolLayerV2* >( layer );
1263+
if ( bound.isNull() )
1264+
bound = symbolLayer->bounds( point, symbolContext );
1265+
else
1266+
bound = symbolLayer->bounds( point, symbolContext );
1267+
}
12501268
}
12511269
return bound;
12521270
}
@@ -1370,14 +1388,16 @@ QgsDataDefined QgsLineSymbolV2::dataDefinedWidth() const
13701388
return QgsDataDefined();
13711389

13721390
// check that all layers width expressions match the "en masse" pattern
1373-
for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1391+
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
13741392
{
1375-
const QgsLineSymbolLayerV2* layer = static_cast<const QgsLineSymbolLayerV2*>( *it );
1393+
if ( layer->type() != QgsSymbolV2::Line )
1394+
continue;
1395+
const QgsLineSymbolLayerV2* lineLayer = static_cast<const QgsLineSymbolLayerV2*>( layer );
13761396

1377-
QgsDataDefined* layerWidthDD = layer->getDataDefinedProperty( "width" );
1378-
QgsDataDefined* layerOffsetDD = layer->getDataDefinedProperty( "offset" );
1397+
QgsDataDefined* layerWidthDD = lineLayer->getDataDefinedProperty( "width" );
1398+
QgsDataDefined* layerOffsetDD = lineLayer->getDataDefinedProperty( "offset" );
13791399

1380-
if ( qgsDoubleNear( layer->width(), symbolWidth ) )
1400+
if ( qgsDoubleNear( lineLayer->width(), symbolWidth ) )
13811401
{
13821402
if ( !layerWidthDD || *layerWidthDD != *symbolDD )
13831403
return QgsDataDefined();
@@ -1387,12 +1407,12 @@ QgsDataDefined QgsLineSymbolV2::dataDefinedWidth() const
13871407
if ( symbolWidth == 0 )
13881408
return QgsDataDefined();
13891409

1390-
QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( layer->width() / symbolWidth, *symbolDD ) );
1410+
QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( lineLayer->width() / symbolWidth, *symbolDD ) );
13911411
if ( !layerWidthDD || *layerWidthDD != *( scaledDD.data() ) )
13921412
return QgsDataDefined();
13931413
}
13941414

1395-
QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( layer->offset() / symbolWidth, *symbolDD ) );
1415+
QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( lineLayer->offset() / symbolWidth, *symbolDD ) );
13961416
if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
13971417
return QgsDataDefined();
13981418
}
@@ -1422,7 +1442,9 @@ void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, const QgsFeature*
14221442

14231443
Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
14241444
{
1425-
QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1445+
if ( symbolLayer->type() != QgsSymbolV2::Line )
1446+
continue;
1447+
QgsLineSymbolLayerV2* lineLayer = static_cast<QgsLineSymbolLayerV2*>( symbolLayer );
14261448

14271449
if ( lineLayer )
14281450
renderPolylineUsingLayer( lineLayer, points, symbolContext );
@@ -1480,9 +1502,9 @@ void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>*
14801502

14811503
if ( layerIdx != -1 )
14821504
{
1483-
if ( layerIdx >= 0 && layerIdx < mLayers.count() )
1505+
QgsSymbolLayerV2* layer = mLayers.value( layerIdx );
1506+
if ( layer )
14841507
{
1485-
QgsSymbolLayerV2* layer = mLayers.at( layerIdx );
14861508
if ( layer->type() == Fill || layer->type() == Line )
14871509
renderPolygonUsingLayer( layer, points, rings, symbolContext );
14881510
else
@@ -1582,7 +1604,10 @@ void QgsFillSymbolV2::setAngle( double angle )
15821604
{
15831605
Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
15841606
{
1585-
QgsFillSymbolLayerV2* fillLayer = dynamic_cast<QgsFillSymbolLayerV2*>( layer );
1607+
if ( layer->type() != QgsSymbolV2::Fill )
1608+
continue;
1609+
1610+
QgsFillSymbolLayerV2* fillLayer = static_cast<QgsFillSymbolLayerV2*>( layer );
15861611

15871612
if ( fillLayer )
15881613
fillLayer->setAngle( angle );

0 commit comments

Comments
 (0)