src/hbcore/ovgeffects/hbvgmaskeffect.cpp
changeset 21 4633027730f5
parent 7 923ff622b8b9
equal deleted inserted replaced
7:923ff622b8b9 21:4633027730f5
    43  * with setForceSwMode().
    43  * with setForceSwMode().
    44  *
    44  *
    45  * Currently the sw version only support masks set by setMask() or
    45  * Currently the sw version only support masks set by setMask() or
    46  * provided via the callback.  Mask rectangles are not supported.
    46  * provided via the callback.  Mask rectangles are not supported.
    47  *
    47  *
       
    48  * When using this effect in a chain, sw mode must always be forced
       
    49  * via setForceSwMode().
       
    50  *
    48  * \internal
    51  * \internal
    49  */
    52  */
    50 
    53 
    51 HbVgMaskEffectPrivate::HbVgMaskEffectPrivate()
    54 HbVgMaskEffectPrivate::HbVgMaskEffectPrivate()
    52     : maskRectIsInDeviceCoords(false),
    55     : maskRectIsInDeviceCoords(false),
   413  *
   416  *
   414  * The behavior for partially visible items (clipped by the device rect) is
   417  * The behavior for partially visible items (clipped by the device rect) is
   415  * somewhat wrong, the mask is never clipped, it is just scaled down to match
   418  * somewhat wrong, the mask is never clipped, it is just scaled down to match
   416  * the visible part of the item.
   419  * the visible part of the item.
   417  */
   420  */
   418 void HbVgMaskEffect::performEffectSw(QPainter *painter)
   421 void HbVgMaskEffect::performEffectSw(QPainter *devicePainter, QPixmap *result, QPointF *resultPos)
   419 {
   422 {
   420     Q_D(HbVgMaskEffect);
   423     Q_D(HbVgMaskEffect);
       
   424 
       
   425     if (!devicePainter->paintEngine()) {
       
   426         drawSource(devicePainter);
       
   427         return;
       
   428     }
   421 
   429 
   422     QPoint offset;
   430     QPoint offset;
   423     QPixmap srcPixmap = sourcePixmap(Qt::DeviceCoordinates, &offset); // needs the original world transform
   431     QPixmap srcPixmap = sourcePixmapForRoot(Qt::DeviceCoordinates, &offset); // needs the original world transform
   424     if (srcPixmap.isNull()) {
   432     if (srcPixmap.isNull()) {
   425         return;
   433         return;
   426     }
   434     }
   427 
   435 
   428     QPaintDevice *pdev = painter->paintEngine()->paintDevice();
   436     QPaintDevice *pdev = devicePainter->paintEngine()->paintDevice();
   429     d->worldTransform = painter->worldTransform(); // deviceRectForSource needs this
   437     d->worldTransform = devicePainter->worldTransform(); // deviceRectForSource needs this
   430     // The full source rect (without child items) would be
   438     // The full source rect (without child items) would be
   431     // d->worldTransform.mapRect(sourceItemForRoot()->boundingRect()).toRect()
   439     // d->worldTransform.mapRect(sourceItemForRoot()->boundingRect()).toRect()
   432     // but we only care about the visible part here so clipping must be applied.
   440     // but we only care about the visible part here so clipping must be applied.
   433     QRect srcDevRect(d->deviceRectForSource(HbVgFrameEffectPrivate::ExcludeChildren, pdev).toRect());
   441     QRect srcDevRect(d->deviceRectForSource(HbVgFrameEffectPrivate::ExcludeChildren, pdev).toRect());
   434     QPoint pos = d->includeSourceItemOnly ? srcDevRect.topLeft() : offset;
   442     QPoint pos = d->includeSourceItemOnly ? srcDevRect.topLeft() : offset;
   435     QSize size = d->includeSourceItemOnly ? srcDevRect.size() : srcPixmap.size();
   443     QSize size = d->includeSourceItemOnly ? srcDevRect.size() : srcPixmap.size();
   436     if (size.width() <= 0 || size.height() <= 0) {
   444     if (size.width() <= 0 || size.height() <= 0) {
   437         return;
   445         return;
   438     }
   446     }
   439 
   447 
       
   448     if (resultPos) {
       
   449         *resultPos = pos;
       
   450     }
       
   451 
       
   452     QPixmap cachedPm = cached(size);
       
   453     if (!cachedPm.isNull()) {
       
   454         if (result) {
       
   455             *result = cachedPm;
       
   456         } else {
       
   457             devicePainter->setWorldTransform(QTransform());
       
   458             devicePainter->drawPixmap(pos, cachedPm);
       
   459             devicePainter->setWorldTransform(d->worldTransform);
       
   460         }
       
   461         return;
       
   462     }
       
   463 
   440     QPixmap maskPixmap;
   464     QPixmap maskPixmap;
   441     if (d->maskCallback) {
   465     if (d->maskCallback) {
   442         if (d->callbackResult.isNull() || d->callbackResult.size() != size) {
   466         if (d->callbackResult.isNull() || d->callbackResult.size() != size) {
   443             d->callbackResult = d->maskCallback(size, d->maskCallbackParam);
   467             d->callbackResult = d->maskCallback(size, d->maskCallbackParam);
   444             d->rotatedPixmap = QPixmap();
   468             d->rotatedPixmap = QPixmap();
   453             d->rotatedPixmap = QPixmap();
   477             d->rotatedPixmap = QPixmap();
   454         }
   478         }
   455         maskPixmap = d->scaledMask;
   479         maskPixmap = d->scaledMask;
   456     } else {
   480     } else {
   457         // Masking via rectangles is not supported here.
   481         // Masking via rectangles is not supported here.
   458         drawSource(painter);
   482         drawSource(devicePainter);
   459         return;
   483         return;
   460     }
   484     }
   461 
   485 
   462     qreal rotationAngle = d->mainWindowRotation();
   486     qreal rotationAngle = d->mainWindowRotation();
   463     if (rotationAngle != 0) {
   487     if (rotationAngle != 0) {
   470 
   494 
   471     if (d->includeSourceItemOnly) {
   495     if (d->includeSourceItemOnly) {
   472         // Take only the source item itself, excluding its children.
   496         // Take only the source item itself, excluding its children.
   473         srcPixmap = srcPixmap.copy(srcDevRect.adjusted(-offset.x(), -offset.y(), -offset.x(), -offset.y()));
   497         srcPixmap = srcPixmap.copy(srcDevRect.adjusted(-offset.x(), -offset.y(), -offset.x(), -offset.y()));
   474     }
   498     }
   475 
       
   476     painter->setWorldTransform(QTransform());
       
   477 
   499 
   478     QImage image(size, QImage::Format_ARGB32_Premultiplied);
   500     QImage image(size, QImage::Format_ARGB32_Premultiplied);
   479     QPainter p(&image);
   501     QPainter p(&image);
   480     p.setCompositionMode(QPainter::CompositionMode_Source);
   502     p.setCompositionMode(QPainter::CompositionMode_Source);
   481     p.fillRect(image.rect(), Qt::transparent);
   503     p.fillRect(image.rect(), Qt::transparent);
   483     p.drawPixmap(0, 0, srcPixmap);
   505     p.drawPixmap(0, 0, srcPixmap);
   484     p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
   506     p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
   485     p.drawPixmap(0, 0, maskPixmap);
   507     p.drawPixmap(0, 0, maskPixmap);
   486     p.end();
   508     p.end();
   487 
   509 
   488     painter->drawImage(pos, image);
   510     if (result) {
   489 
   511         *result = QPixmap(size);
   490     painter->setWorldTransform(d->worldTransform);
   512         result->fill(Qt::transparent);
   491 }
   513         QPainter p(result);
       
   514         p.drawImage(QPointF(0, 0), image);
       
   515         p.end();
       
   516         tryCache(*result);
       
   517     } else {
       
   518         devicePainter->setWorldTransform(QTransform());
       
   519         devicePainter->drawImage(pos, image);
       
   520         devicePainter->setWorldTransform(d->worldTransform);
       
   521         tryCache(QPixmap::fromImage(image));
       
   522     }
       
   523 }
       
   524 
       
   525 HbVgEffect::ChainBehavior HbVgMaskEffect::chainBehavior() const
       
   526 {
       
   527     Q_D(const HbVgMaskEffect);
       
   528     // This is actually incorrect if sw mode is not forced and we are
       
   529     // rendering on a raster painter, but mask effects without sw mode
       
   530     // forcing should not be used in a chain at all.
       
   531     return d->forceSwMode ? ChainBehavAsSource : ChainBehavNormal;
       
   532 }