diff -r 7516d6d86cf5 -r ed14f46c0e55 src/hbcore/image/hbicon.cpp --- a/src/hbcore/image/hbicon.cpp Mon Oct 04 17:49:30 2010 +0300 +++ b/src/hbcore/image/hbicon.cpp Mon Oct 18 18:23:13 2010 +0300 @@ -146,6 +146,14 @@ HbIcon instance (before the first paint of the icon) to have any performance benefits. + \b KeepDefaultQIconSize \b (0x20) This flag disables all scaling for icons constructed + from QIcon. It has no effect on regular, native HbIcons. It only affects the + painting: The size of the HbIcon will remain whatever was set via setSize(), but + only a part of that area will be painted. This is similar to + HbIconItem::setIconScaling(false) but in that case the underlying icon's size + would also be changed to match the default size, while here size() remains + unaffected. + */ /*! @@ -183,7 +191,10 @@ HbIconPrivate::HbIconPrivate() : engine(new HbIconEngine(QString())), qicon(engine), - badgeInfo(0) + badgeInfo(0), + mQIconFlags(0), + mQIconPixmapMode(QIcon::Normal), + mQIconPixmapState(QIcon::Off) { ref.ref(); // Need to do extra ref so the shared null does not get destructed } @@ -194,7 +205,10 @@ HbIconPrivate::HbIconPrivate(const QIcon &qicon) : engine(0), qicon(qicon), - badgeInfo(0) + badgeInfo(0), + mQIconFlags(0), + mQIconPixmapMode(QIcon::Normal), + mQIconPixmapState(QIcon::Off) { } @@ -204,7 +218,10 @@ HbIconPrivate::HbIconPrivate(const QString &iconName) : engine(new HbIconEngine(iconName)), qicon(engine), - badgeInfo(0) + badgeInfo(0), + mQIconFlags(0), + mQIconPixmapMode(QIcon::Normal), + mQIconPixmapState(QIcon::Off) { } @@ -216,7 +233,11 @@ size(other.size), engine(0), qicon(), - badgeInfo(0) + badgeInfo(0), + mQIconFlags(other.mQIconFlags), + mQIconPixmap(other.mQIconPixmap), + mQIconPixmapMode(other.mQIconPixmapMode), + mQIconPixmapState(other.mQIconPixmapState) { if (other.engine) { engine = new HbIconEngine(*other.engine); @@ -311,7 +332,7 @@ QDataStream &operator>>(QDataStream &stream, HbIconPrivate &icon) { stream >> icon.size; - int enginePtr = 0; + qptrdiff enginePtr = 0; stream >> enginePtr; if (enginePtr) { icon.engine = new HbIconEngine(stream); @@ -378,6 +399,27 @@ return result; } +/*! + \internal +*/ +void HbIconPrivate::setAsync(bool async, HbIconEngine::AsyncCallback callback, void *param) +{ + if (engine) { + engine->setAsync(async, callback, param); + } +} + +/*! + \internal +*/ +bool HbIconPrivate::async() const +{ + if (engine) { + return engine->async(); + } + return false; +} + /*! Default constructor. If this constructor is used, the icon name needs to be set * by calling HbIcon::setIconName. */ @@ -392,27 +434,31 @@ /*! Constructs a new icon with the icon name \a iconName. */ -HbIcon::HbIcon(const QString &iconName) +HbIcon::HbIcon(const QString &iconName) : d( new HbIconPrivate(iconName) ) { - d = new HbIconPrivate(iconName); } -/*! Constructs a new icon to be a copy of the given QIcon. -* Due to the limitations listed below, this constructor should be used only for -* compatibility reasons if a QIcon instance needs to be passed as a parameter -* to a method taking a HbIcon parameter. -* \note If this constructor is used, there are the following limitations in the HbIcon methods. -* - HbIcon::defaultSize() may return QSizeF(). -* - HbIcon::paint() ignores the parameter aspectRatioMode and converts the given QRectF to QRect. -* - HbIcon::iconName() returns empty string by default. -* - HbIcon::pixmap() returns null pixmap. -* - Colorization and mirroring support are not available. -* This method should only be used if absolute necessary, as this is not ideal for hardware accelerated environment -* and there may be huge differences in painting performance when compared to a native HbIcon. -*/ -HbIcon::HbIcon(const QIcon &icon) +/*! + * Constructs a new icon to be a copy of the given QIcon. Due to the + * limitations listed below, this constructor should be used only for + * compatibility reasons if a QIcon instance needs to be passed as a parameter + * to a method taking a HbIcon parameter. + * + * \note If this constructor is used, the following limitations apply: + * + * - HbIcon::defaultSize() may return QSizeF(). + * - HbIcon::paint() ignores the parameter aspectRatioMode and converts the given QRectF to QRect. + * - HbIcon::iconName() returns empty string by default. + * - HbIcon::pixmap() returns null pixmap. + * - Colorization and mirroring support are not available. + * + * This method should only be used if absolute necessary, as this is not ideal + * for hardware accelerated environment and there may be huge differences in + * painting performance when compared to a native HbIcon. Some advanced resource + * management features are not available for such icons either. + */ +HbIcon::HbIcon(const QIcon &icon) : d( new HbIconPrivate(icon) ) { - d = new HbIconPrivate(icon); } /*! @@ -518,9 +564,6 @@ * However it is possible to override this theme-specific color with a custom one * by calling this function. * -* \warning Currently this method makes use of pixmap() routine in case of NVG icons. -* pixmap() slows down the hardware accelerated rendering. -* * \sa HbIcon::color(), HbIcon::Colorized */ void HbIcon::setColor(const QColor &color) @@ -569,9 +612,10 @@ void HbIcon::setIconName(const QString &iconName) { if (d->engine && d->engine->iconName() != iconName) { + // Icon was normal HbIcon and the name is changed. d.detach(); d->engine->setIconName(iconName); - } else { + } else if (!d->engine) { // Icon was earlier copy constructed from QIcon, but now its name is set, // so it becomes a 'real' HbIcon. d.detach(); @@ -581,7 +625,9 @@ // QIcon's assignment operator shares the engine. QIcon temp(d->engine); d->qicon = temp; + d->mQIconPixmap = QPixmap(); } + // Otherwise icon was normal HbIcon and the name is same as before, so do nothing. } /*! @@ -637,24 +683,50 @@ } else { // This HbIcon was copy constructed from QIcon and // we cannot use HbIconEngine for painting. + + // Find out the size: It can be the size set via setSize(), or, in case of + // KeepDefaultQIconSize, the first available size, or, if none are set, the + // target area's size. QSizeF size = this->size(); - if (!size.isValid()) { - // If size is not set, have to use rect size because QIcon - // does not provide defaultSize information. - size = rect.size(); + if (flags().testFlag(KeepDefaultQIconSize)) { + QList sizes = d->qicon.availableSizes(); + if (!sizes.isEmpty()) { + size = sizes.at(0); + } + } else { + if (!size.isValid()) { + size = rect.size(); + } } - QPixmap pixmap = d->qicon.pixmap(size.toSize(), mode, state); + // Get the pixmap with the needed size. + QPixmap pixmap; + QSize intSize = size.toSize(); + bool usingCached = false; + if (d->mQIconPixmap.size() == intSize + && mode == d->mQIconPixmapMode + && state == d->mQIconPixmapState) + { + pixmap = d->mQIconPixmap; + usingCached = true; + } else { + pixmap = d->qicon.pixmap(intSize, mode, state); + d->mQIconPixmap = pixmap; + d->mQIconPixmapMode = mode; + d->mQIconPixmapState = state; + } QSizeF pixmapSize = pixmap.size(); - // QIcon::pixmap() will not do upscaling. - if (pixmapSize.width() < size.width() || pixmapSize.height() < size.height()) { + // QIcon::pixmap() will not do upscaling, do it here if needed. + if (!pixmap.isNull() && !usingCached && !flags().testFlag(KeepDefaultQIconSize) + && (pixmapSize.width() < size.width() || pixmapSize.height() < size.height())) + { // Native HbIcons are scaled using SmoothTransformation so use the same. pixmap = pixmap.scaled(size.toSize(), aspectRatioMode, Qt::SmoothTransformation); pixmapSize = pixmap.size(); } - // Adjust the alignment + // Adjust the alignment. QPointF topLeft = rect.topLeft(); if (alignment & Qt::AlignRight) { @@ -669,9 +741,10 @@ topLeft.setY(topLeft.y() + (rect.height() - pixmapSize.height()) / 2); } + // Draw. painter->drawPixmap(topLeft, pixmap, pixmap.rect()); - // Draw the badges on this icon + // Draw the badges on this icon. if (d->badgeInfo) { d->badgeInfo->paint(painter, rect, mode, state, false); } @@ -684,7 +757,7 @@ */ QSizeF HbIcon::size() const { - if ((static_cast(flags()) & HbIcon::ResolutionCorrected)) { + if (flags().testFlag(HbIcon::ResolutionCorrected)) { if (d->engine) { d->size = d->engine->size(); } @@ -794,7 +867,7 @@ if (d->engine) { return d->engine->flags(); } else { - return (HbIcon::Flags)0; + return d->mQIconFlags; } } @@ -807,6 +880,9 @@ d.detach(); d->engine->setFlags(flags); } + } else if (flags != d->mQIconFlags) { + d.detach(); + d->mQIconFlags = flags; } } @@ -912,7 +988,7 @@ * Adds a badge icon to the existing icon. The badge icons * are drawn relative to the alignment you specify with the * z-order you provide. - * + * * By default the badge icon will use its default size. If this is * not suitable (which is typical in case of vector graphics) then * call setSize() explicitly on \a badge before passing it to this @@ -1002,14 +1078,14 @@ Clears the icon data (e.g. QPixmaps that are stored internally) but does not touch the settings, e.g. the size, state, flags, unlike clear(). - The call is simply forwarded to the underlying HbIconEngine. This function - has no effect when the icon was constructed from a QIcon. - \internal */ void HbIconPrivate::clearStoredIconContent() { + // No need to detach here, usually the more icon's data we drop, the better. There are + // no visual results anyway, icon data is reloaded next time the icon is painted. if (engine) { engine->clearStoredIconContent(); } + mQIconPixmap = QPixmap(); }