@@ -125,20 +125,9 @@ QgsRuleBasedRendererV2::QgsRuleBasedRendererV2( QgsSymbolV2* defaultSymbol )
125
125
}
126
126
127
127
128
- QgsSymbolV2* QgsRuleBasedRendererV2::symbolForFeature ( QgsFeature& feature )
128
+ QgsSymbolV2* QgsRuleBasedRendererV2::symbolForFeature ( QgsFeature& )
129
129
{
130
- if ( ! usingFirstRule () )
131
- return mCurrentSymbol ;
132
-
133
- for ( QList<Rule*>::iterator it = mCurrentRules .begin (); it != mCurrentRules .end (); ++it )
134
- {
135
- Rule* rule = *it;
136
-
137
- if ( rule->isFilterOK ( feature ) )
138
- {
139
- return rule->symbol (); // works with levels but takes only first rule
140
- }
141
- }
130
+ // not used at all
142
131
return 0 ;
143
132
}
144
133
@@ -148,16 +137,37 @@ void QgsRuleBasedRendererV2::renderFeature( QgsFeature& feature,
148
137
bool selected,
149
138
bool drawVertexMarker )
150
139
{
140
+
141
+ // TODO: selected features, vertex markers
142
+
143
+ // check each active rule
144
+ QgsFeature* featPtr = NULL ;
151
145
for ( QList<Rule*>::iterator it = mCurrentRules .begin (); it != mCurrentRules .end (); ++it )
152
146
{
153
147
Rule* rule = *it;
148
+ // if matching: add rendering job to queue
154
149
if ( rule->isFilterOK ( feature ) )
155
150
{
156
- mCurrentSymbol = rule->symbol ();
157
- // will ask for mCurrentSymbol
158
- QgsFeatureRendererV2::renderFeature ( feature, context, layer, selected, drawVertexMarker );
151
+ // QgsDebugMsg(QString("matching fid %1").arg(feature.id()));
152
+ // make a copy of the feature if not yet exists
153
+ if ( !featPtr )
154
+ {
155
+ featPtr = new QgsFeature ( feature );
156
+ mCurrentFeatures .append ( featPtr );
157
+ }
158
+
159
+ // create job for this feature and this symbol, add to list of jobs
160
+ // RenderJob* job = new RenderJob( featPtr, rule->symbol() );
161
+ // mRenderJobs.append( job );
162
+ // add job to the queue: each symbol's zLevel must be added
163
+ foreach ( int normZLevel, rule->mSymbolNormZLevels )
164
+ {
165
+ // QgsDebugMsg(QString("add job at level %1").arg(normZLevel));
166
+ mRenderQueue .levels [normZLevel].jobs .append ( new RenderJob ( featPtr, rule->symbol () ) );
167
+ }
159
168
}
160
169
}
170
+
161
171
}
162
172
163
173
@@ -166,6 +176,7 @@ void QgsRuleBasedRendererV2::startRender( QgsRenderContext& context, const QgsVe
166
176
double currentScale = context.rendererScale ();
167
177
// filter out rules which are not compatible with this scale
168
178
179
+ // build temporary list of active rules (usable with this scale)
169
180
mCurrentRules .clear ();
170
181
for ( QList<Rule>::iterator it = mRules .begin (); it != mRules .end (); ++it )
171
182
{
@@ -176,18 +187,98 @@ void QgsRuleBasedRendererV2::startRender( QgsRenderContext& context, const QgsVe
176
187
177
188
QgsFieldMap pendingFields = vlayer->pendingFields ();
178
189
179
- for ( QList<Rule*>::iterator it = mCurrentRules .begin (); it != mCurrentRules .end (); ++it )
190
+ QSet<int > symbolZLevelsSet;
191
+
192
+ QList<Rule*>::iterator it;
193
+ for ( it = mCurrentRules .begin (); it != mCurrentRules .end (); ++it )
180
194
{
181
195
Rule* rule = *it;
182
196
QgsExpression* exp = rule->filter ();
183
197
if ( exp )
184
198
exp->prepare ( pendingFields );
185
- rule->symbol ()->startRender ( context, vlayer );
199
+
200
+ // prepare symbol
201
+ QgsSymbolV2* s = rule->symbol ();
202
+ s->startRender ( context, vlayer );
203
+
204
+ QgsDebugMsg ( " rule " + rule->dump () );
205
+
206
+ // find out which Z-levels are used
207
+ for ( int i = 0 ; i < s->symbolLayerCount (); i++ )
208
+ {
209
+ symbolZLevelsSet.insert ( s->symbolLayer ( i )->renderingPass () );
210
+ rule->mSymbolNormZLevels .clear ();
211
+ }
212
+ }
213
+
214
+ // create mapping from unnormalized levels [unlimited range] to normalized levels [0..N-1]
215
+ // and prepare rendering queue
216
+ QMap<int , int > zLevelsToNormLevels;
217
+ int maxNormLevel = -1 ;
218
+ mRenderQueue .levels .clear ();
219
+ foreach ( int zLevel, symbolZLevelsSet.toList () )
220
+ {
221
+ zLevelsToNormLevels[zLevel] = ++maxNormLevel;
222
+ mRenderQueue .levels .append ( RenderLevel ( zLevel ) );
223
+ QgsDebugMsg ( QString ( " zLevel %1 -> %2" ).arg ( zLevel ).arg ( maxNormLevel ) );
224
+ }
225
+
226
+ // prepare list of normalized levels for each rule
227
+ for ( it = mCurrentRules .begin (); it != mCurrentRules .end (); ++it )
228
+ {
229
+ Rule* rule = *it;
230
+ QgsSymbolV2* s = rule->symbol ();
231
+ for ( int i = 0 ; i < s->symbolLayerCount (); i++ )
232
+ {
233
+ int normLevel = zLevelsToNormLevels.value ( s->symbolLayer ( i )->renderingPass () );
234
+ rule->mSymbolNormZLevels .append ( normLevel );
235
+ }
186
236
}
187
237
}
188
238
189
239
void QgsRuleBasedRendererV2::stopRender ( QgsRenderContext& context )
190
240
{
241
+ //
242
+ // do the actual rendering
243
+ //
244
+
245
+ // TODO: selected, markers
246
+ bool selected = false ;
247
+ bool drawVertexMarker = false ;
248
+
249
+ // go through all levels
250
+ foreach ( const RenderLevel& level, mRenderQueue .levels )
251
+ {
252
+ // QgsDebugMsg(QString("level %1").arg(level.zIndex));
253
+ // go through all jobs at the level
254
+ foreach ( const RenderJob* job, level.jobs )
255
+ {
256
+ // QgsDebugMsg(QString("job fid %1").arg(job->f->id()));
257
+ // render feature - but only with symbol layers with specified zIndex
258
+ QgsSymbolV2* s = job->symbol ;
259
+ int count = s->symbolLayerCount ();
260
+ for ( int i = 0 ; i < count; i++ )
261
+ {
262
+ // TODO: better solution for this
263
+ // renderFeatureWithSymbol asks which symbol layer to draw
264
+ // but there are multiple transforms going on!
265
+ if ( s->symbolLayer ( i )->renderingPass () == level.zIndex )
266
+ {
267
+ renderFeatureWithSymbol ( *job->f , job->symbol , context, i, selected, drawVertexMarker );
268
+ }
269
+ }
270
+ }
271
+ }
272
+
273
+ // TODO:
274
+ // clear render queue, render jobs
275
+
276
+ foreach ( QgsFeature* f, mCurrentFeatures )
277
+ {
278
+ delete f;
279
+ }
280
+ mCurrentFeatures .clear ();
281
+
191
282
for ( QList<Rule*>::iterator it = mCurrentRules .begin (); it != mCurrentRules .end (); ++it )
192
283
{
193
284
Rule* rule = *it;
0 commit comments