21
21
#include " qgslinesymbollayerv2.h"
22
22
23
23
#include " qgscoordinatetransform.h"
24
+ #include " qgsfillsymbollayerv2.h"
24
25
#include " qgsgeometry.h"
25
26
#include " qgshighlight.h"
27
+ #include " qgslinesymbollayerv2.h"
28
+ #include " qgslinesymbollayerv2.h"
26
29
#include " qgsmapcanvas.h"
27
30
#include " qgsmaplayer.h"
28
31
#include " qgsmaprenderer.h"
32
+ #include " qgsmarkersymbollayerv2.h"
29
33
#include " qgsrendercontext.h"
30
34
#include " qgssymbollayerv2.h"
31
35
#include " qgssymbolv2.h"
32
36
#include " qgsvectorlayer.h"
33
37
38
+ /* Few notes about highligting (RB):
39
+ - The highlight fill must always be partially transparent because above highlighted layer
40
+ may be another layer which must remain partially visible.
41
+ - Because single highlight color does not work well with layers using similar layer color
42
+ there were considered various possibilities but no optimal solution was found.
43
+ What does not work:
44
+ - lighter/darker color: it would work more or less for fully opaque highlight, but
45
+ overlaying transparent lighter color over original has small visual efect.
46
+ - complemetary color: mixing transparent (128) complement color with original color
47
+ results in grey for all colors
48
+ - contrast line style/ fill pattern: impression is not highligh but just different style
49
+ - line buffer with contrast (or 2 contrast) color: the same as with patterns, no highlight impression
50
+ - fill with highlight or contrast color but opaque and using pattern
51
+ (e.g. Qt::Dense7Pattern): again no highlight impression
52
+ */
34
53
/* !
35
54
\class QgsHighlight
36
55
\brief The QgsHighlight class provides a transparent overlay widget
39
58
QgsHighlight::QgsHighlight ( QgsMapCanvas* mapCanvas, QgsGeometry *geom, QgsMapLayer *layer )
40
59
: QgsMapCanvasItem( mapCanvas )
41
60
, mLayer( layer )
42
- , mRenderer( 0 )
61
+ , mBuffer( 0 )
62
+ , mMinWidth( 0 )
43
63
{
44
64
mGeometry = geom ? new QgsGeometry ( *geom ) : 0 ;
45
65
init ();
@@ -48,7 +68,8 @@ QgsHighlight::QgsHighlight( QgsMapCanvas* mapCanvas, QgsGeometry *geom, QgsMapLa
48
68
QgsHighlight::QgsHighlight ( QgsMapCanvas* mapCanvas, QgsGeometry *geom, QgsVectorLayer *layer )
49
69
: QgsMapCanvasItem( mapCanvas )
50
70
, mLayer( static_cast <QgsMapLayer *>( layer ) )
51
- , mRenderer( 0 )
71
+ , mBuffer( 0 )
72
+ , mMinWidth( 0 )
52
73
{
53
74
mGeometry = geom ? new QgsGeometry ( *geom ) : 0 ;
54
75
init ();
@@ -59,7 +80,8 @@ QgsHighlight::QgsHighlight( QgsMapCanvas* mapCanvas, const QgsFeature& feature,
59
80
, mGeometry( 0 )
60
81
, mLayer( static_cast <QgsMapLayer *>( layer ) )
61
82
, mFeature( feature )
62
- , mRenderer( 0 )
83
+ , mBuffer( 0 )
84
+ , mMinWidth( 0 )
63
85
{
64
86
init ();
65
87
}
@@ -90,7 +112,6 @@ void QgsHighlight::init()
90
112
QgsHighlight::~QgsHighlight ()
91
113
{
92
114
delete mGeometry ;
93
- delete mRenderer ;
94
115
}
95
116
96
117
/* !
@@ -102,25 +123,34 @@ void QgsHighlight::setColor( const QColor & color )
102
123
QColor fillColor ( color.red (), color.green (), color.blue (), 63 );
103
124
mBrush .setColor ( fillColor );
104
125
mBrush .setStyle ( Qt::SolidPattern );
126
+ }
105
127
106
- delete mRenderer ;
107
- mRenderer = 0 ;
128
+ void QgsHighlight::setFillColor ( const QColor & fillColor )
129
+ {
130
+ mBrush .setColor ( fillColor );
131
+ mBrush .setStyle ( Qt::SolidPattern );
132
+ }
133
+
134
+ QgsFeatureRendererV2 * QgsHighlight::getRenderer ( const QgsRenderContext & context )
135
+ {
136
+ QgsFeatureRendererV2 *renderer = 0 ;
108
137
QgsVectorLayer *layer = vectorLayer ();
109
138
if ( layer && layer->rendererV2 () )
110
139
{
111
- mRenderer = layer->rendererV2 ()->clone ();
140
+ renderer = layer->rendererV2 ()->clone ();
112
141
}
113
- if ( mRenderer )
142
+ if ( renderer )
114
143
{
115
- foreach ( QgsSymbolV2* symbol, mRenderer ->symbols () )
144
+ foreach ( QgsSymbolV2* symbol, renderer ->symbols () )
116
145
{
117
146
if ( !symbol ) continue ;
118
- setSymbolColor ( symbol, color );
147
+ setSymbol ( symbol, context, mPen . color () );
119
148
}
120
149
}
150
+ return renderer;
121
151
}
122
152
123
- void QgsHighlight::setSymbolColor ( QgsSymbolV2* symbol, const QColor & color )
153
+ void QgsHighlight::setSymbol ( QgsSymbolV2* symbol, const QgsRenderContext & context, const QColor & color )
124
154
{
125
155
if ( !symbol ) return ;
126
156
@@ -146,20 +176,49 @@ void QgsHighlight::setSymbolColor( QgsSymbolV2* symbol, const QColor & color )
146
176
147
177
if ( symbolLayer->subSymbol () )
148
178
{
149
- setSymbolColor ( symbolLayer->subSymbol (), color );
179
+ setSymbol ( symbolLayer->subSymbol (), context , color );
150
180
}
151
181
else
152
182
{
153
183
symbolLayer->setColor ( color ); // line symbology layers
154
184
symbolLayer->setOutlineColor ( color ); // marker and fill symbology layers
155
185
symbolLayer->setFillColor ( mTemporaryFillColor ); // marker and fill symbology layers
156
186
187
+ // Data defined widths overwrite what we set here (widths do not work with data defined)
188
+ QgsSimpleMarkerSymbolLayerV2 * simpleMarker = dynamic_cast <QgsSimpleMarkerSymbolLayerV2*>( symbolLayer );
189
+ if ( simpleMarker )
190
+ {
191
+ simpleMarker->setOutlineWidth ( getSymbolWidth ( context, simpleMarker->outlineWidth (), simpleMarker->outlineWidthUnit () ) );
192
+ }
193
+ QgsSimpleLineSymbolLayerV2 * simpleLine = dynamic_cast <QgsSimpleLineSymbolLayerV2*>( symbolLayer );
194
+ if ( simpleLine )
195
+ {
196
+ simpleLine->setWidth ( getSymbolWidth ( context, simpleLine->width (), simpleLine->widthUnit () ) );
197
+ }
198
+ QgsSimpleFillSymbolLayerV2 * simpleFill = dynamic_cast <QgsSimpleFillSymbolLayerV2*>( symbolLayer );
199
+ if ( simpleFill )
200
+ {
201
+ simpleFill->setBorderWidth ( getSymbolWidth ( context, simpleFill->borderWidth (), simpleFill->outputUnit () ) );
202
+ }
157
203
symbolLayer->removeDataDefinedProperty ( " color" );
158
204
symbolLayer->removeDataDefinedProperty ( " color_border" );
159
205
}
160
206
}
161
207
}
162
208
209
+ double QgsHighlight::getSymbolWidth ( const QgsRenderContext & context, double width, QgsSymbolV2::OutputUnit unit )
210
+ {
211
+ // if necessary scale mm to map units
212
+ double scale = 1 .;
213
+ if ( unit == QgsSymbolV2::MapUnit )
214
+ {
215
+ scale = QgsSymbolLayerV2Utils::lineWidthScaleFactor ( context, QgsSymbolV2::MM ) / QgsSymbolLayerV2Utils::lineWidthScaleFactor ( context, QgsSymbolV2::MapUnit );
216
+ }
217
+ return qMax ( width + 2 *mBuffer *scale, mMinWidth *scale );
218
+
219
+
220
+ }
221
+
163
222
/* !
164
223
Set the outline width.
165
224
*/
@@ -299,50 +358,41 @@ void QgsHighlight::paint( QPainter* p )
299
358
return ;
300
359
}
301
360
}
302
- else if ( mFeature .geometry () && mRenderer )
361
+ else if ( mFeature .geometry () )
303
362
{
304
363
QgsVectorLayer *layer = vectorLayer ();
305
- if ( layer )
306
- {
307
- QgsRenderContext context = *( mMapCanvas ->mapRenderer ()->rendererContext () );
364
+ QgsMapSettings mapSettings = mMapCanvas ->mapSettings ();
365
+ QgsRenderContext context = QgsRenderContext::fromMapSettings ( mapSettings );
308
366
309
- // The context is local rectangle of QgsHighlight we previously set.
310
- // Because QgsMapCanvasItem::setRect() adds 1 pixel on border we cannot simply
311
- // use boundingRect().height() for QgsMapToPixel height.
367
+ QgsFeatureRendererV2 *renderer = getRenderer ( context );
368
+ if ( layer && renderer )
369
+ {
312
370
QgsRectangle extent = mMapCanvas ->extent ();
313
371
if ( extent != rect () ) // catches also canvas resize as it is causing extent change
314
372
{
315
373
updateRect ();
316
374
return ; // it will be repainted after updateRect()
317
375
}
318
376
319
-
320
- QPointF ll = toCanvasCoordinates ( QgsPoint ( extent.xMinimum (), extent.yMinimum () ) );
321
- QPointF ur = toCanvasCoordinates ( QgsPoint ( extent.xMaximum (), extent.yMaximum () ) );
322
- double height = ll.y () - ur.y ();
323
- double width = ur.x () - ll.x ();
324
-
325
377
// Because lower level outlines must be covered by upper level fill color
326
378
// we render first with temporary opaque color, which is then replaced
327
379
// by final transparent fill color.
328
- QImage image = QImage (( int )width, ( int )height, QImage::Format_ARGB32 );
380
+ // QImage image = QImage(( int )width, ( int )height, QImage::Format_ARGB32 );
381
+ QSize imageSize ( mMapCanvas ->mapSettings ().outputSize () );
382
+ QImage image = QImage ( imageSize.width (), imageSize.height (), QImage::Format_ARGB32 );
329
383
image.fill ( 0 );
330
384
QPainter *imagePainter = new QPainter ( &image );
331
385
imagePainter->setRenderHint ( QPainter::Antialiasing, true );
332
386
333
- QgsMapToPixel mapToPixel = QgsMapToPixel ( mMapCanvas ->mapUnitsPerPixel (),
334
- height, extent.yMinimum (), extent.xMinimum () );
335
- context.setMapToPixel ( mapToPixel );
336
- context.setExtent ( extent );
337
- context.setCoordinateTransform ( 0 ); // we reprojected geometry in init()
338
387
context.setPainter ( imagePainter );
339
388
340
- mRenderer ->startRender ( context, layer );
341
- mRenderer ->renderFeature ( mFeature , context );
342
- mRenderer ->stopRender ( context );
389
+ renderer ->startRender ( context, layer-> pendingFields () );
390
+ renderer ->renderFeature ( mFeature , context );
391
+ renderer ->stopRender ( context );
343
392
344
393
imagePainter->end ();
345
394
395
+ // overwrite temporary fill color
346
396
QRgb temporaryRgb = mTemporaryFillColor .rgba ();
347
397
QColor color = QColor ( mBrush .color () );
348
398
color.setAlpha ( 63 );
@@ -363,6 +413,7 @@ void QgsHighlight::paint( QPainter* p )
363
413
p->drawImage ( 0 , 0 , image );
364
414
365
415
delete imagePainter;
416
+ delete renderer;
366
417
}
367
418
}
368
419
}
@@ -404,3 +455,4 @@ QgsVectorLayer * QgsHighlight::vectorLayer()
404
455
{
405
456
return dynamic_cast <QgsVectorLayer *>( mLayer );
406
457
}
458
+
0 commit comments