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
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
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
00118
00119 QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QString& svgFilePath, double width ): mPatternWidth( width ), mOutline( 0 )
00120 {
00121 setSvgFilePath( svgFilePath );
00122 mOutlineWidth = 0.3;
00123 setSubSymbol( new QgsLineSymbolV2() );
00124 }
00125
00126 QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer( const QByteArray& svgData, double width ): mPatternWidth( width ), mSvgData( svgData ), mOutline( 0 )
00127 {
00128 storeViewBox();
00129 mOutlineWidth = 0.3;
00130 setSubSymbol( new QgsLineSymbolV2() );
00131 }
00132
00133 QgsSVGFillSymbolLayer::~QgsSVGFillSymbolLayer()
00134 {
00135 delete mOutline;
00136 }
00137
00138 void QgsSVGFillSymbolLayer::setSvgFilePath( const QString& svgPath )
00139 {
00140 QFile svgFile( svgPath );
00141 if( svgFile.open( QFile::ReadOnly ) )
00142 {
00143 mSvgData = svgFile.readAll();
00144 storeViewBox();
00145 }
00146 mSvgFilePath = svgPath;
00147 }
00148
00149 QgsSymbolLayerV2* QgsSVGFillSymbolLayer::create( const QgsStringMap& properties )
00150 {
00151 QByteArray data;
00152 double width = 20;
00153 QString svgFilePath;
00154
00155
00156 if( properties.contains( "width" ) )
00157 {
00158 width = properties["width"].toDouble();
00159 }
00160 if( properties.contains( "svgFile" ) )
00161 {
00162 QString svgName = properties["svgFile"];
00163 QString savePath = QgsSvgMarkerSymbolLayerV2::symbolNameToPath( svgName );
00164 svgFilePath = ( savePath.isEmpty() ? svgName : savePath );
00165 }
00166
00167 if( !svgFilePath.isEmpty() )
00168 {
00169 return new QgsSVGFillSymbolLayer( svgFilePath, width );
00170 }
00171 else
00172 {
00173 if( properties.contains( "data" ) )
00174 {
00175 data = QByteArray::fromHex( properties["data"].toLocal8Bit() );
00176 }
00177
00178 return new QgsSVGFillSymbolLayer( data, width );
00179 }
00180 }
00181
00182 QString QgsSVGFillSymbolLayer::layerType() const
00183 {
00184 return "SVGFill";
00185 }
00186
00187 void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
00188 {
00189 if( mSvgViewBox.isNull() )
00190 {
00191 return;
00192 }
00193
00194
00195 int pixelWidth = context.outputPixelSize( mPatternWidth );
00196 int pixelHeight = pixelWidth / mSvgViewBox.width() * mSvgViewBox.height();
00197
00198 QImage textureImage( pixelWidth, pixelHeight, QImage::Format_ARGB32_Premultiplied );
00199 textureImage.fill( 0 );
00200
00201
00202 QPainter p( &textureImage );
00203 QSvgRenderer r( mSvgData );
00204 if( !r.isValid() )
00205 {
00206 return;
00207 }
00208 r.render( &p );
00209
00210 if( context.alpha() < 1.0 )
00211 {
00212 QgsSymbolLayerV2Utils::multiplyImageOpacity( &textureImage, context.alpha() );
00213 }
00214
00215 QTransform brushTransform;
00216 brushTransform.scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() );
00217 mBrush.setTextureImage( textureImage );
00218 mBrush.setTransform( brushTransform );
00219
00220 if( mOutline )
00221 {
00222 mOutline->startRender( context.renderContext() );
00223 }
00224 }
00225
00226 void QgsSVGFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
00227 {
00228 if( mOutline )
00229 {
00230 mOutline->stopRender( context.renderContext() );
00231 }
00232 }
00233
00234 void QgsSVGFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
00235 {
00236 QPainter* p = context.renderContext().painter();
00237 if( !p )
00238 {
00239 return;
00240 }
00241 p->setPen( QPen( Qt::NoPen ) );
00242 if( context.selected() )
00243 {
00244 QColor selColor = context.selectionColor();
00245 if( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() );
00246 p->setBrush( QBrush( selColor ) );
00247 _renderPolygon( p, points, rings );
00248 }
00249 p->setBrush( mBrush );
00250 _renderPolygon( p, points, rings );
00251 if( mOutline )
00252 {
00253 mOutline->renderPolyline( points, context.renderContext(), -1, selectFillBorder && context.selected() );
00254 if( rings )
00255 {
00256 QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
00257 for( ; ringIt != rings->constEnd(); ++ringIt )
00258 {
00259 mOutline->renderPolyline( *ringIt, context.renderContext(), -1, selectFillBorder && context.selected() );
00260 }
00261 }
00262 }
00263 }
00264
00265 QgsStringMap QgsSVGFillSymbolLayer::properties() const
00266 {
00267 QgsStringMap map;
00268 if( !mSvgFilePath.isEmpty() )
00269 {
00270 map.insert( "svgFile", QgsSvgMarkerSymbolLayerV2::symbolPathToName( mSvgFilePath ) );
00271 }
00272 else
00273 {
00274 map.insert( "data", QString( mSvgData.toHex() ) );
00275 }
00276
00277 map.insert( "width", QString::number( mPatternWidth ) );
00278 return map;
00279 }
00280
00281 QgsSymbolLayerV2* QgsSVGFillSymbolLayer::clone() const
00282 {
00283 QgsSymbolLayerV2* clonedLayer = 0;
00284 if( !mSvgFilePath.isEmpty() )
00285 {
00286 clonedLayer = new QgsSVGFillSymbolLayer( mSvgFilePath, mPatternWidth );
00287 }
00288 else
00289 {
00290 clonedLayer = new QgsSVGFillSymbolLayer( mSvgData, mPatternWidth );
00291 }
00292
00293 if( mOutline )
00294 {
00295 clonedLayer->setSubSymbol( mOutline->clone() );
00296 }
00297 return clonedLayer;
00298 }
00299
00300 void QgsSVGFillSymbolLayer::storeViewBox()
00301 {
00302 if( !mSvgData.isEmpty() )
00303 {
00304 QSvgRenderer r( mSvgData );
00305 if( r.isValid() )
00306 {
00307 mSvgViewBox = r.viewBoxF();
00308 return;
00309 }
00310 }
00311
00312 mSvgViewBox = QRectF();
00313 return;
00314 }
00315
00316 bool QgsSVGFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
00317 {
00318 if( !symbol || symbol->type() != QgsSymbolV2::Line )
00319 {
00320 delete symbol;
00321 return false;
00322 }
00323
00324 QgsLineSymbolV2* lineSymbol = dynamic_cast<QgsLineSymbolV2*>( symbol );
00325 if( lineSymbol )
00326 {
00327 delete mOutline;
00328 mOutline = lineSymbol;
00329 return true;
00330 }
00331
00332 delete symbol;
00333 return false;
00334 }