diff -r 000000000000 -r 16d8024aca5e src/hbcore/image/hbframedrawer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hbcore/image/hbframedrawer.cpp Mon Apr 19 14:02:13 2010 +0300 @@ -0,0 +1,1489 @@ +/**************************************************************************** +** +** 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 HbCore 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 "hbframedrawer.h" +#include "hbframedrawer_p.h" +#include "hbimagetraces_p.h" + +#include +#include +#include +#include "hbmaskableiconimpl_p.h" + +#include +#include +#include +#include +#include + +/*! + @stable + @hbcore + \class HbFrameDrawer + \brief HbFrameDrawer draws frames graphics. + + This class is not intended to be derived from. + + Frame graphics mean graphics that consist of either 3 or 9 parts that are positioned + and scaled followingly. + + A 9-piece frame consists of a 3x3 grid, where the corner parts have a fixed size and + the other parts are scaled. + + A 3-piece frame consists of 3 parts tiled either horizontally of vertically. The side + parts preserve their aspect ratio and the center part is scaled to fill the remaining space. + + For convenience, frame drawer can also draw the frame with a single graphic. + + The frame drawer implements the logic of scaling and positioning the frame parts and + takes care that there are no visible gaps between the frame parts when the whole frame + is painted to the display even if the frame bounding rectangle uses floating point accuracy. + + Filenames for 9-piece frame graphics are defined according to the following. + + - top left _tl. + - top _t. + - top right _tr. + - left _l. + - center _c. + - right _r. + - bottom left _bl. + - bottom _b. + - bottom right _br. + + Filenames for 3-piece horizontal frame graphics are defined according to the following. + + - left _l. + - center _c. + - right _r. + + Filenames for 3-piece vertical frame graphics are defined according to the following. + + - top _t. + - center _c. + - bottom _b. + + \note The suffixes (e.g. "_l") in the filenames can be redefined with method + HbFrameDrawer::setFileNameSuffixList(). + + \note If all of the frame pieces cannot be found, the frame drawer falls back to a single + frame graphics piece with filename . to draw the frame. + If even that does not exist, nothing is drawn. + + See class HbIcon for information of supported icon formats and file locations. + + The frame drawer stores the whole generated frame graphics in a pixmap for + improving the speed of the paint operations. Therefore, the frame drawer instance should not + be re-created each time the frame needs to be rendered. + + Example of how to create a frame drawer and use it. + + \dontinclude ultimatecodesnippet/ultimatecodesnippet.cpp + \skip nine-piece + \until } + + \sa class HbFrameItem +*/ + +/*! + \enum HbFrameDrawer::FrameType + + \b Undefined The frame type is undefined. It must be defined before being able to draw the frame. + + \b OnePiece The frame consist of a single graphic piece, which is scaled to the frame's bounding rectangle. + + \b ThreePiecesHorizontal The frame consists of three graphic pieces that are tiled horizontally. + As default, the side parts preserve their aspect ratio and the center part is scaled to fill the remaining space. + Filenames for 3-piece horizontal frame graphics are defined according to the following. + + - left _l. + - center _c. + - right _r. + + \b ThreePiecesVertical The frame consists of three graphic pieces that are tiled vertically. + As default, the side parts preserve their aspect ratio and the center part is scaled to fill the remaining space. + Filenames for 3-piece vertical frame graphics are defined according to the following. + + - top _t. + - center _c. + - bottom _b. + + \b NinePieces The frame consists of a 3x3 grid of graphic pieces, where as default the corner + parts have a fixed size and the other parts are scaled. + Filenames for 9-piece frame graphics are defined according to the following. + + - top left _tl. + - top _t. + - top right _tr. + - left _l. + - center _c. + - right _r. + - bottom left _bl. + - bottom _b. + - bottom right _br. +*/ + +#define DEFAULT_OPTIONS (HbIconLoader::ReturnUnknownIcon | HbIconLoader::BitmapIcons | HbIconLoader::VectorIcons) +// Same rounding function is used everywhere for consistency +static inline int realToInt(qreal r) +{ + return (int)(r + 0.5); +} + +/*! +\internal +*/ +HbFrameDrawerPrivate::HbFrameDrawerPrivate() : + QSharedData(), + type(HbFrameDrawer::Undefined), + frameParts(0), + mirroring(HbIcon::Default), + defaultMirroring(Unknown), + flags(0), + layoutDirection(Qt::LeftToRight), + graphicsItem(0), + color(), + icon(0), + maskChanged(false) +{ + borderWidths[0]=0.0; + borderWidths[1]=0.0; + borderWidths[2]=0.0; + borderWidths[3]=0.0; +} + +/*! +\internal +*/ +HbFrameDrawerPrivate::HbFrameDrawerPrivate(const QString &frameGraphicsName, HbFrameDrawer::FrameType type) : + QSharedData(), + frameGraphicsName(frameGraphicsName), + type(type), + mask(QPixmap()), + frameParts(0), + mirroring(HbIcon::Default), + defaultMirroring(Unknown), + flags( 0 ), + layoutDirection(Qt::LeftToRight), + graphicsItem(0), + color(), + icon(0), + maskChanged(false) +{ + borderWidths[0]=0.0; + borderWidths[1]=0.0; + borderWidths[2]=0.0; + borderWidths[3]=0.0; + + // Remove possible file extension + int index = this->frameGraphicsName.lastIndexOf(QChar('.')); + if (index>0) { + this->frameGraphicsName.resize(index); + } +} + +/*! +\internal +*/ +HbFrameDrawerPrivate::HbFrameDrawerPrivate(const HbFrameDrawerPrivate &other) : + QSharedData(other), + frameGraphicsName(other.frameGraphicsName), + type(other.type), + rect(other.rect), + mask(QPixmap()), + frameParts(other.frameParts), + mirroring(other.mirroring), + defaultMirroring(other.defaultMirroring), + flags( other.flags ), + layoutDirection( other.layoutDirection ), + graphicsItem( other.graphicsItem ), + color(other.color), + icon(0), + maskChanged(false) +{ + borderWidths[0]=other.borderWidths[0]; + borderWidths[1]=other.borderWidths[1]; + borderWidths[2]=other.borderWidths[2]; + borderWidths[3]=other.borderWidths[3]; +} + +/*! +\internal +*/ +HbFrameDrawerPrivate::~HbFrameDrawerPrivate() +{ + unLoadIcon(); +} + +/*! +\internal +*/ +void HbFrameDrawerPrivate::prepareFrameIcon() +{ + if (!frameParts) { + checkFrameParts(); + } + if ((!icon ) && (!fallbackMaskableIconList.count()) ) { + createFrameIcon(); + } +} + +/*! +* Returns whether this frame drawer's border widths have been set by API +* +* \sa HbFrameDrawerPrivate::setBorderApiProtectionFlag() +*/ +bool HbFrameDrawerPrivate::testBorderApiProtectionFlag() const +{ + return flags & HbFrameDrawerPrivate::BorderWidthSetByApi; +} + +/*! +* Clears the flag denoting that the border widths have been set by API. +* This will cause control of border widths to return to the CSS system. +* +* \sa HbFrameDrawerPrivate::testBorderApiProtectionFlag() +*/ +void HbFrameDrawerPrivate::setBorderApiProtectionFlag(bool on) +{ + if(on){ + flags |= HbFrameDrawerPrivate::BorderWidthSetByApi; + }else{ + flags &= ~HbFrameDrawerPrivate::BorderWidthSetByApi; + } +} + +/*! +* Checks whether all the frame parts are available for the given frame type. +* Fallback is 1-part frame rendering. +* \internal +*/ +void HbFrameDrawerPrivate::checkFrameParts() +{ + // fall back is 1 piece frame + frameParts = 1; + + if (type == HbFrameDrawer::ThreePiecesHorizontal || type == HbFrameDrawer::ThreePiecesVertical) { + if (HbIconLoader::iconsExist(frameGraphicsName, fileNameSuffixList())) { + frameParts = 3; + } + } else if (type == HbFrameDrawer::NinePieces) { + if (HbIconLoader::iconsExist(frameGraphicsName, fileNameSuffixList())) { + frameParts = 9; + } + } +} + +/*! +\internal +*/ +QStringList HbFrameDrawerPrivate::fileNameSuffixList() const +{ + // If the suffix list has been set explicitly, return that if it contains enough suffixes. + if (!suffixList.isEmpty()) { + switch (type) { + case HbFrameDrawer::ThreePiecesHorizontal: // fall through + case HbFrameDrawer::ThreePiecesVertical: + if (suffixList.count() >= 3) { + return suffixList; + } + break; + + case HbFrameDrawer::NinePieces: + if (suffixList.count() >= 9) { + return suffixList; + } + break; + + default: + return suffixList; + } + } + + // Otherwise, return default suffix list. + QStringList list; + + switch (type) { + case HbFrameDrawer::ThreePiecesHorizontal: + list << "_l" << "_c" << "_r"; + break; + case HbFrameDrawer::ThreePiecesVertical: + list << "_t" << "_c" << "_b"; + break; + case HbFrameDrawer::NinePieces: + list << "_tl" << "_t" << "_tr" << "_l" << "_c" << "_r" << "_bl" << "_b" << "_br"; + break; + default: + break; + } + + return list; +} + +/*! +* Creates a consolidated HbIconImpl (Icon) with the available piece information +* If failed to create the same, then creates HbIconImpls for the pieces. +* \internal +*/ +void HbFrameDrawerPrivate::createFrameIcon() +{ + // Divide rectangle area to the frame parts first. + HbMultiPartSizeData data; + QSize frameIconSize = divideSpace(data); + data.multiPartIconId = multiPartIconId(); + multiPartSizeData = data; + + // Create the frame icon and add it in the icon cache + HbIconLoader *loader = HbIconLoader::global(); + + //If it's one-piece frame-item, it's loaded using HbIconLoader::loadIcon() + if (frameParts == 1) { + HbIconImpl * iconImpl = loader->loadIcon(frameGraphicsName, HbIconLoader::AnyType, + HbIconLoader::AnyPurpose, + frameIconSize, + Qt::IgnoreAspectRatio, + QIcon::Normal, + iconLoaderOptions()); + if (iconImpl) { + icon = new HbMaskableIconImpl(iconImpl); + } + + } else { + QStringList multiPieceFileNames; + QStringList list = fileNameSuffixList(); + int nameListCount = list.count(); + for (int i = 0; i < nameListCount; i++) { + multiPieceFileNames.append(frameGraphicsName + list[i]); + if (data.pixmapSizes[i].isEmpty()) { + data.pixmapSizes[i] = QSize(0,0); + } + } + + QVector listOfIcons; + + //For multi-piece frame-items, HbIocnLoader::loadMultipieceIcon is used + //This function returns the consolidate (stitched) icon created on the themeserver. + //If the consolidated icon-creation on themeserver fails, then server returns a list + //of individual frame-items. + HbIconImpl * iconImpl = loader->loadMultiPieceIcon(multiPieceFileNames, data, frameIconSize, + Qt::IgnoreAspectRatio, QIcon::Normal, iconLoaderOptions(), + listOfIcons, color); + + if (iconImpl) { + icon = new HbMaskableIconImpl(iconImpl); + } else { + int implCount = listOfIcons.count(); + for (int i = 0; i < implCount; i++) { + fallbackMaskableIconList.append(new HbMaskableIconImpl(listOfIcons[i])); + } + } + + } +} + +/*! +\internal +*/ +void HbFrameDrawerPrivate::paint(QPainter *painter) +{ + // createFrameIcon() must be called before calling this method. + + QRectF centeredRect(rect); + QRect integerRect = rect.toRect(); + if (icon) { + QSize size = icon->size(); + + if (integerRect.width() != size.width()) { + centeredRect.adjust((rect.width() - size.width()) / 2, 0, 0, 0); + centeredRect.setWidth(size.width()); + } + if (integerRect.height() != size.height()) { + centeredRect.adjust(0, (rect.height() - size.height()) / 2, 0, 0); + centeredRect.setHeight(size.height()); + } + + if (!mask.isNull() && maskChanged) { + icon->setMask(mask); + } + //paint the stitched icon + icon->paint(painter, centeredRect, Qt::AlignHCenter); + + #ifdef HB_FRAME_DRAWER_TRACES + qDebug() << "FRAMENAME: " << frameGraphicsName << "Drawn at: " + << centeredRect.topLeft().x() << "," << centeredRect.topLeft().y() << " | " + << centeredRect.bottomRight().x() << "," << centeredRect.bottomRight().y(); + #endif + } else { + for (int i = 0; i < fileNameSuffixList().count(); i++) { + if (i < fallbackMaskableIconList.count() && fallbackMaskableIconList[i]) { + QPoint position = multiPartSizeData.targets[i].topLeft(); + if (isMirrored()) { + int centerTopRightX = (int)(centeredRect.topLeft().x() + centeredRect.width()); + int targetTopRightX = multiPartSizeData.targets[i].topLeft().x() + + multiPartSizeData.targets[i].width(); + position.setX((int)(centeredRect.topLeft().x() + (centerTopRightX - targetTopRightX))); + } else { + position.setX((int)(centeredRect.topLeft().x() + position.x())); + } + position.setY((int)(centeredRect.topLeft().y() + position.y())); + if ((!mask.isNull()) && maskChanged) { + QBitmap pieceMask ; + QRect maskRect(position.x(), position.y(), multiPartSizeData.targets[i].width(), multiPartSizeData.targets[i].height()); + pieceMask = mask.copy(maskRect); + fallbackMaskableIconList[i]->setMask(pieceMask); + } + if(!multiPartSizeData.targets[i].isEmpty()) { + fallbackMaskableIconList[i]->paint(painter, QRect(position,multiPartSizeData.pixmapSizes[i]), Qt::AlignHCenter); + } + } + } + } + maskChanged = false; +} + +/*! +\internal +*/ +bool HbFrameDrawerPrivate::fillWholeRect() const +{ + return flags & HbFrameDrawerPrivate::FillWholeRect; +} + +/*! +* Calculates frame part rectangles and icon sizes based on the following information. +* - frame bounding rectangle +* - frame inner rectangle (optional) +* - default sizes of the frame corner (9-piece) or side (3-piece) graphics. +* +* Note! Integer pixel sizes are used in this function to avoid one pixel gaps between the frame parts. +* \internal +*/ +QSize HbFrameDrawerPrivate::divideSpace(HbMultiPartSizeData &data) +{ + // Do not need to divide space if there is only one frame part. + if (frameParts == 1) { + QSizeF size = rect.size(); + // If the whole rect is not filled, use default graphics size to define one of the dimensions. + if (type == HbFrameDrawer::ThreePiecesHorizontal && !fillWholeRect()) { + qreal defaultHeight = defaultSize("").height(); + if (defaultHeight < size.height()) { + size.setHeight(defaultHeight); + } + } else if (type == HbFrameDrawer::ThreePiecesVertical && !fillWholeRect()) { + qreal defaultWidth = defaultSize("").width(); + if (defaultWidth < size.width()) { + size.setWidth(defaultWidth); + } + } + + // Using same rounding as in other code below + return QSize(realToInt(size.width()), realToInt(size.height())); + } + + // Frame part filename suffix list is needed. + QStringList suffixList = fileNameSuffixList(); + + int fullWidth = realToInt(rect.width()); + int fullHeight = realToInt(rect.height()); + + if (type == HbFrameDrawer::ThreePiecesHorizontal) { + int leftWidth; + int rightWidth; + + if (borderWidths[0] == 0 && borderWidths[2] == 0) { + QSizeF leftSize = defaultSize(suffixList.at(0)); // index 0 is leftmost frame part + QSizeF rightSize = defaultSize(suffixList.at(2)); // index 2 is rightmost frame part + + if (fillWholeRect()) { + leftSize.scale(rect.size(), Qt::KeepAspectRatio); + rightSize.scale(rect.size(), Qt::KeepAspectRatio); + } else { + int leftHeight = leftSize.toSize().height(); + if (leftHeight < fullHeight) { + fullHeight = leftHeight; + } + } + + leftWidth = leftSize.toSize().width(); + rightWidth = rightSize.toSize().width(); + + } else { + // QSizeF::toSize rounds to nearest integer so do the same here + leftWidth = realToInt(borderWidths[0]); + rightWidth = realToInt(borderWidths[2]); + + // If whole rect is not filled, take height from default graphics height + if (!fillWholeRect()) { + QSizeF leftSize = defaultSize(suffixList.at(0)); // index 0 is leftmost frame part + + int leftHeight = leftSize.toSize().height(); + if (leftHeight < fullHeight) { + fullHeight = leftHeight; + } + } + } + + int centerWidth = fullWidth - leftWidth - rightWidth; + + // Do all 3 pieces fit? + if (fullWidth >= leftWidth + rightWidth) { + data.targets[0] = QRect(0, 0, leftWidth, fullHeight); + data.targets[1] = QRect(leftWidth, 0, centerWidth, fullHeight); + data.targets[2] = QRect(fullWidth-rightWidth, 0, rightWidth, fullHeight); + + data.pixmapSizes[0] = QSize(leftWidth, fullHeight); + data.pixmapSizes[1] = QSize(centerWidth, fullHeight); + data.pixmapSizes[2] = QSize(rightWidth, fullHeight); + + data.sources[0] = QRect(QPoint(0,0), data.pixmapSizes[0]); + data.sources[1] = QRect(QPoint(0,0), data.pixmapSizes[1]); + data.sources[2] = QRect(QPoint(0,0), data.pixmapSizes[2]); + } else { + // Only sides fit + int totalSideWidth = leftWidth + rightWidth; + data.targets[0] = QRect(0, 0, leftWidth * fullWidth / totalSideWidth, fullHeight); + data.targets[1] = QRect(); + data.targets[2] = QRect(data.targets[0].width(), 0, fullWidth - data.targets[0].width(), fullHeight); + + data.pixmapSizes[0] = QSize(data.targets[0].width(), fullHeight); + data.pixmapSizes[1] = QSize(); + data.pixmapSizes[2] = QSize(data.targets[2].width(), fullHeight); + + data.sources[0] = data.targets[0]; + data.sources[1] = QRect(); + data.sources[2] = data.targets[2]; + data.sources[2].moveLeft(data.pixmapSizes[2].width() - data.targets[2].width()); + } + } else if (type == HbFrameDrawer::ThreePiecesVertical) { + + int topHeight; + int bottomHeight; + + if (borderWidths[1] == 0 && borderWidths[3] == 0) { + QSizeF topSize = defaultSize(suffixList.at(0)); // index 0 is top frame part + QSizeF bottomSize = defaultSize(suffixList.at(2)); // index 2 is bottom frame part + + if (fillWholeRect()) { + topSize.scale(rect.size(), Qt::KeepAspectRatio); + bottomSize.scale(rect.size(), Qt::KeepAspectRatio); + } else { + int topWidth = topSize.toSize().width(); + if (topWidth < fullWidth) { + fullWidth = topWidth; + } + } + + topHeight = topSize.toSize().height(); + bottomHeight = bottomSize.toSize().height(); + } else { + // QSizeF::toSize rounds to nearest integer so do the same here + topHeight = realToInt(borderWidths[1]); + bottomHeight = realToInt(borderWidths[3]); + + // If whole rect is not filled, take width from default graphics height + if (!fillWholeRect()) { + QSizeF topSize = defaultSize(suffixList.at(0)); // index 0 is top frame part + + int topWidth = topSize.toSize().width(); + if (topWidth < fullWidth) { + fullWidth = topWidth; + } + } + } + + int centerHeight = fullHeight - topHeight - bottomHeight; + + // Do all 3 pieces fit? + if (fullHeight >= topHeight + bottomHeight) { + data.targets[0] = QRect(0, 0, fullWidth, topHeight); + data.targets[1] = QRect(0, topHeight, fullWidth, centerHeight); + data.targets[2] = QRect(0, fullHeight - bottomHeight, fullWidth, bottomHeight); + + data.pixmapSizes[0] = QSize(fullWidth, topHeight); + data.pixmapSizes[1] = QSize(fullWidth, centerHeight); + data.pixmapSizes[2] = QSize(fullWidth, bottomHeight); + + data.sources[0] = QRect(QPoint(0,0), data.pixmapSizes[0]); + data.sources[1] = QRect(QPoint(0,0), data.pixmapSizes[1]); + data.sources[2] = QRect(QPoint(0,0), data.pixmapSizes[2]); + } else { + // Only sides fit + int totalSideHeight = topHeight + bottomHeight; + data.targets[0] = QRect(0, 0, fullWidth, topHeight * fullHeight / totalSideHeight); + data.targets[1] = QRect(); + data.targets[2] = QRect(0, data.targets[0].height(), fullWidth, fullHeight - data.targets[0].height()); + + data.pixmapSizes[0] = QSize(fullWidth,data.targets[0].height()); + data.pixmapSizes[1] = QSize(); + data.pixmapSizes[2] = QSize(fullWidth,data.targets[2].height()); + + data.sources[0] = data.targets[0]; + data.sources[1] = QRect(); + data.sources[2] = data.targets[2]; + data.sources[2].moveTop(data.pixmapSizes[2].height() - data.targets[2].height()); + } + + } else if (type == HbFrameDrawer::NinePieces) { + QSize tlSize; + QSize brSize; + + if (!hasBorderWidths()) { + tlSize = defaultSize(suffixList.at(0)).toSize(); // index 0 is top left + brSize = defaultSize(suffixList.at(8)).toSize(); // index 8 is bottom right + } else { + tlSize = QSizeF(borderWidths[0], borderWidths[1]).toSize(); + brSize = QSizeF(borderWidths[2], borderWidths[3]).toSize(); + } + + // Do all 9 pieces fit? + if (fullWidth >= tlSize.width() + brSize.width() && + fullHeight >= tlSize.height() + brSize.height()) { + + int centerWidth = fullWidth - tlSize.width() - brSize.width(); + int centerHeight = fullHeight - tlSize.height() - brSize.height(); + + data.targets[0] = QRect(0, 0, tlSize.width(), tlSize.height()); + data.targets[1] = QRect(tlSize.width(), 0, centerWidth, tlSize.height()); + data.targets[2] = QRect(tlSize.width() + centerWidth, 0, brSize.width(), tlSize.height()); + data.targets[3] = QRect(0, tlSize.height(), tlSize.width(), centerHeight); + data.targets[4] = QRect(tlSize.width(), tlSize.height(), centerWidth, centerHeight); + data.targets[5] = QRect(tlSize.width() + centerWidth, tlSize.height(), brSize.width(), centerHeight); + data.targets[6] = QRect(0, tlSize.height() + centerHeight, tlSize.width(), brSize.height()); + data.targets[7] = QRect(tlSize.width(), tlSize.height() + centerHeight, centerWidth, brSize.height()); + data.targets[8] = QRect(tlSize.width() + centerWidth, tlSize.height() + centerHeight, brSize.width(), brSize.height()); + + data.pixmapSizes[0] = data.targets[0].size(); + data.pixmapSizes[1] = data.targets[1].size(); + data.pixmapSizes[2] = data.targets[2].size(); + data.pixmapSizes[3] = data.targets[3].size(); + data.pixmapSizes[4] = data.targets[4].size(); + data.pixmapSizes[5] = data.targets[5].size(); + data.pixmapSizes[6] = data.targets[6].size(); + data.pixmapSizes[7] = data.targets[7].size(); + data.pixmapSizes[8] = data.targets[8].size(); + + data.sources[0] = QRect(QPoint(0,0), data.pixmapSizes[0]); + data.sources[1] = QRect(QPoint(0,0), data.pixmapSizes[1]); + data.sources[2] = QRect(QPoint(0,0), data.pixmapSizes[2]); + data.sources[3] = QRect(QPoint(0,0), data.pixmapSizes[3]); + data.sources[4] = QRect(QPoint(0,0), data.pixmapSizes[4]); + data.sources[5] = QRect(QPoint(0,0), data.pixmapSizes[5]); + data.sources[6] = QRect(QPoint(0,0), data.pixmapSizes[6]); + data.sources[7] = QRect(QPoint(0,0), data.pixmapSizes[7]); + data.sources[8] = QRect(QPoint(0,0), data.pixmapSizes[8]); + + } else { + // All 9 pieces do not fit. + // Corners are drawn always but it is possible that either left&right or top&bottom parts get drawn also. + int totalCornerWidth = tlSize.width() + brSize.width(); + int totalCornerHeight = tlSize.height() + brSize.height(); + + int splitPointX = 0; + int splitPointY = 0; + + // If corners do not fit fully horizontally or vertically, define split point + if (totalCornerWidth > fullWidth) { + splitPointX = tlSize.width() * fullWidth / totalCornerWidth; + } + + if (totalCornerHeight > fullHeight) { + splitPointY = tlSize.height() * fullHeight / totalCornerHeight; + } + + calculateShrinkedNinePieceCorners( + data, tlSize, brSize, + QSize(fullWidth, fullHeight), QPoint(splitPointX, splitPointY)); + + // Left and right get drawn if corners height does not cover the total height + if (!splitPointY) { + data.targets[3] = QRect(0, data.targets[0].height(), data.targets[0].width(), fullHeight - tlSize.height() - brSize.height()); + data.targets[5] = QRect(splitPointX, data.targets[0].height(), data.targets[2].width(), data.targets[3].height()); + } else { + data.targets[3] = QRect(); + data.targets[5] = QRect(); + } + + // Top and bottom get drawn if corners width does not cover the total width + if (!splitPointX) { + data.targets[1] = QRect(data.targets[0].width(), 0, fullWidth - tlSize.width() - brSize.width(), data.targets[0].height()); + data.targets[7] = QRect(data.targets[0].width(), splitPointY, data.targets[1].width(), data.targets[8].height()); + } else { + data.targets[1] = QRect(); + data.targets[7] = QRect(); + } + + // Center is always empty + data.targets[4] = QRect(); + + data.pixmapSizes[0] = data.targets[0].size(); + data.pixmapSizes[1] = data.targets[1].size(); + data.pixmapSizes[2] = data.targets[2].size(); + data.pixmapSizes[3] = data.targets[3].size(); + data.pixmapSizes[4] = QSize(); // Center is always empty + data.pixmapSizes[5] = data.targets[5].size(); + data.pixmapSizes[6] = data.targets[6].size(); + data.pixmapSizes[7] = data.targets[7].size(); + data.pixmapSizes[8] = data.targets[8].size(); + + data.sources[0] = data.targets[0]; + data.sources[1] = QRect(QPoint(0,0), data.pixmapSizes[1]); + data.sources[2] = QRect(QPoint(0,0), data.pixmapSizes[2]); + data.sources[2].setBottomLeft(QPoint(data.pixmapSizes[2].width() - data.targets[2].width(), data.targets[2].height() - 1)); + data.sources[3] = QRect(QPoint(0,0), data.pixmapSizes[3]); + data.sources[4] = QRect(); // center is always empty + data.sources[5] = QRect(QPoint(0,0), data.pixmapSizes[5]); + data.sources[6] = QRect(QPoint(0,0), data.pixmapSizes[6]); + data.sources[6].setTopRight(QPoint(data.targets[6].width() - 1, data.pixmapSizes[6].height() - data.targets[6].height())); + data.sources[7] = QRect(QPoint(0,0), data.pixmapSizes[7]); + data.sources[8] = QRect(QPoint(0,0), data.pixmapSizes[8]); + data.sources[8].setTopLeft(QPoint(data.pixmapSizes[8].width() - data.targets[8].width(), data.pixmapSizes[8].height() - data.targets[8].height())); + } + } + +#ifdef HB_FRAME_DRAWER_TRACES + qDebug() << "FRAMENAME: " << frameGraphicsName << "Size: " << fullWidth << ", " << fullHeight; +#endif + + return QSize(fullWidth, fullHeight); +} + + +/*! +\internal +*/ +void HbFrameDrawerPrivate::calculateShrinkedNinePieceCorners( + HbMultiPartSizeData &data, + const QSize& tlSize, const QSize& brSize, + const QSize& fullSize, const QPoint& splitPoint) +{ + // Make sure that corner sizes don't exceed frames full size + + // Top-left corner + int topLeftWidth = splitPoint.x() ? splitPoint.x() : tlSize.width(); + int topLeftHeight = splitPoint.y() ? splitPoint.y() : tlSize.height(); + data.targets[0] = QRect( + 0, + 0, + topLeftWidth < fullSize.width() ? topLeftWidth : fullSize.width(), + topLeftHeight < fullSize.height() ? topLeftHeight : fullSize.height()); + + // Top-right corner + int topRightX = splitPoint.x() ? splitPoint.x() : fullSize.width() - brSize.width(); + int topRightWidth = splitPoint.x() ? fullSize.width() - splitPoint.x() : brSize.width(); + if (topRightWidth > fullSize.width()) { + topRightWidth = fullSize.width(); + topRightX = 0; + } + int topRightHeight = splitPoint.y() ? splitPoint.y() : tlSize.height(); + if (topRightHeight > fullSize.height()) { + topRightHeight = fullSize.height(); + } + data.targets[2] = QRect(topRightX, 0, topRightWidth, topRightHeight); + + // Bottom-left corner + int bottomLeftY = splitPoint.y() ? splitPoint.y() : fullSize.height() - brSize.height(); + int bottomLeftWidth = splitPoint.x() ? splitPoint.x() : tlSize.width(); + if (bottomLeftWidth > fullSize.width()) { + bottomLeftWidth = fullSize.width(); + } + int bottomLeftHeight = splitPoint.y() ? fullSize.height() - splitPoint.y() : brSize.height(); + if (bottomLeftHeight > fullSize.height()) { + bottomLeftHeight = fullSize.height(); + bottomLeftY = 0; + } + data.targets[6] = QRect(0, bottomLeftY, bottomLeftWidth, bottomLeftHeight); + + // Bottom-right corner + int bottomRightX = splitPoint.x() ? splitPoint.x() : fullSize.width() - brSize.width(); + int bottomRightY = splitPoint.y() ? splitPoint.y() : fullSize.height() - brSize.height(); + int bottomRightWidth = splitPoint.x() ? fullSize.width() - splitPoint.x() : brSize.width(); + if (bottomRightWidth > fullSize.width()) { + bottomRightWidth = fullSize.width(); + bottomRightX = 0; + } + int bottomRightHeight = splitPoint.y() ? fullSize.height() - splitPoint.y() : brSize.height(); + if (bottomRightHeight > fullSize.height()) { + bottomRightHeight = fullSize.height(); + bottomRightY = 0; + } + data.targets[8] = QRect( bottomRightX, bottomRightY, bottomRightWidth, bottomRightHeight); +} + +/*! +\internal +*/ +QSizeF HbFrameDrawerPrivate::defaultSize(const QString &framePartSuffix) +{ + HbIconLoader *loader = HbIconLoader::global(); + return loader->defaultSize(frameGraphicsName + framePartSuffix).toSize(); +} + +bool HbFrameDrawerPrivate::isMirrored() +{ + // If mirroring mode is default, check automatic mirroring from loader. + if (mirroring == HbIcon::Default && defaultMirroring == Unknown) { + HbIconLoader *loader = HbIconLoader::global(); + defaultMirroring = loader->isAutomaticallyMirrored(frameGraphicsName) ? Enabled : Disabled; + } + + bool basedOnLayoutDir = false; + // Handle the different mirroring modes + + // Default + if (mirroring == HbIcon::Default) { + if (defaultMirroring == Enabled) { + basedOnLayoutDir = true; + } else if (defaultMirroring == Disabled) { + return false; + } + // Forced + } else if (mirroring == HbIcon::Forced) { + return true; + // Prevented + } else if (mirroring == HbIcon::Prevented) { + return false; + // LayoutDirection + } else if (mirroring == HbIcon::LayoutDirection) { + basedOnLayoutDir = true; + } + + if (basedOnLayoutDir) { + Qt::LayoutDirection usedDirection = Qt::LeftToRight; // default; + if ( flags&HbFrameDrawerPrivate::LayoutDirectionSet ) { + usedDirection = layoutDirection; + } else { + usedDirection = QApplication::layoutDirection(); + } + + return usedDirection == Qt::LeftToRight ? false : true; + } + +#ifdef HB_FRAME_DRAWER_TRACES + qDebug() << "HbFrameDrawerPrivate, invalid mirroring mode"; +#endif + return false; +} + +/*! +\internal +*/ +bool HbFrameDrawerPrivate::hasBorderWidths() const +{ + return borderWidths[1] > 0 + || borderWidths[2] > 0 + || borderWidths[2] > 0 + || borderWidths[3] > 0; +} + +/*! +\internal +*/ +void HbFrameDrawerPrivate::reset( bool resetFrameCount ) +{ + unLoadIcon(); + if ( resetFrameCount ) { + frameParts = 0; + } +} + +HbIconLoader::IconLoaderOptions HbFrameDrawerPrivate::iconLoaderOptions() +{ + HbIconLoader::IconLoaderOptions options = DEFAULT_OPTIONS; + if (flags & HbFrameDrawerPrivate::DoNotCache) { + options |= HbIconLoader::DoNotCache; + } + if (isMirrored()) { + options |= HbIconLoader::HorizontallyMirrored; + } + if (flags & HbFrameDrawerPrivate::ResolutionCorrected) { + options |= HbIconLoader::ResolutionCorrected; + } + if (flags & HbFrameDrawerPrivate::NoAutoStartAnimation) { + options |= HbIconLoader::NoAutoStartAnimation; + } + return options; +} + + + +QString HbFrameDrawerPrivate::multiPartIconId() const +{ + QString id; + id = frameGraphicsName; + if (type == HbFrameDrawer::ThreePiecesHorizontal) { + id.append("_3PH"); + } else if (type == HbFrameDrawer::ThreePiecesVertical) { + id.append("_3PV"); + } else if (type == HbFrameDrawer::NinePieces) { + id.append("_9P"); + } else { + id.append("_1P"); + } + + if (type != HbFrameDrawer::OnePiece) { + if (fillWholeRect()) { + id.append("_1"); + } else { + id.append("_0"); + } + + for (int i = 0;i < 4; i++) { + QString boundary; + id.append("_"); + id.append(boundary.setNum(borderWidths[i])); + } + } + + for (int i = 0; i < suffixList.count(); i++) { + id.append( suffixList[i] ); + } + + return id; +} + +void HbFrameDrawerPrivate::unLoadIcon() +{ + HbIconLoader *loader = HbIconLoader::global(); + if (icon) { + //If a consolidated (stitched) icon was created on the themeserver, then + //HbIconLoader::unloadIcon() is used to unload it. + loader->unLoadIcon(icon->iconImpl()); + icon->dispose(); + icon = 0; + } + + // get a vector of QVector from QVector for unloading. + QVector fallbackIconList; + int count = fallbackMaskableIconList.count(); + for (int i = 0; i < count ; i++) { + if (fallbackMaskableIconList[i]) { + fallbackIconList.append(fallbackMaskableIconList[i]->iconImpl()); + } + } + count = fallbackIconList.count(); + if (count > 0) { + //If a consolidated (stitched) icon-creation on themeserver fails, unload-request for all individual + //frame-items are batched together in a single IPC, which is initiated in HbIconLoader::unLoadMultiIcon(). + loader->unLoadMultiIcon(fallbackIconList); + for (int i=0; i < count ; i++) { + if (fallbackMaskableIconList[i]) { + fallbackMaskableIconList[i]->dispose(); + } + } + } + fallbackIconList.clear(); // vector of HbIconImpl* + fallbackMaskableIconList.clear(); // vector of HbMaskableIconImpl* +} + +/*! Constructs a new frame drawer item with the cacheFlag enabled by default. +*/ +HbFrameDrawer::HbFrameDrawer(bool cacheFlag) +{ + d = new HbFrameDrawerPrivate(); + if ( !cacheFlag ) { + d->flags &= HbFrameDrawerPrivate::DoNotCache; + } +} + +/*! Constructs a new frame drawer with the given \a frameGraphicsName and \a type and cacheFlag is enabled. +*/ +HbFrameDrawer::HbFrameDrawer(const QString &frameGraphicsName, FrameType type, bool cacheFlag) +{ + d = new HbFrameDrawerPrivate(frameGraphicsName, type); + if ( !cacheFlag ) { + d->flags &= HbFrameDrawerPrivate::DoNotCache; + } +} + +/*! +* Copy constructs a new frame drawer using the \a other frame drawer. +* This is very fast. +* Copy-on-write semantics is used, so this only does a shallow copy. +*/ +HbFrameDrawer::HbFrameDrawer(const HbFrameDrawer &other) : + d(other.d) +{ +} + +/*! +* Assigns the \a other frame drawer to this frame drawer and returns a reference to +* this frame drawer. Copy-on-write semantics is used, so this only does a shallow copy. +*/ +HbFrameDrawer &HbFrameDrawer::operator=(const HbFrameDrawer &other) +{ + if (&other != this) { + d = other.d; + } + return *this; +} + +/*! +* Destroys the frame drawer. +*/ +HbFrameDrawer::~HbFrameDrawer() +{ + delete d; +} + +/*! +* Returns true if the frame drawer has been constructed with the default constructor +* and the frame graphics name has not been set. +* \note Even a non-null frame drawer might not be able to draw anything, e.g. if the graphics file do not exist or cannot be read. +*/ +bool HbFrameDrawer::isNull() const +{ + return d->frameGraphicsName.isNull(); +} + +/*! +* Returns the frame graphics name. +* \sa HbFrameDrawer::setFrameGraphicsName() +*/ +QString HbFrameDrawer::frameGraphicsName() const +{ + return d->frameGraphicsName; +} + +/*! +* Sets the frame graphics name. See the class description for the file name convention for different frame parts. +* \sa HbFrameDrawer::frameGraphicsName() +*/ +void HbFrameDrawer::setFrameGraphicsName(const QString &frameGraphicsName) +{ + // Remove possible file extension + QString nameWithoutExt = frameGraphicsName; + int index = nameWithoutExt.lastIndexOf(QChar('.')); + if (index>0) { + nameWithoutExt.resize(index); + } + + if (d->frameGraphicsName != nameWithoutExt) { + d->frameGraphicsName = nameWithoutExt; + // Frame graphics changed, clear frame icon + d->reset(); + // Frame graphics changed, clear default frame mirroring information based on the automatic mirroring list + d->defaultMirroring = HbFrameDrawerPrivate::Unknown; + + // if graphicsItem is set, request redraw + if ( d->graphicsItem ) { + d->graphicsItem->update(); + } + } +} + +/*! +* Returns the frame type. +* \sa HbFrameDrawer::setFrameType() +*/ +HbFrameDrawer::FrameType HbFrameDrawer::frameType() const +{ + return d->type; +} + +/*! +* Sets the frame type. +* \sa HbFrameDrawer::frameType() +*/ +void HbFrameDrawer::setFrameType(HbFrameDrawer::FrameType type) +{ + if (d->type != type) { + d->type = type; + // Frame type changed, clear frame icon + d->reset(); + } +} + +/*! +* Returns the border width values. If the border widths has not been set by calling setBorderWidths(), +* this method returns zero for all values. +* +* \sa HbFrameDrawer::setBorderWidths() +*/ +void HbFrameDrawer::borderWidths(qreal &left, qreal &top, qreal &right, qreal &bottom) const +{ + left = d->borderWidths[0]; + top = d->borderWidths[1]; + right = d->borderWidths[2]; + bottom = d->borderWidths[3]; +} + +/*! +* Sets the frame border widths ("frame thickness") explicitly for the 3 or 9 parts of the frame. +* +* \note If this method is not called, the bounding rectangle of the frame is divided as follows. +* +* Frame type \b ThreePiecesHorizontal: +* +* - Left part width = (default size of the left part graphics scaled to the bounding rectangle).width +* - Right part width = (default size of the right part graphics scaled to the bounding rectangle).width +* - Center part width = remaining width +* +* Frame type \b ThreePiecesVertical: +* +* - Top part height = (default size of the top part graphics scaled to the bounding rectangle).height +* - Bottom part height = (default size of the bottom part graphics scaled to the bounding rectangle).height +* - Center part height = remaining height +* +* Frame type \b NinePieces: +* +* - Default sizes of the top left and bottom right part graphics are used. +* - Other sizes are calculated from them and the bounding rectangle. +* +* \sa HbFrameDrawer::borderWidths() +*/ +void HbFrameDrawer::setBorderWidths(const qreal left, const qreal top, const qreal right, const qreal bottom) +{ + d->setBorderApiProtectionFlag(true); + if ( left != d->borderWidths[0] || top != d->borderWidths[1] || + right != d->borderWidths[2] || bottom != d->borderWidths[3] ) { + // Negative values are converted to zero. + d->borderWidths[0] = qMax((qreal)0.0, left); + d->borderWidths[1] = qMax((qreal)0.0, top); + d->borderWidths[2] = qMax((qreal)0.0, right); + d->borderWidths[3] = qMax((qreal)0.0, bottom); + // borderWidths changed, clear frame icon + d->reset( false ); + } +} + +/*! +* This is a convenience method. Equals to: +* +* setBorderWidths( horizontal, vertical, horizontal, vertical ); +* +* \sa HbFrameDrawer::borderWidths() +*/ +void HbFrameDrawer::setBorderWidths(const qreal horizontal, const qreal vertical) +{ + setBorderWidths( horizontal, vertical, horizontal, vertical ); +} + +/*! +* This is a convenience method. Equals to: +* +* setBorderWidths( width, width, width, width ); +* +* \sa HbFrameDrawer::borderWidths() +*/ +void HbFrameDrawer::setBorderWidth(const qreal width) +{ + setBorderWidths( width, width, width, width ); +} + + +/*! +* Returns the bounding rectangle of the frame. +* \sa HbFrameDrawer::setRect() +*/ +QRectF HbFrameDrawer::rect() const +{ + return d->rect; +} + +/*! +* Sets the bounding rectangle for the frame. +* \sa HbFrameDrawer::rect() +*/ +void HbFrameDrawer::setRect(const QRectF &rect) +{ + if (rect != d->rect) { + d->rect = rect; + // Rect changed, clear frame icon + d->reset( false ); + } +} + +/*! +* Paints the frame with the given \a painter. +*/ +void HbFrameDrawer::paint(QPainter *painter, const QRectF &rect) const +{ + const_cast(this)->setRect( rect ); + + if (d->frameGraphicsName.isEmpty() || d->type == HbFrameDrawer::Undefined || d->rect.isEmpty()) { + return; + } + + // Lazy graphics rasterizing is used. + // Rasterize the frame parts now if that has not been done yet. + if (d->icon && (rect.toRect().size() != d->prevRect.size())) { + d->reset(); + } + d->prepareFrameIcon(); + d->prevRect = rect.toRect(); + // Paint the frame + d->paint(painter); +} + +/*! +* Returns whether the whole bounding rectangle is always filled by the frame graphics. +* By default, this property is false and in that case, the 3-piece horizontal frame height +* and 3-piece vertical frame width are defined by the default sizes of the frame part graphics. +* If the whole bounding rectangle is not filled, the frame area is centered +* in the bounding rectangle. +* +* \note 9-piece frames always fill the whole bounding rectangle. +* +* \sa HbFrameDrawer::setFillWholeRect() +*/ +bool HbFrameDrawer::fillWholeRect() const +{ + return d->fillWholeRect(); +} + +/*! +* Sets the property whether the whole bounding rectangle is always filled by the frame graphics. +* By default, this property is false and in that case, the 3-piece horizontal frame height +* and 3-piece vertical frame width are defined by the default sizes of the frame part graphics. +* If the whole bounding rectangle is not filled, the frame area is centered +* in the bounding rectangle. +* +* \note 9-piece frames always fill the whole bounding rectangle. +* +* \sa HbFrameDrawer::fillWholeRect() +*/ +void HbFrameDrawer::setFillWholeRect(bool fill) +{ + if ( (fill && !d->fillWholeRect()) || (!fill && d->fillWholeRect()) ) { + if ( fill ) { + d->flags |= HbFrameDrawerPrivate::FillWholeRect; + } else { + d->flags &= ~HbFrameDrawerPrivate::FillWholeRect; + } + + // Fill mode changed, clear frame Icon + d->reset( false ); + } +} + +/*! Returns the mirroring mode set for the frame drawer. +* \sa HbFrameDrawer::setMirroringMode() +*/ +HbIcon::MirroringMode HbFrameDrawer::mirroringMode() const +{ + return d->mirroring; +} + +/*! Sets the mirroring \a mode for the frame drawer. +* \sa HbFrameDrawer::mirroringMode() +*/ +void HbFrameDrawer::setMirroringMode(HbIcon::MirroringMode mode) +{ + if (mode != d->mirroring) { + d->mirroring = mode; + // Mirroring changed, clear frame Icon + d->reset( false ); + } +} + +/*! Returns the filename suffix list. +* See the class level documentation for how frame part filenames are determined +* using the these filename suffixes. If the suffix list has been set explicitly with +* method HbFrameDrawer::setFileNameSuffixList, that list is returned. +* Otherwise, a list of default suffixes (see class level documentation) is returned. +* +* \note If the explicitly given suffix list does not have enough entries for the +* defined frame type, the default suffix list is returned. +* +* \sa HbFrameDrawer::setFileNameSuffixList() +*/ +QStringList HbFrameDrawer::fileNameSuffixList() const +{ + return d->fileNameSuffixList(); +} + +/*! Sets the filename suffix list. +* If the frame type is ThreePiecesHorizontal or ThreePiecesVertical, the list must contain three entries. +* If the frame type is NinePieces, the list must contain nine entries. +* The order of the list entries is the following. +* +* Frame type \b ThreePiecesHorizontal: +* +* - [0] left +* - [1] center +* - [2] right +* +* Frame type \b ThreePiecesVertical: +* +* - [0] top +* - [1] center +* - [2] bottom +* +* Frame type \b NinePieces: +* +* - [0] top left +* - [1] top +* - [2] top right +* - [3] left +* - [4] center +* - [5] right +* - [6] bottom left +* - [7] bottom +* - [8] bottom right +* +* Example: +* +* A three piece frame has the following frame part filenames: +* ":/myapp/frame_a.svg", ":/myapp/frame_b.svg", ":/myapp/frame_c.svg". +* The following code sets the frame graphics name and the filename suffixes. +* +* \dontinclude ultimatecodesnippet/ultimatecodesnippet.cpp +* \skip Start of snippet 20 +* \until End of snippet 20 +* +* \sa HbFrameDrawer::fileNameSuffixList() +*/ +void HbFrameDrawer::setFileNameSuffixList(const QStringList &list) +{ + if (list != d->suffixList) { + d->suffixList = list; + // Frame part filename suffix list changed, clear frame parts count info and generated frame icon. + d->reset(); + } +} + +/*! +* Sets the mask to be applied with the the entire frame icon. +* If the mask is also a frame item, use another frame drawer to draw it. +* Mask should be of the same size as returned by frameSize(). +* To unset the mask, set it to a null pixmap. +* +* \warning Currently this method makes use of pixmap() routine in case of NVG icons. +* pixmap() slows down the hardware accelerated rendering. +* \sa frameSize(), mask() +*/ +void HbFrameDrawer::setMask(const QPixmap &mask) +{ + d->mask = mask; + d->maskChanged = true; +} + +/*! +* Sets the mask to be applied with the the entire frame icon. +* If the mask is also a frame item, use another frame drawer to draw it. +* Mask should be of the same size as returned by frameSize(). +* To unset the mask, set it to a null bitmap. +* + \warning Currently this method makes use of pixmap() routine in case of NVG icons. +* pixmap() slows down the hardware accelerated rendering. +* +*\sa frameSize(), mask() +*/ +void HbFrameDrawer::setMask(const QBitmap &mask) +{ + d->mask = mask; + d->maskChanged = true; +} + +/*! +* Returns the mask set on the frame drawer. +* As default, returns a null pixmap. +* \sa setMask() +*/ + +QPixmap HbFrameDrawer::mask() const +{ + return d->mask; +} + + +/*! +* Returns the mask set on the frame drawer. +* As default, returns a null bitmap. +* \sa setMask() +*/ +QBitmap HbFrameDrawer::maskBitmap() const +{ + return d->mask; +} +/*! + * Returns the size of the entire frame icon. + * Use this method to retrieve the correct size for a mask pixmap that can be set with method setMask(). + * If the frame graphics name, bounding rectangle or frame type have not been set, this method returns + * an empty size. + */ +QSize HbFrameDrawer::frameSize() const +{ + if (d->frameGraphicsName.isEmpty() || d->type == HbFrameDrawer::Undefined || d->rect.isEmpty()) { + return QSize(0, 0); + } + + d->prepareFrameIcon(); + + if (d->icon) { + return d->icon->keySize().toSize(); + } else if (d->fallbackMaskableIconList.count()) { + QSize sz; + for (int i = 0, ie = d->fallbackMaskableIconList.count(); i != ie; ++i) { + if (d->fallbackMaskableIconList[i]) { + sz += d->multiPartSizeData.targets[i].size(); + } + } + return sz; + } + + return QSize(0, 0); +} + +/*! +* This function should be called when the theme changes. This clears the used frame +* graphic. +*/ +void HbFrameDrawer::themeChanged() +{ + d->reset(); +} + +/*! +* Sets the layout direction of the frame drawer. +* +* Valid only when the mirroring mode is HbIcon::LayoutDirection. +*/ +void HbFrameDrawer::setLayoutDirection( Qt::LayoutDirection direction ) +{ + d->flags |= HbFrameDrawerPrivate::LayoutDirectionSet; + + if ( d->layoutDirection != direction ) { + d->layoutDirection = direction; + + if ( ( d->mirroring == HbIcon::Default + && d->defaultMirroring == HbFrameDrawerPrivate::Enabled ) || + d->mirroring == HbIcon::LayoutDirection) { + + d->reset( false ); + } + } +} + +/*! +* Sets the \a item which is needs to be redrawn when the frame drawer +* needs re-paint. +*/ +void HbFrameDrawer::setGraphicsItem( QGraphicsItem *item ) +{ + d->graphicsItem = item; +} + + +// End of File