/****************************************************************************
**
** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (developer.feedback@nokia.com)
**
** This file is part of the HbServers module of the UI Extensions for Mobile.
**
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at developer.feedback@nokia.com.
**
****************************************************************************/

#include "hbiconcacheitemcreator_p.h"
#include "hbpixmapiconprocessor_p.h"
#include "hbpiciconprocessor_p.h"
#include "hbthemeserverutils_p.h"
#include "hbmemorymanager_p.h"
#include "hbiconsource_p.h"
#include "hbmemoryutils_p.h"
#ifdef Q_OS_SYMBIAN
#include "hbthemeserver_symbian_p_p.h"
#endif
#include <QFile>

#ifdef HB_NVG_CS_ICON
#include "hbnvgiconprocessor_p.h"
#ifdef HB_SGIMAGE_ICON
#include "hbsgimageiconprocessor_p.h"
#endif
#endif

/*!
    @hbserver
    \class HbIconCacheItemCreator
    \brief HbIconCacheItemCreator is a factory class responsible for creating the cache items.
    The cache item structure internally maintains details of
    the icons created both in the Gpu and the Cpu memory.

*/

/*! Description of data members for HbIconCacheItem
    //Icon data for icon created on GPU
    HbSharedIconInfo       rasterIconData;
    //Icon data for icon created on CPU
    HbSharedIconInfo       vectorIconData;
    // reference count
    int refCount;
    // linkage of HbIconCacheItems used by LRU list for GPU memory
    HBDLink<HbIconCacheItem> gpuLink;
    // linkage of HbIconCacheItems used by LRU list for CPU memory
    HBDLink<HbIconCacheItem> cpuLink;
    //size of shared raster Icon data on GPU
    int     rasterIconDataCost;
    //size of shared CPU Icon data
    int     vectorIconDataCost;
    // IconLoader options
    HbIconLoader::IconLoaderOptions iconOptions;
*/

QString HbIconCacheItemCreator::KSvg = "SVG";
QString HbIconCacheItemCreator::KNvg = "NVG";
QString HbIconCacheItemCreator::KPic = "PIC";
QString HbIconCacheItemCreator::KBlob = "BLOB";
QString HbIconCacheItemCreator::KSgimage = "SGIMAGE";


/*!
    \fn HbIconCacheItemCreator::createCacheItem()
    The createCacheItem is responsible for creating an icon in cpu or gpu memory
    based on the format provided.
    \a key denotes the unique identifier for the cache item
    \a options indicate different ways of loading icons
    \a format indicates the icon format e.g. svg/nvg etc.\
    \a renderingMode rendering mode to be used for creating CacheItem.
 */
HbIconCacheItem *HbIconCacheItemCreator::createCacheItem(const HbIconKey &key,
        HbIconLoader::IconLoaderOptions options,
        const QString &format,
        HbRenderingMode renderMode,
        bool isMultiPiece)
{
#ifndef Q_OS_SYMBIAN
    Q_UNUSED(isMultiPiece)
    Q_UNUSED(renderMode)
#endif
    QScopedPointer <HbIconCacheItem> tempIconCacheItem(new HbIconCacheItem);
    HbIconCacheItem *item = tempIconCacheItem.data();
    QScopedPointer <HbIconProcessor> rasterIcon;
    QScopedPointer <HbIconProcessor> vectorIcon;
    
    bool isIconCreated = false;

    if ((format == KSvg) || (format == KPic)) {
        rasterIcon.reset(new HbPixmapIconProcessor(key, options, format));
        
#ifdef SVG_INTERMEDIATE_PIC
        vectorIcon.reset(new HbPicIconProcessor(key, options, format));
#endif
    } else if (format == KNvg) {
#ifdef HB_NVG_CS_ICON
        if (!isMultiPiece) {
#ifdef HB_SGIMAGE_ICON
            if(renderMode == ESWRendering){ 
                rasterIcon.reset(new HbPixmapIconProcessor(key, options, format));
            } else {
                if (HbThemeServerPrivate::gpuMemoryState()) {
                    rasterIcon.reset(new HbSgimageIconProcessor(key, options, format));
                }

                if(!rasterIcon.data()) {
                    rasterIcon.reset(new HbPixmapIconProcessor(key, options, format));
                } else {
                    vectorIcon.reset(new HbNvgIconProcessor(key, options, format));
                }
            }
#endif
            
// if sgImage support is enabled by default remove this block
#ifndef HB_SGIMAGE_ICON
            if(renderMode == ESWRendering){
                rasterIcon.reset(new HbPixmapIconProcessor(key, options, format));
            } else {
                vectorIcon.reset(new HbNvgIconProcessor(key, options, format));
            }
#endif
// block end
        }
        else {
            if(renderMode == ESWRendering){
                rasterIcon.reset(new HbPixmapIconProcessor(key, options, format));
            } else {
                // multipieceIcon So make nvgiconimpl for .nvg files
                // No raster icon data is created
                vectorIcon.reset(new HbNvgIconProcessor(key, options, format));
            }
        }
#endif
    } else if (format == KBlob) {
        item->blobIconData.type = BLOB;
        bool fail = true;
        HbIconSource *source = HbThemeServerUtils::getIconSource(key.filename);
        if (source) {
            QByteArray *content = source->byteArray();
            if (content) {
                GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory);
                item->blobIconData.blobData.offset = manager->alloc(content->length());
                if (item->blobIconData.blobData.offset != -1) {
                    fail = false;
                    // Store vector cost because blobs go into the "cpu" cache.
                    item->blobIconData.blobData.dataSize
                    = item->vectorIconDataCost
                    = content->length();
                    item->blobIconData.renderingMode = ESWRendering;
                    memcpy(HbMemoryUtils::getAddress<char>(
                              HbMemoryManager::SharedMemory,
                              item->blobIconData.blobData.offset),
                              content->data(),
                              content->length());
                }   
                
            }
        }
        if (fail) {
            return 0;
        }
    } else {
        rasterIcon.reset(new HbPixmapIconProcessor(key, options, format));
    }

    if (rasterIcon.data()) {
        isIconCreated = rasterIcon.data()->createIconData(key.filename);
        if (isIconCreated) {
            item->rasterIconData = rasterIcon.data()->sharedIconData();
            item->rasterIconDataCost = rasterIcon.data()->sharedIconDataCost();
        } else if(format == KNvg && renderMode == EHWRendering){
#ifdef HB_SGIMAGE_ICON
            rasterIcon.reset(new HbPixmapIconProcessor(key, options, format));
            if (rasterIcon.data()) {
                isIconCreated = rasterIcon.data()->createIconData(key.filename);
                if (isIconCreated) {
                    item->rasterIconData = rasterIcon.data()->sharedIconData();
                    item->rasterIconDataCost = rasterIcon.data()->sharedIconDataCost();
                }
            }
#endif
        }
    }

    if (vectorIcon.data()) {
        isIconCreated = vectorIcon.data()->createIconData(key.filename);
        if (isIconCreated) {
            item->vectorIconData = vectorIcon.data()->sharedIconData();
            item->vectorIconDataCost = vectorIcon.data()->sharedIconDataCost();
        }
    }

    if (item) {
        item->iconOptions = options;
    }
    if (tempIconCacheItem.data()) {
        tempIconCacheItem.take();
    }
    return item;
}


/*!
    \fn HbIconCacheItemCreator::createCacheItem()
    This overloaded createCacheItem is a helper function to populate a cache item
    if this item is already created with some parameters either on the Gpu or the Cpu
    \a iconCacheItem denotes the cacheItem to be populated
    \a key unique identifier to identify the cache item
    \a currentRenderingMode ThemeServer's current rendering mode state

 */
void HbIconCacheItemCreator::createCacheItem(HbIconCacheItem &iconCacheItem,
                                                const HbIconKey &key,
                                                HbRenderingMode currentRenderingMode)
{
#ifndef Q_OS_SYMBIAN
    Q_UNUSED(currentRenderingMode)
#endif
    QScopedPointer <HbIconProcessor> rasterIcon;
    QScopedPointer <HbIconProcessor> vectorIcon;
    
    // Set the render mode to EHWRendering, only if the client is requesting a HW rendered icon
    // and ThemeServer is in HW rendering mode
    HbRenderingMode renderMode = ESWRendering;
#ifndef Q_OS_SYMBIAN
    Q_UNUSED(renderMode)
#endif   

#if defined(HB_SGIMAGE_ICON) || defined(HB_NVG_CS_ICON)
    if((key.renderMode == EHWRendering) && (currentRenderingMode == EHWRendering)) {
        renderMode = EHWRendering;
    }
#endif    
    bool isIconCreated = false;
    QString format = HbThemeServerUtils::formatFromPath(key.filename);

    // If the item is already created on the CPU side but not on the GPU side
    if (iconCacheItem.rasterIconData.type == INVALID_FORMAT &&
            iconCacheItem.vectorIconData.type != INVALID_FORMAT) {
        if ((format == KSvg) || (format == KPic)) {
            rasterIcon.reset(new HbPixmapIconProcessor(key, iconCacheItem.iconOptions, format));
        }
        if (format == KNvg) {
#ifdef HB_SGIMAGE_ICON
            if(renderMode == EHWRendering){
                if (HbThemeServerPrivate::gpuMemoryState()){
                    rasterIcon.reset(new HbSgimageIconProcessor(key, iconCacheItem.iconOptions,
                                                                 format));
                }
                if(!rasterIcon.data()) {
                    rasterIcon.reset(new HbPixmapIconProcessor(key, iconCacheItem.iconOptions, format));
                } 
            } else {
                rasterIcon.reset(new HbPixmapIconProcessor(key, iconCacheItem.iconOptions,
                                                           format));
            }
#endif
#ifdef NVG_ICON
            rasterIcon.reset(new HbPixmapIconProcessor(key, options, format));
#endif
        }
        if (rasterIcon.data()) {
            isIconCreated = rasterIcon.data()->createIconData(key.filename);
            if (isIconCreated) {
                iconCacheItem.rasterIconData = rasterIcon.data()->sharedIconData();
                iconCacheItem.rasterIconDataCost = rasterIcon.data()->sharedIconDataCost();
            } else if(format == KNvg && renderMode == EHWRendering){
#ifdef HB_SGIMAGE_ICON
                rasterIcon.reset(new HbPixmapIconProcessor(key, iconCacheItem.iconOptions, format));
                if (rasterIcon.data()) {
                    isIconCreated = rasterIcon.data()->createIconData(key.filename);
                    if (isIconCreated) {
                    iconCacheItem.rasterIconData = rasterIcon.data()->sharedIconData();
                    iconCacheItem.rasterIconDataCost = rasterIcon.data()->sharedIconDataCost();
                    }
                }
#endif
            }
        }
    }

    // If the item is already created on the GPU side but not on the CPU side
    if (iconCacheItem.rasterIconData.type == SGIMAGE &&
            iconCacheItem.vectorIconData.type == INVALID_FORMAT) {
        if ((format == KSvg) || (format == KPic)) {
#ifdef SVG_INTERMEDIATE_PIC
            vectorIcon.reset(new HbPicIconProcessor(key, options, format));
#endif
        }
        if (format == KNvg) {
#ifdef NVG_ICON
            vectorIcon.reset(new HbNvgIconProcessor(key, options, format));
#endif
        }
        if (vectorIcon.data()) {
            isIconCreated = vectorIcon.data()->createIconData(key.filename);
            if (isIconCreated) {
                iconCacheItem.vectorIconData = vectorIcon.data()->sharedIconData();
                iconCacheItem.vectorIconDataCost = vectorIcon.data()->sharedIconDataCost();
            }
        }
    }
}

HbIconCacheItem * HbIconCacheItemCreator::createMultiPieceCacheItem(
    const HbIconKey &finalIconKey,
    HbIconLoader::IconLoaderOptions options,
    const QString &format,
    const QVector<HbSharedIconInfo> &multiPieceIconInfo,
    HbMultiIconParams &multiPieceIconParams,
    bool allNvg,
    HbRenderingMode renderMode)
{

#ifndef Q_OS_SYMBIAN
    Q_UNUSED(renderMode)
#endif   
    
    HbIconCacheItem *item = 0;
    QScopedPointer<HbIconCacheItem> tempIconCacheItem;
    bool isIconCreated = false;
    QScopedPointer<HbIconProcessor> rasterIcon;
    
    if (allNvg) {
#ifdef HB_SGIMAGE_ICON
        if(renderMode == EHWRendering){ 
            if (HbThemeServerPrivate::gpuMemoryState()) {
                rasterIcon.reset(new HbSgimageIconProcessor(
                                             finalIconKey,
                                             (HbIconLoader::IconLoaderOptions)multiPieceIconParams.options,
                                             KSgimage));
                
                if(!rasterIcon.data()) {
                    rasterIcon.reset(new HbPixmapIconProcessor( 
                                               finalIconKey, 
                                               (HbIconLoader::IconLoaderOptions)multiPieceIconParams.options, 
                                               KNvg));
                }
            }
            
        } else {
            rasterIcon.reset(new HbPixmapIconProcessor( 
                                finalIconKey, 
                                (HbIconLoader::IconLoaderOptions)multiPieceIconParams.options, 
                                KNvg));
        }
#else
        return item;
#endif
    } else {
        rasterIcon.reset(new HbPixmapIconProcessor(finalIconKey,
            static_cast<HbIconLoader::IconLoaderOptions>(multiPieceIconParams.options), format));
    }

    if (rasterIcon.data()) {
        isIconCreated = rasterIcon->createMultiPieceIconData(multiPieceIconInfo, multiPieceIconParams);
        if (isIconCreated) {
            tempIconCacheItem.reset(new HbIconCacheItem());
            item = tempIconCacheItem.data();
            item->rasterIconData = rasterIcon->sharedIconData();
            item->rasterIconDataCost = rasterIcon->sharedIconDataCost();
            item->iconOptions = options;
        } else {
#ifdef HB_SGIMAGE_ICON
            if(renderMode == EHWRendering && allNvg ) { 
               rasterIcon.reset(new HbPixmapIconProcessor( 
                                                          finalIconKey, 
                                                          (HbIconLoader::IconLoaderOptions)multiPieceIconParams.options, 
                                                          KNvg));
                
                if (rasterIcon.data()) {
                    isIconCreated = rasterIcon->createMultiPieceIconData(multiPieceIconInfo, multiPieceIconParams);
                    if (isIconCreated) {
                        tempIconCacheItem.reset(new HbIconCacheItem());
                        item = tempIconCacheItem.data();
                        item->rasterIconData = rasterIcon->sharedIconData();
                        item->rasterIconDataCost = rasterIcon->sharedIconDataCost();
                        item->iconOptions = options;
                    }
                }
            }
#endif         
        } 
        
    }
    tempIconCacheItem.take();
    return item;
}
