Quantum GIS API Documentation
1.7.4
|
00001 #include "qgsfillsymbollayerv2.h" 00002 #include "qgsmarkersymbollayerv2.h" 00003 #include "qgssymbollayerv2utils.h" 00004 00005 #include "qgsrendercontext.h" 00006 #include "qgsproject.h" 00007 00008 #include <QPainter> 00009 #include <QFile> 00010 #include <QSvgRenderer> 00011 00012 QgsSimpleFillSymbolLayerV2::QgsSimpleFillSymbolLayerV2( QColor color, Qt::BrushStyle style, QColor borderColor, Qt::PenStyle borderStyle, double borderWidth ) 00013 : mBrushStyle( style ), mBorderColor( borderColor ), mBorderStyle( borderStyle ), mBorderWidth( borderWidth ) 00014 { 00015 mColor = color; 00016 } 00017 00018 00019 QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::create( const QgsStringMap& props ) 00020 { 00021 QColor color = DEFAULT_SIMPLEFILL_COLOR; 00022 Qt::BrushStyle style = DEFAULT_SIMPLEFILL_STYLE; 00023 QColor borderColor = DEFAULT_SIMPLEFILL_BORDERCOLOR; 00024 Qt::PenStyle borderStyle = DEFAULT_SIMPLEFILL_BORDERSTYLE; 00025 double borderWidth = DEFAULT_SIMPLEFILL_BORDERWIDTH; 00026 QPointF offset; 00027 00028 if ( props.contains( "color" ) ) 00029 color = QgsSymbolLayerV2Utils::decodeColor( props["color"] ); 00030 if ( props.contains( "style" ) ) 00031 style = QgsSymbolLayerV2Utils::decodeBrushStyle( props["style"] ); 00032 if ( props.contains( "color_border" ) ) 00033 borderColor = QgsSymbolLayerV2Utils::decodeColor( props["color_border"] ); 00034 if ( props.contains( "style_border" ) ) 00035 borderStyle = QgsSymbolLayerV2Utils::decodePenStyle( props["style_border"] ); 00036 if ( props.contains( "width_border" ) ) 00037 borderWidth = props["width_border"].toDouble(); 00038 if ( props.contains( "offset" ) ) 00039 offset = QgsSymbolLayerV2Utils::decodePoint( props["offset"] ); 00040 00041 QgsSimpleFillSymbolLayerV2* sl = new QgsSimpleFillSymbolLayerV2( color, style, borderColor, borderStyle, borderWidth ); 00042 sl->setOffset( offset ); 00043 return sl; 00044 } 00045 00046 00047 QString QgsSimpleFillSymbolLayerV2::layerType() const 00048 { 00049 return "SimpleFill"; 00050 } 00051 00052 void QgsSimpleFillSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) 00053 { 00054 mColor.setAlphaF( context.alpha() ); 00055 mBrush = QBrush( mColor, mBrushStyle ); 00056 00057 // scale brush content for printout 00058 double rasterScaleFactor = context.renderContext().rasterScaleFactor(); 00059 if ( rasterScaleFactor != 1.0 ) 00060 { 00061 mBrush.setMatrix( QMatrix().scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ) ); 00062 } 00063 00064 QColor selColor = context.selectionColor(); 00065 // selColor.setAlphaF( context.alpha() ); 00066 mSelBrush = QBrush( selColor ); 00067 if ( selectFillStyle ) mSelBrush.setStyle( mBrushStyle ); 00068 mBorderColor.setAlphaF( context.alpha() ); 00069 mPen = QPen( mBorderColor ); 00070 mPen.setStyle( mBorderStyle ); 00071 mPen.setWidthF( context.outputLineWidth( mBorderWidth ) ); 00072 } 00073 00074 void QgsSimpleFillSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context ) 00075 { 00076 } 00077 00078 void QgsSimpleFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) 00079 { 00080 QPainter* p = context.renderContext().painter(); 00081 if ( !p ) 00082 { 00083 return; 00084 } 00085 00086 p->setBrush( context.selected() ? mSelBrush : mBrush ); 00087 p->setPen( mPen ); 00088 00089 if ( !mOffset.isNull() ) 00090 p->translate( mOffset ); 00091 00092 _renderPolygon( p, points, rings ); 00093 00094 if ( !mOffset.isNull() ) 00095 p->translate( -mOffset ); 00096 } 00097 00098 QgsStringMap QgsSimpleFillSymbolLayerV2::properties() const 00099 { 00100 QgsStringMap map; 00101 map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor ); 00102 map["style"] = QgsSymbolLayerV2Utils::encodeBrushStyle( mBrushStyle ); 00103 map["color_border"] = QgsSymbolLayerV2Utils::encodeColor( mBorderColor ); 00104 map["style_border"] = QgsSymbolLayerV2Utils::encodePenStyle( mBorderStyle ); 00105 map["width_border"] = QString::number( mBorderWidth ); 00106 map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset ); 00107 return map; 00108 } 00109 00110 QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::clone() const 00111 { 00112 QgsSimpleFillSymbolLayerV2* sl = new QgsSimpleFillSymbolLayerV2( mColor, mBrushStyle, mBorderColor, mBorderStyle, mBorderWidth ); 00113 sl->setOffset( mOffset ); 00114 return sl; 00115 } 00116 00117 //QgsSVGFillSymbolLayer 00118 00119 QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QString& svgFilePath, double width, double angle ): mPatternWidth( width ), mOutline( 0 ) 00120 { 00121 setSvgFilePath( svgFilePath ); 00122 mOutlineWidth = 0.3; 00123 mAngle = angle; 00124 setSubSymbol( new QgsLineSymbolV2() ); 00125 } 00126 00127 QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray& svgData, double width, double angle ): mPatternWidth( width ), 00128 mSvgData( svgData ), mOutline( 0 ) 00129 { 00130 storeViewBox(); 00131 mOutlineWidth = 0.3; 00132 mAngle = angle; 00133 setSubSymbol( new QgsLineSymbolV2() ); 00134 } 00135 00136 QgsSVGFillSymbolLayer::~QgsSVGFillSymbolLayer() 00137 { 00138 delete mOutline; 00139 } 00140 00141 void QgsSVGFillSymbolLayer::setSvgFilePath( const QString& svgPath ) 00142 { 00143 QFile svgFile( svgPath ); 00144 if ( svgFile.open( QFile::ReadOnly ) ) 00145 { 00146 mSvgData = svgFile.readAll(); 00147 storeViewBox(); 00148 } 00149 mSvgFilePath = svgPath; 00150 } 00151 00152 QgsSymbolLayerV2* QgsSVGFillSymbolLayer::create( const QgsStringMap& properties ) 00153 { 00154 QByteArray data; 00155 double width = 20; 00156 QString svgFilePath; 00157 double angle = 0.0; 00158 00159 00160 if ( properties.contains( "width" ) ) 00161 { 00162 width = properties["width"].toDouble(); 00163 } 00164 if ( properties.contains( "svgFile" ) ) 00165 { 00166 QString svgName = properties["svgFile"]; 00167 QString savePath = QgsSvgMarkerSymbolLayerV2::symbolNameToPath( svgName ); 00168 svgFilePath = ( savePath.isEmpty() ? svgName : savePath ); 00169 } 00170 if ( properties.contains( "angle" ) ) 00171 { 00172 angle = properties["angle"].toDouble(); 00173 } 00174 00175 if ( !svgFilePath.isEmpty() ) 00176 { 00177 return new QgsSVGFillSymbolLayer( svgFilePath, width, angle ); 00178 } 00179 else 00180 { 00181 if ( properties.contains( "data" ) ) 00182 { 00183 data = QByteArray::fromHex( properties["data"].toLocal8Bit() ); 00184 } 00185 00186 return new QgsSVGFillSymbolLayer( data, width, angle ); 00187 } 00188 } 00189 00190 QString QgsSVGFillSymbolLayer::layerType() const 00191 { 00192 return "SVGFill"; 00193 } 00194 00195 void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) 00196 { 00197 if ( mSvgViewBox.isNull() ) 00198 { 00199 return; 00200 } 00201 00202 //create QImage with appropriate dimensions 00203 int pixelWidth = context.outputPixelSize( mPatternWidth ); 00204 int pixelHeight = pixelWidth / mSvgViewBox.width() * mSvgViewBox.height(); 00205 00206 QImage textureImage( pixelWidth, pixelHeight, QImage::Format_ARGB32_Premultiplied ); 00207 textureImage.fill( 0 ); // transparent background 00208 00209 //rasterise byte array to image 00210 QPainter p( &textureImage ); 00211 QSvgRenderer r( mSvgData ); 00212 if ( !r.isValid() ) 00213 { 00214 return; 00215 } 00216 00217 r.render( &p ); 00218 00219 if ( context.alpha() < 1.0 ) 00220 { 00221 QgsSymbolLayerV2Utils::multiplyImageOpacity( &textureImage, context.alpha() ); 00222 } 00223 00224 QTransform brushTransform; 00225 brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); 00226 mBrush.setTextureImage( textureImage ); 00227 mBrush.setTransform( brushTransform ); 00228 00229 if ( mOutline ) 00230 { 00231 mOutline->startRender( context.renderContext() ); 00232 } 00233 } 00234 00235 void QgsSVGFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context ) 00236 { 00237 if ( mOutline ) 00238 { 00239 mOutline->stopRender( context.renderContext() ); 00240 } 00241 } 00242 00243 void QgsSVGFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) 00244 { 00245 QPainter* p = context.renderContext().painter(); 00246 if ( !p ) 00247 { 00248 return; 00249 } 00250 p->setPen( QPen( Qt::NoPen ) ); 00251 if ( context.selected() ) 00252 { 00253 QColor selColor = context.selectionColor(); 00254 if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() ); 00255 p->setBrush( QBrush( selColor ) ); 00256 _renderPolygon( p, points, rings ); 00257 } 00258 00259 if ( doubleNear( mAngle, 0.0 ) ) 00260 { 00261 p->setBrush( mBrush ); 00262 } 00263 else 00264 { 00265 QTransform t = mBrush.transform(); 00266 t.rotate( mAngle ); 00267 QBrush rotatedBrush = mBrush; 00268 rotatedBrush.setTransform( t ); 00269 p->setBrush( rotatedBrush ); 00270 } 00271 _renderPolygon( p, points, rings ); 00272 if ( mOutline ) 00273 { 00274 mOutline->renderPolyline( points, context.renderContext(), -1, selectFillBorder && context.selected() ); 00275 if ( rings ) 00276 { 00277 QList<QPolygonF>::const_iterator ringIt = rings->constBegin(); 00278 for ( ; ringIt != rings->constEnd(); ++ringIt ) 00279 { 00280 mOutline->renderPolyline( *ringIt, context.renderContext(), -1, selectFillBorder && context.selected() ); 00281 } 00282 } 00283 } 00284 } 00285 00286 QgsStringMap QgsSVGFillSymbolLayer::properties() const 00287 { 00288 QgsStringMap map; 00289 if ( !mSvgFilePath.isEmpty() ) 00290 { 00291 map.insert( "svgFile", QgsSvgMarkerSymbolLayerV2::symbolPathToName( mSvgFilePath ) ); 00292 } 00293 else 00294 { 00295 map.insert( "data", QString( mSvgData.toHex() ) ); 00296 } 00297 00298 map.insert( "width", QString::number( mPatternWidth ) ); 00299 map.insert( "angle", QString::number( mAngle ) ); 00300 return map; 00301 } 00302 00303 QgsSymbolLayerV2* QgsSVGFillSymbolLayer::clone() const 00304 { 00305 QgsSymbolLayerV2* clonedLayer = 0; 00306 if ( !mSvgFilePath.isEmpty() ) 00307 { 00308 clonedLayer = new QgsSVGFillSymbolLayer( mSvgFilePath, mPatternWidth, mAngle ); 00309 } 00310 else 00311 { 00312 clonedLayer = new QgsSVGFillSymbolLayer( mSvgData, mPatternWidth, mAngle ); 00313 } 00314 00315 if ( mOutline ) 00316 { 00317 clonedLayer->setSubSymbol( mOutline->clone() ); 00318 } 00319 return clonedLayer; 00320 } 00321 00322 void QgsSVGFillSymbolLayer::storeViewBox() 00323 { 00324 if ( !mSvgData.isEmpty() ) 00325 { 00326 QSvgRenderer r( mSvgData ); 00327 if ( r.isValid() ) 00328 { 00329 mSvgViewBox = r.viewBoxF(); 00330 return; 00331 } 00332 } 00333 00334 mSvgViewBox = QRectF(); 00335 return; 00336 } 00337 00338 bool QgsSVGFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol ) 00339 { 00340 if ( !symbol || symbol->type() != QgsSymbolV2::Line ) 00341 { 00342 delete symbol; 00343 return false; 00344 } 00345 00346 QgsLineSymbolV2* lineSymbol = dynamic_cast<QgsLineSymbolV2*>( symbol ); 00347 if ( lineSymbol ) 00348 { 00349 delete mOutline; 00350 mOutline = lineSymbol; 00351 return true; 00352 } 00353 00354 delete symbol; 00355 return false; 00356 } 00357 00358 00360 00361 00362 QgsCentroidFillSymbolLayerV2::QgsCentroidFillSymbolLayerV2() 00363 { 00364 mMarker = NULL; 00365 setSubSymbol( new QgsMarkerSymbolV2() ); 00366 } 00367 00368 QgsCentroidFillSymbolLayerV2::~QgsCentroidFillSymbolLayerV2() 00369 { 00370 delete mMarker; 00371 } 00372 00373 QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::create( const QgsStringMap& /*properties*/ ) 00374 { 00375 return new QgsCentroidFillSymbolLayerV2(); 00376 } 00377 00378 QString QgsCentroidFillSymbolLayerV2::layerType() const 00379 { 00380 return "CentroidFill"; 00381 } 00382 00383 void QgsCentroidFillSymbolLayerV2::setColor( const QColor& color ) 00384 { 00385 mMarker->setColor( color ); 00386 mColor = color; 00387 } 00388 00389 void QgsCentroidFillSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) 00390 { 00391 mMarker->setAlpha( context.alpha() ); 00392 mMarker->setOutputUnit( context.outputUnit() ); 00393 00394 mMarker->startRender( context.renderContext() ); 00395 } 00396 00397 void QgsCentroidFillSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context ) 00398 { 00399 mMarker->stopRender( context.renderContext() ); 00400 } 00401 00402 void QgsCentroidFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) 00403 { 00404 // calculate centroid 00405 double cx = 0, cy = 0; 00406 double area, sum = 0; 00407 for ( int i = points.count() - 1, j = 0; j < points.count(); i = j++ ) 00408 { 00409 const QPointF& p1 = points[i]; 00410 const QPointF& p2 = points[j]; 00411 area = p1.x() * p2.y() - p1.y() * p2.x(); 00412 sum += area; 00413 cx += ( p1.x() + p2.x() ) * area; 00414 cy += ( p1.y() + p2.y() ) * area; 00415 } 00416 sum *= 3.0; 00417 cx /= sum; 00418 cy /= sum; 00419 00420 mMarker->renderPoint( QPointF( cx, cy ), context.renderContext(), -1, context.selected() ); 00421 } 00422 00423 QgsStringMap QgsCentroidFillSymbolLayerV2::properties() const 00424 { 00425 return QgsStringMap(); 00426 } 00427 00428 QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::clone() const 00429 { 00430 QgsCentroidFillSymbolLayerV2* x = new QgsCentroidFillSymbolLayerV2(); 00431 x->setSubSymbol( mMarker->clone() ); 00432 return x; 00433 } 00434 00435 00436 QgsSymbolV2* QgsCentroidFillSymbolLayerV2::subSymbol() 00437 { 00438 return mMarker; 00439 } 00440 00441 bool QgsCentroidFillSymbolLayerV2::setSubSymbol( QgsSymbolV2* symbol ) 00442 { 00443 if ( symbol == NULL || symbol->type() != QgsSymbolV2::Marker ) 00444 { 00445 delete symbol; 00446 return false; 00447 } 00448 00449 delete mMarker; 00450 mMarker = static_cast<QgsMarkerSymbolV2*>( symbol ); 00451 mColor = mMarker->color(); 00452 return true; 00453 }