src/hbcore/image/hbicon.cpp
changeset 34 ed14f46c0e55
parent 7 923ff622b8b9
equal deleted inserted replaced
31:7516d6d86cf5 34:ed14f46c0e55
   144          there is no need to handle theme and layout direction changes for this icon.
   144          there is no need to handle theme and layout direction changes for this icon.
   145          This is merely an optimization flag and must be set directly after creating the
   145          This is merely an optimization flag and must be set directly after creating the
   146          HbIcon instance (before the first paint of the icon) to have any performance
   146          HbIcon instance (before the first paint of the icon) to have any performance
   147          benefits.
   147          benefits.
   148 
   148 
       
   149   \b KeepDefaultQIconSize \b (0x20) This flag disables all scaling for icons constructed
       
   150          from QIcon. It has no effect on regular, native HbIcons. It only affects the
       
   151          painting: The size of the HbIcon will remain whatever was set via setSize(), but
       
   152          only a part of that area will be painted. This is similar to
       
   153          HbIconItem::setIconScaling(false) but in that case the underlying icon's size
       
   154          would also be changed to match the default size, while here size() remains
       
   155          unaffected.
       
   156 
   149 */
   157 */
   150 
   158 
   151 /*!
   159 /*!
   152   \enum HbIcon::MirroringMode
   160   \enum HbIcon::MirroringMode
   153 
   161 
   181 \internal
   189 \internal
   182 */
   190 */
   183 HbIconPrivate::HbIconPrivate() :
   191 HbIconPrivate::HbIconPrivate() :
   184     engine(new HbIconEngine(QString())),
   192     engine(new HbIconEngine(QString())),
   185     qicon(engine),
   193     qicon(engine),
   186     badgeInfo(0)
   194     badgeInfo(0),
       
   195     mQIconFlags(0),
       
   196     mQIconPixmapMode(QIcon::Normal),
       
   197     mQIconPixmapState(QIcon::Off)
   187 {
   198 {
   188     ref.ref(); // Need to do extra ref so the shared null does not get destructed
   199     ref.ref(); // Need to do extra ref so the shared null does not get destructed
   189 }
   200 }
   190 
   201 
   191 /*!
   202 /*!
   192 \internal
   203 \internal
   193 */
   204 */
   194 HbIconPrivate::HbIconPrivate(const QIcon &qicon) :
   205 HbIconPrivate::HbIconPrivate(const QIcon &qicon) :
   195     engine(0),
   206     engine(0),
   196     qicon(qicon),
   207     qicon(qicon),
   197     badgeInfo(0)
   208     badgeInfo(0),
       
   209     mQIconFlags(0),
       
   210     mQIconPixmapMode(QIcon::Normal),
       
   211     mQIconPixmapState(QIcon::Off)
   198 {
   212 {
   199 }
   213 }
   200 
   214 
   201 /*!
   215 /*!
   202 \internal
   216 \internal
   203 */
   217 */
   204 HbIconPrivate::HbIconPrivate(const QString &iconName) :
   218 HbIconPrivate::HbIconPrivate(const QString &iconName) :
   205     engine(new HbIconEngine(iconName)),
   219     engine(new HbIconEngine(iconName)),
   206     qicon(engine),
   220     qicon(engine),
   207     badgeInfo(0)
   221     badgeInfo(0),
       
   222     mQIconFlags(0),
       
   223     mQIconPixmapMode(QIcon::Normal),
       
   224     mQIconPixmapState(QIcon::Off)
   208 {
   225 {
   209 }
   226 }
   210 
   227 
   211 /*!
   228 /*!
   212 \internal
   229 \internal
   214 HbIconPrivate::HbIconPrivate(const HbIconPrivate &other) :
   231 HbIconPrivate::HbIconPrivate(const HbIconPrivate &other) :
   215     QSharedData(other),
   232     QSharedData(other),
   216     size(other.size),
   233     size(other.size),
   217     engine(0),
   234     engine(0),
   218     qicon(),
   235     qicon(),
   219     badgeInfo(0)
   236     badgeInfo(0),
       
   237     mQIconFlags(other.mQIconFlags),
       
   238     mQIconPixmap(other.mQIconPixmap),
       
   239     mQIconPixmapMode(other.mQIconPixmapMode),
       
   240     mQIconPixmapState(other.mQIconPixmapState)
   220 {
   241 {
   221     if (other.engine) {
   242     if (other.engine) {
   222         engine = new HbIconEngine(*other.engine);
   243         engine = new HbIconEngine(*other.engine);
   223         // Have to instantiate a temporary QIcon because
   244         // Have to instantiate a temporary QIcon because
   224         // QIcon's copy constructor shares the engine.
   245         // QIcon's copy constructor shares the engine.
   309 \internal
   330 \internal
   310 */
   331 */
   311 QDataStream &operator>>(QDataStream &stream, HbIconPrivate &icon)
   332 QDataStream &operator>>(QDataStream &stream, HbIconPrivate &icon)
   312 {
   333 {
   313     stream >> icon.size;
   334     stream >> icon.size;
   314     int enginePtr = 0;
   335     qptrdiff enginePtr = 0;
   315     stream >> enginePtr;
   336     stream >> enginePtr;
   316     if (enginePtr) {
   337     if (enginePtr) {
   317         icon.engine = new HbIconEngine(stream);
   338         icon.engine = new HbIconEngine(stream);
   318     } else {
   339     } else {
   319         stream >> icon.qicon;
   340         stream >> icon.qicon;
   376     }
   397     }
   377 
   398 
   378     return result;
   399     return result;
   379 }
   400 }
   380 
   401 
       
   402 /*!
       
   403   \internal
       
   404 */
       
   405 void HbIconPrivate::setAsync(bool async, HbIconEngine::AsyncCallback callback, void *param)
       
   406 {
       
   407     if (engine) {
       
   408         engine->setAsync(async, callback, param);
       
   409     }
       
   410 }
       
   411 
       
   412 /*!
       
   413   \internal
       
   414 */
       
   415 bool HbIconPrivate::async() const
       
   416 {
       
   417     if (engine) {
       
   418         return engine->async();
       
   419     }
       
   420     return false;
       
   421 }
       
   422 
   381 /*! Default constructor. If this constructor is used, the icon name needs to be set
   423 /*! Default constructor. If this constructor is used, the icon name needs to be set
   382 * by calling HbIcon::setIconName.
   424 * by calling HbIcon::setIconName.
   383 */
   425 */
   384 HbIcon::HbIcon()
   426 HbIcon::HbIcon()
   385 {
   427 {
   390     d = shared_null;
   432     d = shared_null;
   391 }
   433 }
   392 
   434 
   393 /*! Constructs a new icon with the icon name \a iconName.
   435 /*! Constructs a new icon with the icon name \a iconName.
   394 */
   436 */
   395 HbIcon::HbIcon(const QString &iconName)
   437 HbIcon::HbIcon(const QString &iconName) : d( new HbIconPrivate(iconName) )
   396 {
   438 {
   397     d = new HbIconPrivate(iconName);
   439 }
   398 }
   440 
   399 
   441 /*!
   400 /*! Constructs a new icon to be a copy of the given QIcon.
   442  * Constructs a new icon to be a copy of the given QIcon.  Due to the
   401 * Due to the limitations listed below, this constructor should be used only for
   443  * limitations listed below, this constructor should be used only for
   402 * compatibility reasons if a QIcon instance needs to be passed as a parameter
   444  * compatibility reasons if a QIcon instance needs to be passed as a parameter
   403 * to a method taking a HbIcon parameter.
   445  * to a method taking a HbIcon parameter.
   404 * \note If this constructor is used, there are the following limitations in the HbIcon methods.
   446  *
   405 * - HbIcon::defaultSize() may return QSizeF().
   447  * \note If this constructor is used, the following limitations apply:
   406 * - HbIcon::paint() ignores the parameter aspectRatioMode and converts the given QRectF to QRect.
   448  *
   407 * - HbIcon::iconName() returns empty string by default.
   449  * - HbIcon::defaultSize() may return QSizeF().
   408 * - HbIcon::pixmap() returns null pixmap.
   450  * - HbIcon::paint() ignores the parameter aspectRatioMode and converts the given QRectF to QRect.
   409 * - Colorization and mirroring support are not available.
   451  * - HbIcon::iconName() returns empty string by default.
   410 * This method should only be used if absolute necessary, as this is not ideal for hardware accelerated environment
   452  * - HbIcon::pixmap() returns null pixmap.
   411 * and there may be huge differences in painting performance when compared to a native HbIcon.
   453  * - Colorization and mirroring support are not available.
   412 */
   454  *
   413 HbIcon::HbIcon(const QIcon &icon)
   455  * This method should only be used if absolute necessary, as this is not ideal
   414 {
   456  * for hardware accelerated environment and there may be huge differences in
   415     d = new HbIconPrivate(icon);
   457  * painting performance when compared to a native HbIcon.  Some advanced resource
       
   458  * management features are not available for such icons either.
       
   459  */
       
   460 HbIcon::HbIcon(const QIcon &icon) : d( new HbIconPrivate(icon) )
       
   461 {
   416 }
   462 }
   417 
   463 
   418 /*!
   464 /*!
   419 * Copy constructs a new icon using the \a other icon.
   465 * Copy constructs a new icon using the \a other icon.
   420 * Copy-on-write semantics is used, so this only does a shallow copy.
   466 * Copy-on-write semantics is used, so this only does a shallow copy.
   516 * HbIcon::Colorized flag set.
   562 * HbIcon::Colorized flag set.
   517 *
   563 *
   518 * However it is possible to override this theme-specific color with a custom one
   564 * However it is possible to override this theme-specific color with a custom one
   519 * by calling this function.
   565 * by calling this function.
   520 *
   566 *
   521 * \warning Currently this method makes use of pixmap() routine in case of NVG icons.
       
   522 * pixmap() slows down the hardware accelerated rendering.
       
   523 *
       
   524 * \sa HbIcon::color(), HbIcon::Colorized
   567 * \sa HbIcon::color(), HbIcon::Colorized
   525 */
   568 */
   526 void HbIcon::setColor(const QColor &color)
   569 void HbIcon::setColor(const QColor &color)
   527 {
   570 {
   528     if (d->engine) {
   571     if (d->engine) {
   567 * \sa HbIcon::iconName()
   610 * \sa HbIcon::iconName()
   568 */
   611 */
   569 void HbIcon::setIconName(const QString &iconName)
   612 void HbIcon::setIconName(const QString &iconName)
   570 {
   613 {
   571     if (d->engine && d->engine->iconName() != iconName) {
   614     if (d->engine && d->engine->iconName() != iconName) {
       
   615         // Icon was normal HbIcon and the name is changed.
   572         d.detach();
   616         d.detach();
   573         d->engine->setIconName(iconName);
   617         d->engine->setIconName(iconName);
   574     } else {
   618     } else if (!d->engine) {
   575         // Icon was earlier copy constructed from QIcon, but now its name is set,
   619         // Icon was earlier copy constructed from QIcon, but now its name is set,
   576         // so it becomes a 'real' HbIcon.
   620         // so it becomes a 'real' HbIcon.
   577         d.detach();
   621         d.detach();
   578         d->engine = new HbIconEngine(iconName);
   622         d->engine = new HbIconEngine(iconName);
   579         d->engine->setSize(d->size);
   623         d->engine->setSize(d->size);
   580         // Have to instantiate a temporary QIcon because
   624         // Have to instantiate a temporary QIcon because
   581         // QIcon's assignment operator shares the engine.
   625         // QIcon's assignment operator shares the engine.
   582         QIcon temp(d->engine);
   626         QIcon temp(d->engine);
   583         d->qicon = temp;
   627         d->qicon = temp;
   584     }
   628         d->mQIconPixmap = QPixmap();
       
   629     }
       
   630     // Otherwise icon was normal HbIcon and the name is same as before, so do nothing.
   585 }
   631 }
   586 
   632 
   587 /*!
   633 /*!
   588 * Returns the name of the icon in the specified \a mode and \a state.
   634 * Returns the name of the icon in the specified \a mode and \a state.
   589 * If there is no icon name set for the specified \a mode and \a state,
   635 * If there is no icon name set for the specified \a mode and \a state,
   635         if (d->engine) {
   681         if (d->engine) {
   636             d->engine->paint(painter, rect, aspectRatioMode, alignment, mode, state);
   682             d->engine->paint(painter, rect, aspectRatioMode, alignment, mode, state);
   637         } else {
   683         } else {
   638             // This HbIcon was copy constructed from QIcon and
   684             // This HbIcon was copy constructed from QIcon and
   639             // we cannot use HbIconEngine for painting.
   685             // we cannot use HbIconEngine for painting.
       
   686 
       
   687             // Find out the size: It can be the size set via setSize(), or, in case of
       
   688             // KeepDefaultQIconSize, the first available size, or, if none are set, the
       
   689             // target area's size.
   640             QSizeF size = this->size();
   690             QSizeF size = this->size();
   641             if (!size.isValid()) {
   691             if (flags().testFlag(KeepDefaultQIconSize)) {
   642                 // If size is not set, have to use rect size because QIcon
   692                 QList<QSize> sizes = d->qicon.availableSizes();
   643                 // does not provide defaultSize information.
   693                 if (!sizes.isEmpty()) {
   644                 size = rect.size();
   694                     size = sizes.at(0);
       
   695                 }
       
   696             } else {
       
   697                 if (!size.isValid()) {
       
   698                     size = rect.size();
       
   699                 }
   645             }
   700             }
   646 
   701 
   647             QPixmap pixmap = d->qicon.pixmap(size.toSize(), mode, state);
   702             // Get the pixmap with the needed size.
       
   703             QPixmap pixmap;
       
   704             QSize intSize = size.toSize();
       
   705             bool usingCached = false;
       
   706             if (d->mQIconPixmap.size() == intSize
       
   707                 && mode == d->mQIconPixmapMode
       
   708                 && state == d->mQIconPixmapState)
       
   709             {
       
   710                 pixmap = d->mQIconPixmap;
       
   711                 usingCached = true;
       
   712             } else {
       
   713                 pixmap = d->qicon.pixmap(intSize, mode, state);
       
   714                 d->mQIconPixmap = pixmap;
       
   715                 d->mQIconPixmapMode = mode;
       
   716                 d->mQIconPixmapState = state;
       
   717             }
   648             QSizeF pixmapSize = pixmap.size();
   718             QSizeF pixmapSize = pixmap.size();
   649 
   719 
   650             // QIcon::pixmap() will not do upscaling.
   720             // QIcon::pixmap() will not do upscaling, do it here if needed.
   651             if (pixmapSize.width() < size.width() || pixmapSize.height() < size.height()) {
   721             if (!pixmap.isNull() && !usingCached && !flags().testFlag(KeepDefaultQIconSize)
       
   722                 && (pixmapSize.width() < size.width() || pixmapSize.height() < size.height()))
       
   723             {
   652                 // Native HbIcons are scaled using SmoothTransformation so use the same.
   724                 // Native HbIcons are scaled using SmoothTransformation so use the same.
   653                 pixmap = pixmap.scaled(size.toSize(), aspectRatioMode, Qt::SmoothTransformation);
   725                 pixmap = pixmap.scaled(size.toSize(), aspectRatioMode, Qt::SmoothTransformation);
   654                 pixmapSize = pixmap.size();
   726                 pixmapSize = pixmap.size();
   655             }
   727             }
   656 
   728 
   657             // Adjust the alignment
   729             // Adjust the alignment.
   658             QPointF topLeft = rect.topLeft();
   730             QPointF topLeft = rect.topLeft();
   659 
   731 
   660             if (alignment & Qt::AlignRight) {
   732             if (alignment & Qt::AlignRight) {
   661                 topLeft.setX(rect.right() - pixmapSize.width());
   733                 topLeft.setX(rect.right() - pixmapSize.width());
   662             } else if (alignment & Qt::AlignHCenter) {
   734             } else if (alignment & Qt::AlignHCenter) {
   667                 topLeft.setY(rect.bottom() - pixmapSize.height());
   739                 topLeft.setY(rect.bottom() - pixmapSize.height());
   668             } else if (alignment & Qt::AlignVCenter) {
   740             } else if (alignment & Qt::AlignVCenter) {
   669                 topLeft.setY(topLeft.y() + (rect.height() - pixmapSize.height()) / 2);
   741                 topLeft.setY(topLeft.y() + (rect.height() - pixmapSize.height()) / 2);
   670             }
   742             }
   671 
   743 
       
   744             // Draw.
   672             painter->drawPixmap(topLeft, pixmap, pixmap.rect());
   745             painter->drawPixmap(topLeft, pixmap, pixmap.rect());
   673 
   746 
   674             // Draw the badges on this icon
   747             // Draw the badges on this icon.
   675             if (d->badgeInfo) {
   748             if (d->badgeInfo) {
   676                 d->badgeInfo->paint(painter, rect, mode, state, false);
   749                 d->badgeInfo->paint(painter, rect, mode, state, false);
   677             }
   750             }
   678         }
   751         }
   679     }
   752     }
   682 /*! Returns the current size of the icon.
   755 /*! Returns the current size of the icon.
   683 * \sa HbIcon::setSize(), HbIcon::defaultSize()
   756 * \sa HbIcon::setSize(), HbIcon::defaultSize()
   684 */
   757 */
   685 QSizeF HbIcon::size() const
   758 QSizeF HbIcon::size() const
   686 {
   759 {
   687     if ((static_cast<int>(flags()) & HbIcon::ResolutionCorrected)) {
   760     if (flags().testFlag(HbIcon::ResolutionCorrected)) {
   688         if (d->engine) {
   761         if (d->engine) {
   689             d->size = d->engine->size();
   762             d->size = d->engine->size();
   690         }
   763         }
   691         if (d->size.isValid()) {
   764         if (d->size.isValid()) {
   692             return d->size;
   765             return d->size;
   792 HbIcon::Flags HbIcon::flags() const
   865 HbIcon::Flags HbIcon::flags() const
   793 {
   866 {
   794     if (d->engine) {
   867     if (d->engine) {
   795         return d->engine->flags();
   868         return d->engine->flags();
   796     } else {
   869     } else {
   797         return (HbIcon::Flags)0;
   870         return d->mQIconFlags;
   798     }
   871     }
   799 }
   872 }
   800 
   873 
   801 /*! Sets the flags for the icon.
   874 /*! Sets the flags for the icon.
   802 */
   875 */
   805     if (d->engine) {
   878     if (d->engine) {
   806         if (flags != d->engine->flags()) {
   879         if (flags != d->engine->flags()) {
   807             d.detach();
   880             d.detach();
   808             d->engine->setFlags(flags);
   881             d->engine->setFlags(flags);
   809         }
   882         }
       
   883     } else if (flags != d->mQIconFlags) {
       
   884         d.detach();
       
   885         d->mQIconFlags = flags;
   810     }
   886     }
   811 }
   887 }
   812 
   888 
   813 /*! Sets the size for the icon. Without calling this method, the icon uses its default size.
   889 /*! Sets the size for the icon. Without calling this method, the icon uses its default size.
   814 * \sa HbIcon::size(), HbIcon::defaultSize()
   890 * \sa HbIcon::size(), HbIcon::defaultSize()
   910 
   986 
   911 /*!
   987 /*!
   912  * Adds a badge icon to the existing icon. The badge icons
   988  * Adds a badge icon to the existing icon. The badge icons
   913  * are drawn relative to the alignment you specify with the
   989  * are drawn relative to the alignment you specify with the
   914  * z-order you provide.
   990  * z-order you provide.
   915  * 
   991  *
   916  * By default the badge icon will use its default size.  If this is
   992  * By default the badge icon will use its default size.  If this is
   917  * not suitable (which is typical in case of vector graphics) then
   993  * not suitable (which is typical in case of vector graphics) then
   918  * call setSize() explicitly on \a badge before passing it to this
   994  * call setSize() explicitly on \a badge before passing it to this
   919  * function.
   995  * function.
   920  *
   996  *
  1000 
  1076 
  1001 /*!
  1077 /*!
  1002     Clears the icon data (e.g. QPixmaps that are stored internally) but does not
  1078     Clears the icon data (e.g. QPixmaps that are stored internally) but does not
  1003     touch the settings, e.g. the size, state, flags, unlike clear().
  1079     touch the settings, e.g. the size, state, flags, unlike clear().
  1004 
  1080 
  1005     The call is simply forwarded to the underlying HbIconEngine. This function
       
  1006     has no effect when the icon was constructed from a QIcon.
       
  1007 
       
  1008     \internal
  1081     \internal
  1009 */
  1082 */
  1010 void HbIconPrivate::clearStoredIconContent()
  1083 void HbIconPrivate::clearStoredIconContent()
  1011 {
  1084 {
       
  1085     // No need to detach here, usually the more icon's data we drop, the better. There are
       
  1086     // no visual results anyway, icon data is reloaded next time the icon is painted.
  1012     if (engine) {
  1087     if (engine) {
  1013         engine->clearStoredIconContent();
  1088         engine->clearStoredIconContent();
  1014     }
  1089     }
  1015 }
  1090     mQIconPixmap = QPixmap();
       
  1091 }