src/hbcore/ovgeffects/hbvgreflectioneffect.cpp
changeset 5 627c4a0fd0e7
parent 0 16d8024aca5e
child 7 923ff622b8b9
equal deleted inserted replaced
3:11d3954df52a 5:627c4a0fd0e7
    33 
    33 
    34 /*!
    34 /*!
    35  * \class HbVgReflectionEffect
    35  * \class HbVgReflectionEffect
    36  *
    36  *
    37  * \brief OpenVG-based reflection effect.
    37  * \brief OpenVG-based reflection effect.
    38  * 
    38  *
    39  * \internal
    39  * \internal
    40  */
    40  */
    41 
    41 
    42 HbVgReflectionEffectPrivate::HbVgReflectionEffectPrivate()
    42 HbVgReflectionEffectPrivate::HbVgReflectionEffectPrivate()
    43     : fade(0), fadeInited(false)
    43     : fade(0), fadeInited(false)
    44 {    
    44 {
    45 }
    45 }
    46 
    46 
    47 HbVgReflectionEffectPrivate::~HbVgReflectionEffectPrivate()
    47 HbVgReflectionEffectPrivate::~HbVgReflectionEffectPrivate()
    48 {
    48 {
    49 #ifdef HB_EFFECTS_OPENVG
    49 #ifdef HB_EFFECTS_OPENVG
    74 }
    74 }
    75 
    75 
    76 void HbVgReflectionEffect::setOffset(const QPointF &offset)
    76 void HbVgReflectionEffect::setOffset(const QPointF &offset)
    77 {
    77 {
    78     Q_D(HbVgReflectionEffect);
    78     Q_D(HbVgReflectionEffect);
    79     if (offset == d->offset)
    79     if (offset == d->offset) {
    80         return;
    80         return;
       
    81     }
    81     d->offset = offset;
    82     d->offset = offset;
    82     updateEffectBoundingRect();
    83     updateEffectBoundingRect();
    83     emit offsetChanged(offset);
    84     emit offsetChanged(offset);
    84 }
    85 }
    85 
    86 
    98  * to be invisible, 1 shows nothing from the reflection (it is completely faded out).
    99  * to be invisible, 1 shows nothing from the reflection (it is completely faded out).
    99  */
   100  */
   100 void HbVgReflectionEffect::setFade(qreal fade)
   101 void HbVgReflectionEffect::setFade(qreal fade)
   101 {
   102 {
   102     Q_D(HbVgReflectionEffect);
   103     Q_D(HbVgReflectionEffect);
   103     if (fade == d->fade)
   104     if (fade == d->fade) {
   104         return;
   105         return;
       
   106     }
   105     d->fade = fade;
   107     d->fade = fade;
   106     updateEffect();
   108     updateEffect();
   107     emit fadeChanged(fade);
   109     emit fadeChanged(fade);
   108 }
   110 }
   109 
   111 
   114 }
   116 }
   115 
   117 
   116 void HbVgReflectionEffect::setColor(const QColor &color)
   118 void HbVgReflectionEffect::setColor(const QColor &color)
   117 {
   119 {
   118     Q_D(HbVgReflectionEffect);
   120     Q_D(HbVgReflectionEffect);
   119     if (color == d->color)
   121     if (color == d->color) {
   120         return;
   122         return;
       
   123     }
   121     d->color = color;
   124     d->color = color;
   122     updateEffect();
   125     updateEffect();
   123     emit colorChanged(color);
   126     emit colorChanged(color);
   124 }
   127 }
   125 
   128 
   127 {
   130 {
   128     // Double the height of the rectangle but take also the offset into account.
   131     // Double the height of the rectangle but take also the offset into account.
   129     Q_D(const HbVgReflectionEffect);
   132     Q_D(const HbVgReflectionEffect);
   130     QRectF r(rect);
   133     QRectF r(rect);
   131     QPointF mappedOffset = d->mapOffset(d->offset);
   134     QPointF mappedOffset = d->mapOffset(d->offset);
   132     qreal rotationAngle = d->mainWindowRotation();  
   135     qreal rotationAngle = d->mainWindowRotation();
   133     
   136 
   134     if (rotationAngle == 0) 
   137     if (rotationAngle == 0) {
   135         r.adjust(0, 0, 0, r.height());
   138         r.adjust(0, 0, 0, r.height());
   136     else if (rotationAngle == 90 || rotationAngle == -270)
   139     } else if (rotationAngle == 90 || rotationAngle == -270) {
   137         r.adjust(-r.width(), 0, 0, 0);
   140         r.adjust(-r.width(), 0, 0, 0);
   138     else if (rotationAngle == -90 || rotationAngle == 270)
   141     } else if (rotationAngle == -90 || rotationAngle == 270) {
   139         r.adjust(0, 0, r.width(), 0);
   142         r.adjust(0, 0, r.width(), 0);
   140       
   143     }
       
   144 
   141     qreal x1 = qMin(r.left(), r.left() + mappedOffset.x());
   145     qreal x1 = qMin(r.left(), r.left() + mappedOffset.x());
   142     qreal y1 = qMin(r.top(), r.top() + mappedOffset.y());
   146     qreal y1 = qMin(r.top(), r.top() + mappedOffset.y());
   143     qreal x2 = qMax(r.right(), r.right() + mappedOffset.x());
   147     qreal x2 = qMax(r.right(), r.right() + mappedOffset.x());
   144     qreal y2 = qMax(r.bottom(), r.bottom() + mappedOffset.y());
   148     qreal y2 = qMax(r.bottom(), r.bottom() + mappedOffset.y());
   145         
   149 
   146     return QRectF(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
   150     return QRectF(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
   147 }
   151 }
   148 
   152 
   149 void HbVgReflectionEffect::performEffect(QPainter *painter,
   153 void HbVgReflectionEffect::performEffect(QPainter *painter,
   150                                          const QPointF &offset,
   154         const QPointF &offset,
   151                                          const QVariant &vgImage,
   155         const QVariant &vgImage,
   152                                          const QSize &vgImageSize)
   156         const QSize &vgImageSize)
   153 {
   157 {
   154 #ifdef HB_EFFECTS_OPENVG
   158 #ifdef HB_EFFECTS_OPENVG
   155     Q_D(HbVgReflectionEffect);
   159     Q_D(HbVgReflectionEffect);
   156 
   160 
   157     if (d->hints & ForceFrameHint) {
   161     if (d->hints & ForceFrameHint) {
   160         painter->restore();
   164         painter->restore();
   161     }
   165     }
   162 
   166 
   163     QPaintDevice *pdev = painter->device();
   167     QPaintDevice *pdev = painter->device();
   164     QRectF rectWithChildren = d->deviceRectForSource(
   168     QRectF rectWithChildren = d->deviceRectForSource(
   165         HbVgFrameEffectPrivate::IncludeChildren,
   169                                   HbVgFrameEffectPrivate::IncludeChildren,
   166         pdev);
   170                                   pdev);
   167     QRectF rectWithoutChildren = d->deviceRectForSource(
   171     QRectF rectWithoutChildren = d->deviceRectForSource(
   168         HbVgFrameEffectPrivate::ExcludeChildren,
   172                                      HbVgFrameEffectPrivate::ExcludeChildren,
   169         pdev);
   173                                      pdev);
   170     VGImage srcImage = vgImage.value<VGImage>();
   174     VGImage srcImage = vgImage.value<VGImage>();
   171     VGImage dstImage = d->ensurePixmap(&d->dstPixmap, vgImageSize);
   175     VGImage dstImage = d->ensurePixmap(&d->dstPixmap, vgImageSize);
   172 
   176 
   173     // Draw the source pixmap using the painter, this will also set up the
   177     // Draw the source pixmap using the painter, this will also set up the
   174     // IMAGE_USER_TO_SURFACE matrix.
   178     // IMAGE_USER_TO_SURFACE matrix.
   175     painter->drawPixmap(offset, d->srcPixmap);
   179     painter->drawPixmap(offset, d->srcPixmap);
   176 
   180 
   177     // Prepare the mirrored image.    
   181     // Prepare the mirrored image.
   178     qreal rotationAngle = d->mainWindowRotation();
   182     qreal rotationAngle = d->mainWindowRotation();
   179     qreal absRotationAngle = qAbs(rotationAngle);
   183     qreal absRotationAngle = qAbs(rotationAngle);
   180     
   184 
   181     VGfloat m[9];
   185     VGfloat m[9];
   182     vgGetMatrix(m);
   186     vgGetMatrix(m);
   183     vgLoadIdentity();
   187     vgLoadIdentity();
   184     if (absRotationAngle == 0)
   188     if (absRotationAngle == 0) {
   185         m[4] *= -1.0f;
   189         m[4] *= -1.0f;
   186     else if (absRotationAngle == 90 || absRotationAngle == 270)
   190     } else if (absRotationAngle == 90 || absRotationAngle == 270) {
   187         m[0] *= -1.0f;
   191         m[0] *= -1.0f;
       
   192     }
   188     vgMultMatrix(m);
   193     vgMultMatrix(m);
   189     
   194 
   190     // Must move the mirrored image to have it on top of the original and then down
   195     // Must move the mirrored image to have it on top of the original and then down
   191     // again to have it below in portrait-mode. Rotation angles -90 or 270 causes image to be moved to right,
   196     // again to have it below in portrait-mode. Rotation angles -90 or 270 causes image to be moved to right,
   192     // and in rotation angles -90 and 270, image is in correct place initially.
   197     // and in rotation angles -90 and 270, image is in correct place initially.
   193     // Try to take the exclude-children hint into account when performing the second move.
   198     // Try to take the exclude-children hint into account when performing the second move.
   194     
   199 
   195     VGfloat trans;
   200     VGfloat trans;
   196     if (absRotationAngle == 0) {        
   201     if (absRotationAngle == 0) {
   197         if (d->hints & ExcludeChildrenHint)
   202         if (d->hints & ExcludeChildrenHint) {
   198             trans = -rectWithChildren.height() - rectWithoutChildren.height();
   203             trans = -rectWithChildren.height() - rectWithoutChildren.height();
   199         else
   204         } else {
   200             trans = -2.0f * rectWithChildren.height();
   205             trans = -2.0f * rectWithChildren.height();
   201         
   206         }
       
   207 
   202         vgTranslate(0.0f, trans);
   208         vgTranslate(0.0f, trans);
   203     }  
   209     } else if (absRotationAngle == 90 || absRotationAngle == 270) {
   204     else if (absRotationAngle == 90 || absRotationAngle == 270) {
   210         if (d->hints & ExcludeChildrenHint) {
   205         if (d->hints & ExcludeChildrenHint)
       
   206             trans = -rectWithChildren.width() - rectWithoutChildren.width();
   211             trans = -rectWithChildren.width() - rectWithoutChildren.width();
   207         else
   212         } else {
   208             trans = -2.0f * rectWithChildren.width();
   213             trans = -2.0f * rectWithChildren.width();
   209         
   214         }
       
   215 
   210         vgTranslate(trans, 0.0f);
   216         vgTranslate(trans, 0.0f);
   211     }
   217     }
   212         
   218 
   213     // Apply the additional offset. Note: down = minus, right = plus.
   219     // Apply the additional offset. Note: down = minus, right = plus.
   214     QPointF mappedOffset = d->mapOffset(d->offset);    
   220     QPointF mappedOffset = d->mapOffset(d->offset);
   215     VGfloat ox = (VGfloat) mappedOffset.x();
   221     VGfloat ox = (VGfloat) mappedOffset.x();
   216     VGfloat oy = (VGfloat) mappedOffset.y();
   222     VGfloat oy = (VGfloat) mappedOffset.y();
   217 
   223 
   218     if (rotationAngle == 0)   
   224     if (rotationAngle == 0) {
   219         vgTranslate(ox, -oy); 
   225         vgTranslate(ox, -oy);
   220     else if (rotationAngle == 90 || rotationAngle == -270)
   226     } else if (rotationAngle == 90 || rotationAngle == -270) {
   221         vgTranslate(-ox, oy);   
   227         vgTranslate(-ox, oy);
   222     else if (rotationAngle == -90 || rotationAngle == 270)
   228     } else if (rotationAngle == -90 || rotationAngle == 270) {
   223         vgTranslate(-ox, oy); 
   229         vgTranslate(-ox, oy);
   224     
   230     }
       
   231 
   225     // Apply the opacity and the color. When no color was set and the opacity is 1, the
   232     // Apply the opacity and the color. When no color was set and the opacity is 1, the
   226     // source image will be used as it is. This is the only place where we can try to use
   233     // source image will be used as it is. This is the only place where we can try to use
   227     // the pixmap cache.
   234     // the pixmap cache.
   228     VGImage imgToDraw = srcImage;
   235     VGImage imgToDraw = srcImage;
   229     QPixmap cachedPm = cached(vgImageSize);
   236     QPixmap cachedPm = cached(vgImageSize);
   230    if (cachedPm.isNull()) {
   237     if (cachedPm.isNull()) {
   231         VGImage tmpImage = VG_INVALID_HANDLE;
   238         VGImage tmpImage = VG_INVALID_HANDLE;
   232         if (d->color.isValid()) {
   239         if (d->color.isValid()) {
   233             // Perform a colorize effect (ignore the opacity here because it must be set for
   240             // Perform a colorize effect (ignore the opacity here because it must be set for
   234             // the full image, not just the color overlay).
   241             // the full image, not just the color overlay).
   235             tmpImage = d->ensurePixmap(&d->tmpPixmap, vgImageSize);
   242             tmpImage = d->ensurePixmap(&d->tmpPixmap, vgImageSize);
   240         }
   247         }
   241         qreal opacity = clamp(d->opacity, 0.0f, 1.0f);
   248         qreal opacity = clamp(d->opacity, 0.0f, 1.0f);
   242         if (d->opacity < 1.0f - HBVG_EPSILON) {
   249         if (d->opacity < 1.0f - HBVG_EPSILON) {
   243             // Apply the opacity, i.e. modify the alpha channel.
   250             // Apply the opacity, i.e. modify the alpha channel.
   244             if (d->paramsChanged) {
   251             if (d->paramsChanged) {
   245                 for (int i = 0; i < 256; ++i)
   252                 for (int i = 0; i < 256; ++i) {
   246                     d->alphaLUT[i] = (VGubyte) (i * opacity);
   253                     d->alphaLUT[i] = (VGubyte)(i * opacity);
       
   254                 }
   247             }
   255             }
   248             vgLookup(dstImage, imgToDraw,
   256             vgLookup(dstImage, imgToDraw,
   249                      identityLUT, identityLUT, identityLUT, d->alphaLUT,
   257                      identityLUT, identityLUT, identityLUT, d->alphaLUT,
   250                      VG_TRUE, VG_FALSE);
   258                      VG_TRUE, VG_FALSE);
   251             imgToDraw = dstImage;
   259             imgToDraw = dstImage;
   252         }
   260         }
   253         // If colorize and/or opacity was used then try to cache the result.
   261         // If colorize and/or opacity was used then try to cache the result.
   254         if (imgToDraw == tmpImage)
   262         if (imgToDraw == tmpImage) {
   255             tryCache(d->tmpPixmap);
   263             tryCache(d->tmpPixmap);
   256         else if (imgToDraw == dstImage)
   264         } else if (imgToDraw == dstImage) {
   257             tryCache(d->dstPixmap);
   265             tryCache(d->dstPixmap);
       
   266         }
   258     } else {
   267     } else {
   259         imgToDraw = qPixmapToVGImage(cachedPm);
   268         imgToDraw = qPixmapToVGImage(cachedPm);
   260     }
   269     }
   261 
   270 
   262     // Fade out the lower part of the mirrored image. Skip this if 'fade' is 0, i.e. there
   271     // Fade out the lower part of the mirrored image. Skip this if 'fade' is 0, i.e. there
   287         }
   296         }
   288 
   297 
   289         // Set up the linear gradient based on the (transformed) size of the source.
   298         // Set up the linear gradient based on the (transformed) size of the source.
   290         VGfloat sw = (VGfloat) rectWithChildren.width();
   299         VGfloat sw = (VGfloat) rectWithChildren.width();
   291         VGfloat sh = (VGfloat) rectWithChildren.height();
   300         VGfloat sh = (VGfloat) rectWithChildren.height();
   292          // must be bottom-up to get the proper effect
   301         // must be bottom-up to get the proper effect
   293         if (rotationAngle == 0)  {
   302         if (absRotationAngle == 0) {
   294             VGfloat grad[] = { sw / 2.0f, sh,
   303             VGfloat grad[] = { sw / 2.0f, sh,
   295                                sw / 2.0f, 0.0f };            
   304                                sw / 2.0f, 0.0f
       
   305                              };
   296             vgSetParameterfv(d->fadePaint, VG_PAINT_LINEAR_GRADIENT, 4, grad);
   306             vgSetParameterfv(d->fadePaint, VG_PAINT_LINEAR_GRADIENT, 4, grad);
   297         }
   307         } else if (absRotationAngle == 90 || absRotationAngle == 270) {
   298         else if (rotationAngle == -90 || rotationAngle == 270){
       
   299             VGfloat grad[] = { sw, sh / 2.0f,
   308             VGfloat grad[] = { sw, sh / 2.0f,
   300                                0.0f, sh / 2.0f };
   309                                0.0f, sh / 2.0f
       
   310                              };
   301             vgSetParameterfv(d->fadePaint, VG_PAINT_LINEAR_GRADIENT, 4, grad);
   311             vgSetParameterfv(d->fadePaint, VG_PAINT_LINEAR_GRADIENT, 4, grad);
   302         }
   312         }
   303         else if (rotationAngle == 90 || rotationAngle == -270){
       
   304             VGfloat grad[] = { 0.0f, sh / 2.0f,
       
   305                                sw, sh / 2.0f };
       
   306             vgSetParameterfv(d->fadePaint, VG_PAINT_LINEAR_GRADIENT, 4, grad);
       
   307         }        
       
   308 
   313 
   309         // Draw the mirrored image by using the paint to get a gradual fade-out effect.
   314         // Draw the mirrored image by using the paint to get a gradual fade-out effect.
   310         vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
   315         vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
   311         vgLoadIdentity();
   316         vgLoadIdentity();
   312         vgSetPaint(d->fadePaint, VG_FILL_PATH);
   317         vgSetPaint(d->fadePaint, VG_FILL_PATH);