src/hbcore/image/hbframedrawer.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /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 <hbinstance.h>
+#include <hbiconimpl_p.h>
+#include <hbiconloader_p.h>
+#include "hbmaskableiconimpl_p.h"
+
+#include <QPainter>
+#include <QIcon>
+#include <QPixmap>
+#include <QDebug>
+#include <QBitmap>
+
+/*!
+	@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        <name>_tl.<ext>
+    - top             <name>_t.<ext>
+    - top right       <name>_tr.<ext>
+    - left            <name>_l.<ext>
+    - center          <name>_c.<ext>
+    - right           <name>_r.<ext>
+    - bottom left     <name>_bl.<ext>
+    - bottom          <name>_b.<ext>
+    - bottom right    <name>_br.<ext>
+
+    Filenames for 3-piece horizontal frame graphics are defined according to the following.
+
+    - left            <name>_l.<ext>
+    - center          <name>_c.<ext>
+    - right           <name>_r.<ext>
+
+    Filenames for 3-piece vertical frame graphics are defined according to the following.
+
+    - top             <name>_t.<ext>
+    - center          <name>_c.<ext>
+    - bottom          <name>_b.<ext>
+
+    \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 <name>.<ext> 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            <name>_l.<ext>
+            - center          <name>_c.<ext>
+            - right           <name>_r.<ext>
+
+  \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             <name>_t.<ext>
+            - center          <name>_c.<ext>
+            - bottom          <name>_b.<ext>
+
+  \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        <name>_tl.<ext>
+            - top             <name>_t.<ext>
+            - top right       <name>_tr.<ext>
+            - left            <name>_l.<ext>
+            - center          <name>_c.<ext>
+            - right           <name>_r.<ext>
+            - bottom left     <name>_bl.<ext>
+            - bottom          <name>_b.<ext>
+            - bottom right    <name>_br.<ext>
+*/
+
+#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<HbIconImpl *> 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<HbIconImpl*> from QVector<HbMaskableIconImpl*> for unloading.
+    QVector<HbIconImpl *> 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<HbFrameDrawer*>(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