@@ -1237,7 +1237,7 @@ void QgsSVGFillSymbolLayer::prepareExpressions( const QgsVectorLayer* vl )
12371237}
12381238
12391239QgsLinePatternFillSymbolLayer::QgsLinePatternFillSymbolLayer (): QgsImageFillSymbolLayer(), mDistanceUnit( QgsSymbolV2::MM ), mLineWidthUnit( QgsSymbolV2::MM ),
1240- mOffsetUnit( QgsSymbolV2::MM )
1240+ mOffsetUnit( QgsSymbolV2::MM ), mLineAngleExpression( 0 ), mDistanceExpression( 0 ), mLineWidthExpression( 0 ), mColorExpression( 0 )
12411241{
12421242}
12431243
@@ -1316,6 +1316,24 @@ QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::create( const QgsStringMap& pro
13161316 {
13171317 patternLayer->setOffsetUnit ( QgsSymbolLayerV2Utils::decodeOutputUnit ( properties[" offset_unit" ] ) );
13181318 }
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+ }
13191337 return patternLayer;
13201338}
13211339
@@ -1324,24 +1342,25 @@ QString QgsLinePatternFillSymbolLayer::layerType() const
13241342 return " LinePatternFill" ;
13251343}
13261344
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 )
13281347{
13291348 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 );
13321351 double outputPixelOffset = mOffset * QgsSymbolLayerV2Utils::pixelSizeScaleFactor ( ctx, mOffsetUnit );
13331352
13341353 // create image
13351354 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 ) )
13371356 {
13381357 height = outputPixelDist;
13391358 width = height; // width can be set to arbitrary value
13401359 }
13411360 else
13421361 {
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 ) );
13451364 }
13461365
13471366 // 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
13601379 QPainter p ( &patternImage );
13611380
13621381 p.setRenderHint ( QPainter::Antialiasing, true );
1363- QPen pen ( mColor );
1382+ QPen pen ( color );
13641383 pen.setWidthF ( outlinePixelWidth );
13651384 pen.setCapStyle ( Qt::FlatCap );
13661385 p.setPen ( pen );
13671386
13681387 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 ) )
13701389 {
13711390 p1 = QPoint ( 0 , height );
13721391 p2 = QPoint ( width, height );
@@ -1375,7 +1394,7 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& conte
13751394 p5 = QPoint ( 0 , 2 * height );
13761395 p6 = QPoint ( width, 2 * height );
13771396 }
1378- else if ( doubleNear ( mLineAngle , 90.0 ) || doubleNear ( mLineAngle , 270.0 ) )
1397+ else if ( doubleNear ( lineAngle , 90.0 ) || doubleNear ( lineAngle , 270.0 ) )
13791398 {
13801399 p1 = QPoint ( 0 , height );
13811400 p2 = QPoint ( 0 , 0 );
@@ -1384,21 +1403,21 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& conte
13841403 p5 = QPoint ( -width, height );
13851404 p6 = QPoint ( -width, 0 );
13861405 }
1387- else if (( mLineAngle > 0 && mLineAngle < 90 ) || ( mLineAngle > 180 && mLineAngle < 270 ) )
1406+ else if (( lineAngle > 0 && lineAngle < 90 ) || ( lineAngle > 180 && lineAngle < 270 ) )
13881407 {
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 );
13911410 p1 = QPoint ( 0 , height );
13921411 p2 = QPoint ( width, 0 );
13931412 p3 = QPoint ( -dx, height - dy );
13941413 p4 = QPoint ( width - dx, -dy ); // p4 = QPoint( p3.x() + width, p3.y() - height );
13951414 p5 = QPoint ( dx, height + dy );
13961415 p6 = QPoint ( width + dx, dy ); // p6 = QPoint( p5.x() + width, p5.y() - height );
13971416 }
1398- else if (( mLineAngle < 180 ) || ( mLineAngle > 270 && mLineAngle < 360 ) )
1417+ else if (( lineAngle < 180 ) || ( lineAngle > 270 && lineAngle < 360 ) )
13991418 {
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 );
14021421 p1 = QPoint ( width, height );
14031422 p2 = QPoint ( 0 , 0 );
14041423 p5 = QPoint ( width + dx, height - dy );
@@ -1436,21 +1455,28 @@ void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& conte
14361455 {
14371456 QImage transparentImage = patternImage.copy ();
14381457 QgsSymbolLayerV2Utils::multiplyImageOpacity ( &transparentImage, context.alpha () );
1439- mBrush .setTextureImage ( transparentImage );
1458+ brush .setTextureImage ( transparentImage );
14401459 }
14411460 else
14421461 {
1443- mBrush .setTextureImage ( patternImage );
1462+ brush .setTextureImage ( patternImage );
14441463 }
14451464
14461465 QTransform brushTransform;
14471466 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 );
14491473
14501474 if ( mOutline )
14511475 {
14521476 mOutline ->startRender ( context.renderContext () );
14531477 }
1478+
1479+ prepareExpressions ( context.layer () );
14541480}
14551481
14561482void QgsLinePatternFillSymbolLayer::stopRender ( QgsSymbolV2RenderContext & )
@@ -1468,6 +1494,25 @@ QgsStringMap QgsLinePatternFillSymbolLayer::properties() const
14681494 map.insert ( " distance_unit" , QgsSymbolLayerV2Utils::encodeOutputUnit ( mDistanceUnit ) );
14691495 map.insert ( " line_width_unit" , QgsSymbolLayerV2Utils::encodeOutputUnit ( mLineWidthUnit ) );
14701496 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+
14711516 return map;
14721517}
14731518
@@ -1481,6 +1526,24 @@ QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::clone() const
14811526 clonedLayer->setDistanceUnit ( mDistanceUnit );
14821527 clonedLayer->setLineWidthUnit ( mLineWidthUnit );
14831528 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+
14841547 return clonedLayer;
14851548}
14861549
@@ -1547,6 +1610,152 @@ QString QgsLinePatternFillSymbolLayer::ogrFeatureStyleWidth( double widthScaleFa
15471610 return featureStyle;
15481611}
15491612
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+
15501759QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::createFromSld ( QDomElement &element )
15511760{
15521761 QgsDebugMsg ( " Entered." );
0 commit comments