~ubuntu-branches/ubuntu/maverick/qgis/maverick

« back to all changes in this revision

Viewing changes to src/core/symbology-ng/qgssymbolv2.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "qgssymbolv2.h"
 
3
#include "qgssymbollayerv2.h"
 
4
 
 
5
#include "qgslinesymbollayerv2.h"
 
6
#include "qgsmarkersymbollayerv2.h"
 
7
#include "qgsfillsymbollayerv2.h"
 
8
 
 
9
#include "qgslogger.h"
 
10
#include "qgsrendercontext.h" // for bigSymbolPreview
 
11
 
 
12
#include <QColor>
 
13
#include <QImage>
 
14
#include <QPainter>
 
15
#include <QSize>
 
16
 
 
17
#include <cmath>
 
18
 
 
19
QgsSymbolV2::QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers )
 
20
    : mType( type ), mLayers( layers )
 
21
{
 
22
 
 
23
  // check they're all correct symbol layers
 
24
  for ( int i = 0; i < mLayers.count(); i++ )
 
25
  {
 
26
    if ( mLayers[i] == NULL )
 
27
    {
 
28
      mLayers.removeAt( i-- );
 
29
    }
 
30
    else if ( mLayers[i]->type() != mType )
 
31
    {
 
32
      delete mLayers[i];
 
33
      mLayers.removeAt( i-- );
 
34
    }
 
35
  }
 
36
 
 
37
}
 
38
 
 
39
QgsSymbolV2::~QgsSymbolV2()
 
40
{
 
41
  // delete all symbol layers (we own them, so it's okay)
 
42
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
43
    delete *it;
 
44
}
 
45
 
 
46
QgsSymbolV2* QgsSymbolV2::defaultSymbol( QGis::GeometryType geomType )
 
47
{
 
48
  QgsSymbolV2* s;
 
49
  switch ( geomType )
 
50
  {
 
51
    case QGis::Point: s = new QgsMarkerSymbolV2(); break;
 
52
    case QGis::Line:  s = new QgsLineSymbolV2(); break;
 
53
    case QGis::Polygon: s = new QgsFillSymbolV2(); break;
 
54
    default: QgsDebugMsg( "unknown layer's geometry type" ); return NULL;
 
55
  }
 
56
 
 
57
  s->setColor( QColor::fromHsv( rand() % 360, 64 + rand() % 192, 128 + rand() % 128 ) );
 
58
  return s;
 
59
}
 
60
 
 
61
 
 
62
QgsSymbolLayerV2* QgsSymbolV2::symbolLayer( int layer )
 
63
{
 
64
  if ( layer < 0 || layer >= mLayers.count() )
 
65
    return NULL;
 
66
 
 
67
  return mLayers[layer];
 
68
}
 
69
 
 
70
 
 
71
 
 
72
bool QgsSymbolV2::insertSymbolLayer( int index, QgsSymbolLayerV2* layer )
 
73
{
 
74
  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
 
75
    return false;
 
76
  if ( layer == NULL || layer->type() != mType )
 
77
    return false;
 
78
 
 
79
  mLayers.insert( index, layer );
 
80
  return true;
 
81
}
 
82
 
 
83
 
 
84
bool QgsSymbolV2::appendSymbolLayer( QgsSymbolLayerV2* layer )
 
85
{
 
86
  if ( layer == NULL || layer->type() != mType )
 
87
    return false;
 
88
 
 
89
  mLayers.append( layer );
 
90
  return true;
 
91
}
 
92
 
 
93
 
 
94
bool QgsSymbolV2::deleteSymbolLayer( int index )
 
95
{
 
96
  if ( index < 0 || index >= mLayers.count() )
 
97
    return false;
 
98
 
 
99
  delete mLayers[index];
 
100
  mLayers.removeAt( index );
 
101
  return true;
 
102
}
 
103
 
 
104
 
 
105
QgsSymbolLayerV2* QgsSymbolV2::takeSymbolLayer( int index )
 
106
{
 
107
  if ( index < 0 || index >= mLayers.count() )
 
108
    return NULL;
 
109
 
 
110
  return mLayers.takeAt( index );
 
111
}
 
112
 
 
113
 
 
114
bool QgsSymbolV2::changeSymbolLayer( int index, QgsSymbolLayerV2* layer )
 
115
{
 
116
  if ( index < 0 || index >= mLayers.count() )
 
117
    return false;
 
118
  if ( layer == NULL || layer->type() != mType )
 
119
    return false;
 
120
 
 
121
  delete mLayers[index]; // first delete the original layer
 
122
  mLayers[index] = layer; // set new layer
 
123
  return true;
 
124
}
 
125
 
 
126
 
 
127
void QgsSymbolV2::startRender( QgsRenderContext& context )
 
128
{
 
129
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
130
    ( *it )->startRender( context );
 
131
}
 
132
 
 
133
void QgsSymbolV2::stopRender( QgsRenderContext& context )
 
134
{
 
135
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
136
    ( *it )->stopRender( context );
 
137
}
 
138
 
 
139
void QgsSymbolV2::setColor( const QColor& color )
 
140
{
 
141
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
142
  {
 
143
    if ( !( *it )->isLocked() )
 
144
      ( *it )->setColor( color );
 
145
  }
 
146
}
 
147
 
 
148
QColor QgsSymbolV2::color()
 
149
{
 
150
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
151
  {
 
152
    // return color of the first unlocked layer
 
153
    if ( !( *it )->isLocked() )
 
154
      return ( *it )->color();
 
155
  }
 
156
  return QColor( 0, 0, 0 );
 
157
}
 
158
 
 
159
void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size )
 
160
{
 
161
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
162
  {
 
163
    ( *it )->drawPreviewIcon( painter, size );
 
164
  }
 
165
}
 
166
 
 
167
 
 
168
QImage QgsSymbolV2::bigSymbolPreviewImage()
 
169
{
 
170
  QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
 
171
  preview.fill( 0 );
 
172
 
 
173
  QPainter p( &preview );
 
174
  p.setRenderHint( QPainter::Antialiasing );
 
175
  p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialising
 
176
 
 
177
  if ( mType == QgsSymbolV2::Marker )
 
178
  {
 
179
    p.setPen( QPen( QColor( 230, 230, 230 ) ) );
 
180
    p.drawLine( 0, 50, 100, 50 );
 
181
    p.drawLine( 50, 0, 50, 100 );
 
182
  }
 
183
 
 
184
  QgsRenderContext context;
 
185
  context.setPainter( &p );
 
186
 
 
187
  startRender( context );
 
188
 
 
189
  if ( mType == QgsSymbolV2::Line )
 
190
  {
 
191
    QPolygonF poly;
 
192
    poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
 
193
    static_cast<QgsLineSymbolV2*>( this )->renderPolyline( poly, context );
 
194
  }
 
195
  else if ( mType == QgsSymbolV2::Fill )
 
196
  {
 
197
    QPolygonF polygon;
 
198
    polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 );
 
199
    static_cast<QgsFillSymbolV2*>( this )->renderPolygon( polygon, NULL, context );
 
200
  }
 
201
  else // marker
 
202
  {
 
203
    static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( QPointF( 50, 50 ), context );
 
204
  }
 
205
 
 
206
  stopRender( context );
 
207
  return preview;
 
208
}
 
209
 
 
210
 
 
211
QString QgsSymbolV2::dump()
 
212
{
 
213
  QString t;
 
214
  switch ( type() )
 
215
  {
 
216
    case QgsSymbolV2::Marker: t = "MARKER"; break;
 
217
    case QgsSymbolV2::Line: t = "LINE"; break;
 
218
    case QgsSymbolV2::Fill: t = "FILL"; break;
 
219
    default: Q_ASSERT( 0 && "unknown symbol type" );
 
220
  }
 
221
  QString s = QString( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerV2Utils::encodeColor( color() ) );
 
222
 
 
223
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
224
  {
 
225
    // TODO:
 
226
  }
 
227
  return s;
 
228
}
 
229
 
 
230
QgsSymbolLayerV2List QgsSymbolV2::cloneLayers() const
 
231
{
 
232
  QgsSymbolLayerV2List lst;
 
233
  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
234
  {
 
235
    QgsSymbolLayerV2* layer = ( *it )->clone();
 
236
    layer->setLocked(( *it )->isLocked() );
 
237
    layer->setRenderingPass(( *it )->renderingPass() );
 
238
    lst.append( layer );
 
239
  }
 
240
  return lst;
 
241
}
 
242
 
 
243
 
 
244
///////////////////
 
245
 
 
246
 
 
247
QgsMarkerSymbolV2::QgsMarkerSymbolV2( QgsSymbolLayerV2List layers )
 
248
    : QgsSymbolV2( Marker, layers )
 
249
{
 
250
  if ( mLayers.count() == 0 )
 
251
    mLayers.append( new QgsSimpleMarkerSymbolLayerV2() );
 
252
}
 
253
 
 
254
void QgsMarkerSymbolV2::setAngle( double angle )
 
255
{
 
256
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
257
  {
 
258
    QgsMarkerSymbolLayerV2* layer = ( QgsMarkerSymbolLayerV2* ) * it;
 
259
    layer->setAngle( angle );
 
260
  }
 
261
}
 
262
 
 
263
double QgsMarkerSymbolV2::angle()
 
264
{
 
265
  QgsSymbolLayerV2List::const_iterator it = mLayers.begin();
 
266
 
 
267
  if ( it == mLayers.end() )
 
268
    return 0;
 
269
 
 
270
  // return angle of the first symbol layer
 
271
  const QgsMarkerSymbolLayerV2 *layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
 
272
  return layer->angle();
 
273
}
 
274
 
 
275
void QgsMarkerSymbolV2::setSize( double s )
 
276
{
 
277
  double origSize = size();
 
278
 
 
279
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
280
  {
 
281
    QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2*>( *it );
 
282
    if ( layer->size() == origSize )
 
283
      layer->setSize( s );
 
284
    else
 
285
    {
 
286
      // proportionally scale size
 
287
      if ( origSize != 0 )
 
288
        layer->setSize( layer->size() * s / origSize );
 
289
    }
 
290
  }
 
291
}
 
292
 
 
293
double QgsMarkerSymbolV2::size()
 
294
{
 
295
  // return size of the largest symbol
 
296
  double maxSize = 0;
 
297
  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
298
  {
 
299
    const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
 
300
    double lsize = layer->size();
 
301
    if ( lsize > maxSize )
 
302
      maxSize = lsize;
 
303
  }
 
304
  return maxSize;
 
305
}
 
306
 
 
307
void QgsMarkerSymbolV2::renderPoint( const QPointF& point, QgsRenderContext& context, int layer )
 
308
{
 
309
  if ( layer != -1 )
 
310
  {
 
311
    if ( layer >= 0 && layer < mLayers.count() )
 
312
      (( QgsMarkerSymbolLayerV2* ) mLayers[layer] )->renderPoint( point, context );
 
313
    return;
 
314
  }
 
315
 
 
316
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
317
  {
 
318
    QgsMarkerSymbolLayerV2* layer = ( QgsMarkerSymbolLayerV2* ) * it;
 
319
    layer->renderPoint( point, context );
 
320
  }
 
321
}
 
322
 
 
323
QgsSymbolV2* QgsMarkerSymbolV2::clone() const
 
324
{
 
325
  return new QgsMarkerSymbolV2( cloneLayers() );
 
326
}
 
327
 
 
328
 
 
329
///////////////////
 
330
// LINE
 
331
 
 
332
QgsLineSymbolV2::QgsLineSymbolV2( QgsSymbolLayerV2List layers )
 
333
    : QgsSymbolV2( Line, layers )
 
334
{
 
335
  if ( mLayers.count() == 0 )
 
336
    mLayers.append( new QgsSimpleLineSymbolLayerV2() );
 
337
}
 
338
 
 
339
void QgsLineSymbolV2::setWidth( double w )
 
340
{
 
341
  double origWidth = width();
 
342
 
 
343
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
344
  {
 
345
    QgsLineSymbolLayerV2* layer = ( QgsLineSymbolLayerV2* ) * it;
 
346
    if ( layer->width() == origWidth )
 
347
    {
 
348
      layer->setWidth( w );
 
349
    }
 
350
    else
 
351
    {
 
352
      // proportionally scale the width
 
353
      if ( origWidth != 0 )
 
354
        layer->setWidth( layer->width() * w / origWidth );
 
355
    }
 
356
  }
 
357
}
 
358
 
 
359
double QgsLineSymbolV2::width()
 
360
{
 
361
  double maxWidth = 0;
 
362
  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
363
  {
 
364
    const QgsLineSymbolLayerV2* layer = ( const QgsLineSymbolLayerV2* ) * it;
 
365
    double width = layer->width();
 
366
    if ( width > maxWidth )
 
367
      maxWidth = width;
 
368
  }
 
369
  return maxWidth;
 
370
}
 
371
 
 
372
void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, QgsRenderContext& context, int layer )
 
373
{
 
374
  if ( layer != -1 )
 
375
  {
 
376
    if ( layer >= 0 && layer < mLayers.count() )
 
377
      (( QgsLineSymbolLayerV2* ) mLayers[layer] )->renderPolyline( points, context );
 
378
    return;
 
379
  }
 
380
 
 
381
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
382
  {
 
383
    QgsLineSymbolLayerV2* layer = ( QgsLineSymbolLayerV2* ) * it;
 
384
    layer->renderPolyline( points, context );
 
385
  }
 
386
}
 
387
 
 
388
 
 
389
QgsSymbolV2* QgsLineSymbolV2::clone() const
 
390
{
 
391
  return new QgsLineSymbolV2( cloneLayers() );
 
392
}
 
393
 
 
394
///////////////////
 
395
// FILL
 
396
 
 
397
QgsFillSymbolV2::QgsFillSymbolV2( QgsSymbolLayerV2List layers )
 
398
    : QgsSymbolV2( Fill, layers )
 
399
{
 
400
  if ( mLayers.count() == 0 )
 
401
    mLayers.append( new QgsSimpleFillSymbolLayerV2() );
 
402
}
 
403
 
 
404
void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsRenderContext& context, int layer )
 
405
{
 
406
  if ( layer != -1 )
 
407
  {
 
408
    if ( layer >= 0 && layer < mLayers.count() )
 
409
      (( QgsFillSymbolLayerV2* ) mLayers[layer] )->renderPolygon( points, rings, context );
 
410
    return;
 
411
  }
 
412
 
 
413
  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
 
414
  {
 
415
    QgsFillSymbolLayerV2* layer = ( QgsFillSymbolLayerV2* ) * it;
 
416
    layer->renderPolygon( points, rings, context );
 
417
  }
 
418
}
 
419
 
 
420
 
 
421
QgsSymbolV2* QgsFillSymbolV2::clone() const
 
422
{
 
423
  return new QgsFillSymbolV2( cloneLayers() );
 
424
}