src/hbcore/ovgeffects/hbvgchainedeffect.cpp
changeset 34 ed14f46c0e55
parent 7 923ff622b8b9
equal deleted inserted replaced
31:7516d6d86cf5 34:ed14f46c0e55
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
    25 
    25 
    26 #include "hbvgchainedeffect_p.h"
    26 #include "hbvgchainedeffect_p.h"
    27 #include "hbvgchainedeffect_p_p.h"
    27 #include "hbvgchainedeffect_p_p.h"
       
    28 #include "hbinstance_p.h"
    28 #include <QPainter>
    29 #include <QPainter>
    29 
    30 
    30 /*!
    31 /*!
    31  * \class HbVgChainedEffect
    32  * \class HbVgChainedEffect
    32  *
    33  *
    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  */
   134  */
   140  */
   135 HbVgEffect *HbVgChainedEffect::at(int index)
   141 HbVgEffect *HbVgChainedEffect::at(int index)
   136 {
   142 {
   137     Q_D(HbVgChainedEffect);
   143     Q_D(HbVgChainedEffect);
   138     return d->effects.at(index);
   144     return d->effects.at(index);
       
   145 }
       
   146 
       
   147 /*!
       
   148  * Returns all effects in a list and removes them from the chain
       
   149  * without destroying them.
       
   150  */
       
   151 QList<HbVgEffect *> HbVgChainedEffect::takeAll()
       
   152 {
       
   153     Q_D(HbVgChainedEffect);
       
   154     QList<HbVgEffect *> result = d->effects.toList();
       
   155     d->effects.clear();
       
   156     return result;
   139 }
   157 }
   140 
   158 
   141 /*!
   159 /*!
   142  * \reimp
   160  * \reimp
   143  */
   161  */
   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