@@ -1237,7 +1237,7 @@ void QgsSVGFillSymbolLayer::prepareExpressions( const QgsVectorLayer* vl )
1237
1237
}
1238
1238
1239
1239
QgsLinePatternFillSymbolLayer::QgsLinePatternFillSymbolLayer (): QgsImageFillSymbolLayer(), mDistanceUnit( QgsSymbolV2::MM ), mLineWidthUnit( QgsSymbolV2::MM ),
1240
- mOffsetUnit( QgsSymbolV2::MM )
1240
+ mOffsetUnit( QgsSymbolV2::MM ), mLineAngleExpression( 0 ), mDistanceExpression( 0 ), mLineWidthExpression( 0 ), mColorExpression( 0 )
1241
1241
{
1242
1242
}
1243
1243
@@ -1316,6 +1316,24 @@ QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::create( const QgsStringMap& pro
1316
1316
{
1317
1317
patternLayer->setOffsetUnit ( QgsSymbolLayerV2Utils::decodeOutputUnit ( properties[" offset_unit" ] ) );
1318
1318
}
1319
+
1320
+ // data defined properties
1321
+ if ( properties.contains ( " lineangle_expression" ) )
1322
+ {
1323
+ patternLayer->setDataDefinedProperty ( " lineangle" , properties[" lineangle_expression" ] );
1324
+ }
1325
+ if ( properties.contains ( " distance_expression" ) )
1326
+ {
1327
+ patternLayer->setDataDefinedProperty ( " distance" , properties[" distance_expression" ] );
1328
+ }
1329
+ if ( properties.contains ( " linewidth_expression" ) )
1330
+ {
1331
+ patternLayer->setDataDefinedProperty ( " linewidth" , properties[" linewidth_expression" ] );
1332
+ }
1333
+ if ( properties.contains ( " color_expression" ) )
1334
+ {
1335
+ patternLayer->setDataDefinedProperty ( " color" , properties[" color_expression" ] );
1336
+ }
1319
1337
return patternLayer;
1320
1338
}
1321
1339
@@ -1324,24 +1342,25 @@ QString QgsLinePatternFillSymbolLayer::layerType() const
1324
1342
return " LinePatternFill" ;
1325
1343
}
1326
1344
1327
- void QgsLinePatternFillSymbolLayer::startRender ( QgsSymbolV2RenderContext& context )
1345
+ void QgsLinePatternFillSymbolLayer::applyPattern ( const QgsSymbolV2RenderContext& context, QBrush& brush, double lineAngle, double distance,
1346
+ double lineWidth, const QColor& color )
1328
1347
{
1329
1348
const QgsRenderContext& ctx = context.renderContext ();
1330
- double outlinePixelWidth = mLineWidth * QgsSymbolLayerV2Utils::pixelSizeScaleFactor ( ctx, mLineWidthUnit );
1331
- double outputPixelDist = mDistance * QgsSymbolLayerV2Utils::pixelSizeScaleFactor ( ctx, mDistanceUnit );
1349
+ double outlinePixelWidth = lineWidth * QgsSymbolLayerV2Utils::pixelSizeScaleFactor ( ctx, mLineWidthUnit );
1350
+ double outputPixelDist = distance * QgsSymbolLayerV2Utils::pixelSizeScaleFactor ( ctx, mDistanceUnit );
1332
1351
double outputPixelOffset = mOffset * QgsSymbolLayerV2Utils::pixelSizeScaleFactor ( ctx, mOffsetUnit );
1333
1352
1334
1353
// create image
1335
1354
int height, width;
1336
- if ( doubleNear ( mLineAngle , 0 ) || doubleNear ( mLineAngle , 360 ) || doubleNear ( mLineAngle , 90 ) || doubleNear ( mLineAngle , 180 ) || doubleNear ( mLineAngle , 270 ) )
1355
+ if ( doubleNear ( lineAngle , 0 ) || doubleNear ( lineAngle , 360 ) || doubleNear ( lineAngle , 90 ) || doubleNear ( lineAngle , 180 ) || doubleNear ( lineAngle , 270 ) )
1337
1356
{
1338
1357
height = outputPixelDist;
1339
1358
width = height; // width can be set to arbitrary value
1340
1359
}
1341
1360
else
1342
1361
{
1343
- height = qAbs ( outputPixelDist / cos ( mLineAngle * M_PI / 180 ) ); // keep perpendicular distance between lines constant
1344
- width = qAbs ( height / tan ( mLineAngle * M_PI / 180 ) );
1362
+ height = qAbs ( outputPixelDist / cos ( lineAngle * M_PI / 180 ) ); // keep perpendicular distance between lines constant
1363
+ width = qAbs ( height / tan ( lineAngle * M_PI / 180 ) );
1345
1364
}
1346
1365
1347
1366
// depending on the angle, we might need to render into a larger image and use a subset of it
@@ -1360,13 +1379,13 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& conte
1360
1379
QPainter p ( &patternImage );
1361
1380
1362
1381
p.setRenderHint ( QPainter::Antialiasing, true );
1363
- QPen pen ( mColor );
1382
+ QPen pen ( color );
1364
1383
pen.setWidthF ( outlinePixelWidth );
1365
1384
pen.setCapStyle ( Qt::FlatCap );
1366
1385
p.setPen ( pen );
1367
1386
1368
1387
QPoint p1, p2, p3, p4, p5, p6;
1369
- if ( doubleNear ( mLineAngle , 0.0 ) || doubleNear ( mLineAngle , 360.0 ) || doubleNear ( mLineAngle , 180.0 ) )
1388
+ if ( doubleNear ( lineAngle , 0.0 ) || doubleNear ( lineAngle , 360.0 ) || doubleNear ( lineAngle , 180.0 ) )
1370
1389
{
1371
1390
p1 = QPoint ( 0 , height );
1372
1391
p2 = QPoint ( width, height );
@@ -1375,7 +1394,7 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& conte
1375
1394
p5 = QPoint ( 0 , 2 * height );
1376
1395
p6 = QPoint ( width, 2 * height );
1377
1396
}
1378
- else if ( doubleNear ( mLineAngle , 90.0 ) || doubleNear ( mLineAngle , 270.0 ) )
1397
+ else if ( doubleNear ( lineAngle , 90.0 ) || doubleNear ( lineAngle , 270.0 ) )
1379
1398
{
1380
1399
p1 = QPoint ( 0 , height );
1381
1400
p2 = QPoint ( 0 , 0 );
@@ -1384,21 +1403,21 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& conte
1384
1403
p5 = QPoint ( -width, height );
1385
1404
p6 = QPoint ( -width, 0 );
1386
1405
}
1387
- else if (( mLineAngle > 0 && mLineAngle < 90 ) || ( mLineAngle > 180 && mLineAngle < 270 ) )
1406
+ else if (( lineAngle > 0 && lineAngle < 90 ) || ( lineAngle > 180 && lineAngle < 270 ) )
1388
1407
{
1389
- dx = outputPixelDist * cos (( 90 - mLineAngle ) * M_PI / 180.0 );
1390
- dy = outputPixelDist * sin (( 90 - mLineAngle ) * M_PI / 180.0 );
1408
+ dx = outputPixelDist * cos (( 90 - lineAngle ) * M_PI / 180.0 );
1409
+ dy = outputPixelDist * sin (( 90 - lineAngle ) * M_PI / 180.0 );
1391
1410
p1 = QPoint ( 0 , height );
1392
1411
p2 = QPoint ( width, 0 );
1393
1412
p3 = QPoint ( -dx, height - dy );
1394
1413
p4 = QPoint ( width - dx, -dy ); // p4 = QPoint( p3.x() + width, p3.y() - height );
1395
1414
p5 = QPoint ( dx, height + dy );
1396
1415
p6 = QPoint ( width + dx, dy ); // p6 = QPoint( p5.x() + width, p5.y() - height );
1397
1416
}
1398
- else if (( mLineAngle < 180 ) || ( mLineAngle > 270 && mLineAngle < 360 ) )
1417
+ else if (( lineAngle < 180 ) || ( lineAngle > 270 && lineAngle < 360 ) )
1399
1418
{
1400
- dy = outputPixelDist * cos (( 180 - mLineAngle ) * M_PI / 180 );
1401
- dx = outputPixelDist * sin (( 180 - mLineAngle ) * M_PI / 180 );
1419
+ dy = outputPixelDist * cos (( 180 - lineAngle ) * M_PI / 180 );
1420
+ dx = outputPixelDist * sin (( 180 - lineAngle ) * M_PI / 180 );
1402
1421
p1 = QPoint ( width, height );
1403
1422
p2 = QPoint ( 0 , 0 );
1404
1423
p5 = QPoint ( width + dx, height - dy );
@@ -1436,21 +1455,28 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& conte
1436
1455
{
1437
1456
QImage transparentImage = patternImage.copy ();
1438
1457
QgsSymbolLayerV2Utils::multiplyImageOpacity ( &transparentImage, context.alpha () );
1439
- mBrush .setTextureImage ( transparentImage );
1458
+ brush .setTextureImage ( transparentImage );
1440
1459
}
1441
1460
else
1442
1461
{
1443
- mBrush .setTextureImage ( patternImage );
1462
+ brush .setTextureImage ( patternImage );
1444
1463
}
1445
1464
1446
1465
QTransform brushTransform;
1447
1466
brushTransform.scale ( 1.0 / context.renderContext ().rasterScaleFactor (), 1.0 / context.renderContext ().rasterScaleFactor () );
1448
- mBrush .setTransform ( brushTransform );
1467
+ brush.setTransform ( brushTransform );
1468
+ }
1469
+
1470
+ void QgsLinePatternFillSymbolLayer::startRender ( QgsSymbolV2RenderContext& context )
1471
+ {
1472
+ applyPattern ( context, mBrush , mLineAngle , mDistance , mLineWidth , mColor );
1449
1473
1450
1474
if ( mOutline )
1451
1475
{
1452
1476
mOutline ->startRender ( context.renderContext () );
1453
1477
}
1478
+
1479
+ prepareExpressions ( context.layer () );
1454
1480
}
1455
1481
1456
1482
void QgsLinePatternFillSymbolLayer::stopRender ( QgsSymbolV2RenderContext & )
@@ -1468,6 +1494,25 @@ QgsStringMap QgsLinePatternFillSymbolLayer::properties() const
1468
1494
map.insert ( " distance_unit" , QgsSymbolLayerV2Utils::encodeOutputUnit ( mDistanceUnit ) );
1469
1495
map.insert ( " line_width_unit" , QgsSymbolLayerV2Utils::encodeOutputUnit ( mLineWidthUnit ) );
1470
1496
map.insert ( " offset_unit" , QgsSymbolLayerV2Utils::encodeOutputUnit ( mOffsetUnit ) );
1497
+
1498
+ // data defined properties
1499
+ if ( mLineAngleExpression )
1500
+ {
1501
+ map.insert ( " lineangle_expression" , mLineAngleExpression ->dump () );
1502
+ }
1503
+ if ( mDistanceExpression )
1504
+ {
1505
+ map.insert ( " distance_expression" , mDistanceExpression ->dump () );
1506
+ }
1507
+ if ( mLineWidthExpression )
1508
+ {
1509
+ map.insert ( " linewidth_expression" , mLineWidthExpression ->dump () );
1510
+ }
1511
+ if ( mColorExpression )
1512
+ {
1513
+ map.insert ( " color_expression" , mColorExpression ->dump () );
1514
+ }
1515
+
1471
1516
return map;
1472
1517
}
1473
1518
@@ -1481,6 +1526,24 @@ QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::clone() const
1481
1526
clonedLayer->setDistanceUnit ( mDistanceUnit );
1482
1527
clonedLayer->setLineWidthUnit ( mLineWidthUnit );
1483
1528
clonedLayer->setOffsetUnit ( mOffsetUnit );
1529
+
1530
+ if ( mLineAngleExpression )
1531
+ {
1532
+ clonedLayer->setDataDefinedProperty ( " lineangle" , mLineAngleExpression ->dump () );
1533
+ }
1534
+ if ( mDistanceExpression )
1535
+ {
1536
+ clonedLayer->setDataDefinedProperty ( " distance" , mDistanceExpression ->dump () );
1537
+ }
1538
+ if ( mLineWidthExpression )
1539
+ {
1540
+ clonedLayer->setDataDefinedProperty ( " linewidth" , mLineWidthExpression ->dump () );
1541
+ }
1542
+ if ( mColorExpression )
1543
+ {
1544
+ clonedLayer->setDataDefinedProperty ( " color" , mColorExpression ->dump () );
1545
+ }
1546
+
1484
1547
return clonedLayer;
1485
1548
}
1486
1549
@@ -1547,6 +1610,152 @@ QString QgsLinePatternFillSymbolLayer::ogrFeatureStyleWidth( double widthScaleFa
1547
1610
return featureStyle;
1548
1611
}
1549
1612
1613
+ const QgsExpression* QgsLinePatternFillSymbolLayer::dataDefinedProperty ( const QString& property ) const
1614
+ {
1615
+ if ( property == " lineangle" )
1616
+ {
1617
+ return mLineAngleExpression ;
1618
+ }
1619
+ else if ( property == " distance" )
1620
+ {
1621
+ return mDistanceExpression ;
1622
+ }
1623
+ else if ( property == " linewidth" )
1624
+ {
1625
+ return mLineWidthExpression ;
1626
+ }
1627
+ else if ( property == " color" )
1628
+ {
1629
+ return mColorExpression ;
1630
+ }
1631
+ return 0 ;
1632
+ }
1633
+
1634
+ QString QgsLinePatternFillSymbolLayer::dataDefinedPropertyString ( const QString& property ) const
1635
+ {
1636
+ const QgsExpression* ex = dataDefinedProperty ( property );
1637
+ return ex ? ex->dump () : QString ();
1638
+ }
1639
+
1640
+ void QgsLinePatternFillSymbolLayer::setDataDefinedProperty ( const QString& property, const QString& expressionString )
1641
+ {
1642
+ if ( property == " lineangle" )
1643
+ {
1644
+ delete mLineAngleExpression ; mLineAngleExpression = new QgsExpression ( expressionString );
1645
+ }
1646
+ else if ( property == " distance" )
1647
+ {
1648
+ delete mDistanceExpression ; mDistanceExpression = new QgsExpression ( expressionString );
1649
+ }
1650
+ else if ( property == " linewidth" )
1651
+ {
1652
+ delete mLineWidthExpression ; mLineWidthExpression = new QgsExpression ( expressionString );
1653
+ }
1654
+ else if ( property == " color" )
1655
+ {
1656
+ delete mColorExpression ; mColorExpression = new QgsExpression ( expressionString );
1657
+ }
1658
+ }
1659
+
1660
+ void QgsLinePatternFillSymbolLayer::removeDataDefinedProperty ( const QString& property )
1661
+ {
1662
+ if ( property == " lineangle" )
1663
+ {
1664
+ delete mLineAngleExpression ; mLineAngleExpression = 0 ;
1665
+ }
1666
+ else if ( property == " distance" )
1667
+ {
1668
+ delete mDistanceExpression ; mDistanceExpression = 0 ;
1669
+ }
1670
+ else if ( property == " linewidth" )
1671
+ {
1672
+ delete mLineWidthExpression ; mLineWidthExpression = 0 ;
1673
+ }
1674
+ else if ( property == " color" )
1675
+ {
1676
+ delete mColorExpression ; mColorExpression = 0 ;
1677
+ }
1678
+ }
1679
+
1680
+ void QgsLinePatternFillSymbolLayer::removeDataDefinedProperties ()
1681
+ {
1682
+ delete mLineAngleExpression ; mLineAngleExpression = 0 ;
1683
+ delete mDistanceExpression ; mDistanceExpression = 0 ;
1684
+ delete mLineWidthExpression ; mLineWidthExpression = 0 ;
1685
+ delete mColorExpression ; mColorExpression = 0 ;
1686
+ }
1687
+
1688
+ QSet<QString> QgsLinePatternFillSymbolLayer::usedAttributes () const
1689
+ {
1690
+ QSet<QString> attributes;
1691
+
1692
+ // add data defined attributes
1693
+ QStringList columns;
1694
+ if ( mLineAngleExpression )
1695
+ columns.append ( mLineAngleExpression ->referencedColumns () );
1696
+ if ( mDistanceExpression )
1697
+ columns.append ( mDistanceExpression ->referencedColumns () );
1698
+ if ( mLineWidthExpression )
1699
+ columns.append ( mLineWidthExpression ->referencedColumns () );
1700
+ if ( mColorExpression )
1701
+ columns.append ( mColorExpression ->referencedColumns () );
1702
+
1703
+ QStringList::const_iterator it = columns.constBegin ();
1704
+ for ( ; it != columns.constEnd (); ++it )
1705
+ {
1706
+ attributes.insert ( *it );
1707
+ }
1708
+ return attributes;
1709
+ }
1710
+
1711
+ void QgsLinePatternFillSymbolLayer::applyDataDefinedSettings ( const QgsSymbolV2RenderContext& context )
1712
+ {
1713
+ if ( !mLineAngleExpression && !mDistanceExpression && !mLineWidthExpression && !mColorExpression )
1714
+ {
1715
+ return ; // no data defined settings
1716
+ }
1717
+
1718
+ double lineAngle = mLineAngle ;
1719
+ if ( mLineAngleExpression )
1720
+ {
1721
+ lineAngle = mLineAngleExpression ->evaluate ( const_cast <QgsFeature*>( context.feature () ) ).toDouble ();
1722
+ }
1723
+ double distance = mDistance ;
1724
+ if ( mDistanceExpression )
1725
+ {
1726
+ distance = mDistanceExpression ->evaluate ( const_cast <QgsFeature*>( context.feature () ) ).toDouble ();
1727
+ }
1728
+ double lineWidth = mLineWidth ;
1729
+ if ( mLineWidthExpression )
1730
+ {
1731
+ lineWidth = mLineWidthExpression ->evaluate ( const_cast <QgsFeature*>( context.feature () ) ).toDouble ();
1732
+ }
1733
+ QColor color = mColor ;
1734
+ if ( mColorExpression )
1735
+ {
1736
+ color = QColor ( mColorExpression ->evaluate ( const_cast <QgsFeature*>( context.feature () ) ).toString () );
1737
+ }
1738
+ applyPattern ( context, mBrush , lineAngle, distance, lineWidth, color );
1739
+ }
1740
+
1741
+ void QgsLinePatternFillSymbolLayer::prepareExpressions ( const QgsVectorLayer* vl )
1742
+ {
1743
+ if ( !vl )
1744
+ {
1745
+ return ;
1746
+ }
1747
+
1748
+ const QgsFields& fields = vl->pendingFields ();
1749
+ if ( mLineAngleExpression )
1750
+ mLineAngleExpression ->prepare ( fields );
1751
+ if ( mDistanceExpression )
1752
+ mDistanceExpression ->prepare ( fields );
1753
+ if ( mLineWidthExpression )
1754
+ mLineWidthExpression ->prepare ( fields );
1755
+ if ( mColorExpression )
1756
+ mColorExpression ->prepare ( fields );
1757
+ }
1758
+
1550
1759
QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::createFromSld ( QDomElement &element )
1551
1760
{
1552
1761
QgsDebugMsg ( " Entered." );
0 commit comments