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(); |
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 } |