src/hbcore/image/hbiconsource.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbCore module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 // Macro HB_BOOTSTRAPPED builds a stripped version of HbIconSource that is
       
    27 // used by ThemeIndexer build tool, to avoid unwanted dependencies.
       
    28 
       
    29 #include "hbiconsource_p.h"
       
    30 #ifndef HB_BOOTSTRAPPED
       
    31 #include "hbiconloader_p.h"
       
    32 #endif // HB_BOOTSTRAPPED
       
    33 #include <QtSvg/QSvgRenderer>
       
    34 #include <QPicture>
       
    35 #include <QScopedPointer>
       
    36 #include <QImageReader>
       
    37 #include <QPixmap>
       
    38 #include <QDir>
       
    39 #include <QFile>
       
    40 #include <QByteArray>
       
    41 #ifndef HB_BOOTSTRAPPED
       
    42 #ifdef HB_NVG_CS_ICON
       
    43 #include "hbnvg_p.h"
       
    44 #endif // HB_NVG_CS_ICON
       
    45 #endif // HB_BOOTSTRAPPED
       
    46 
       
    47 #ifdef HB_BOOTSTRAPPED
       
    48 
       
    49 // Copied from HbIconLoader::formatFromPath,
       
    50 // to avoid IconLoader dependency in ThemeIndexer, which needs this source file.
       
    51 QString iconTypeFromFilename(const QString &iconPath)
       
    52 {
       
    53     QString loweredIconPath = iconPath.toLower();
       
    54 
       
    55     if (loweredIconPath.endsWith(".svgz") ) {
       
    56         return "SVG";
       
    57     }
       
    58     if (loweredIconPath.endsWith(".qpic") ) {
       
    59         return "PIC";
       
    60     }
       
    61 
       
    62     if (loweredIconPath.endsWith(".svg")
       
    63         || loweredIconPath.endsWith(".png")
       
    64         || loweredIconPath.endsWith(".mng")
       
    65         || loweredIconPath.endsWith(".gif")
       
    66         || loweredIconPath.endsWith(".xpm")
       
    67         || loweredIconPath.endsWith(".jpg")
       
    68         || loweredIconPath.endsWith(".nvg")) {
       
    69         return iconPath.right(3).toUpper();
       
    70     }
       
    71 
       
    72     if (loweredIconPath.endsWith(".xml")
       
    73         || loweredIconPath.endsWith(".axml")
       
    74         || loweredIconPath.endsWith(".fxml"))
       
    75     {
       
    76         return "BLOB";
       
    77     }
       
    78 
       
    79     return iconPath.section('.', -1);
       
    80 }
       
    81 
       
    82 static const qint32 NVG_VIEWBOX_WIDTH_OFS   = 44;
       
    83 static const qint32 NVG_VIEWBOX_HEIGHT_OFS  = 48;
       
    84 
       
    85 // Copied from HbNvgEnginePrivate::contentDimensions,
       
    86 // to avoid NVG dependency in ThemeIndexer
       
    87 QSize nvgContentDimensions(const QByteArray &buffer)
       
    88 {
       
    89     QSize ret(0,0);
       
    90      if (buffer.length() < static_cast<qint32>(NVG_VIEWBOX_HEIGHT_OFS + sizeof (float))){
       
    91         ret = QSize(0, 0);
       
    92         } 
       
    93      
       
    94     const quint8* lBuf = (quint8*) buffer.data();
       
    95     if((buffer.length() > NVG_VIEWBOX_WIDTH_OFS) && (buffer.length() > NVG_VIEWBOX_HEIGHT_OFS)) {	
       
    96 	    float lViewboxWidth = * (float*)(lBuf + NVG_VIEWBOX_WIDTH_OFS);
       
    97 	    float lViewboxHeight = * (float*)(lBuf + NVG_VIEWBOX_HEIGHT_OFS);
       
    98 
       
    99 	    if (lViewboxWidth > 0 && lViewboxHeight > 0) {
       
   100 	        ret = QSize(lViewboxWidth, lViewboxHeight);
       
   101 	    } else {
       
   102 	        ret = QSize(0, 0);
       
   103 	    }
       
   104     }
       
   105     return ret;
       
   106 }
       
   107 
       
   108 
       
   109 #endif // HB_BOOTSTRAPPED
       
   110 
       
   111 /*!
       
   112   \class HbIconSource
       
   113   
       
   114   \brief Encapsulates access (size and pixel data reading) to image files.
       
   115 
       
   116   \internal
       
   117 */
       
   118 
       
   119 HbIconSource::HbIconSource(const QString &filename) :
       
   120     mFilename(filename),
       
   121     mPicture(0),
       
   122     mPixmap(0),
       
   123     mByteArray(0),
       
   124     mSvgRenderer(0),
       
   125     mImageReader(0)
       
   126 {
       
   127     mFullFilename = QDir(mFilename).absolutePath();
       
   128 }
       
   129 
       
   130 HbIconSource::HbIconSource(const QString &filename, const QString &type) :
       
   131     mFilename(filename),
       
   132     mType(type),
       
   133     mPicture(0),
       
   134     mPixmap(0),
       
   135     mByteArray(0),
       
   136     mSvgRenderer(0),
       
   137     mImageReader(0)
       
   138 {
       
   139     mFullFilename = QDir(mFilename).absolutePath();
       
   140 }
       
   141 
       
   142 HbIconSource::~HbIconSource()
       
   143 {
       
   144     delete mImageReader;
       
   145     delete mSvgRenderer;
       
   146     delete mPicture;
       
   147     delete mPixmap;
       
   148     delete mByteArray;
       
   149 }
       
   150 
       
   151 QString HbIconSource::filename() const
       
   152 {
       
   153     return mFilename;
       
   154 }
       
   155 
       
   156 QString HbIconSource::type()
       
   157 {
       
   158 #ifndef HB_BOOTSTRAPPED
       
   159     if (mType.isEmpty()) {
       
   160         mType = HbIconLoader::formatFromPath(mFilename);
       
   161     }
       
   162 #else
       
   163     mType = iconTypeFromFilename(mFilename);
       
   164 #endif // HB_BOOTSTRAPPED
       
   165     return mType;
       
   166 }
       
   167 
       
   168 QSizeF HbIconSource::defaultSize()
       
   169 {
       
   170     // If the default size has not been fetched yet, do it now.
       
   171     if (!mDefaultSize.isValid()) {
       
   172         type(); // make sure type is initialized
       
   173         if (mType == "NVG") {
       
   174 #ifndef HB_BOOTSTRAPPED
       
   175 #ifdef HB_NVG_CS_ICON
       
   176         if(!mByteArray){
       
   177             QFile file(mFilename);
       
   178             if (!file.open(QIODevice::NotOpen | QIODevice::ReadOnly)) {
       
   179                 return QSizeF();
       
   180             }                
       
   181             mByteArray = new QByteArray(file.readAll());
       
   182         }
       
   183         HbNvgEngine nvgEngine; 
       
   184         mDefaultSize = nvgEngine.contentDimensions(*mByteArray);
       
   185 #endif // HB_NVG_CS_ICON
       
   186 #else // HB_BOOTSTRAPPED
       
   187 
       
   188         if(!mByteArray){
       
   189             QFile file(mFilename);
       
   190             if (!file.open(QIODevice::NotOpen | QIODevice::ReadOnly)) {
       
   191                 return QSizeF();
       
   192             }                
       
   193             mByteArray = new QByteArray (file.readAll());
       
   194         }
       
   195 
       
   196         mDefaultSize = nvgContentDimensions(*mByteArray);
       
   197 #endif
       
   198         }
       
   199         else if (mType == "SVG") {
       
   200             QSvgRenderer *renderer = svgRenderer();
       
   201             if (renderer) { // isValid() is already checked in svgRenderer()
       
   202                 mDefaultSize = renderer->defaultSize();
       
   203             }
       
   204             releaseSvgRenderer();
       
   205         }
       
   206         else if (mType == "PIC") {
       
   207             if (!mPicture) {
       
   208                 mPicture = new QPicture;
       
   209                 mPicture->load(mFilename);
       
   210             }
       
   211             mDefaultSize = mPicture->boundingRect().size();
       
   212         }
       
   213         // Image reader supports getting the default size without rasterizing the image so
       
   214         // using it with the formats that it supports.
       
   215         else if (mType == "MNG" || mType == "GIF" || mType == "JPG" || mType == "PNG") {
       
   216             // Note that QImageReader::canRead() results in opening the file and so the
       
   217             // file will be locked until the QImageReader instance is
       
   218             // destroyed. Therefore the image reader instance must be destroyed as soon
       
   219             // as possible and must not be kept for later use.
       
   220             // Exception: Files on Z drive on Symbian. See canKeepOpen() and releaseImageReader().
       
   221             QImageReader *reader = imageReader();
       
   222             if (reader) { // canRead() is already checked in imageReader()
       
   223                 if (mType != "MNG") {
       
   224                     mDefaultSize = reader->size();
       
   225                 } else {
       
   226                     // MNG handler does not support size query so have to render it to get the size
       
   227                     QImage img = reader->read();
       
   228                     mDefaultSize = img.size();
       
   229                 }
       
   230             }
       
   231             releaseImageReader();
       
   232         }
       
   233         else if (mType != "BLOB") {
       
   234             if (!mPixmap) {
       
   235                 mPixmap = new QPixmap(mFilename);
       
   236             }
       
   237             mDefaultSize = mPixmap->size();
       
   238         }
       
   239     }
       
   240 
       
   241     return QSizeF(mDefaultSize);
       
   242 }
       
   243 
       
   244 /*!  Returns a QSvgRenderer instance. Ownership is not transferred to the
       
   245   caller. However make sure to call releaseSvgRenderer() as soon as possible.
       
   246  */
       
   247 QSvgRenderer *HbIconSource::svgRenderer()
       
   248 {
       
   249     if (!mSvgRenderer) {
       
   250         mSvgRenderer = new QSvgRenderer(mFilename);
       
   251     }
       
   252     return mSvgRenderer && mSvgRenderer->isValid() ? mSvgRenderer : 0;
       
   253 }
       
   254 
       
   255 /*!
       
   256     Must be called after the pointer returned by svgRenderer() is not needed by the client anymore.
       
   257 */
       
   258 void HbIconSource::releaseSvgRenderer()
       
   259 {
       
   260     if (mSvgRenderer && !canKeepOpen()) {
       
   261         delete mSvgRenderer;
       
   262         mSvgRenderer = 0;
       
   263     }
       
   264 }
       
   265 
       
   266 /*!
       
   267     Transfers the ownership of the pointer returned by svgRenderer() to the client.
       
   268 */
       
   269 void HbIconSource::takeSvgRenderer()
       
   270 {
       
   271     mSvgRenderer = 0;
       
   272 }
       
   273     
       
   274 QByteArray* HbIconSource::byteArray()
       
   275 {
       
   276     if (!mByteArray) {
       
   277     #ifdef HB_NVG_CS_ICON
       
   278         QFile file(mFilename);
       
   279         if (!file.open(QIODevice::NotOpen | QIODevice::ReadOnly)) {
       
   280             return 0;
       
   281         }
       
   282         mByteArray = new QByteArray (file.readAll());
       
   283     #endif//nvg 
       
   284     }
       
   285     
       
   286     if (!mByteArray->isEmpty()) {
       
   287         return mByteArray;
       
   288     } else {
       
   289         return 0;
       
   290     }
       
   291 }
       
   292 
       
   293 QPicture *HbIconSource::picture()
       
   294 {
       
   295     if (!mPicture) {
       
   296         mPicture = new QPicture;
       
   297         mPicture->load(mFilename);
       
   298     }
       
   299 
       
   300     return mPicture;
       
   301 }
       
   302 
       
   303 /*!  Returns a QImageReader instance. Ownership is not transferred to the
       
   304   caller. However make sure to call releaseImageReader() as soon as possible.
       
   305  */
       
   306 QImageReader *HbIconSource::imageReader()
       
   307 {
       
   308     if (!mImageReader) {
       
   309         mImageReader = new QImageReader(mFilename, mType.toLatin1());
       
   310     }
       
   311     return mImageReader && mImageReader->canRead() ? mImageReader : 0;
       
   312 }
       
   313 
       
   314 /*!
       
   315     Must be called after the pointer returned by imageReader() is not needed by the client anymore.
       
   316 */
       
   317 void HbIconSource::releaseImageReader()
       
   318 {
       
   319     if (mImageReader && !canKeepOpen()) {
       
   320         delete mImageReader;
       
   321         mImageReader = 0;
       
   322     }
       
   323 }
       
   324 
       
   325 /*!
       
   326     Transfers the ownership of the pointer returned by imageReader() to the client.
       
   327 */
       
   328 void HbIconSource::takeImageReader()
       
   329 {
       
   330     mImageReader = 0;
       
   331 }
       
   332 
       
   333 QPixmap *HbIconSource::pixmap()
       
   334 {
       
   335     if (!mPixmap) {
       
   336         mPixmap = new QPixmap(mFilename);
       
   337     }
       
   338 
       
   339     return mPixmap;
       
   340 }
       
   341 
       
   342 void HbIconSource::deletePixmapIfLargerThan(int limitInBytes)
       
   343 {
       
   344     if (mPixmap) {
       
   345         QSize size = mPixmap->size();
       
   346         int sizeInBytes = size.width() * size.height() * mPixmap->depth();
       
   347         sizeInBytes /= 8; // depth is in bits, we want bytes
       
   348 
       
   349         if (sizeInBytes > limitInBytes) {
       
   350             delete mPixmap;
       
   351             mPixmap = 0;
       
   352         }
       
   353     }
       
   354 }
       
   355 
       
   356 bool HbIconSource::canKeepOpen() const
       
   357 {
       
   358 #ifdef Q_OS_SYMBIAN
       
   359     if (mFullFilename.isEmpty()) {
       
   360         return false;
       
   361     } else {
       
   362         QChar driveLetter = mFullFilename.at(0);
       
   363         return driveLetter.toUpper() == 'Z';
       
   364     }
       
   365 #else
       
   366     return false;
       
   367 #endif
       
   368 }