diff -r 923ff622b8b9 -r 4633027730f5 src/hbcore/ovgeffects/hbvgmaskeffect.cpp --- a/src/hbcore/ovgeffects/hbvgmaskeffect.cpp Tue Jul 06 14:36:53 2010 +0300 +++ b/src/hbcore/ovgeffects/hbvgmaskeffect.cpp Wed Aug 18 10:05:37 2010 +0300 @@ -45,6 +45,9 @@ * Currently the sw version only support masks set by setMask() or * provided via the callback. Mask rectangles are not supported. * + * When using this effect in a chain, sw mode must always be forced + * via setForceSwMode(). + * * \internal */ @@ -415,18 +418,23 @@ * somewhat wrong, the mask is never clipped, it is just scaled down to match * the visible part of the item. */ -void HbVgMaskEffect::performEffectSw(QPainter *painter) +void HbVgMaskEffect::performEffectSw(QPainter *devicePainter, QPixmap *result, QPointF *resultPos) { Q_D(HbVgMaskEffect); + if (!devicePainter->paintEngine()) { + drawSource(devicePainter); + return; + } + QPoint offset; - QPixmap srcPixmap = sourcePixmap(Qt::DeviceCoordinates, &offset); // needs the original world transform + QPixmap srcPixmap = sourcePixmapForRoot(Qt::DeviceCoordinates, &offset); // needs the original world transform if (srcPixmap.isNull()) { return; } - QPaintDevice *pdev = painter->paintEngine()->paintDevice(); - d->worldTransform = painter->worldTransform(); // deviceRectForSource needs this + QPaintDevice *pdev = devicePainter->paintEngine()->paintDevice(); + d->worldTransform = devicePainter->worldTransform(); // deviceRectForSource needs this // The full source rect (without child items) would be // d->worldTransform.mapRect(sourceItemForRoot()->boundingRect()).toRect() // but we only care about the visible part here so clipping must be applied. @@ -437,6 +445,22 @@ return; } + if (resultPos) { + *resultPos = pos; + } + + QPixmap cachedPm = cached(size); + if (!cachedPm.isNull()) { + if (result) { + *result = cachedPm; + } else { + devicePainter->setWorldTransform(QTransform()); + devicePainter->drawPixmap(pos, cachedPm); + devicePainter->setWorldTransform(d->worldTransform); + } + return; + } + QPixmap maskPixmap; if (d->maskCallback) { if (d->callbackResult.isNull() || d->callbackResult.size() != size) { @@ -455,7 +479,7 @@ maskPixmap = d->scaledMask; } else { // Masking via rectangles is not supported here. - drawSource(painter); + drawSource(devicePainter); return; } @@ -473,8 +497,6 @@ srcPixmap = srcPixmap.copy(srcDevRect.adjusted(-offset.x(), -offset.y(), -offset.x(), -offset.y())); } - painter->setWorldTransform(QTransform()); - QImage image(size, QImage::Format_ARGB32_Premultiplied); QPainter p(&image); p.setCompositionMode(QPainter::CompositionMode_Source); @@ -485,7 +507,26 @@ p.drawPixmap(0, 0, maskPixmap); p.end(); - painter->drawImage(pos, image); + if (result) { + *result = QPixmap(size); + result->fill(Qt::transparent); + QPainter p(result); + p.drawImage(QPointF(0, 0), image); + p.end(); + tryCache(*result); + } else { + devicePainter->setWorldTransform(QTransform()); + devicePainter->drawImage(pos, image); + devicePainter->setWorldTransform(d->worldTransform); + tryCache(QPixmap::fromImage(image)); + } +} - painter->setWorldTransform(d->worldTransform); +HbVgEffect::ChainBehavior HbVgMaskEffect::chainBehavior() const +{ + Q_D(const HbVgMaskEffect); + // This is actually incorrect if sw mode is not forced and we are + // rendering on a raster painter, but mask effects without sw mode + // forcing should not be used in a chain at all. + return d->forceSwMode ? ChainBehavAsSource : ChainBehavNormal; }