@@ -64,22 +64,7 @@ void QgsSimpleFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<Q
64
64
p->setBrush ( mBrush );
65
65
p->setPen ( mPen );
66
66
67
- if ( rings == NULL )
68
- {
69
- // simple polygon without holes
70
- p->drawPolygon ( points );
71
- }
72
- else
73
- {
74
- // polygon with holes must be drawn using painter path
75
- QPainterPath path;
76
- path.addPolygon ( points );
77
- QList<QPolygonF>::iterator it;
78
- for ( it = rings->begin (); it != rings->end (); ++it )
79
- path.addPolygon ( *it );
80
-
81
- p->drawPath ( path );
82
- }
67
+ _renderPolygon ( p, points, rings );
83
68
}
84
69
85
70
QgsStringMap QgsSimpleFillSymbolLayerV2::properties () const
@@ -97,3 +82,212 @@ QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::clone() const
97
82
{
98
83
return new QgsSimpleFillSymbolLayerV2 ( mColor , mBrushStyle , mBorderColor , mBorderStyle , mBorderWidth );
99
84
}
85
+
86
+ // QgsSVGFillSymbolLayer
87
+ #include < QFile>
88
+ #include < QSvgRenderer>
89
+
90
+ QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer ( const QString& svgFilePath, double width ): mPatternWidth( width ), mOutline( 0 )
91
+ {
92
+ setSvgFilePath ( svgFilePath );
93
+ mOutlineWidth = 0.3 ;
94
+ setSubSymbol ( new QgsLineSymbolV2 () );
95
+ }
96
+
97
+ QgsSVGFillSymbolLayer::QgsSVGFillSymbolLayer ( const QByteArray& svgData, double width ): mSvgData( svgData ), mPatternWidth( width ), mOutline( 0 )
98
+ {
99
+ storeViewBox ();
100
+ mOutlineWidth = 0.3 ;
101
+ setSubSymbol ( new QgsLineSymbolV2 () );
102
+ }
103
+
104
+ QgsSVGFillSymbolLayer::~QgsSVGFillSymbolLayer ()
105
+ {
106
+ delete mOutline ;
107
+ }
108
+
109
+ void QgsSVGFillSymbolLayer::setSvgFilePath ( const QString& svgPath )
110
+ {
111
+ QFile svgFile ( svgPath );
112
+ if ( svgFile.open ( QFile::ReadOnly ) )
113
+ {
114
+ mSvgData = svgFile.readAll ();
115
+ storeViewBox ();
116
+ }
117
+ mSvgFilePath = svgPath;
118
+ }
119
+
120
+ QgsSymbolLayerV2* QgsSVGFillSymbolLayer::create ( const QgsStringMap& properties )
121
+ {
122
+ QByteArray data;
123
+ double width = 20 ;
124
+ QString svgFilePath;
125
+
126
+
127
+ if ( properties.contains ( " width" ) )
128
+ {
129
+ width = properties[" width" ].toDouble ();
130
+ }
131
+ if ( properties.contains ( " svgFile" ) )
132
+ {
133
+ svgFilePath = properties[" svgFile" ];
134
+ }
135
+
136
+ if ( !svgFilePath.isEmpty () )
137
+ {
138
+ return new QgsSVGFillSymbolLayer ( svgFilePath, width );
139
+ }
140
+ else
141
+ {
142
+ if ( properties.contains ( " data" ) )
143
+ {
144
+ data = QByteArray::fromHex ( properties[" data" ].toLocal8Bit () );
145
+ }
146
+
147
+ return new QgsSVGFillSymbolLayer ( data, width );
148
+ }
149
+ }
150
+
151
+ QString QgsSVGFillSymbolLayer::layerType () const
152
+ {
153
+ return " SVGFill" ;
154
+ }
155
+
156
+ void QgsSVGFillSymbolLayer::startRender ( QgsSymbolV2RenderContext& context )
157
+ {
158
+ if ( mSvgViewBox .isNull () )
159
+ {
160
+ return ;
161
+ }
162
+
163
+ // create QImage with appropriate dimensions
164
+ int pixelWidth = context.outputPixelSize ( mPatternWidth );// mPatternWidth.value( context, QgsOutputUnit::Pixel );
165
+ int pixelHeight = pixelWidth / mSvgViewBox .width () * mSvgViewBox .height ();
166
+
167
+ QImage textureImage ( pixelWidth, pixelHeight, QImage::Format_ARGB32_Premultiplied );
168
+ textureImage.fill ( QColor ( 255 , 255 , 255 , 0 ).rgba () );
169
+
170
+ // rasterise byte array to image
171
+ QPainter p ( &textureImage );
172
+ QSvgRenderer r ( mSvgData );
173
+ if ( !r.isValid () )
174
+ {
175
+ return ;
176
+ }
177
+ r.render ( &p );
178
+
179
+ QTransform brushTransform;
180
+ brushTransform.scale ( 1.0 / context.renderContext ().rasterScaleFactor (), 1.0 / context.renderContext ().rasterScaleFactor () );
181
+ mBrush .setTextureImage ( textureImage );
182
+ mBrush .setTransform ( brushTransform );
183
+
184
+ if ( mOutline )
185
+ {
186
+ mOutline ->startRender ( context.renderContext () );
187
+ }
188
+ }
189
+
190
+ void QgsSVGFillSymbolLayer::stopRender ( QgsSymbolV2RenderContext& context )
191
+ {
192
+ if ( mOutline )
193
+ {
194
+ mOutline ->stopRender ( context.renderContext () );
195
+ }
196
+ }
197
+
198
+ void QgsSVGFillSymbolLayer::renderPolygon ( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
199
+ {
200
+ QPainter* p = context.renderContext ().painter ();
201
+ if ( !p )
202
+ {
203
+ return ;
204
+ }
205
+ p->setBrush ( mBrush );
206
+ p->setPen ( QPen ( Qt::NoPen ) );
207
+ _renderPolygon ( p, points, rings );
208
+ if ( mOutline )
209
+ {
210
+ mOutline ->renderPolyline ( points, context.renderContext () );
211
+ if ( rings )
212
+ {
213
+ QList<QPolygonF>::const_iterator ringIt = rings->constBegin ();
214
+ for ( ; ringIt != rings->constEnd (); ++ringIt )
215
+ {
216
+ mOutline ->renderPolyline ( *ringIt, context.renderContext () );
217
+ }
218
+ }
219
+ }
220
+ }
221
+
222
+ QgsStringMap QgsSVGFillSymbolLayer::properties () const
223
+ {
224
+ QgsStringMap map;
225
+ if ( !mSvgFilePath .isEmpty () )
226
+ {
227
+ map.insert ( " svgFile" , mSvgFilePath );
228
+ }
229
+ else
230
+ {
231
+ map.insert ( " data" , QString ( mSvgData .toHex () ) );
232
+ }
233
+
234
+ map.insert ( " width" , QString::number ( mPatternWidth ) );
235
+ return map;
236
+ }
237
+
238
+ QgsSymbolLayerV2* QgsSVGFillSymbolLayer::clone () const
239
+ {
240
+ QgsSymbolLayerV2* clonedLayer = 0 ;
241
+ if ( !mSvgFilePath .isEmpty () )
242
+ {
243
+ clonedLayer = new QgsSVGFillSymbolLayer ( mSvgFilePath , mPatternWidth );
244
+ }
245
+ else
246
+ {
247
+ clonedLayer = new QgsSVGFillSymbolLayer ( mSvgData , mPatternWidth );
248
+ }
249
+
250
+ if ( mOutline )
251
+ {
252
+ clonedLayer->setSubSymbol ( mOutline ->clone () );
253
+ }
254
+ return clonedLayer;
255
+ }
256
+
257
+ void QgsSVGFillSymbolLayer::storeViewBox ()
258
+ {
259
+ if ( !mSvgData .isEmpty () )
260
+ {
261
+ QSvgRenderer r ( mSvgData );
262
+ if ( r.isValid () )
263
+ {
264
+ mSvgViewBox = r.viewBoxF ();
265
+ return ;
266
+ }
267
+ }
268
+
269
+ mSvgViewBox = QRectF ();
270
+ return ;
271
+ }
272
+
273
+ bool QgsSVGFillSymbolLayer::setSubSymbol ( QgsSymbolV2* symbol )
274
+ {
275
+
276
+ if ( !symbol || symbol->type () != QgsSymbolV2::Line )
277
+ {
278
+ delete symbol;
279
+ return false ;
280
+ }
281
+
282
+
283
+ QgsLineSymbolV2* lineSymbol = dynamic_cast <QgsLineSymbolV2*>( symbol );
284
+ if ( lineSymbol )
285
+ {
286
+ delete mOutline ;
287
+ mOutline = lineSymbol;
288
+ return true ;
289
+ }
290
+
291
+ delete symbol;
292
+ return false ;
293
+ }
0 commit comments