47 * something else. |
48 * something else. |
48 * |
49 * |
49 * For the sake of simplicity the opacity and caching properties of |
50 * For the sake of simplicity the opacity and caching properties of |
50 * ChainedEffect instances is ignored, use the property of the |
51 * ChainedEffect instances is ignored, use the property of the |
51 * individual effects instead. |
52 * individual effects instead. |
|
53 * |
|
54 * Software-based mask effects in the chain are handled specially. If |
|
55 * such an effect is present at any position, it will be applied first |
|
56 * and the other effects will get its output as their source pixmap. |
|
57 * (this works only in hw mode) |
52 */ |
58 */ |
53 |
59 |
54 /*! |
60 /*! |
55 * Constructs a new chained effect instance. |
61 * Constructs a new chained effect instance. |
56 */ |
62 */ |
179 const QVariant &vgImage, |
197 const QVariant &vgImage, |
180 const QSize &vgImageSize) |
198 const QSize &vgImageSize) |
181 { |
199 { |
182 #ifdef HB_EFFECTS_OPENVG |
200 #ifdef HB_EFFECTS_OPENVG |
183 Q_D(HbVgChainedEffect); |
201 Q_D(HbVgChainedEffect); |
|
202 // If some effect wants to be the source then have it rendered |
|
203 // into a pixmap first (works only for sw-based effects). |
|
204 QPixmap src = d->srcPixmap; |
|
205 QVariant srcVgImage = vgImage; |
184 foreach(HbVgEffect * effect, d->effects) { |
206 foreach(HbVgEffect * effect, d->effects) { |
|
207 if (effect->chainBehavior() == ChainBehavAsSource) { |
|
208 // Restore the world transform temporarily because the sw |
|
209 // version has slightly different semantics. |
|
210 painter->setWorldTransform(d->worldTransform); |
|
211 QPixmap modSrc = src; |
|
212 QPointF modOffset; |
|
213 // This can be nothing but a mask effect and it can produce smaller output if |
|
214 // the source is based on a scroll area (or anything that clips its children, |
|
215 // as long as the source pixmaps are not restricted to obey the clipping). So |
|
216 // have its output in a temporary pixmap and copy it into the original source |
|
217 // pixmap to the (hopefully) appropriate position afterwards. |
|
218 effect->performEffectSw(painter, &modSrc, &modOffset); |
|
219 qreal dx = modOffset.x() - offset.x(); |
|
220 qreal dy = modOffset.y() - offset.y(); |
|
221 painter->setWorldTransform(QTransform()); |
|
222 if (dx >= 0 && dy >= 0) { |
|
223 src.fill(Qt::transparent); |
|
224 QPainter p(&src); |
|
225 p.drawPixmap(QPointF(dx, dy), modSrc); |
|
226 p.end(); |
|
227 srcVgImage = QVariant::fromValue<VGImage>(qPixmapToVGImage(src)); |
|
228 } |
|
229 break; |
|
230 } |
|
231 } |
|
232 bool hadNormalEffects = false; |
|
233 foreach(HbVgEffect * effect, d->effects) { |
|
234 if (effect->chainBehavior() == ChainBehavAsSource) { |
|
235 continue; |
|
236 } |
185 // Set up srcPixmap and others for the individual effects |
237 // Set up srcPixmap and others for the individual effects |
186 // because the base class does it only for us, not for the |
238 // because the base class does it only for us, not for the |
187 // contained ones. |
239 // contained ones. |
188 HbVgEffectPrivate *effD = HbVgEffectPrivate::d_ptr(effect); |
240 HbVgEffectPrivate *effD = HbVgEffectPrivate::d_ptr(effect); |
189 effD->srcPixmap = d->srcPixmap; |
241 effD->srcPixmap = src; |
190 effD->worldTransform = d->worldTransform; |
242 effD->worldTransform = d->worldTransform; |
191 // Draw. |
243 // Draw. |
192 effect->performEffect(painter, offset, vgImage, vgImageSize); |
244 effect->performEffect(painter, offset, srcVgImage, vgImageSize); |
193 // The flags must be cleared manually for the contained effects. |
245 // The flags must be cleared manually for the contained effects. |
194 effD->paramsChanged = effD->cacheInvalidated = false; |
246 effD->paramsChanged = effD->cacheInvalidated = false; |
|
247 if (effD->alwaysClearPixmaps || HbInstancePrivate::d_ptr()->mDropHiddenIconData) { |
|
248 effD->clearPixmaps(); |
|
249 } |
|
250 hadNormalEffects = true; |
195 } |
251 } |
196 // If there are no effects in the chain then just draw the source. |
252 // If there are no effects in the chain then just draw the source. |
197 if (d->effects.isEmpty()) { |
253 if (d->effects.isEmpty() || !hadNormalEffects) { |
198 painter->drawPixmap(offset, d->srcPixmap); |
254 painter->drawPixmap(offset, src); |
199 } |
255 } |
200 |
256 |
201 #else |
257 #else |
202 Q_UNUSED(painter); |
258 Q_UNUSED(painter); |
203 Q_UNUSED(offset); |
259 Q_UNUSED(offset); |
206 #endif |
262 #endif |
207 } |
263 } |
208 |
264 |
209 /*! |
265 /*! |
210 * \reimp |
266 * \reimp |
211 */ |
267 * |
212 void HbVgChainedEffect::performEffectSw(QPainter *painter) |
268 * Sw-mode for a chained effect does not make much sense and will |
|
269 * usually not have any good results because typically the only |
|
270 * sw-based effect is the mask effect and that would need special |
|
271 * handling which is impossible to provide here. |
|
272 */ |
|
273 void HbVgChainedEffect::performEffectSw(QPainter *devicePainter, |
|
274 QPixmap *result, |
|
275 QPointF *resultPos) |
213 { |
276 { |
214 Q_D(HbVgChainedEffect); |
277 Q_D(HbVgChainedEffect); |
215 foreach(HbVgEffect * effect, d->effects) { |
278 foreach(HbVgEffect * effect, d->effects) { |
216 effect->performEffectSw(painter); |
279 effect->performEffectSw(devicePainter, result, resultPos); |
217 HbVgEffectPrivate *effD = HbVgEffectPrivate::d_ptr(effect); |
280 HbVgEffectPrivate *effD = HbVgEffectPrivate::d_ptr(effect); |
218 effD->paramsChanged = effD->cacheInvalidated = false; |
281 effD->paramsChanged = effD->cacheInvalidated = false; |
219 } |
282 } |
220 if (d->effects.isEmpty()) { |
283 if (d->effects.isEmpty()) { |
221 drawSource(painter); |
284 drawSource(devicePainter); |
222 } |
285 } |
223 } |
286 } |
224 |
287 |
225 /*! |
288 /*! |
226 \reimp |
289 \reimp |