@@ -250,47 +250,76 @@ void QgsEllipseSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2Rend
250
250
preparePath ( symbolName, context, &scaledWidth, &scaledHeight, context.feature () );
251
251
}
252
252
253
- // offset
254
- double offsetX = 0 ;
255
- double offsetY = 0 ;
256
- markerOffset ( context, scaledWidth, scaledHeight, mSymbolWidthUnit , mSymbolHeightUnit , offsetX, offsetY, mSymbolWidthMapUnitScale , mSymbolHeightMapUnitScale ) ;
257
- QPointF off ( offsetX, offsetY );
253
+ // offset and rotation
254
+ bool hasDataDefinedRotation = false ;
255
+ QPointF offset ;
256
+ double angle = 0 ;
257
+ calculateOffsetAndRotation ( context, scaledWidth, scaledHeight, hasDataDefinedRotation, offset, angle );
258
258
259
259
QPainter* p = context.renderContext ().painter ();
260
260
if ( !p )
261
261
{
262
262
return ;
263
263
}
264
264
265
- // priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
266
- double rotation = 0.0 ;
267
-
268
- if ( hasDataDefinedProperty ( QgsSymbolLayerV2::EXPR_ROTATION ) )
265
+ QMatrix transform;
266
+ transform.translate ( point.x () + offset.x (), point.y () + offset.y () );
267
+ if ( !qgsDoubleNear ( angle, 0.0 ) )
269
268
{
270
- context.setOriginalValueVariable ( mAngle );
271
- rotation = evaluateDataDefinedProperty ( QgsSymbolLayerV2::EXPR_ROTATION, context, mAngle ).toDouble () + mLineAngle ;
272
-
273
- const QgsMapToPixel& m2p = context.renderContext ().mapToPixel ();
274
- rotation += m2p.mapRotation ();
269
+ transform.rotate ( angle );
275
270
}
276
- else if ( !qgsDoubleNear ( mAngle + mLineAngle , 0.0 ) )
271
+
272
+ p->setPen ( mPen );
273
+ p->setBrush ( mBrush );
274
+ p->drawPath ( transform.map ( mPainterPath ) );
275
+ }
276
+
277
+
278
+ void QgsEllipseSymbolLayerV2::calculateOffsetAndRotation ( QgsSymbolV2RenderContext& context,
279
+ double scaledWidth,
280
+ double scaledHeight,
281
+ bool & hasDataDefinedRotation,
282
+ QPointF& offset,
283
+ double & angle ) const
284
+ {
285
+ double offsetX = 0 ;
286
+ double offsetY = 0 ;
287
+ markerOffset ( context, scaledWidth, scaledHeight, mSymbolWidthUnit , mSymbolHeightUnit , offsetX, offsetY, mSymbolWidthMapUnitScale , mSymbolHeightMapUnitScale );
288
+ offset = QPointF ( offsetX, offsetY );
289
+
290
+ // priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
291
+ bool ok = true ;
292
+ angle = mAngle + mLineAngle ;
293
+ bool usingDataDefinedRotation = false ;
294
+ if ( hasDataDefinedProperty ( QgsSymbolLayerV2::EXPR_ROTATION ) )
277
295
{
278
- rotation = mAngle + mLineAngle ;
296
+ context.setOriginalValueVariable ( angle );
297
+ angle = evaluateDataDefinedProperty ( QgsSymbolLayerV2::EXPR_ROTATION, context, mAngle , &ok ).toDouble () + mLineAngle ;
298
+ usingDataDefinedRotation = ok;
279
299
}
280
300
281
- if ( rotation )
282
- off = _rotatedOffset ( off, rotation );
283
-
284
- QMatrix transform;
285
- transform.translate ( point.x () + off.x (), point.y () + off.y () );
286
- if ( !qgsDoubleNear ( rotation, 0.0 ) )
301
+ hasDataDefinedRotation = context.renderHints () & QgsSymbolV2::DataDefinedRotation || usingDataDefinedRotation;
302
+ if ( hasDataDefinedRotation )
287
303
{
288
- transform.rotate ( rotation );
304
+ // For non-point markers, "dataDefinedRotation" means following the
305
+ // shape (shape-data defined). For them, "field-data defined" does
306
+ // not work at all. TODO: if "field-data defined" ever gets implemented
307
+ // we'll need a way to distinguish here between the two, possibly
308
+ // using another flag in renderHints()
309
+ const QgsFeature* f = context.feature ();
310
+ if ( f )
311
+ {
312
+ const QgsGeometry *g = f->constGeometry ();
313
+ if ( g && g->type () == QGis::Point )
314
+ {
315
+ const QgsMapToPixel& m2p = context.renderContext ().mapToPixel ();
316
+ angle += m2p.mapRotation ();
317
+ }
318
+ }
289
319
}
290
320
291
- p->setPen ( mPen );
292
- p->setBrush ( mBrush );
293
- p->drawPath ( transform.map ( mPainterPath ) );
321
+ if ( angle )
322
+ offset = _rotatedOffset ( offset, angle );
294
323
}
295
324
296
325
QString QgsEllipseSymbolLayerV2::layerType () const
@@ -465,11 +494,8 @@ QgsStringMap QgsEllipseSymbolLayerV2::properties() const
465
494
return map;
466
495
}
467
496
468
- void QgsEllipseSymbolLayerV2::preparePath ( const QString& symbolName, QgsSymbolV2RenderContext& context, double * scaledWidth, double * scaledHeight, const QgsFeature* )
497
+ QSizeF QgsEllipseSymbolLayerV2::calculateSize ( QgsSymbolV2RenderContext& context, double * scaledWidth, double * scaledHeight )
469
498
{
470
- mPainterPath = QPainterPath ();
471
- const QgsRenderContext& ct = context.renderContext ();
472
-
473
499
double width = 0 ;
474
500
475
501
if ( hasDataDefinedProperty ( QgsSymbolLayerV2::EXPR_WIDTH ) ) // 1. priority: data defined setting on symbol layer le
@@ -489,7 +515,7 @@ void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV
489
515
{
490
516
*scaledWidth = width;
491
517
}
492
- width = QgsSymbolLayerV2Utils::convertToPainterUnits ( ct , width, mSymbolWidthUnit , mSymbolHeightMapUnitScale );
518
+ width = QgsSymbolLayerV2Utils::convertToPainterUnits ( context. renderContext () , width, mSymbolWidthUnit , mSymbolHeightMapUnitScale );
493
519
494
520
double height = 0 ;
495
521
if ( hasDataDefinedProperty ( QgsSymbolLayerV2::EXPR_HEIGHT ) ) // 1. priority: data defined setting on symbol layer level
@@ -509,29 +535,37 @@ void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV
509
535
{
510
536
*scaledHeight = height;
511
537
}
512
- height = QgsSymbolLayerV2Utils::convertToPainterUnits ( ct, height, mSymbolHeightUnit , mSymbolHeightMapUnitScale );
538
+ height = QgsSymbolLayerV2Utils::convertToPainterUnits ( context.renderContext (), height, mSymbolHeightUnit , mSymbolHeightMapUnitScale );
539
+ return QSizeF ( width, height );
540
+ }
541
+
542
+ void QgsEllipseSymbolLayerV2::preparePath ( const QString& symbolName, QgsSymbolV2RenderContext& context, double * scaledWidth, double * scaledHeight, const QgsFeature* )
543
+ {
544
+ mPainterPath = QPainterPath ();
545
+
546
+ QSizeF size = calculateSize ( context, scaledWidth, scaledHeight );
513
547
514
548
if ( symbolName == " circle" )
515
549
{
516
- mPainterPath .addEllipse ( QRectF ( -width / 2.0 , -height / 2.0 , width, height ) );
550
+ mPainterPath .addEllipse ( QRectF ( -size. width () / 2.0 , -size. height () / 2.0 , size. width (), size. height () ) );
517
551
}
518
552
else if ( symbolName == " rectangle" )
519
553
{
520
- mPainterPath .addRect ( QRectF ( -width / 2.0 , -height / 2.0 , width, height ) );
554
+ mPainterPath .addRect ( QRectF ( -size. width () / 2.0 , -size. height () / 2.0 , size. width (), size. height () ) );
521
555
}
522
556
else if ( symbolName == " cross" )
523
557
{
524
- mPainterPath .moveTo ( 0 , -height / 2.0 );
525
- mPainterPath .lineTo ( 0 , height / 2.0 );
526
- mPainterPath .moveTo ( -width / 2.0 , 0 );
527
- mPainterPath .lineTo ( width / 2.0 , 0 );
558
+ mPainterPath .moveTo ( 0 , -size. height () / 2.0 );
559
+ mPainterPath .lineTo ( 0 , size. height () / 2.0 );
560
+ mPainterPath .moveTo ( -size. width () / 2.0 , 0 );
561
+ mPainterPath .lineTo ( size. width () / 2.0 , 0 );
528
562
}
529
563
else if ( symbolName == " triangle" )
530
564
{
531
- mPainterPath .moveTo ( 0 , -height / 2.0 );
532
- mPainterPath .lineTo ( -width / 2.0 , height / 2.0 );
533
- mPainterPath .lineTo ( width / 2.0 , height / 2.0 );
534
- mPainterPath .lineTo ( 0 , -height / 2.0 );
565
+ mPainterPath .moveTo ( 0 , -size. height () / 2.0 );
566
+ mPainterPath .lineTo ( -size. width () / 2.0 , size. height () / 2.0 );
567
+ mPainterPath .lineTo ( size. width () / 2.0 , size. height () / 2.0 );
568
+ mPainterPath .lineTo ( 0 , -size. height () / 2.0 );
535
569
}
536
570
}
537
571
@@ -572,6 +606,61 @@ QgsMapUnitScale QgsEllipseSymbolLayerV2::mapUnitScale() const
572
606
return QgsMapUnitScale ();
573
607
}
574
608
609
+ QRectF QgsEllipseSymbolLayerV2::bounds ( const QPointF& point, QgsSymbolV2RenderContext& context )
610
+ {
611
+ QSizeF size = calculateSize ( context );
612
+
613
+ bool hasDataDefinedRotation = false ;
614
+ QPointF offset;
615
+ double angle = 0 ;
616
+ calculateOffsetAndRotation ( context, size.width (), size.height (), hasDataDefinedRotation, offset, angle );
617
+
618
+ double pixelSize = 1.0 / context.renderContext ().rasterScaleFactor ();
619
+
620
+ QMatrix transform;
621
+
622
+ // move to the desired position
623
+ transform.translate ( point.x () + offset.x (), point.y () + offset.y () );
624
+
625
+ if ( !qgsDoubleNear ( angle, 0.0 ) )
626
+ transform.rotate ( angle );
627
+
628
+ double penWidth = 0.0 ;
629
+ bool ok = true ;
630
+ if ( hasDataDefinedProperty ( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) )
631
+ {
632
+ context.setOriginalValueVariable ( mOutlineWidth );
633
+ double outlineWidth = evaluateDataDefinedProperty ( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context, QVariant (), &ok ).toDouble ();
634
+ if ( ok )
635
+ {
636
+ penWidth = QgsSymbolLayerV2Utils::convertToPainterUnits ( context.renderContext (), outlineWidth, mOutlineWidthUnit , mOutlineWidthMapUnitScale );
637
+ }
638
+ }
639
+ if ( hasDataDefinedProperty ( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE ) )
640
+ {
641
+ context.setOriginalValueVariable ( QgsSymbolLayerV2Utils::encodePenStyle ( mPen .style () ) );
642
+ QString outlineStyle = evaluateDataDefinedProperty ( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE, context, QVariant (), &ok ).toString ();
643
+ if ( ok && outlineStyle == " no" )
644
+ {
645
+ penWidth = 0.0 ;
646
+ }
647
+ }
648
+
649
+ // antialiasing
650
+ penWidth += pixelSize;
651
+
652
+ QRectF symbolBounds = transform.mapRect ( QRectF ( -size.width () / 2.0 ,
653
+ -size.height () / 2.0 ,
654
+ size.width (),
655
+ size.height () ) );
656
+
657
+ // extend bounds by pen width / 2.0
658
+ symbolBounds.adjust ( -penWidth / 2.0 , -penWidth / 2.0 ,
659
+ penWidth / 2.0 , penWidth / 2.0 );
660
+
661
+ return symbolBounds;
662
+ }
663
+
575
664
bool QgsEllipseSymbolLayerV2::writeDxf ( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, QgsSymbolV2RenderContext *context, const QgsFeature*, const QPointF& shift ) const
576
665
{
577
666
// width
0 commit comments