Quantum GIS API Documentation
1.8
|
00001 /*************************************************************************** 00002 qgsfillsymbollayerv2.cpp 00003 --------------------- 00004 begin : November 2009 00005 copyright : (C) 2009 by Martin Dobias 00006 email : wonder.sk at gmail.com 00007 *************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 #include "qgsfillsymbollayerv2.h" 00016 #include "qgsmarkersymbollayerv2.h" 00017 #include "qgssymbollayerv2utils.h" 00018 00019 #include "qgsrendercontext.h" 00020 #include "qgsproject.h" 00021 #include "qgssvgcache.h" 00022 #include "qgslogger.h" 00023 00024 #include <QPainter> 00025 #include <QFile> 00026 #include <QSvgRenderer> 00027 #include <QDomDocument> 00028 #include <QDomElement> 00029 00030 QgsSimpleFillSymbolLayerV2::QgsSimpleFillSymbolLayerV2( QColor color, Qt::BrushStyle style, QColor borderColor, Qt::PenStyle borderStyle, double borderWidth ) 00031 : mBrushStyle( style ), mBorderColor( borderColor ), mBorderStyle( borderStyle ), mBorderWidth( borderWidth ) 00032 { 00033 mColor = color; 00034 } 00035 00036 00037 QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::create( const QgsStringMap& props ) 00038 { 00039 QColor color = DEFAULT_SIMPLEFILL_COLOR; 00040 Qt::BrushStyle style = DEFAULT_SIMPLEFILL_STYLE; 00041 QColor borderColor = DEFAULT_SIMPLEFILL_BORDERCOLOR; 00042 Qt::PenStyle borderStyle = DEFAULT_SIMPLEFILL_BORDERSTYLE; 00043 double borderWidth = DEFAULT_SIMPLEFILL_BORDERWIDTH; 00044 QPointF offset; 00045 00046 if ( props.contains( "color" ) ) 00047 color = QgsSymbolLayerV2Utils::decodeColor( props["color"] ); 00048 if ( props.contains( "style" ) ) 00049 style = QgsSymbolLayerV2Utils::decodeBrushStyle( props["style"] ); 00050 if ( props.contains( "color_border" ) ) 00051 borderColor = QgsSymbolLayerV2Utils::decodeColor( props["color_border"] ); 00052 if ( props.contains( "style_border" ) ) 00053 borderStyle = QgsSymbolLayerV2Utils::decodePenStyle( props["style_border"] ); 00054 if ( props.contains( "width_border" ) ) 00055 borderWidth = props["width_border"].toDouble(); 00056 if ( props.contains( "offset" ) ) 00057 offset = QgsSymbolLayerV2Utils::decodePoint( props["offset"] ); 00058 00059 QgsSimpleFillSymbolLayerV2* sl = new QgsSimpleFillSymbolLayerV2( color, style, borderColor, borderStyle, borderWidth ); 00060 sl->setOffset( offset ); 00061 return sl; 00062 } 00063 00064 00065 QString QgsSimpleFillSymbolLayerV2::layerType() const 00066 { 00067 return "SimpleFill"; 00068 } 00069 00070 void QgsSimpleFillSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) 00071 { 00072 mColor.setAlphaF( context.alpha() ); 00073 mBrush = QBrush( mColor, mBrushStyle ); 00074 00075 // scale brush content for printout 00076 double rasterScaleFactor = context.renderContext().rasterScaleFactor(); 00077 if ( rasterScaleFactor != 1.0 ) 00078 { 00079 mBrush.setMatrix( QMatrix().scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ) ); 00080 } 00081 00082 QColor selColor = context.selectionColor(); 00083 // selColor.setAlphaF( context.alpha() ); 00084 mSelBrush = QBrush( selColor ); 00085 if ( selectFillStyle ) 00086 mSelBrush.setStyle( mBrushStyle ); 00087 mBorderColor.setAlphaF( context.alpha() ); 00088 mPen = QPen( mBorderColor ); 00089 mPen.setStyle( mBorderStyle ); 00090 mPen.setWidthF( context.outputLineWidth( mBorderWidth ) ); 00091 } 00092 00093 void QgsSimpleFillSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context ) 00094 { 00095 Q_UNUSED( context ); 00096 } 00097 00098 void QgsSimpleFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) 00099 { 00100 QPainter* p = context.renderContext().painter(); 00101 if ( !p ) 00102 { 00103 return; 00104 } 00105 00106 p->setBrush( context.selected() ? mSelBrush : mBrush ); 00107 p->setPen( mPen ); 00108 00109 if ( !mOffset.isNull() ) 00110 p->translate( mOffset ); 00111 00112 _renderPolygon( p, points, rings ); 00113 00114 if ( !mOffset.isNull() ) 00115 p->translate( -mOffset ); 00116 } 00117 00118 QgsStringMap QgsSimpleFillSymbolLayerV2::properties() const 00119 { 00120 QgsStringMap map; 00121 map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor ); 00122 map["style"] = QgsSymbolLayerV2Utils::encodeBrushStyle( mBrushStyle ); 00123 map["color_border"] = QgsSymbolLayerV2Utils::encodeColor( mBorderColor ); 00124 map["style_border"] = QgsSymbolLayerV2Utils::encodePenStyle( mBorderStyle ); 00125 map["width_border"] = QString::number( mBorderWidth ); 00126 map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset ); 00127 return map; 00128 } 00129 00130 QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::clone() const 00131 { 00132 QgsSimpleFillSymbolLayerV2* sl = new QgsSimpleFillSymbolLayerV2( mColor, mBrushStyle, mBorderColor, mBorderStyle, mBorderWidth ); 00133 sl->setOffset( mOffset ); 00134 return sl; 00135 } 00136 00137 void QgsSimpleFillSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const 00138 { 00139 if ( mBrushStyle == Qt::NoBrush && mBorderStyle == Qt::NoPen ) 00140 return; 00141 00142 QDomElement symbolizerElem = doc.createElement( "se:PolygonSymbolizer" ); 00143 if ( !props.value( "uom", "" ).isEmpty() ) 00144 symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) ); 00145 element.appendChild( symbolizerElem ); 00146 00147 // <Geometry> 00148 QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) ); 00149 00150 if ( mBrushStyle != Qt::NoBrush ) 00151 { 00152 // <Fill> 00153 QDomElement fillElem = doc.createElement( "se:Fill" ); 00154 symbolizerElem.appendChild( fillElem ); 00155 QgsSymbolLayerV2Utils::fillToSld( doc, fillElem, mBrushStyle, mColor ); 00156 } 00157 00158 if ( mBorderStyle != Qt::NoPen ) 00159 { 00160 // <Stroke> 00161 QDomElement strokeElem = doc.createElement( "se:Stroke" ); 00162 symbolizerElem.appendChild( strokeElem ); 00163 QgsSymbolLayerV2Utils::lineToSld( doc, strokeElem, mBorderStyle, mBorderColor, mBorderWidth ); 00164 } 00165 00166 // <se:Displacement> 00167 QgsSymbolLayerV2Utils::createDisplacementElement( doc, symbolizerElem, mOffset ); 00168 } 00169 00170 QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::createFromSld( QDomElement &element ) 00171 { 00172 QgsDebugMsg( "Entered." ); 00173 00174 QColor color, borderColor; 00175 Qt::BrushStyle fillStyle; 00176 Qt::PenStyle borderStyle; 00177 double borderWidth; 00178 00179 QDomElement fillElem = element.firstChildElement( "Fill" ); 00180 QgsSymbolLayerV2Utils::fillFromSld( fillElem, fillStyle, color ); 00181 00182 QDomElement strokeElem = element.firstChildElement( "Stroke" ); 00183 QgsSymbolLayerV2Utils::lineFromSld( strokeElem, borderStyle, borderColor, borderWidth ); 00184 00185 QPointF offset; 00186 QgsSymbolLayerV2Utils::displacementFromSldElement( element, offset ); 00187 00188 QgsSimpleFillSymbolLayerV2* sl = new QgsSimpleFillSymbolLayerV2( color, fillStyle, borderColor, borderStyle, borderWidth ); 00189 sl->setOffset( offset ); 00190 return sl; 00191 } 00192 00193 00194 //QgsImageFillSymbolLayer 00195 00196 QgsImageFillSymbolLayer::QgsImageFillSymbolLayer(): mOutlineWidth( 0.0 ), mOutline( 0 ) 00197 { 00198 setSubSymbol( new QgsLineSymbolV2() ); 00199 } 00200 00201 QgsImageFillSymbolLayer::~QgsImageFillSymbolLayer() 00202 { 00203 } 00204 00205 void QgsImageFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) 00206 { 00207 QPainter* p = context.renderContext().painter(); 00208 if ( !p ) 00209 { 00210 return; 00211 } 00212 p->setPen( QPen( Qt::NoPen ) ); 00213 if ( context.selected() ) 00214 { 00215 QColor selColor = context.selectionColor(); 00216 if ( ! selectionIsOpaque ) 00217 selColor.setAlphaF( context.alpha() ); 00218 p->setBrush( QBrush( selColor ) ); 00219 _renderPolygon( p, points, rings ); 00220 } 00221 00222 if ( doubleNear( mAngle, 0.0 ) ) 00223 { 00224 p->setBrush( mBrush ); 00225 } 00226 else 00227 { 00228 QTransform t = mBrush.transform(); 00229 t.rotate( mAngle ); 00230 QBrush rotatedBrush = mBrush; 00231 rotatedBrush.setTransform( t ); 00232 p->setBrush( rotatedBrush ); 00233 } 00234 _renderPolygon( p, points, rings ); 00235 if ( mOutline ) 00236 { 00237 mOutline->renderPolyline( points, context.feature(), context.renderContext(), -1, selectFillBorder && context.selected() ); 00238 if ( rings ) 00239 { 00240 QList<QPolygonF>::const_iterator ringIt = rings->constBegin(); 00241 for ( ; ringIt != rings->constEnd(); ++ringIt ) 00242 { 00243 mOutline->renderPolyline( *ringIt, context.feature(), context.renderContext(), -1, selectFillBorder && context.selected() ); 00244 } 00245 } 00246 } 00247 } 00248 00249 bool QgsImageFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol ) 00250 { 00251 if ( !symbol ) //unset current outline 00252 { 00253 delete mOutline; 00254 mOutline = 0; 00255 return true; 00256 } 00257 00258 if ( symbol->type() != QgsSymbolV2::Line ) 00259 { 00260 delete symbol; 00261 return false; 00262 } 00263 00264 QgsLineSymbolV2* lineSymbol = dynamic_cast<QgsLineSymbolV2*>( symbol ); 00265 if ( lineSymbol ) 00266 { 00267 delete mOutline; 00268 mOutline = lineSymbol; 00269 return true; 00270 } 00271 00272 delete symbol; 00273 return false; 00274 } 00275 00276 //QgsSVGFillSymbolLayer 00277 00278 QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QString& svgFilePath, double width, double angle ): QgsImageFillSymbolLayer(), mPatternWidth( width ) 00279 { 00280 setSvgFilePath( svgFilePath ); 00281 mOutlineWidth = 0.3; 00282 mAngle = angle; 00283 setDefaultSvgParams(); 00284 } 00285 00286 QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray& svgData, double width, double angle ): QgsImageFillSymbolLayer(), mPatternWidth( width ), 00287 mSvgData( svgData ) 00288 { 00289 storeViewBox(); 00290 mOutlineWidth = 0.3; 00291 mAngle = angle; 00292 setSubSymbol( new QgsLineSymbolV2() ); 00293 setDefaultSvgParams(); 00294 } 00295 00296 QgsSVGFillSymbolLayer::~QgsSVGFillSymbolLayer() 00297 { 00298 delete mOutline; 00299 } 00300 00301 void QgsSVGFillSymbolLayer::setSvgFilePath( const QString& svgPath ) 00302 { 00303 QFile svgFile( svgPath ); 00304 if ( svgFile.open( QFile::ReadOnly ) ) 00305 { 00306 mSvgData = svgFile.readAll(); 00307 00308 storeViewBox(); 00309 } 00310 mSvgFilePath = svgPath; 00311 setDefaultSvgParams(); 00312 } 00313 00314 QgsSymbolLayerV2* QgsSVGFillSymbolLayer::create( const QgsStringMap& properties ) 00315 { 00316 QByteArray data; 00317 double width = 20; 00318 QString svgFilePath; 00319 double angle = 0.0; 00320 00321 if ( properties.contains( "width" ) ) 00322 { 00323 width = properties["width"].toDouble(); 00324 } 00325 if ( properties.contains( "svgFile" ) ) 00326 { 00327 QString svgName = properties["svgFile"]; 00328 QString savePath = QgsSvgMarkerSymbolLayerV2::symbolNameToPath( svgName ); 00329 svgFilePath = ( savePath.isEmpty() ? svgName : savePath ); 00330 } 00331 if ( properties.contains( "angle" ) ) 00332 { 00333 angle = properties["angle"].toDouble(); 00334 } 00335 00336 QgsSVGFillSymbolLayer* symbolLayer = 0; 00337 if ( !svgFilePath.isEmpty() ) 00338 { 00339 symbolLayer = new QgsSVGFillSymbolLayer( svgFilePath, width, angle ); 00340 } 00341 else 00342 { 00343 if ( properties.contains( "data" ) ) 00344 { 00345 data = QByteArray::fromHex( properties["data"].toLocal8Bit() ); 00346 } 00347 symbolLayer = new QgsSVGFillSymbolLayer( data, width, angle ); 00348 } 00349 00350 //svg parameters 00351 if ( properties.contains( "svgFillColor" ) ) 00352 { 00353 symbolLayer->setSvgFillColor( QColor( properties["svgFillColor"] ) ); 00354 } 00355 if ( properties.contains( "svgOutlineColor" ) ) 00356 { 00357 symbolLayer->setSvgOutlineColor( QColor( properties["svgOutlineColor"] ) ); 00358 } 00359 if ( properties.contains( "svgOutlineWidth" ) ) 00360 { 00361 symbolLayer->setSvgOutlineWidth( properties["svgOutlineWidth"].toDouble() ); 00362 } 00363 00364 00365 return symbolLayer; 00366 } 00367 00368 QString QgsSVGFillSymbolLayer::layerType() const 00369 { 00370 return "SVGFill"; 00371 } 00372 00373 void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) 00374 { 00375 if ( mSvgViewBox.isNull() ) 00376 { 00377 return; 00378 } 00379 00380 int size = context.outputPixelSize( mPatternWidth ); 00381 const QImage& patternImage = QgsSvgCache::instance()->svgAsImage( mSvgFilePath, size, mSvgFillColor, mSvgOutlineColor, mSvgOutlineWidth, 00382 context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor() ); 00383 QTransform brushTransform; 00384 brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); 00385 if ( !doubleNear( context.alpha(), 1.0 ) ) 00386 { 00387 QImage transparentImage = patternImage.copy(); 00388 QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); 00389 mBrush.setTextureImage( transparentImage ); 00390 } 00391 else 00392 { 00393 mBrush.setTextureImage( patternImage ); 00394 } 00395 mBrush.setTransform( brushTransform ); 00396 00397 if ( mOutline ) 00398 { 00399 mOutline->startRender( context.renderContext() ); 00400 } 00401 } 00402 00403 void QgsSVGFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context ) 00404 { 00405 if ( mOutline ) 00406 { 00407 mOutline->stopRender( context.renderContext() ); 00408 } 00409 } 00410 00411 QgsStringMap QgsSVGFillSymbolLayer::properties() const 00412 { 00413 QgsStringMap map; 00414 if ( !mSvgFilePath.isEmpty() ) 00415 { 00416 map.insert( "svgFile", QgsSvgMarkerSymbolLayerV2::symbolPathToName( mSvgFilePath ) ); 00417 } 00418 else 00419 { 00420 map.insert( "data", QString( mSvgData.toHex() ) ); 00421 } 00422 00423 map.insert( "width", QString::number( mPatternWidth ) ); 00424 map.insert( "angle", QString::number( mAngle ) ); 00425 00426 //svg parameters 00427 map.insert( "svgFillColor", mSvgFillColor.name() ); 00428 map.insert( "svgOutlineColor", mSvgOutlineColor.name() ); 00429 map.insert( "svgOutlineWidth", QString::number( mSvgOutlineWidth ) ); 00430 00431 return map; 00432 } 00433 00434 QgsSymbolLayerV2* QgsSVGFillSymbolLayer::clone() const 00435 { 00436 QgsSymbolLayerV2* clonedLayer = 0; 00437 if ( !mSvgFilePath.isEmpty() ) 00438 { 00439 clonedLayer = new QgsSVGFillSymbolLayer( mSvgFilePath, mPatternWidth, mAngle ); 00440 QgsSVGFillSymbolLayer* sl = static_cast<QgsSVGFillSymbolLayer*>( clonedLayer ); 00441 sl->setSvgFillColor( mSvgFillColor ); 00442 sl->setSvgOutlineColor( mSvgOutlineColor ); 00443 sl->setSvgOutlineWidth( mSvgOutlineWidth ); 00444 } 00445 else 00446 { 00447 clonedLayer = new QgsSVGFillSymbolLayer( mSvgData, mPatternWidth, mAngle ); 00448 } 00449 00450 if ( mOutline ) 00451 { 00452 clonedLayer->setSubSymbol( mOutline->clone() ); 00453 } 00454 return clonedLayer; 00455 } 00456 00457 void QgsSVGFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const 00458 { 00459 QDomElement symbolizerElem = doc.createElement( "se:PolygonSymbolizer" ); 00460 if ( !props.value( "uom", "" ).isEmpty() ) 00461 symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) ); 00462 element.appendChild( symbolizerElem ); 00463 00464 QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) ); 00465 00466 QDomElement fillElem = doc.createElement( "se:Fill" ); 00467 symbolizerElem.appendChild( fillElem ); 00468 00469 QDomElement graphicFillElem = doc.createElement( "se:GraphicFill" ); 00470 fillElem.appendChild( graphicFillElem ); 00471 00472 QDomElement graphicElem = doc.createElement( "se:Graphic" ); 00473 graphicFillElem.appendChild( graphicElem ); 00474 00475 if ( !mSvgFilePath.isEmpty() ) 00476 { 00477 QgsSymbolLayerV2Utils::externalGraphicToSld( doc, graphicElem, mSvgFilePath, "image/svg+xml", mSvgFillColor, mPatternWidth ); 00478 } 00479 else 00480 { 00481 // TODO: create svg from data 00482 // <se:InlineContent> 00483 symbolizerElem.appendChild( doc.createComment( "SVG from data not implemented yet" ) ); 00484 } 00485 00486 if ( mSvgOutlineColor.isValid() || mSvgOutlineWidth >= 0 ) 00487 { 00488 QgsSymbolLayerV2Utils::lineToSld( doc, graphicElem, Qt::SolidLine, mSvgOutlineColor, mSvgOutlineWidth ); 00489 } 00490 00491 // <Rotation> 00492 QString angleFunc; 00493 bool ok; 00494 double angle = props.value( "angle", "0" ).toDouble( &ok ); 00495 if ( !ok ) 00496 { 00497 angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle ); 00498 } 00499 else if ( angle + mAngle != 0 ) 00500 { 00501 angleFunc = QString::number( angle + mAngle ); 00502 } 00503 QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc ); 00504 00505 if ( mOutline ) 00506 { 00507 // the outline sub symbol should be stored within the Stroke element, 00508 // but it will be stored in a separated LineSymbolizer because it could 00509 // have more than one layer 00510 mOutline->toSld( doc, element, props ); 00511 } 00512 } 00513 00514 QgsSymbolLayerV2* QgsSVGFillSymbolLayer::createFromSld( QDomElement &element ) 00515 { 00516 QgsDebugMsg( "Entered." ); 00517 00518 QString path, mimeType; 00519 QColor fillColor, borderColor; 00520 Qt::PenStyle penStyle; 00521 double size, borderWidth; 00522 00523 QDomElement fillElem = element.firstChildElement( "Fill" ); 00524 if ( fillElem.isNull() ) 00525 return NULL; 00526 00527 QDomElement graphicFillElem = fillElem.firstChildElement( "GraphicFill" ); 00528 if ( graphicFillElem.isNull() ) 00529 return NULL; 00530 00531 QDomElement graphicElem = graphicFillElem.firstChildElement( "Graphic" ); 00532 if ( graphicElem.isNull() ) 00533 return NULL; 00534 00535 if ( !QgsSymbolLayerV2Utils::externalGraphicFromSld( graphicElem, path, mimeType, fillColor, size ) ) 00536 return NULL; 00537 00538 if ( mimeType != "image/svg+xml" ) 00539 return NULL; 00540 00541 QgsSymbolLayerV2Utils::lineFromSld( graphicElem, penStyle, borderColor, borderWidth ); 00542 00543 double angle = 0.0; 00544 QString angleFunc; 00545 if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) ) 00546 { 00547 bool ok; 00548 double d = angleFunc.toDouble( &ok ); 00549 if ( ok ) 00550 angle = d; 00551 } 00552 00553 QgsSVGFillSymbolLayer* sl = new QgsSVGFillSymbolLayer( path, size, angle ); 00554 sl->setSvgFillColor( fillColor ); 00555 sl->setSvgOutlineColor( borderColor ); 00556 sl->setSvgOutlineWidth( borderWidth ); 00557 00558 // try to get the outline 00559 QDomElement strokeElem = element.firstChildElement( "Stroke" ); 00560 if ( !strokeElem.isNull() ) 00561 { 00562 QgsSymbolLayerV2 *l = QgsSymbolLayerV2Utils::createLineLayerFromSld( strokeElem ); 00563 if ( l ) 00564 { 00565 QgsSymbolLayerV2List layers; 00566 layers.append( l ); 00567 sl->setSubSymbol( new QgsLineSymbolV2( layers ) ); 00568 } 00569 } 00570 00571 return sl; 00572 } 00573 00574 void QgsSVGFillSymbolLayer::storeViewBox() 00575 { 00576 if ( !mSvgData.isEmpty() ) 00577 { 00578 QSvgRenderer r( mSvgData ); 00579 if ( r.isValid() ) 00580 { 00581 mSvgViewBox = r.viewBoxF(); 00582 return; 00583 } 00584 } 00585 00586 mSvgViewBox = QRectF(); 00587 return; 00588 } 00589 00590 void QgsSVGFillSymbolLayer::setDefaultSvgParams() 00591 { 00592 //default values 00593 mSvgFillColor = QColor( 0, 0, 0 ); 00594 mSvgOutlineColor = QColor( 0, 0, 0 ); 00595 mSvgOutlineWidth = 0.3; 00596 00597 if ( mSvgFilePath.isEmpty() ) 00598 { 00599 return; 00600 } 00601 00602 bool hasFillParam, hasOutlineParam, hasOutlineWidthParam; 00603 QColor defaultFillColor, defaultOutlineColor; 00604 double defaultOutlineWidth; 00605 QgsSvgCache::instance()->containsParams( mSvgFilePath, hasFillParam, defaultFillColor, hasOutlineParam, defaultOutlineColor, hasOutlineWidthParam, 00606 defaultOutlineWidth ); 00607 00608 if ( hasFillParam ) 00609 { 00610 mSvgFillColor = defaultFillColor; 00611 } 00612 if ( hasOutlineParam ) 00613 { 00614 mSvgOutlineColor = defaultOutlineColor; 00615 } 00616 if ( hasOutlineWidthParam ) 00617 { 00618 mSvgOutlineWidth = defaultOutlineWidth; 00619 } 00620 } 00621 00622 QgsLinePatternFillSymbolLayer::QgsLinePatternFillSymbolLayer(): QgsImageFillSymbolLayer() 00623 { 00624 } 00625 00626 QgsLinePatternFillSymbolLayer::~QgsLinePatternFillSymbolLayer() 00627 { 00628 } 00629 00630 QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::create( const QgsStringMap& properties ) 00631 { 00632 QgsLinePatternFillSymbolLayer* patternLayer = new QgsLinePatternFillSymbolLayer(); 00633 00634 //default values 00635 double lineAngle = 45; 00636 double distance = 5; 00637 double lineWidth = 0.5; 00638 QColor color( Qt::black ); 00639 double offset = 0.0; 00640 00641 if ( properties.contains( "lineangle" ) ) 00642 { 00643 lineAngle = properties["lineangle"].toDouble(); 00644 } 00645 patternLayer->setLineAngle( lineAngle ); 00646 00647 if ( properties.contains( "distance" ) ) 00648 { 00649 distance = properties["distance"].toDouble(); 00650 } 00651 patternLayer->setDistance( distance ); 00652 00653 if ( properties.contains( "linewidth" ) ) 00654 { 00655 lineWidth = properties["linewidth"].toDouble(); 00656 } 00657 patternLayer->setLineWidth( lineWidth ); 00658 00659 if ( properties.contains( "color" ) ) 00660 { 00661 color = QgsSymbolLayerV2Utils::decodeColor( properties["color"] ); 00662 } 00663 patternLayer->setColor( color ); 00664 00665 if ( properties.contains( "offset" ) ) 00666 { 00667 offset = properties["offset"].toDouble(); 00668 } 00669 patternLayer->setOffset( offset ); 00670 return patternLayer; 00671 } 00672 00673 QString QgsLinePatternFillSymbolLayer::layerType() const 00674 { 00675 return "LinePatternFill"; 00676 } 00677 00678 void QgsLinePatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) 00679 { 00680 double outlinePixelWidth = context.outputPixelSize( mLineWidth ); 00681 double outputPixelDist = context.outputPixelSize( mDistance ); 00682 double outputPixelOffset = context.outputPixelSize( mOffset ); 00683 00684 //create image 00685 int height, width; 00686 if ( doubleNear( mLineAngle, 0 ) || doubleNear( mLineAngle, 360 ) || doubleNear( mLineAngle, 90 ) || doubleNear( mLineAngle, 180 ) || doubleNear( mLineAngle, 270 ) ) 00687 { 00688 height = outputPixelDist; 00689 width = height; //width can be set to arbitrary value 00690 } 00691 else 00692 { 00693 height = qAbs( outputPixelDist / cos( mLineAngle * M_PI / 180 ) ); //keep perpendicular distance between lines constant 00694 width = qAbs( height / tan( mLineAngle * M_PI / 180 ) ); 00695 } 00696 00697 //depending on the angle, we might need to render into a larger image and use a subset of it 00698 int dx = 0; 00699 int dy = 0; 00700 00701 QImage patternImage( width, height, QImage::Format_ARGB32 ); 00702 patternImage.fill( 0 ); 00703 QPainter p( &patternImage ); 00704 00705 p.setRenderHint( QPainter::Antialiasing, true ); 00706 QPen pen( mColor ); 00707 pen.setWidthF( outlinePixelWidth ); 00708 pen.setCapStyle( Qt::FlatCap ); 00709 p.setPen( pen ); 00710 00711 QPoint p1, p2, p3, p4, p5, p6; 00712 if ( doubleNear( mLineAngle, 0.0 ) || doubleNear( mLineAngle, 360.0 ) || doubleNear( mLineAngle, 180.0 ) ) 00713 { 00714 p1 = QPoint( 0, height ); 00715 p2 = QPoint( width, height ); 00716 p3 = QPoint( 0, 0 ); 00717 p4 = QPoint( width, 0 ); 00718 p5 = QPoint( 0, 2 * height ); 00719 p6 = QPoint( width, 2 * height ); 00720 } 00721 else if ( doubleNear( mLineAngle, 90.0 ) || doubleNear( mLineAngle, 270.0 ) ) 00722 { 00723 p1 = QPoint( 0, height ); 00724 p2 = QPoint( 0, 0 ); 00725 p3 = QPoint( width, height ); 00726 p4 = QPoint( width, 0 ); 00727 p5 = QPoint( -width, height ); 00728 p6 = QPoint( -width, 0 ); 00729 } 00730 else if (( mLineAngle > 0 && mLineAngle < 90 ) || ( mLineAngle > 180 && mLineAngle < 270 ) ) 00731 { 00732 dx = outputPixelDist * cos(( 90 - mLineAngle ) * M_PI / 180.0 ); 00733 dy = outputPixelDist * sin(( 90 - mLineAngle ) * M_PI / 180.0 ); 00734 p1 = QPoint( 0, height ); 00735 p2 = QPoint( width, 0 ); 00736 p3 = QPoint( -dx, height - dy ); 00737 p4 = QPoint( width - dx, -dy ); //p4 = QPoint( p3.x() + width, p3.y() - height ); 00738 p5 = QPoint( dx, height + dy ); 00739 p6 = QPoint( width + dx, dy ); //p6 = QPoint( p5.x() + width, p5.y() - height ); 00740 } 00741 else if (( mLineAngle < 180 ) || ( mLineAngle > 270 && mLineAngle < 360 ) ) 00742 { 00743 dy = outputPixelDist * cos(( 180 - mLineAngle ) * M_PI / 180 ); 00744 dx = outputPixelDist * sin(( 180 - mLineAngle ) * M_PI / 180 ); 00745 p1 = QPoint( width, height ); 00746 p2 = QPoint( 0, 0 ); 00747 p5 = QPoint( width + dx, height - dy ); 00748 p6 = QPoint( p5.x() - width, p5.y() - height ); //p6 = QPoint( dx, -dy ); 00749 p3 = QPoint( width - dx, height + dy ); 00750 p4 = QPoint( p3.x() - width, p3.y() - height ); //p4 = QPoint( -dx, dy ); 00751 } 00752 00753 if ( !doubleNear( mOffset, 0.0 ) ) //shift everything 00754 { 00755 QPointF tempPt; 00756 tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p3, outputPixelDist + outputPixelOffset ); 00757 p3 = QPoint( tempPt.x(), tempPt.y() ); 00758 tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p4, outputPixelDist + outputPixelOffset ); 00759 p4 = QPoint( tempPt.x(), tempPt.y() ); 00760 tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p5, outputPixelDist - outputPixelOffset ); 00761 p5 = QPoint( tempPt.x(), tempPt.y() ); 00762 tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p6, outputPixelDist - outputPixelOffset ); 00763 p6 = QPoint( tempPt.x(), tempPt.y() ); 00764 00765 //update p1, p2 last 00766 tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p1, p3, outputPixelOffset ).toPoint(); 00767 p1 = QPoint( tempPt.x(), tempPt.y() ); 00768 tempPt = QgsSymbolLayerV2Utils::pointOnLineWithDistance( p2, p4, outputPixelOffset ).toPoint(); 00769 p2 = QPoint( tempPt.x(), tempPt.y() );; 00770 } 00771 00772 p.drawLine( p1, p2 ); 00773 p.drawLine( p3, p4 ); 00774 p.drawLine( p5, p6 ); 00775 p.end(); 00776 00777 //set image to mBrush 00778 if ( !doubleNear( context.alpha(), 1.0 ) ) 00779 { 00780 QImage transparentImage = patternImage.copy(); 00781 QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); 00782 mBrush.setTextureImage( transparentImage ); 00783 } 00784 else 00785 { 00786 mBrush.setTextureImage( patternImage ); 00787 } 00788 00789 QTransform brushTransform; 00790 brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); 00791 mBrush.setTransform( brushTransform ); 00792 00793 if ( mOutline ) 00794 { 00795 mOutline->startRender( context.renderContext() ); 00796 } 00797 } 00798 00799 void QgsLinePatternFillSymbolLayer::stopRender( QgsSymbolV2RenderContext & ) 00800 { 00801 } 00802 00803 QgsStringMap QgsLinePatternFillSymbolLayer::properties() const 00804 { 00805 QgsStringMap map; 00806 map.insert( "lineangle", QString::number( mLineAngle ) ); 00807 map.insert( "distance", QString::number( mDistance ) ); 00808 map.insert( "linewidth", QString::number( mLineWidth ) ); 00809 map.insert( "color", QgsSymbolLayerV2Utils::encodeColor( mColor ) ); 00810 map.insert( "offset", QString::number( mOffset ) ); 00811 return map; 00812 } 00813 00814 QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::clone() const 00815 { 00816 QgsSymbolLayerV2* clonedLayer = QgsLinePatternFillSymbolLayer::create( properties() ); 00817 if ( mOutline ) 00818 { 00819 clonedLayer->setSubSymbol( mOutline->clone() ); 00820 } 00821 return clonedLayer; 00822 } 00823 00824 void QgsLinePatternFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const 00825 { 00826 QDomElement symbolizerElem = doc.createElement( "se:PolygonSymbolizer" ); 00827 if ( !props.value( "uom", "" ).isEmpty() ) 00828 symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) ); 00829 element.appendChild( symbolizerElem ); 00830 00831 // <Geometry> 00832 QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) ); 00833 00834 QDomElement fillElem = doc.createElement( "se:Fill" ); 00835 symbolizerElem.appendChild( fillElem ); 00836 00837 QDomElement graphicFillElem = doc.createElement( "se:GraphicFill" ); 00838 fillElem.appendChild( graphicFillElem ); 00839 00840 QDomElement graphicElem = doc.createElement( "se:Graphic" ); 00841 graphicFillElem.appendChild( graphicElem ); 00842 00843 QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, "horline", QColor(), mColor, mLineWidth, mDistance ); 00844 00845 // <Rotation> 00846 QString angleFunc; 00847 bool ok; 00848 double angle = props.value( "angle", "0" ).toDouble( &ok ); 00849 if ( !ok ) 00850 { 00851 angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mLineAngle ); 00852 } 00853 else if ( angle + mLineAngle != 0 ) 00854 { 00855 angleFunc = QString::number( angle + mLineAngle ); 00856 } 00857 QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc ); 00858 00859 // <se:Displacement> 00860 QPointF lineOffset( qSin( mLineAngle ) * mOffset, qCos( mLineAngle ) * mOffset ); 00861 QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, lineOffset ); 00862 } 00863 00864 QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::createFromSld( QDomElement &element ) 00865 { 00866 Q_UNUSED( element ); 00867 return NULL; 00868 } 00869 00871 00872 QgsPointPatternFillSymbolLayer::QgsPointPatternFillSymbolLayer(): QgsImageFillSymbolLayer(), mMarkerSymbol( 0 ), mDistanceX( 15 ), 00873 mDistanceY( 15 ), mDisplacementX( 0 ), mDisplacementY( 0 ) 00874 { 00875 mDistanceX = 15; 00876 mDistanceY = 15; 00877 mDisplacementX = 0; 00878 mDisplacementY = 0; 00879 setSubSymbol( new QgsMarkerSymbolV2() ); 00880 QgsImageFillSymbolLayer::setSubSymbol( 0 ); //no outline 00881 } 00882 00883 QgsPointPatternFillSymbolLayer::~QgsPointPatternFillSymbolLayer() 00884 { 00885 } 00886 00887 QgsSymbolLayerV2* QgsPointPatternFillSymbolLayer::create( const QgsStringMap& properties ) 00888 { 00889 QgsPointPatternFillSymbolLayer* layer = new QgsPointPatternFillSymbolLayer(); 00890 if ( properties.contains( "distance_x" ) ) 00891 { 00892 layer->setDistanceX( properties["distance_x"].toDouble() ); 00893 } 00894 if ( properties.contains( "distance_y" ) ) 00895 { 00896 layer->setDistanceY( properties["distance_y"].toDouble() ); 00897 } 00898 if ( properties.contains( "displacement_x" ) ) 00899 { 00900 layer->setDisplacementX( properties["displacement_x"].toDouble() ); 00901 } 00902 if ( properties.contains( "displacement_y" ) ) 00903 { 00904 layer->setDisplacementY( properties["displacement_y"].toDouble() ); 00905 } 00906 return layer; 00907 } 00908 00909 QString QgsPointPatternFillSymbolLayer::layerType() const 00910 { 00911 return "PointPatternFill"; 00912 } 00913 00914 void QgsPointPatternFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context ) 00915 { 00916 //render 3 rows and columns in one go to easily incorporate displacement 00917 double width = context.outputPixelSize( mDistanceX ) * 2.0; 00918 double height = context.outputPixelSize( mDistanceY ) * 2.0; 00919 00920 QImage patternImage( width, height, QImage::Format_ARGB32 ); 00921 patternImage.fill( 0 ); 00922 00923 if ( mMarkerSymbol ) 00924 { 00925 QPainter p( &patternImage ); 00926 00927 //marker rendering needs context for drawing on patternImage 00928 QgsRenderContext pointRenderContext; 00929 pointRenderContext.setPainter( &p ); 00930 pointRenderContext.setRasterScaleFactor( 1.0 ); 00931 pointRenderContext.setScaleFactor( context.renderContext().scaleFactor() * context.renderContext().rasterScaleFactor() ); 00932 QgsMapToPixel mtp( context.renderContext().mapToPixel().mapUnitsPerPixel() / context.renderContext().rasterScaleFactor() ); 00933 pointRenderContext.setMapToPixel( mtp ); 00934 pointRenderContext.setForceVectorOutput( false ); 00935 00936 mMarkerSymbol->setOutputUnit( context.outputUnit() ); 00937 mMarkerSymbol->startRender( pointRenderContext ); 00938 00939 //render corner points 00940 mMarkerSymbol->renderPoint( QPointF( 0, 0 ), context.feature(), pointRenderContext ); 00941 mMarkerSymbol->renderPoint( QPointF( width, 0 ), context.feature(), pointRenderContext ); 00942 mMarkerSymbol->renderPoint( QPointF( 0, height ), context.feature(), pointRenderContext ); 00943 mMarkerSymbol->renderPoint( QPointF( width, height ), context.feature(), pointRenderContext ); 00944 00945 //render displaced points 00946 double displacementPixelX = context.outputPixelSize( mDisplacementX ); 00947 double displacementPixelY = context.outputPixelSize( mDisplacementY ); 00948 mMarkerSymbol->renderPoint( QPointF( width / 2.0, -displacementPixelY ), context.feature(), pointRenderContext ); 00949 mMarkerSymbol->renderPoint( QPointF( displacementPixelX, height / 2.0 ), context.feature(), pointRenderContext ); 00950 mMarkerSymbol->renderPoint( QPointF( width / 2.0 + displacementPixelX, height / 2.0 - displacementPixelY ), context.feature(), pointRenderContext ); 00951 mMarkerSymbol->renderPoint( QPointF( width + displacementPixelX, height / 2.0 ), context.feature(), pointRenderContext ); 00952 mMarkerSymbol->renderPoint( QPointF( width / 2.0, height - displacementPixelY ), context.feature(), pointRenderContext ); 00953 00954 mMarkerSymbol->stopRender( pointRenderContext ); 00955 } 00956 00957 if ( !doubleNear( context.alpha(), 1.0 ) ) 00958 { 00959 QImage transparentImage = patternImage.copy(); 00960 QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() ); 00961 mBrush.setTextureImage( transparentImage ); 00962 } 00963 else 00964 { 00965 mBrush.setTextureImage( patternImage ); 00966 } 00967 QTransform brushTransform; 00968 brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() ); 00969 mBrush.setTransform( brushTransform ); 00970 00971 if ( mOutline ) 00972 { 00973 mOutline->startRender( context.renderContext() ); 00974 } 00975 } 00976 00977 void QgsPointPatternFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context ) 00978 { 00979 if ( mOutline ) 00980 { 00981 mOutline->stopRender( context.renderContext() ); 00982 } 00983 } 00984 00985 QgsStringMap QgsPointPatternFillSymbolLayer::properties() const 00986 { 00987 QgsStringMap propertyMap; 00988 propertyMap["distance_x"] = QString::number( mDistanceX ); 00989 propertyMap["distance_y"] = QString::number( mDistanceY ); 00990 propertyMap["displacement_x"] = QString::number( mDisplacementX ); 00991 propertyMap["displacement_y"] = QString::number( mDisplacementY ); 00992 return propertyMap; 00993 } 00994 00995 QgsSymbolLayerV2* QgsPointPatternFillSymbolLayer::clone() const 00996 { 00997 QgsSymbolLayerV2* clonedLayer = QgsPointPatternFillSymbolLayer::create( properties() ); 00998 if ( mMarkerSymbol ) 00999 { 01000 clonedLayer->setSubSymbol( mMarkerSymbol->clone() ); 01001 } 01002 return clonedLayer; 01003 } 01004 01005 void QgsPointPatternFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const 01006 { 01007 for ( int i = 0; i < mMarkerSymbol->symbolLayerCount(); i++ ) 01008 { 01009 QDomElement symbolizerElem = doc.createElement( "se:PolygonSymbolizer" ); 01010 if ( !props.value( "uom", "" ).isEmpty() ) 01011 symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) ); 01012 element.appendChild( symbolizerElem ); 01013 01014 // <Geometry> 01015 QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) ); 01016 01017 QDomElement fillElem = doc.createElement( "se:Fill" ); 01018 symbolizerElem.appendChild( fillElem ); 01019 01020 QDomElement graphicFillElem = doc.createElement( "se:GraphicFill" ); 01021 fillElem.appendChild( graphicFillElem ); 01022 01023 // store distanceX, distanceY, displacementX, displacementY in a <VendorOption> 01024 QString dist = QgsSymbolLayerV2Utils::encodePoint( QPointF( mDistanceX, mDistanceY ) ); 01025 QDomElement distanceElem = QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "distance", dist ); 01026 symbolizerElem.appendChild( distanceElem ); 01027 01028 QgsSymbolLayerV2 *layer = mMarkerSymbol->symbolLayer( i ); 01029 QgsMarkerSymbolLayerV2 *markerLayer = static_cast<QgsMarkerSymbolLayerV2 *>( layer ); 01030 if ( !markerLayer ) 01031 { 01032 QString errorMsg = QString( "MarkerSymbolLayerV2 expected, %1 found. Skip it." ).arg( layer->layerType() ); 01033 graphicFillElem.appendChild( doc.createComment( errorMsg ) ); 01034 } 01035 else 01036 { 01037 markerLayer->writeSldMarker( doc, graphicFillElem, props ); 01038 } 01039 } 01040 } 01041 01042 QgsSymbolLayerV2* QgsPointPatternFillSymbolLayer::createFromSld( QDomElement &element ) 01043 { 01044 Q_UNUSED( element ); 01045 return NULL; 01046 } 01047 01048 bool QgsPointPatternFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol ) 01049 { 01050 if ( !symbol ) 01051 { 01052 return false; 01053 } 01054 01055 if ( symbol->type() == QgsSymbolV2::Marker ) 01056 { 01057 QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( symbol ); 01058 delete mMarkerSymbol; 01059 mMarkerSymbol = markerSymbol; 01060 } 01061 return true; 01062 } 01063 01065 01066 01067 QgsCentroidFillSymbolLayerV2::QgsCentroidFillSymbolLayerV2() 01068 { 01069 mMarker = NULL; 01070 setSubSymbol( new QgsMarkerSymbolV2() ); 01071 } 01072 01073 QgsCentroidFillSymbolLayerV2::~QgsCentroidFillSymbolLayerV2() 01074 { 01075 delete mMarker; 01076 } 01077 01078 QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::create( const QgsStringMap& /*properties*/ ) 01079 { 01080 return new QgsCentroidFillSymbolLayerV2(); 01081 } 01082 01083 QString QgsCentroidFillSymbolLayerV2::layerType() const 01084 { 01085 return "CentroidFill"; 01086 } 01087 01088 void QgsCentroidFillSymbolLayerV2::setColor( const QColor& color ) 01089 { 01090 mMarker->setColor( color ); 01091 mColor = color; 01092 } 01093 01094 void QgsCentroidFillSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context ) 01095 { 01096 mMarker->setAlpha( context.alpha() ); 01097 mMarker->setOutputUnit( context.outputUnit() ); 01098 01099 mMarker->startRender( context.renderContext() ); 01100 } 01101 01102 void QgsCentroidFillSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context ) 01103 { 01104 mMarker->stopRender( context.renderContext() ); 01105 } 01106 01107 void QgsCentroidFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context ) 01108 { 01109 Q_UNUSED( rings ); 01110 01111 // calculate centroid 01112 double cx = 0, cy = 0; 01113 double area, sum = 0; 01114 for ( int i = points.count() - 1, j = 0; j < points.count(); i = j++ ) 01115 { 01116 const QPointF& p1 = points[i]; 01117 const QPointF& p2 = points[j]; 01118 area = p1.x() * p2.y() - p1.y() * p2.x(); 01119 sum += area; 01120 cx += ( p1.x() + p2.x() ) * area; 01121 cy += ( p1.y() + p2.y() ) * area; 01122 } 01123 sum *= 3.0; 01124 cx /= sum; 01125 cy /= sum; 01126 01127 mMarker->renderPoint( QPointF( cx, cy ), context.feature(), context.renderContext(), -1, context.selected() ); 01128 } 01129 01130 QgsStringMap QgsCentroidFillSymbolLayerV2::properties() const 01131 { 01132 return QgsStringMap(); 01133 } 01134 01135 QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::clone() const 01136 { 01137 QgsCentroidFillSymbolLayerV2* x = new QgsCentroidFillSymbolLayerV2(); 01138 x->setSubSymbol( mMarker->clone() ); 01139 return x; 01140 } 01141 01142 void QgsCentroidFillSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const 01143 { 01144 // SLD 1.0 specs says: "if a line, polygon, or raster geometry is 01145 // used with PointSymbolizer, then the semantic is to use the centroid 01146 // of the geometry, or any similar representative point. 01147 mMarker->toSld( doc, element, props ); 01148 } 01149 01150 QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::createFromSld( QDomElement &element ) 01151 { 01152 QgsDebugMsg( "Entered." ); 01153 01154 QgsSymbolLayerV2 *l = QgsSymbolLayerV2Utils::createMarkerLayerFromSld( element ); 01155 if ( !l ) 01156 return NULL; 01157 01158 QgsSymbolLayerV2List layers; 01159 layers.append( l ); 01160 QgsMarkerSymbolV2 *marker = new QgsMarkerSymbolV2( layers ); 01161 01162 QgsCentroidFillSymbolLayerV2* x = new QgsCentroidFillSymbolLayerV2(); 01163 x->setSubSymbol( marker ); 01164 return x; 01165 } 01166 01167 01168 QgsSymbolV2* QgsCentroidFillSymbolLayerV2::subSymbol() 01169 { 01170 return mMarker; 01171 } 01172 01173 bool QgsCentroidFillSymbolLayerV2::setSubSymbol( QgsSymbolV2* symbol ) 01174 { 01175 if ( symbol == NULL || symbol->type() != QgsSymbolV2::Marker ) 01176 { 01177 delete symbol; 01178 return false; 01179 } 01180 01181 delete mMarker; 01182 mMarker = static_cast<QgsMarkerSymbolV2*>( symbol ); 01183 mColor = mMarker->color(); 01184 return true; 01185 }