ganeswidgets/src/hgvgimage.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 03 May 2010 13:32:54 +0300
changeset 1 e48454f237ca
parent 0 89c329efa980
child 2 49c70dcc3f17
permissions -rw-r--r--
Revision: 201015 Kit: 201018

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:    
*
*/

#include "HgVgImage.h"
#include "HgImageFader.h"
#include "hgvgquadrenderer.h"

const int KMaxMirrorWidth(128);
const int KMaxMirrorHeight(64);

static QSize getMirrorSize(const QImage& image)
{
    return QSize(
        qMin(image.width() / 2, KMaxMirrorWidth), 
        qMin(image.height() / 4, KMaxMirrorHeight) 
        );
}

HgVgImage::HgVgImage(HgVgQuadRenderer* renderer) :
    mVgImage(VG_INVALID_HANDLE),
    mMirrorImage(VG_INVALID_HANDLE),
    mMirrorSize(0,0),
    mRenderer(renderer)
{
    setAlpha(1.0);
}

HgVgImage::~HgVgImage()
{
    releaseImage();
}

int HgVgImage::width() const
{
    return mQImage.width();
}

int HgVgImage::height() const
{
    return mQImage.height();
}

VGImage HgVgImage::image() const
{
    return mVgImage;
}

int HgVgImage::mirrorImageWidth() const
{
    return mMirrorSize.width();
}

int HgVgImage::mirrorImageHeight() const
{
    return mMirrorSize.height();
}
    
VGImage HgVgImage::mirrorImage() const
{
    return mMirrorImage;
}


void HgVgImage::setImage(const QImage& image)
{
    if (image.isNull())
        return;

    // release previous images vg data
    releaseImage();
        
    mQImage = image;

    mMirrorSize = getMirrorSize(mQImage);

}

QImage HgVgImage::getQImage() const
{
    return mQImage;
}


void HgVgImage::releaseImage()
{
    if (mVgImage != VG_INVALID_HANDLE)
    {
        vgDestroyImage(mVgImage);
        mVgImage = VG_INVALID_HANDLE;            
    }
    if (mMirrorImage != VG_INVALID_HANDLE)
    {
        vgDestroyImage(mMirrorImage);
        mMirrorImage = VG_INVALID_HANDLE;            
    }
    
    // TODO, check that this will free all the previously reserved image resources.
    mQImage = QImage();
}

void HgVgImage::upload(bool mirror)
{
    if( mQImage.isNull())
        return;    
    
    if (mVgImage == VG_INVALID_HANDLE)
    {            
                
        VGImageFormat format;

        switch (mQImage.format())
        {
        case QImage::Format_ARGB32_Premultiplied:
            format = VG_sARGB_8888_PRE;
            break;
        case QImage::Format_ARGB32:
            format = VG_sARGB_8888;
            break;
        case QImage::Format_RGB16:
            format = VG_sRGB_565;
            break;
        default:
            mQImage = mQImage.convertToFormat(QImage::Format_RGB16);
            format = VG_sRGB_565;
            break;
        }
        

        mVgImage = vgCreateImage(format, 
            mQImage.width(), mQImage.height(),VG_IMAGE_QUALITY_NONANTIALIASED);
        if (mVgImage == VG_INVALID_HANDLE)
        {
            qWarning("HgMediaWall run out of video memory for images!");
            return;
        }
        
        // bits function performs deep copy if we dont fetch data with const specifier.
        const uchar *bits = mQImage.bits();
        
        vgImageSubData(mVgImage, bits, mQImage.bytesPerLine(), 
            format, 0, 0, mQImage.width(), mQImage.height() );
        
    }
    
    if (mirror && mMirrorImage == VG_INVALID_HANDLE)
    {
        mMirrorImage = vgCreateImage(VG_sARGB_8888_PRE, mMirrorSize.width(), mMirrorSize.height(), VG_IMAGE_QUALITY_NONANTIALIASED);
        if (mMirrorImage == VG_INVALID_HANDLE)
        {
            qWarning("HgMediaWall run out of video memory for images!");
            return;
        }
        
        // cut half of the image, then scale to desired width/height if needed
        QImage mirrorImage = mQImage.copy(0, mQImage.height()/2, mQImage.width(), mQImage.height()/2).scaled(mMirrorSize).convertToFormat(QImage::Format_ARGB32);
        
        // apply gradient to alpha channel so that mirror image looks like
        // it fades under the floor
        for (int i = 0; i < mirrorImage.height(); i++)
        {
            qreal t = qreal(i) / qreal(mirrorImage.height());
            int a = (int)(t * 255.0);
            uchar* scanline = mirrorImage.scanLine(i);
            for (int j = 0; j < mirrorImage.width(); j++)
            {
                scanline[j*4+3] = a;
            }        
        }
        
        // copy data to vg image
        vgImageSubData(mMirrorImage, mirrorImage.bits(), mirrorImage.bytesPerLine(), 
            VG_sARGB_8888, 0, 0, mirrorImage.width(), mirrorImage.height() );

    }
    
}