Quantum GIS API Documentation
1.7.4
|
00001 00002 #include "qgsrenderer.h" 00003 #include "qgssymbolv2.h" 00004 #include "qgssymbollayerv2.h" 00005 00006 #include "qgslinesymbollayerv2.h" 00007 #include "qgsmarkersymbollayerv2.h" 00008 #include "qgsfillsymbollayerv2.h" 00009 00010 #include "qgslogger.h" 00011 #include "qgsrendercontext.h" // for bigSymbolPreview 00012 00013 #include <QColor> 00014 #include <QImage> 00015 #include <QPainter> 00016 #include <QSize> 00017 00018 #include <cmath> 00019 00020 QgsSymbolV2::QgsSymbolV2( SymbolType type, QgsSymbolLayerV2List layers ) 00021 : mType( type ), mLayers( layers ), mOutputUnit( MM ), mAlpha( 1.0 ), mRenderHints( 0 ) 00022 { 00023 00024 // check they're all correct symbol layers 00025 for ( int i = 0; i < mLayers.count(); i++ ) 00026 { 00027 if ( mLayers[i] == NULL ) 00028 { 00029 mLayers.removeAt( i-- ); 00030 } 00031 else if ( !isSymbolLayerCompatible( mLayers[i]->type() ) ) 00032 { 00033 delete mLayers[i]; 00034 mLayers.removeAt( i-- ); 00035 } 00036 } 00037 00038 } 00039 00040 QgsSymbolV2::~QgsSymbolV2() 00041 { 00042 // delete all symbol layers (we own them, so it's okay) 00043 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00044 delete *it; 00045 } 00046 00047 QgsSymbolV2* QgsSymbolV2::defaultSymbol( QGis::GeometryType geomType ) 00048 { 00049 QgsSymbolV2* s; 00050 switch ( geomType ) 00051 { 00052 case QGis::Point: s = new QgsMarkerSymbolV2(); break; 00053 case QGis::Line: s = new QgsLineSymbolV2(); break; 00054 case QGis::Polygon: s = new QgsFillSymbolV2(); break; 00055 default: QgsDebugMsg( "unknown layer's geometry type" ); return NULL; 00056 } 00057 00058 s->setColor( QColor::fromHsv( rand() % 360, 64 + rand() % 192, 128 + rand() % 128 ) ); 00059 return s; 00060 } 00061 00062 00063 QgsSymbolLayerV2* QgsSymbolV2::symbolLayer( int layer ) 00064 { 00065 if ( layer < 0 || layer >= mLayers.count() ) 00066 return NULL; 00067 00068 return mLayers[layer]; 00069 } 00070 00071 00072 bool QgsSymbolV2::isSymbolLayerCompatible( SymbolType t ) 00073 { 00074 // fill symbol can contain also line symbol layers for drawing of outlines 00075 if ( mType == Fill && t == Line ) 00076 return true; 00077 00078 return mType == t; 00079 } 00080 00081 00082 bool QgsSymbolV2::insertSymbolLayer( int index, QgsSymbolLayerV2* layer ) 00083 { 00084 if ( index < 0 || index > mLayers.count() ) // can be added also after the last index 00085 return false; 00086 if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) ) 00087 return false; 00088 00089 mLayers.insert( index, layer ); 00090 return true; 00091 } 00092 00093 00094 bool QgsSymbolV2::appendSymbolLayer( QgsSymbolLayerV2* layer ) 00095 { 00096 if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) ) 00097 return false; 00098 00099 mLayers.append( layer ); 00100 return true; 00101 } 00102 00103 00104 bool QgsSymbolV2::deleteSymbolLayer( int index ) 00105 { 00106 if ( index < 0 || index >= mLayers.count() ) 00107 return false; 00108 00109 delete mLayers[index]; 00110 mLayers.removeAt( index ); 00111 return true; 00112 } 00113 00114 00115 QgsSymbolLayerV2* QgsSymbolV2::takeSymbolLayer( int index ) 00116 { 00117 if ( index < 0 || index >= mLayers.count() ) 00118 return NULL; 00119 00120 return mLayers.takeAt( index ); 00121 } 00122 00123 00124 bool QgsSymbolV2::changeSymbolLayer( int index, QgsSymbolLayerV2* layer ) 00125 { 00126 if ( index < 0 || index >= mLayers.count() ) 00127 return false; 00128 if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) ) 00129 return false; 00130 00131 delete mLayers[index]; // first delete the original layer 00132 mLayers[index] = layer; // set new layer 00133 return true; 00134 } 00135 00136 00137 void QgsSymbolV2::startRender( QgsRenderContext& context ) 00138 { 00139 QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, false, mRenderHints ); 00140 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00141 ( *it )->startRender( symbolContext ); 00142 } 00143 00144 void QgsSymbolV2::stopRender( QgsRenderContext& context ) 00145 { 00146 QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, false, mRenderHints ); 00147 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00148 ( *it )->stopRender( symbolContext ); 00149 } 00150 00151 void QgsSymbolV2::setColor( const QColor& color ) 00152 { 00153 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00154 { 00155 if ( !( *it )->isLocked() ) 00156 ( *it )->setColor( color ); 00157 } 00158 } 00159 00160 QColor QgsSymbolV2::color() 00161 { 00162 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00163 { 00164 // return color of the first unlocked layer 00165 if ( !( *it )->isLocked() ) 00166 return ( *it )->color(); 00167 } 00168 return QColor( 0, 0, 0 ); 00169 } 00170 00171 void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size ) 00172 { 00173 QgsRenderContext context = QgsSymbolLayerV2Utils::createRenderContext( painter ); 00174 QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, false, mRenderHints ); 00175 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00176 { 00177 if ( mType == Fill && ( *it )->type() == Line ) 00178 { 00179 // line symbol layer would normally draw just a line 00180 // so we override this case to force it to draw a polygon outline 00181 QgsLineSymbolLayerV2* lsl = ( QgsLineSymbolLayerV2* ) * it; 00182 00183 // from QgsFillSymbolLayerV2::drawPreviewIcon() 00184 QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) ); 00185 lsl->startRender( symbolContext ); 00186 lsl->renderPolygonOutline( poly, NULL, symbolContext ); 00187 lsl->stopRender( symbolContext ); 00188 } 00189 else 00190 ( *it )->drawPreviewIcon( symbolContext, size ); 00191 } 00192 } 00193 00194 00195 QImage QgsSymbolV2::bigSymbolPreviewImage() 00196 { 00197 QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied ); 00198 preview.fill( 0 ); 00199 00200 QPainter p( &preview ); 00201 p.setRenderHint( QPainter::Antialiasing ); 00202 p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialising 00203 00204 if ( mType == QgsSymbolV2::Marker ) 00205 { 00206 p.setPen( QPen( Qt::gray ) ); 00207 p.drawLine( 0, 50, 100, 50 ); 00208 p.drawLine( 50, 0, 50, 100 ); 00209 } 00210 00211 QgsRenderContext context = QgsSymbolLayerV2Utils::createRenderContext( &p ); 00212 startRender( context ); 00213 00214 if ( mType == QgsSymbolV2::Line ) 00215 { 00216 QPolygonF poly; 00217 poly << QPointF( 0, 50 ) << QPointF( 99, 50 ); 00218 static_cast<QgsLineSymbolV2*>( this )->renderPolyline( poly, context ); 00219 } 00220 else if ( mType == QgsSymbolV2::Fill ) 00221 { 00222 QPolygonF polygon; 00223 polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 ); 00224 static_cast<QgsFillSymbolV2*>( this )->renderPolygon( polygon, NULL, context ); 00225 } 00226 else // marker 00227 { 00228 static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( QPointF( 50, 50 ), context ); 00229 } 00230 00231 stopRender( context ); 00232 return preview; 00233 } 00234 00235 00236 QString QgsSymbolV2::dump() 00237 { 00238 QString t; 00239 switch ( type() ) 00240 { 00241 case QgsSymbolV2::Marker: t = "MARKER"; break; 00242 case QgsSymbolV2::Line: t = "LINE"; break; 00243 case QgsSymbolV2::Fill: t = "FILL"; break; 00244 default: Q_ASSERT( 0 && "unknown symbol type" ); 00245 } 00246 QString s = QString( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerV2Utils::encodeColor( color() ) ); 00247 00248 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00249 { 00250 // TODO: 00251 } 00252 return s; 00253 } 00254 00255 QgsSymbolLayerV2List QgsSymbolV2::cloneLayers() const 00256 { 00257 QgsSymbolLayerV2List lst; 00258 for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00259 { 00260 QgsSymbolLayerV2* layer = ( *it )->clone(); 00261 layer->setLocked(( *it )->isLocked() ); 00262 layer->setRenderingPass(( *it )->renderingPass() ); 00263 lst.append( layer ); 00264 } 00265 return lst; 00266 } 00267 00269 00270 QgsSymbolV2RenderContext::QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u, qreal alpha, bool selected, int renderHints ) 00271 : mRenderContext( c ), mOutputUnit( u ), mAlpha( alpha ), mSelected( selected ), mRenderHints( renderHints ) 00272 { 00273 00274 } 00275 00276 QgsSymbolV2RenderContext::~QgsSymbolV2RenderContext() 00277 { 00278 00279 } 00280 00281 QColor QgsSymbolV2RenderContext::selectionColor() 00282 { 00283 return QgsRenderer::selectionColor(); 00284 } 00285 00286 00287 double QgsSymbolV2RenderContext::outputLineWidth( double width ) const 00288 { 00289 return width * QgsSymbolLayerV2Utils::lineWidthScaleFactor( mRenderContext, mOutputUnit ); 00290 } 00291 00292 double QgsSymbolV2RenderContext::outputPixelSize( double size ) const 00293 { 00294 return size * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( mRenderContext, mOutputUnit ); 00295 } 00296 00297 QgsSymbolV2RenderContext& QgsSymbolV2RenderContext::operator=( const QgsSymbolV2RenderContext& ) 00298 { 00299 // This is just a dummy implementation of assignment. 00300 // sip 4.7 generates a piece of code that needs this function to exist. 00301 // It's not generated automatically by the compiler because of 00302 // mRenderContext member which is a reference (and thus can't be changed). 00303 Q_ASSERT( false ); 00304 return *this; 00305 } 00306 00308 00309 QgsMarkerSymbolV2* QgsMarkerSymbolV2::createSimple( const QgsStringMap& properties ) 00310 { 00311 QgsSymbolLayerV2* sl = QgsSimpleMarkerSymbolLayerV2::create( properties ); 00312 if ( sl == NULL ) 00313 return NULL; 00314 00315 QgsSymbolLayerV2List layers; 00316 layers.append( sl ); 00317 return new QgsMarkerSymbolV2( layers ); 00318 } 00319 00320 QgsLineSymbolV2* QgsLineSymbolV2::createSimple( const QgsStringMap& properties ) 00321 { 00322 QgsSymbolLayerV2* sl = QgsSimpleLineSymbolLayerV2::create( properties ); 00323 if ( sl == NULL ) 00324 return NULL; 00325 00326 QgsSymbolLayerV2List layers; 00327 layers.append( sl ); 00328 return new QgsLineSymbolV2( layers ); 00329 } 00330 00331 QgsFillSymbolV2* QgsFillSymbolV2::createSimple( const QgsStringMap& properties ) 00332 { 00333 QgsSymbolLayerV2* sl = QgsSimpleFillSymbolLayerV2::create( properties ); 00334 if ( sl == NULL ) 00335 return NULL; 00336 00337 QgsSymbolLayerV2List layers; 00338 layers.append( sl ); 00339 return new QgsFillSymbolV2( layers ); 00340 } 00341 00343 00344 00345 QgsMarkerSymbolV2::QgsMarkerSymbolV2( QgsSymbolLayerV2List layers ) 00346 : QgsSymbolV2( Marker, layers ) 00347 { 00348 if ( mLayers.count() == 0 ) 00349 mLayers.append( new QgsSimpleMarkerSymbolLayerV2() ); 00350 } 00351 00352 void QgsMarkerSymbolV2::setAngle( double angle ) 00353 { 00354 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00355 { 00356 QgsMarkerSymbolLayerV2* layer = ( QgsMarkerSymbolLayerV2* ) * it; 00357 layer->setAngle( angle ); 00358 } 00359 } 00360 00361 double QgsMarkerSymbolV2::angle() 00362 { 00363 QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); 00364 00365 if ( it == mLayers.end() ) 00366 return 0; 00367 00368 // return angle of the first symbol layer 00369 const QgsMarkerSymbolLayerV2 *layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it ); 00370 return layer->angle(); 00371 } 00372 00373 void QgsMarkerSymbolV2::setSize( double s ) 00374 { 00375 double origSize = size(); 00376 00377 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00378 { 00379 QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2*>( *it ); 00380 if ( layer->size() == origSize ) 00381 layer->setSize( s ); 00382 else 00383 { 00384 // proportionally scale size 00385 if ( origSize != 0 ) 00386 layer->setSize( layer->size() * s / origSize ); 00387 } 00388 } 00389 } 00390 00391 double QgsMarkerSymbolV2::size() 00392 { 00393 // return size of the largest symbol 00394 double maxSize = 0; 00395 for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00396 { 00397 const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it ); 00398 double lsize = layer->size(); 00399 if ( lsize > maxSize ) 00400 maxSize = lsize; 00401 } 00402 return maxSize; 00403 } 00404 00405 void QgsMarkerSymbolV2::renderPoint( const QPointF& point, QgsRenderContext& context, int layer, bool selected ) 00406 { 00407 QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected, mRenderHints ); 00408 if ( layer != -1 ) 00409 { 00410 if ( layer >= 0 && layer < mLayers.count() ) 00411 (( QgsMarkerSymbolLayerV2* ) mLayers[layer] )->renderPoint( point, symbolContext ); 00412 return; 00413 } 00414 00415 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00416 { 00417 QgsMarkerSymbolLayerV2* layer = ( QgsMarkerSymbolLayerV2* ) * it; 00418 layer->renderPoint( point, symbolContext ); 00419 } 00420 } 00421 00422 QgsSymbolV2* QgsMarkerSymbolV2::clone() const 00423 { 00424 QgsSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() ); 00425 cloneSymbol->setOutputUnit( mOutputUnit ); 00426 cloneSymbol->setAlpha( mAlpha ); 00427 return cloneSymbol; 00428 } 00429 00430 00432 // LINE 00433 00434 QgsLineSymbolV2::QgsLineSymbolV2( QgsSymbolLayerV2List layers ) 00435 : QgsSymbolV2( Line, layers ) 00436 { 00437 if ( mLayers.count() == 0 ) 00438 mLayers.append( new QgsSimpleLineSymbolLayerV2() ); 00439 } 00440 00441 void QgsLineSymbolV2::setWidth( double w ) 00442 { 00443 double origWidth = width(); 00444 00445 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00446 { 00447 QgsLineSymbolLayerV2* layer = ( QgsLineSymbolLayerV2* ) * it; 00448 if ( layer->width() == origWidth ) 00449 { 00450 layer->setWidth( w ); 00451 } 00452 else 00453 { 00454 // proportionally scale the width 00455 if ( origWidth != 0 ) 00456 layer->setWidth( layer->width() * w / origWidth ); 00457 } 00458 } 00459 } 00460 00461 double QgsLineSymbolV2::width() 00462 { 00463 double maxWidth = 0; 00464 for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00465 { 00466 const QgsLineSymbolLayerV2* layer = ( const QgsLineSymbolLayerV2* ) * it; 00467 double width = layer->width(); 00468 if ( width > maxWidth ) 00469 maxWidth = width; 00470 } 00471 return maxWidth; 00472 } 00473 00474 void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, QgsRenderContext& context, int layer, bool selected ) 00475 { 00476 QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected, mRenderHints ); 00477 if ( layer != -1 ) 00478 { 00479 if ( layer >= 0 && layer < mLayers.count() ) 00480 (( QgsLineSymbolLayerV2* ) mLayers[layer] )->renderPolyline( points, symbolContext ); 00481 return; 00482 } 00483 00484 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00485 { 00486 QgsLineSymbolLayerV2* layer = ( QgsLineSymbolLayerV2* ) * it; 00487 layer->renderPolyline( points, symbolContext ); 00488 } 00489 } 00490 00491 00492 QgsSymbolV2* QgsLineSymbolV2::clone() const 00493 { 00494 QgsSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() ); 00495 cloneSymbol->setOutputUnit( mOutputUnit ); 00496 cloneSymbol->setAlpha( mAlpha ); 00497 return cloneSymbol; 00498 } 00499 00501 // FILL 00502 00503 QgsFillSymbolV2::QgsFillSymbolV2( QgsSymbolLayerV2List layers ) 00504 : QgsSymbolV2( Fill, layers ) 00505 { 00506 if ( mLayers.count() == 0 ) 00507 mLayers.append( new QgsSimpleFillSymbolLayerV2() ); 00508 } 00509 00510 void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsRenderContext& context, int layer, bool selected ) 00511 { 00512 QgsSymbolV2RenderContext symbolContext( context, mOutputUnit, mAlpha, selected, mRenderHints ); 00513 if ( layer != -1 ) 00514 { 00515 if ( layer >= 0 && layer < mLayers.count() ) 00516 { 00517 QgsSymbolV2::SymbolType layertype = mLayers.at( layer )->type(); 00518 if ( layertype == QgsSymbolV2::Fill ) 00519 (( QgsFillSymbolLayerV2* ) mLayers[layer] )->renderPolygon( points, rings, symbolContext ); 00520 else if ( layertype == QgsSymbolV2::Line ) 00521 (( QgsLineSymbolLayerV2* ) mLayers[layer] )->renderPolygonOutline( points, rings, symbolContext ); 00522 } 00523 return; 00524 } 00525 00526 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00527 { 00528 QgsSymbolV2::SymbolType layertype = ( *it )->type(); 00529 if ( layertype == QgsSymbolV2::Fill ) 00530 { 00531 QgsFillSymbolLayerV2* layer = ( QgsFillSymbolLayerV2* ) * it; 00532 layer->renderPolygon( points, rings, symbolContext ); 00533 } 00534 else if ( layertype == QgsSymbolV2::Line ) 00535 { 00536 QgsLineSymbolLayerV2* layer = ( QgsLineSymbolLayerV2* ) * it; 00537 layer->renderPolygonOutline( points, rings, symbolContext ); 00538 } 00539 } 00540 } 00541 00542 00543 QgsSymbolV2* QgsFillSymbolV2::clone() const 00544 { 00545 QgsSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() ); 00546 cloneSymbol->setOutputUnit( mOutputUnit ); 00547 cloneSymbol->setAlpha( mAlpha ); 00548 return cloneSymbol; 00549 } 00550 00551 void QgsFillSymbolV2::setAngle( double angle ) 00552 { 00553 for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it ) 00554 { 00555 QgsFillSymbolLayerV2* layer = ( QgsFillSymbolLayerV2* ) * it; 00556 layer->setAngle( angle ); 00557 } 00558 }