src/hbcore/image/hbframedrawer.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbCore module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 #include "hbframedrawer.h"
       
    26 #include "hbframedrawer_p.h"
       
    27 #include "hbimagetraces_p.h"
       
    28 
       
    29 #include <hbinstance.h>
       
    30 #include <hbiconimpl_p.h>
       
    31 #include <hbiconloader_p.h>
       
    32 #include "hbmaskableiconimpl_p.h"
       
    33 
       
    34 #include <QPainter>
       
    35 #include <QIcon>
       
    36 #include <QPixmap>
       
    37 #include <QDebug>
       
    38 #include <QBitmap>
       
    39 
       
    40 /*!
       
    41 	@stable
       
    42     @hbcore
       
    43     \class HbFrameDrawer
       
    44     \brief HbFrameDrawer draws frames graphics.
       
    45 
       
    46     This class is not intended to be derived from.
       
    47 
       
    48     Frame graphics mean graphics that consist of either 3 or 9 parts that are positioned
       
    49     and scaled followingly.
       
    50     
       
    51     A 9-piece frame consists of a 3x3 grid, where the corner parts have a fixed size and
       
    52     the other parts are scaled.
       
    53     
       
    54     A 3-piece frame consists of 3 parts tiled either horizontally of vertically. The side
       
    55     parts preserve their aspect ratio and the center part is scaled to fill the remaining space.
       
    56 
       
    57     For convenience, frame drawer can also draw the frame with a single graphic.
       
    58 
       
    59     The frame drawer implements the logic of scaling and positioning the frame parts and
       
    60     takes care that there are no visible gaps between the frame parts when the whole frame
       
    61     is painted to the display even if the frame bounding rectangle uses floating point accuracy.
       
    62 
       
    63     Filenames for 9-piece frame graphics are defined according to the following.
       
    64 
       
    65     - top left        <name>_tl.<ext>
       
    66     - top             <name>_t.<ext>
       
    67     - top right       <name>_tr.<ext>
       
    68     - left            <name>_l.<ext>
       
    69     - center          <name>_c.<ext>
       
    70     - right           <name>_r.<ext>
       
    71     - bottom left     <name>_bl.<ext>
       
    72     - bottom          <name>_b.<ext>
       
    73     - bottom right    <name>_br.<ext>
       
    74 
       
    75     Filenames for 3-piece horizontal frame graphics are defined according to the following.
       
    76 
       
    77     - left            <name>_l.<ext>
       
    78     - center          <name>_c.<ext>
       
    79     - right           <name>_r.<ext>
       
    80 
       
    81     Filenames for 3-piece vertical frame graphics are defined according to the following.
       
    82 
       
    83     - top             <name>_t.<ext>
       
    84     - center          <name>_c.<ext>
       
    85     - bottom          <name>_b.<ext>
       
    86 
       
    87     \note The suffixes (e.g. "_l") in the filenames can be redefined with method
       
    88     HbFrameDrawer::setFileNameSuffixList().
       
    89 
       
    90     \note If all of the frame pieces cannot be found, the frame drawer falls back to a single
       
    91     frame graphics piece with filename <name>.<ext> to draw the frame.
       
    92     If even that does not exist, nothing is drawn.
       
    93 
       
    94     See class HbIcon for information of supported icon formats and file locations.
       
    95 
       
    96     The frame drawer stores the whole generated frame graphics in a pixmap for
       
    97     improving the speed of the paint operations. Therefore, the frame drawer instance should not
       
    98     be re-created each time the frame needs to be rendered.
       
    99 
       
   100     Example of how to create a frame drawer and use it.
       
   101 
       
   102     \dontinclude ultimatecodesnippet/ultimatecodesnippet.cpp
       
   103     \skip nine-piece
       
   104     \until }
       
   105 
       
   106     \sa class HbFrameItem
       
   107 */
       
   108 
       
   109 /*!
       
   110   \enum HbFrameDrawer::FrameType
       
   111 
       
   112   \b Undefined The frame type is undefined. It must be defined before being able to draw the frame.
       
   113 
       
   114   \b OnePiece The frame consist of a single graphic piece, which is scaled to the frame's bounding rectangle.
       
   115 
       
   116   \b ThreePiecesHorizontal The frame consists of three graphic pieces that are tiled horizontally.
       
   117             As default, the side parts preserve their aspect ratio and the center part is scaled to fill the remaining space.
       
   118             Filenames for 3-piece horizontal frame graphics are defined according to the following.
       
   119 
       
   120             - left            <name>_l.<ext>
       
   121             - center          <name>_c.<ext>
       
   122             - right           <name>_r.<ext>
       
   123 
       
   124   \b ThreePiecesVertical The frame consists of three graphic pieces that are tiled vertically.
       
   125             As default, the side parts preserve their aspect ratio and the center part is scaled to fill the remaining space.
       
   126             Filenames for 3-piece vertical frame graphics are defined according to the following.
       
   127 
       
   128             - top             <name>_t.<ext>
       
   129             - center          <name>_c.<ext>
       
   130             - bottom          <name>_b.<ext>
       
   131 
       
   132   \b NinePieces The frame consists of a 3x3 grid of graphic pieces, where as default the corner
       
   133             parts have a fixed size and the other parts are scaled.
       
   134             Filenames for 9-piece frame graphics are defined according to the following.
       
   135 
       
   136             - top left        <name>_tl.<ext>
       
   137             - top             <name>_t.<ext>
       
   138             - top right       <name>_tr.<ext>
       
   139             - left            <name>_l.<ext>
       
   140             - center          <name>_c.<ext>
       
   141             - right           <name>_r.<ext>
       
   142             - bottom left     <name>_bl.<ext>
       
   143             - bottom          <name>_b.<ext>
       
   144             - bottom right    <name>_br.<ext>
       
   145 */
       
   146 
       
   147 #define DEFAULT_OPTIONS (HbIconLoader::ReturnUnknownIcon | HbIconLoader::BitmapIcons | HbIconLoader::VectorIcons)
       
   148 // Same rounding function is used everywhere for consistency
       
   149 static inline int realToInt(qreal r)
       
   150 {
       
   151     return (int)(r + 0.5);
       
   152 }
       
   153 
       
   154 /*!
       
   155 \internal
       
   156 */
       
   157 HbFrameDrawerPrivate::HbFrameDrawerPrivate() :
       
   158     QSharedData(),
       
   159     type(HbFrameDrawer::Undefined),
       
   160     frameParts(0),
       
   161     mirroring(HbIcon::Default),
       
   162     defaultMirroring(Unknown),
       
   163     flags(0),
       
   164     layoutDirection(Qt::LeftToRight),
       
   165     graphicsItem(0),
       
   166     color(),
       
   167     icon(0),
       
   168     maskChanged(false)
       
   169 {
       
   170     borderWidths[0]=0.0;
       
   171     borderWidths[1]=0.0;
       
   172     borderWidths[2]=0.0;
       
   173     borderWidths[3]=0.0;
       
   174 }
       
   175 
       
   176 /*!
       
   177 \internal
       
   178 */
       
   179 HbFrameDrawerPrivate::HbFrameDrawerPrivate(const QString &frameGraphicsName, HbFrameDrawer::FrameType type) :
       
   180     QSharedData(),
       
   181     frameGraphicsName(frameGraphicsName),
       
   182     type(type),
       
   183     mask(QPixmap()),
       
   184     frameParts(0),
       
   185     mirroring(HbIcon::Default),
       
   186     defaultMirroring(Unknown),
       
   187     flags( 0 ),
       
   188     layoutDirection(Qt::LeftToRight),
       
   189     graphicsItem(0),
       
   190     color(),
       
   191     icon(0),
       
   192     maskChanged(false)
       
   193 {
       
   194     borderWidths[0]=0.0;
       
   195     borderWidths[1]=0.0;
       
   196     borderWidths[2]=0.0;
       
   197     borderWidths[3]=0.0;
       
   198 
       
   199     // Remove possible file extension
       
   200     int index = this->frameGraphicsName.lastIndexOf(QChar('.'));
       
   201     if (index>0) {
       
   202         this->frameGraphicsName.resize(index);
       
   203     }
       
   204 }
       
   205 
       
   206 /*!
       
   207 \internal
       
   208 */
       
   209 HbFrameDrawerPrivate::HbFrameDrawerPrivate(const HbFrameDrawerPrivate &other) :
       
   210     QSharedData(other),
       
   211     frameGraphicsName(other.frameGraphicsName),
       
   212     type(other.type),
       
   213     rect(other.rect),
       
   214     mask(QPixmap()),
       
   215     frameParts(other.frameParts),
       
   216     mirroring(other.mirroring),
       
   217     defaultMirroring(other.defaultMirroring),
       
   218     flags( other.flags ),
       
   219     layoutDirection( other.layoutDirection ),
       
   220     graphicsItem( other.graphicsItem ),
       
   221     color(other.color),
       
   222     icon(0),
       
   223     maskChanged(false)
       
   224 {
       
   225     borderWidths[0]=other.borderWidths[0];
       
   226     borderWidths[1]=other.borderWidths[1];
       
   227     borderWidths[2]=other.borderWidths[2];
       
   228     borderWidths[3]=other.borderWidths[3];
       
   229 }
       
   230 
       
   231 /*!
       
   232 \internal
       
   233 */
       
   234 HbFrameDrawerPrivate::~HbFrameDrawerPrivate()
       
   235 {
       
   236     unLoadIcon();
       
   237 }
       
   238 
       
   239 /*!
       
   240 \internal
       
   241 */
       
   242 void HbFrameDrawerPrivate::prepareFrameIcon()
       
   243 {
       
   244     if (!frameParts) {
       
   245         checkFrameParts();
       
   246     }
       
   247     if ((!icon ) && (!fallbackMaskableIconList.count()) ) {
       
   248         createFrameIcon();
       
   249     }
       
   250 }
       
   251 
       
   252 /*!
       
   253 * Returns whether this frame drawer's border widths have been set by API
       
   254 *
       
   255 * \sa HbFrameDrawerPrivate::setBorderApiProtectionFlag()
       
   256 */
       
   257 bool HbFrameDrawerPrivate::testBorderApiProtectionFlag() const
       
   258 {
       
   259 	return flags & HbFrameDrawerPrivate::BorderWidthSetByApi;
       
   260 }
       
   261 
       
   262 /*!
       
   263 * Clears the flag denoting that the border widths have been set by API.
       
   264 * This will cause control of border widths to return to the CSS system.
       
   265 *
       
   266 * \sa HbFrameDrawerPrivate::testBorderApiProtectionFlag()
       
   267 */
       
   268 void HbFrameDrawerPrivate::setBorderApiProtectionFlag(bool on)
       
   269 {
       
   270 	if(on){
       
   271 		flags |= HbFrameDrawerPrivate::BorderWidthSetByApi;
       
   272 	}else{
       
   273 		flags &= ~HbFrameDrawerPrivate::BorderWidthSetByApi;
       
   274 	}
       
   275 }
       
   276 
       
   277 /*!
       
   278 * Checks whether all the frame parts are available for the given frame type.
       
   279 * Fallback is 1-part frame rendering.
       
   280 * \internal
       
   281 */
       
   282 void HbFrameDrawerPrivate::checkFrameParts()
       
   283 {
       
   284     // fall back is 1 piece frame
       
   285     frameParts = 1;
       
   286 
       
   287     if (type == HbFrameDrawer::ThreePiecesHorizontal || type == HbFrameDrawer::ThreePiecesVertical) {
       
   288         if (HbIconLoader::iconsExist(frameGraphicsName, fileNameSuffixList())) {
       
   289             frameParts = 3;
       
   290         }
       
   291     } else if (type == HbFrameDrawer::NinePieces) {
       
   292         if (HbIconLoader::iconsExist(frameGraphicsName, fileNameSuffixList())) {
       
   293             frameParts = 9;
       
   294         }
       
   295     }
       
   296 }
       
   297 
       
   298 /*!
       
   299 \internal
       
   300 */
       
   301 QStringList HbFrameDrawerPrivate::fileNameSuffixList() const
       
   302 {
       
   303     // If the suffix list has been set explicitly, return that if it contains enough suffixes.
       
   304     if (!suffixList.isEmpty()) {
       
   305         switch (type) {
       
   306             case HbFrameDrawer::ThreePiecesHorizontal: // fall through
       
   307             case HbFrameDrawer::ThreePiecesVertical:
       
   308                 if (suffixList.count() >= 3) {
       
   309                     return suffixList;
       
   310                 }
       
   311                 break;
       
   312 
       
   313             case HbFrameDrawer::NinePieces:
       
   314                 if (suffixList.count() >= 9) {
       
   315                     return suffixList;
       
   316                 }
       
   317                 break;
       
   318             
       
   319             default:
       
   320                 return suffixList;
       
   321         }
       
   322     } 
       
   323 
       
   324     // Otherwise, return default suffix list.
       
   325     QStringList list;
       
   326 
       
   327     switch (type) {
       
   328         case HbFrameDrawer::ThreePiecesHorizontal:
       
   329             list << "_l" << "_c" << "_r";
       
   330             break;
       
   331         case HbFrameDrawer::ThreePiecesVertical:
       
   332             list << "_t" << "_c" << "_b";
       
   333             break;
       
   334         case HbFrameDrawer::NinePieces:
       
   335             list << "_tl" << "_t" << "_tr" << "_l" << "_c" << "_r" << "_bl" << "_b" << "_br";
       
   336             break;
       
   337         default:
       
   338             break;
       
   339     }
       
   340 
       
   341     return list;
       
   342 }
       
   343 
       
   344 /*!
       
   345 * Creates a consolidated HbIconImpl (Icon) with the available piece information 
       
   346 * If failed to create the same, then creates HbIconImpls for the pieces.
       
   347 * \internal
       
   348 */
       
   349 void HbFrameDrawerPrivate::createFrameIcon()
       
   350 {
       
   351     // Divide rectangle area to the frame parts first.
       
   352     HbMultiPartSizeData data;
       
   353     QSize frameIconSize = divideSpace(data);
       
   354     data.multiPartIconId = multiPartIconId();
       
   355     multiPartSizeData = data;
       
   356 
       
   357     // Create the frame icon and add it in the icon cache
       
   358     HbIconLoader *loader = HbIconLoader::global();
       
   359     
       
   360     //If it's one-piece frame-item, it's loaded using HbIconLoader::loadIcon()
       
   361     if (frameParts == 1) {
       
   362         HbIconImpl * iconImpl =  loader->loadIcon(frameGraphicsName, HbIconLoader::AnyType,
       
   363                                  HbIconLoader::AnyPurpose,
       
   364                                  frameIconSize,
       
   365                                  Qt::IgnoreAspectRatio,
       
   366                                  QIcon::Normal,
       
   367                                  iconLoaderOptions());
       
   368         if (iconImpl) {
       
   369             icon = new HbMaskableIconImpl(iconImpl);
       
   370         }
       
   371 
       
   372     } else {
       
   373         QStringList multiPieceFileNames;
       
   374         QStringList list = fileNameSuffixList();
       
   375         int nameListCount = list.count();
       
   376         for (int i = 0; i < nameListCount; i++) {
       
   377             multiPieceFileNames.append(frameGraphicsName + list[i]);
       
   378             if (data.pixmapSizes[i].isEmpty()) {
       
   379                 data.pixmapSizes[i] = QSize(0,0);
       
   380             }
       
   381         }
       
   382 
       
   383         QVector<HbIconImpl *> listOfIcons;
       
   384         
       
   385         //For multi-piece frame-items, HbIocnLoader::loadMultipieceIcon is used
       
   386         //This function returns the consolidate (stitched) icon created on the themeserver.
       
   387         //If the consolidated icon-creation on themeserver fails, then server returns a list
       
   388         //of individual frame-items.
       
   389         HbIconImpl * iconImpl = loader->loadMultiPieceIcon(multiPieceFileNames, data, frameIconSize,
       
   390                                           Qt::IgnoreAspectRatio, QIcon::Normal, iconLoaderOptions(),
       
   391                                           listOfIcons, color);
       
   392 
       
   393         if (iconImpl) {
       
   394             icon = new HbMaskableIconImpl(iconImpl);
       
   395         } else {
       
   396             int implCount = listOfIcons.count();
       
   397             for (int i = 0; i < implCount; i++) {
       
   398                 fallbackMaskableIconList.append(new HbMaskableIconImpl(listOfIcons[i]));
       
   399             }
       
   400         }
       
   401  
       
   402     }
       
   403 }
       
   404 
       
   405 /*!
       
   406 \internal
       
   407 */
       
   408 void HbFrameDrawerPrivate::paint(QPainter *painter)
       
   409 {
       
   410     // createFrameIcon() must be called before calling this method.
       
   411 
       
   412     QRectF centeredRect(rect);
       
   413     QRect integerRect = rect.toRect();
       
   414     if (icon) {
       
   415         QSize size = icon->size();
       
   416 
       
   417         if (integerRect.width() != size.width()) {
       
   418             centeredRect.adjust((rect.width() - size.width()) / 2, 0, 0, 0);
       
   419             centeredRect.setWidth(size.width());
       
   420         }
       
   421         if (integerRect.height() != size.height()) {
       
   422             centeredRect.adjust(0, (rect.height() - size.height()) / 2, 0, 0);
       
   423             centeredRect.setHeight(size.height());
       
   424         }
       
   425 
       
   426         if (!mask.isNull() && maskChanged) {
       
   427             icon->setMask(mask);
       
   428         } 
       
   429         //paint the stitched icon
       
   430         icon->paint(painter, centeredRect, Qt::AlignHCenter);
       
   431 
       
   432         #ifdef HB_FRAME_DRAWER_TRACES
       
   433         qDebug() << "FRAMENAME: " << frameGraphicsName << "Drawn at: "
       
   434         << centeredRect.topLeft().x() << "," << centeredRect.topLeft().y() << " | "
       
   435         << centeredRect.bottomRight().x() << "," << centeredRect.bottomRight().y();
       
   436         #endif
       
   437     } else {
       
   438         for (int i = 0; i < fileNameSuffixList().count(); i++) {
       
   439             if (i < fallbackMaskableIconList.count() && fallbackMaskableIconList[i]) {
       
   440                 QPoint position = multiPartSizeData.targets[i].topLeft();
       
   441                 if (isMirrored()) {
       
   442                     int centerTopRightX = (int)(centeredRect.topLeft().x() + centeredRect.width());
       
   443                     int targetTopRightX = multiPartSizeData.targets[i].topLeft().x()
       
   444                                           + multiPartSizeData.targets[i].width();
       
   445                     position.setX((int)(centeredRect.topLeft().x() + (centerTopRightX - targetTopRightX)));
       
   446                 } else {
       
   447                     position.setX((int)(centeredRect.topLeft().x() + position.x()));
       
   448                 }
       
   449                 position.setY((int)(centeredRect.topLeft().y() + position.y()));
       
   450                 if ((!mask.isNull()) && maskChanged) {
       
   451                     QBitmap pieceMask ;
       
   452                     QRect maskRect(position.x(), position.y(), multiPartSizeData.targets[i].width(), multiPartSizeData.targets[i].height());
       
   453                     pieceMask = mask.copy(maskRect);
       
   454                     fallbackMaskableIconList[i]->setMask(pieceMask);
       
   455                 } 
       
   456                 if(!multiPartSizeData.targets[i].isEmpty()) {
       
   457                     fallbackMaskableIconList[i]->paint(painter, QRect(position,multiPartSizeData.pixmapSizes[i]), Qt::AlignHCenter);
       
   458                 }
       
   459             }
       
   460         }
       
   461     }
       
   462     maskChanged = false;
       
   463 }
       
   464 
       
   465 /*!
       
   466 \internal
       
   467 */
       
   468 bool HbFrameDrawerPrivate::fillWholeRect() const 
       
   469 {
       
   470     return flags & HbFrameDrawerPrivate::FillWholeRect;
       
   471 }
       
   472 
       
   473 /*!
       
   474 * Calculates frame part rectangles and icon sizes based on the following information.
       
   475 * - frame bounding rectangle
       
   476 * - frame inner rectangle (optional)
       
   477 * - default sizes of the frame corner (9-piece) or side (3-piece) graphics.
       
   478 * 
       
   479 * Note! Integer pixel sizes are used in this function to avoid one pixel gaps between the frame parts.
       
   480 * \internal
       
   481 */
       
   482 QSize HbFrameDrawerPrivate::divideSpace(HbMultiPartSizeData &data)
       
   483 {
       
   484     // Do not need to divide space if there is only one frame part.
       
   485     if (frameParts == 1) {
       
   486         QSizeF size = rect.size();
       
   487         // If the whole rect is not filled, use default graphics size to define one of the dimensions.
       
   488         if (type == HbFrameDrawer::ThreePiecesHorizontal && !fillWholeRect()) {
       
   489             qreal defaultHeight = defaultSize("").height();
       
   490             if (defaultHeight < size.height()) {
       
   491                 size.setHeight(defaultHeight);
       
   492             }
       
   493         } else if (type == HbFrameDrawer::ThreePiecesVertical && !fillWholeRect()) {
       
   494             qreal defaultWidth = defaultSize("").width();
       
   495             if (defaultWidth < size.width()) {
       
   496                 size.setWidth(defaultWidth);
       
   497             }
       
   498         }
       
   499 
       
   500         // Using same rounding as in other code below
       
   501         return QSize(realToInt(size.width()), realToInt(size.height()));
       
   502     }
       
   503 
       
   504     // Frame part filename suffix list is needed.
       
   505     QStringList suffixList = fileNameSuffixList();
       
   506 
       
   507     int fullWidth = realToInt(rect.width());
       
   508     int fullHeight = realToInt(rect.height());
       
   509 
       
   510     if (type == HbFrameDrawer::ThreePiecesHorizontal) {
       
   511         int leftWidth;
       
   512         int rightWidth;
       
   513 
       
   514         if (borderWidths[0] == 0 && borderWidths[2] == 0) {
       
   515             QSizeF leftSize = defaultSize(suffixList.at(0)); // index 0 is leftmost frame part
       
   516             QSizeF rightSize = defaultSize(suffixList.at(2)); // index 2 is rightmost frame part
       
   517             
       
   518             if (fillWholeRect()) {
       
   519                 leftSize.scale(rect.size(), Qt::KeepAspectRatio);
       
   520                 rightSize.scale(rect.size(), Qt::KeepAspectRatio);
       
   521             } else {
       
   522                 int leftHeight = leftSize.toSize().height();
       
   523                 if (leftHeight < fullHeight) {
       
   524                     fullHeight = leftHeight;
       
   525                 }
       
   526             }
       
   527 
       
   528             leftWidth = leftSize.toSize().width();
       
   529             rightWidth = rightSize.toSize().width();
       
   530 
       
   531         } else {
       
   532             // QSizeF::toSize rounds to nearest integer so do the same here
       
   533             leftWidth = realToInt(borderWidths[0]);
       
   534             rightWidth = realToInt(borderWidths[2]);
       
   535 
       
   536             // If whole rect is not filled, take height from default graphics height
       
   537             if (!fillWholeRect()) {
       
   538                 QSizeF leftSize = defaultSize(suffixList.at(0)); // index 0 is leftmost frame part
       
   539 
       
   540                 int leftHeight = leftSize.toSize().height();
       
   541                 if (leftHeight < fullHeight) {
       
   542                     fullHeight = leftHeight;
       
   543                 }
       
   544             }
       
   545         }
       
   546 
       
   547         int centerWidth = fullWidth - leftWidth - rightWidth;
       
   548 
       
   549         // Do all 3 pieces fit?
       
   550         if (fullWidth >= leftWidth + rightWidth) {
       
   551             data.targets[0] = QRect(0, 0, leftWidth, fullHeight);
       
   552             data.targets[1] = QRect(leftWidth, 0, centerWidth, fullHeight);
       
   553             data.targets[2] = QRect(fullWidth-rightWidth, 0, rightWidth, fullHeight);
       
   554 
       
   555             data.pixmapSizes[0] = QSize(leftWidth, fullHeight);
       
   556             data.pixmapSizes[1] = QSize(centerWidth, fullHeight);
       
   557             data.pixmapSizes[2] = QSize(rightWidth, fullHeight);
       
   558 
       
   559             data.sources[0] = QRect(QPoint(0,0), data.pixmapSizes[0]);
       
   560             data.sources[1] = QRect(QPoint(0,0), data.pixmapSizes[1]);
       
   561             data.sources[2] = QRect(QPoint(0,0), data.pixmapSizes[2]);
       
   562         } else {
       
   563             // Only sides fit
       
   564             int totalSideWidth = leftWidth + rightWidth;
       
   565             data.targets[0] = QRect(0, 0, leftWidth * fullWidth / totalSideWidth, fullHeight);
       
   566             data.targets[1] = QRect();
       
   567             data.targets[2] = QRect(data.targets[0].width(), 0, fullWidth - data.targets[0].width(), fullHeight);
       
   568 
       
   569             data.pixmapSizes[0] = QSize(data.targets[0].width(), fullHeight);
       
   570             data.pixmapSizes[1] = QSize();
       
   571             data.pixmapSizes[2] = QSize(data.targets[2].width(), fullHeight);
       
   572 
       
   573             data.sources[0] = data.targets[0];
       
   574             data.sources[1] = QRect();
       
   575             data.sources[2] = data.targets[2];
       
   576             data.sources[2].moveLeft(data.pixmapSizes[2].width() - data.targets[2].width());
       
   577         }
       
   578     } else if (type == HbFrameDrawer::ThreePiecesVertical) {
       
   579 
       
   580         int topHeight;
       
   581         int bottomHeight;
       
   582 
       
   583         if (borderWidths[1] == 0 && borderWidths[3] == 0) {
       
   584             QSizeF topSize = defaultSize(suffixList.at(0)); // index 0 is top frame part
       
   585             QSizeF bottomSize = defaultSize(suffixList.at(2)); // index 2 is bottom frame part
       
   586             
       
   587             if (fillWholeRect()) {
       
   588                 topSize.scale(rect.size(), Qt::KeepAspectRatio);
       
   589                 bottomSize.scale(rect.size(), Qt::KeepAspectRatio);
       
   590             } else {
       
   591                 int topWidth = topSize.toSize().width();
       
   592                 if (topWidth < fullWidth) {
       
   593                     fullWidth = topWidth;
       
   594                 }
       
   595             }
       
   596 
       
   597             topHeight = topSize.toSize().height();
       
   598             bottomHeight = bottomSize.toSize().height();
       
   599         } else {
       
   600             // QSizeF::toSize rounds to nearest integer so do the same here
       
   601             topHeight = realToInt(borderWidths[1]);
       
   602             bottomHeight = realToInt(borderWidths[3]);
       
   603 
       
   604             // If whole rect is not filled, take width from default graphics height
       
   605             if (!fillWholeRect()) {
       
   606                 QSizeF topSize = defaultSize(suffixList.at(0)); // index 0 is top frame part
       
   607 
       
   608                 int topWidth = topSize.toSize().width();
       
   609                 if (topWidth < fullWidth) {
       
   610                     fullWidth = topWidth;
       
   611                 }
       
   612             }
       
   613         }
       
   614 
       
   615         int centerHeight = fullHeight - topHeight - bottomHeight;
       
   616 
       
   617         // Do all 3 pieces fit?
       
   618         if (fullHeight >= topHeight + bottomHeight) {
       
   619             data.targets[0] = QRect(0, 0, fullWidth, topHeight);
       
   620             data.targets[1] = QRect(0, topHeight, fullWidth, centerHeight);
       
   621             data.targets[2] = QRect(0, fullHeight - bottomHeight, fullWidth, bottomHeight);
       
   622 
       
   623             data.pixmapSizes[0] = QSize(fullWidth, topHeight);
       
   624             data.pixmapSizes[1] = QSize(fullWidth, centerHeight);
       
   625             data.pixmapSizes[2] = QSize(fullWidth, bottomHeight);
       
   626 
       
   627             data.sources[0] = QRect(QPoint(0,0), data.pixmapSizes[0]);
       
   628             data.sources[1] = QRect(QPoint(0,0), data.pixmapSizes[1]);
       
   629             data.sources[2] = QRect(QPoint(0,0), data.pixmapSizes[2]);
       
   630         } else {
       
   631             // Only sides fit
       
   632             int totalSideHeight = topHeight + bottomHeight;
       
   633             data.targets[0] = QRect(0, 0, fullWidth, topHeight * fullHeight / totalSideHeight);
       
   634             data.targets[1] = QRect();
       
   635             data.targets[2] = QRect(0, data.targets[0].height(), fullWidth, fullHeight - data.targets[0].height());
       
   636 
       
   637             data.pixmapSizes[0] = QSize(fullWidth,data.targets[0].height());
       
   638             data.pixmapSizes[1] = QSize();
       
   639             data.pixmapSizes[2] = QSize(fullWidth,data.targets[2].height());
       
   640 
       
   641             data.sources[0] = data.targets[0];
       
   642             data.sources[1] = QRect();
       
   643             data.sources[2] = data.targets[2];
       
   644             data.sources[2].moveTop(data.pixmapSizes[2].height() - data.targets[2].height());
       
   645         }
       
   646 
       
   647     } else if (type == HbFrameDrawer::NinePieces) {
       
   648         QSize tlSize;
       
   649         QSize brSize;
       
   650 
       
   651         if (!hasBorderWidths()) {
       
   652             tlSize = defaultSize(suffixList.at(0)).toSize(); // index 0 is top left
       
   653             brSize = defaultSize(suffixList.at(8)).toSize(); // index 8 is bottom right
       
   654         } else {
       
   655             tlSize = QSizeF(borderWidths[0], borderWidths[1]).toSize();
       
   656             brSize = QSizeF(borderWidths[2], borderWidths[3]).toSize();
       
   657         }
       
   658 
       
   659         // Do all 9 pieces fit?
       
   660         if (fullWidth >= tlSize.width() + brSize.width() &&
       
   661             fullHeight >= tlSize.height() + brSize.height()) {
       
   662 
       
   663             int centerWidth = fullWidth - tlSize.width() - brSize.width();
       
   664             int centerHeight = fullHeight - tlSize.height() - brSize.height();
       
   665 
       
   666             data.targets[0] = QRect(0, 0, tlSize.width(), tlSize.height());
       
   667             data.targets[1] = QRect(tlSize.width(), 0, centerWidth, tlSize.height());
       
   668             data.targets[2] = QRect(tlSize.width() + centerWidth, 0, brSize.width(), tlSize.height());
       
   669             data.targets[3] = QRect(0, tlSize.height(), tlSize.width(), centerHeight);
       
   670             data.targets[4] = QRect(tlSize.width(), tlSize.height(), centerWidth, centerHeight);
       
   671             data.targets[5] = QRect(tlSize.width() + centerWidth, tlSize.height(), brSize.width(), centerHeight);
       
   672             data.targets[6] = QRect(0, tlSize.height() + centerHeight, tlSize.width(), brSize.height());
       
   673             data.targets[7] = QRect(tlSize.width(), tlSize.height() + centerHeight, centerWidth, brSize.height());
       
   674             data.targets[8] = QRect(tlSize.width() + centerWidth, tlSize.height() + centerHeight, brSize.width(), brSize.height());
       
   675 
       
   676             data.pixmapSizes[0] = data.targets[0].size();
       
   677             data.pixmapSizes[1] = data.targets[1].size();
       
   678             data.pixmapSizes[2] = data.targets[2].size();
       
   679             data.pixmapSizes[3] = data.targets[3].size();
       
   680             data.pixmapSizes[4] = data.targets[4].size();
       
   681             data.pixmapSizes[5] = data.targets[5].size();
       
   682             data.pixmapSizes[6] = data.targets[6].size();
       
   683             data.pixmapSizes[7] = data.targets[7].size();
       
   684             data.pixmapSizes[8] = data.targets[8].size();
       
   685 
       
   686             data.sources[0] = QRect(QPoint(0,0), data.pixmapSizes[0]);
       
   687             data.sources[1] = QRect(QPoint(0,0), data.pixmapSizes[1]);
       
   688             data.sources[2] = QRect(QPoint(0,0), data.pixmapSizes[2]);
       
   689             data.sources[3] = QRect(QPoint(0,0), data.pixmapSizes[3]);
       
   690             data.sources[4] = QRect(QPoint(0,0), data.pixmapSizes[4]);
       
   691             data.sources[5] = QRect(QPoint(0,0), data.pixmapSizes[5]);
       
   692             data.sources[6] = QRect(QPoint(0,0), data.pixmapSizes[6]);
       
   693             data.sources[7] = QRect(QPoint(0,0), data.pixmapSizes[7]);
       
   694             data.sources[8] = QRect(QPoint(0,0), data.pixmapSizes[8]);
       
   695 
       
   696         } else {
       
   697             // All 9 pieces do not fit.
       
   698             // Corners are drawn always but it is possible that either left&right or top&bottom parts get drawn also.
       
   699             int totalCornerWidth = tlSize.width() + brSize.width();
       
   700             int totalCornerHeight = tlSize.height() + brSize.height();
       
   701 
       
   702             int splitPointX = 0;
       
   703             int splitPointY = 0;
       
   704 
       
   705             // If corners do not fit fully horizontally or vertically, define split point
       
   706             if (totalCornerWidth > fullWidth) {
       
   707                 splitPointX = tlSize.width() * fullWidth / totalCornerWidth;
       
   708             }
       
   709 
       
   710             if (totalCornerHeight > fullHeight) {
       
   711                 splitPointY = tlSize.height() * fullHeight / totalCornerHeight;
       
   712             }
       
   713 
       
   714             calculateShrinkedNinePieceCorners(
       
   715                     data, tlSize, brSize,
       
   716                     QSize(fullWidth, fullHeight), QPoint(splitPointX, splitPointY));
       
   717 
       
   718             // Left and right get drawn if corners height does not cover the total height
       
   719             if (!splitPointY) {
       
   720                 data.targets[3] = QRect(0, data.targets[0].height(), data.targets[0].width(), fullHeight - tlSize.height() - brSize.height());
       
   721                 data.targets[5] = QRect(splitPointX, data.targets[0].height(), data.targets[2].width(), data.targets[3].height());
       
   722             } else {
       
   723                 data.targets[3] = QRect();
       
   724                 data.targets[5] = QRect();
       
   725             }
       
   726 
       
   727             // Top and bottom get drawn if corners width does not cover the total width
       
   728             if (!splitPointX) {
       
   729                 data.targets[1] = QRect(data.targets[0].width(), 0, fullWidth - tlSize.width() - brSize.width(), data.targets[0].height());
       
   730                 data.targets[7] = QRect(data.targets[0].width(), splitPointY, data.targets[1].width(), data.targets[8].height());
       
   731             } else {
       
   732                 data.targets[1] = QRect();
       
   733                 data.targets[7] = QRect();
       
   734             }
       
   735 
       
   736             // Center is always empty
       
   737             data.targets[4] = QRect();
       
   738 
       
   739             data.pixmapSizes[0] = data.targets[0].size();
       
   740             data.pixmapSizes[1] = data.targets[1].size();
       
   741             data.pixmapSizes[2] = data.targets[2].size();
       
   742             data.pixmapSizes[3] = data.targets[3].size();
       
   743             data.pixmapSizes[4] = QSize(); // Center is always empty
       
   744             data.pixmapSizes[5] = data.targets[5].size();
       
   745             data.pixmapSizes[6] = data.targets[6].size();
       
   746             data.pixmapSizes[7] = data.targets[7].size();
       
   747             data.pixmapSizes[8] = data.targets[8].size();
       
   748 
       
   749             data.sources[0] = data.targets[0];
       
   750             data.sources[1] = QRect(QPoint(0,0), data.pixmapSizes[1]);
       
   751             data.sources[2] = QRect(QPoint(0,0), data.pixmapSizes[2]);
       
   752             data.sources[2].setBottomLeft(QPoint(data.pixmapSizes[2].width() - data.targets[2].width(), data.targets[2].height() - 1));
       
   753             data.sources[3] = QRect(QPoint(0,0), data.pixmapSizes[3]);
       
   754             data.sources[4] = QRect(); // center is always empty
       
   755             data.sources[5] = QRect(QPoint(0,0), data.pixmapSizes[5]);
       
   756             data.sources[6] = QRect(QPoint(0,0), data.pixmapSizes[6]);
       
   757             data.sources[6].setTopRight(QPoint(data.targets[6].width() - 1, data.pixmapSizes[6].height() - data.targets[6].height()));
       
   758             data.sources[7] = QRect(QPoint(0,0), data.pixmapSizes[7]);
       
   759             data.sources[8] = QRect(QPoint(0,0), data.pixmapSizes[8]);
       
   760             data.sources[8].setTopLeft(QPoint(data.pixmapSizes[8].width() - data.targets[8].width(), data.pixmapSizes[8].height() - data.targets[8].height()));
       
   761         }
       
   762     }
       
   763 
       
   764 #ifdef HB_FRAME_DRAWER_TRACES
       
   765     qDebug() << "FRAMENAME: " << frameGraphicsName << "Size: " << fullWidth << ", " << fullHeight;
       
   766 #endif
       
   767 
       
   768     return QSize(fullWidth, fullHeight);
       
   769 }
       
   770 
       
   771 
       
   772 /*!
       
   773 \internal
       
   774 */
       
   775 void HbFrameDrawerPrivate::calculateShrinkedNinePieceCorners(
       
   776         HbMultiPartSizeData &data,
       
   777         const QSize& tlSize, const QSize& brSize,
       
   778         const QSize& fullSize, const QPoint& splitPoint)
       
   779 {
       
   780     // Make sure that corner sizes don't exceed frames full size
       
   781 
       
   782     // Top-left corner
       
   783     int topLeftWidth = splitPoint.x() ? splitPoint.x() : tlSize.width();
       
   784     int topLeftHeight = splitPoint.y() ? splitPoint.y() : tlSize.height();
       
   785     data.targets[0] = QRect(
       
   786         0,
       
   787         0,
       
   788         topLeftWidth < fullSize.width() ? topLeftWidth : fullSize.width(),
       
   789         topLeftHeight < fullSize.height() ? topLeftHeight : fullSize.height());
       
   790 
       
   791     // Top-right corner
       
   792     int topRightX = splitPoint.x() ? splitPoint.x() : fullSize.width() - brSize.width();
       
   793     int topRightWidth = splitPoint.x() ? fullSize.width() - splitPoint.x() : brSize.width();
       
   794     if (topRightWidth > fullSize.width()) {
       
   795         topRightWidth = fullSize.width();
       
   796         topRightX = 0;
       
   797     }
       
   798     int topRightHeight = splitPoint.y() ? splitPoint.y() : tlSize.height();
       
   799     if (topRightHeight > fullSize.height()) {
       
   800         topRightHeight = fullSize.height();
       
   801     }
       
   802     data.targets[2] = QRect(topRightX, 0, topRightWidth, topRightHeight);
       
   803 
       
   804     // Bottom-left corner
       
   805     int bottomLeftY = splitPoint.y() ? splitPoint.y() : fullSize.height() - brSize.height();
       
   806     int bottomLeftWidth = splitPoint.x() ? splitPoint.x() : tlSize.width();
       
   807     if (bottomLeftWidth > fullSize.width()) {
       
   808         bottomLeftWidth = fullSize.width();
       
   809     }
       
   810     int bottomLeftHeight = splitPoint.y() ? fullSize.height() - splitPoint.y() : brSize.height();
       
   811     if (bottomLeftHeight > fullSize.height()) {
       
   812         bottomLeftHeight = fullSize.height();
       
   813         bottomLeftY = 0;
       
   814     }
       
   815     data.targets[6] = QRect(0, bottomLeftY, bottomLeftWidth, bottomLeftHeight);
       
   816 
       
   817     // Bottom-right corner
       
   818     int bottomRightX = splitPoint.x() ? splitPoint.x() : fullSize.width() - brSize.width();
       
   819     int bottomRightY = splitPoint.y() ? splitPoint.y() : fullSize.height() - brSize.height();
       
   820     int bottomRightWidth = splitPoint.x() ? fullSize.width() - splitPoint.x() : brSize.width();
       
   821     if (bottomRightWidth > fullSize.width()) {
       
   822         bottomRightWidth = fullSize.width();
       
   823         bottomRightX = 0;
       
   824     }
       
   825     int bottomRightHeight = splitPoint.y() ? fullSize.height() - splitPoint.y() : brSize.height();
       
   826     if (bottomRightHeight > fullSize.height()) {
       
   827         bottomRightHeight = fullSize.height();
       
   828         bottomRightY = 0;
       
   829     }
       
   830     data.targets[8] = QRect( bottomRightX, bottomRightY, bottomRightWidth, bottomRightHeight);
       
   831 }
       
   832 
       
   833 /*!
       
   834 \internal
       
   835 */
       
   836 QSizeF HbFrameDrawerPrivate::defaultSize(const QString &framePartSuffix)
       
   837 {
       
   838     HbIconLoader *loader = HbIconLoader::global();
       
   839     return loader->defaultSize(frameGraphicsName + framePartSuffix).toSize();
       
   840 }
       
   841 
       
   842 bool HbFrameDrawerPrivate::isMirrored()
       
   843 {
       
   844     // If mirroring mode is default, check automatic mirroring from loader.
       
   845     if (mirroring == HbIcon::Default && defaultMirroring == Unknown) {
       
   846         HbIconLoader *loader = HbIconLoader::global();
       
   847         defaultMirroring = loader->isAutomaticallyMirrored(frameGraphicsName) ? Enabled : Disabled;
       
   848     }
       
   849 
       
   850     bool basedOnLayoutDir = false;
       
   851     // Handle the different mirroring modes
       
   852 
       
   853     // Default
       
   854     if (mirroring == HbIcon::Default) {
       
   855         if (defaultMirroring == Enabled) {
       
   856             basedOnLayoutDir = true;
       
   857         } else if (defaultMirroring == Disabled) {
       
   858             return false;
       
   859         }
       
   860     // Forced
       
   861     } else if (mirroring == HbIcon::Forced) {
       
   862         return true;
       
   863     // Prevented
       
   864     } else if (mirroring == HbIcon::Prevented) {
       
   865         return false;
       
   866     // LayoutDirection
       
   867     } else if (mirroring == HbIcon::LayoutDirection) {
       
   868         basedOnLayoutDir = true;
       
   869     }
       
   870 
       
   871     if (basedOnLayoutDir) {
       
   872         Qt::LayoutDirection usedDirection = Qt::LeftToRight; // default;
       
   873         if ( flags&HbFrameDrawerPrivate::LayoutDirectionSet ) {
       
   874             usedDirection = layoutDirection;
       
   875         } else {
       
   876 			usedDirection = QApplication::layoutDirection();
       
   877         }
       
   878 
       
   879         return usedDirection == Qt::LeftToRight ? false : true;
       
   880     }
       
   881 
       
   882 #ifdef HB_FRAME_DRAWER_TRACES
       
   883     qDebug() << "HbFrameDrawerPrivate, invalid mirroring mode";
       
   884 #endif
       
   885     return false;
       
   886 }
       
   887 
       
   888 /*!
       
   889 \internal
       
   890 */
       
   891 bool HbFrameDrawerPrivate::hasBorderWidths() const
       
   892 {
       
   893     return borderWidths[1] > 0
       
   894         || borderWidths[2] > 0
       
   895         || borderWidths[2] > 0
       
   896         || borderWidths[3] > 0;
       
   897 }
       
   898 
       
   899 /*!
       
   900 \internal
       
   901 */
       
   902 void HbFrameDrawerPrivate::reset( bool resetFrameCount )
       
   903 {
       
   904     unLoadIcon();
       
   905     if ( resetFrameCount ) {
       
   906         frameParts = 0;
       
   907     }
       
   908 }
       
   909 
       
   910 HbIconLoader::IconLoaderOptions HbFrameDrawerPrivate::iconLoaderOptions()
       
   911 {
       
   912     HbIconLoader::IconLoaderOptions options = DEFAULT_OPTIONS;
       
   913     if (flags & HbFrameDrawerPrivate::DoNotCache) {
       
   914         options |= HbIconLoader::DoNotCache;
       
   915     }
       
   916     if (isMirrored()) {
       
   917         options |= HbIconLoader::HorizontallyMirrored;
       
   918     }
       
   919     if (flags & HbFrameDrawerPrivate::ResolutionCorrected) {
       
   920         options |= HbIconLoader::ResolutionCorrected;
       
   921     }
       
   922     if (flags & HbFrameDrawerPrivate::NoAutoStartAnimation) {
       
   923         options |= HbIconLoader::NoAutoStartAnimation;
       
   924     }
       
   925     return options;
       
   926 }
       
   927 
       
   928 
       
   929 
       
   930 QString HbFrameDrawerPrivate::multiPartIconId() const
       
   931 {
       
   932     QString id;
       
   933     id = frameGraphicsName;
       
   934     if (type == HbFrameDrawer::ThreePiecesHorizontal) {
       
   935         id.append("_3PH");
       
   936     } else if (type == HbFrameDrawer::ThreePiecesVertical) {
       
   937         id.append("_3PV");
       
   938     } else if (type == HbFrameDrawer::NinePieces) {
       
   939         id.append("_9P");
       
   940     } else {
       
   941         id.append("_1P");
       
   942     }
       
   943 
       
   944     if (type != HbFrameDrawer::OnePiece) {
       
   945         if (fillWholeRect()) {
       
   946             id.append("_1");
       
   947         } else {
       
   948             id.append("_0");
       
   949         }
       
   950 
       
   951         for (int i = 0;i < 4; i++) { 
       
   952             QString boundary;
       
   953             id.append("_");
       
   954             id.append(boundary.setNum(borderWidths[i]));
       
   955         }
       
   956     }
       
   957 
       
   958     for (int i = 0; i < suffixList.count(); i++) {
       
   959         id.append( suffixList[i] );
       
   960     }
       
   961 
       
   962     return id;
       
   963 }
       
   964 
       
   965 void HbFrameDrawerPrivate::unLoadIcon()
       
   966 {
       
   967     HbIconLoader *loader = HbIconLoader::global();
       
   968     if (icon) {
       
   969         //If a consolidated (stitched) icon was created on the themeserver, then
       
   970         //HbIconLoader::unloadIcon() is used to unload it.
       
   971         loader->unLoadIcon(icon->iconImpl());
       
   972         icon->dispose();
       
   973         icon = 0;
       
   974     }
       
   975 
       
   976     // get a vector of QVector<HbIconImpl*> from QVector<HbMaskableIconImpl*> for unloading.
       
   977     QVector<HbIconImpl *> fallbackIconList;
       
   978     int count = fallbackMaskableIconList.count();
       
   979     for (int i = 0; i < count ; i++) {
       
   980         if (fallbackMaskableIconList[i]) {
       
   981             fallbackIconList.append(fallbackMaskableIconList[i]->iconImpl());
       
   982         }
       
   983     }
       
   984     count = fallbackIconList.count();
       
   985     if (count > 0) {
       
   986         //If a consolidated (stitched) icon-creation on themeserver fails, unload-request for all individual
       
   987         //frame-items are batched together in a single IPC, which is initiated in HbIconLoader::unLoadMultiIcon().
       
   988         loader->unLoadMultiIcon(fallbackIconList);
       
   989         for (int i=0; i < count ; i++) {
       
   990             if (fallbackMaskableIconList[i]) {
       
   991                 fallbackMaskableIconList[i]->dispose();
       
   992             }
       
   993         }
       
   994      }
       
   995     fallbackIconList.clear();  // vector of HbIconImpl*
       
   996     fallbackMaskableIconList.clear(); // vector of HbMaskableIconImpl*
       
   997 }
       
   998 
       
   999 /*! Constructs a new frame drawer item with the cacheFlag enabled  by default.
       
  1000 */
       
  1001 HbFrameDrawer::HbFrameDrawer(bool cacheFlag)
       
  1002 {
       
  1003     d = new HbFrameDrawerPrivate();
       
  1004     if ( !cacheFlag ) {
       
  1005         d->flags &= HbFrameDrawerPrivate::DoNotCache;  
       
  1006     }
       
  1007 }
       
  1008 
       
  1009 /*! Constructs a new frame drawer with the given \a frameGraphicsName and \a type  and cacheFlag is enabled.
       
  1010 */
       
  1011 HbFrameDrawer::HbFrameDrawer(const QString &frameGraphicsName, FrameType type, bool cacheFlag)
       
  1012 {
       
  1013     d = new HbFrameDrawerPrivate(frameGraphicsName, type);
       
  1014     if ( !cacheFlag ) {
       
  1015         d->flags &= HbFrameDrawerPrivate::DoNotCache;
       
  1016     }  
       
  1017 }
       
  1018 
       
  1019 /*!
       
  1020 * Copy constructs a new frame drawer using the \a other frame drawer.
       
  1021 * This is very fast.
       
  1022 * Copy-on-write semantics is used, so this only does a shallow copy. 
       
  1023 */
       
  1024 HbFrameDrawer::HbFrameDrawer(const HbFrameDrawer &other) :
       
  1025     d(other.d)
       
  1026 {
       
  1027 }
       
  1028 
       
  1029 /*!
       
  1030 * Assigns the \a other frame drawer to this frame drawer and returns a reference to
       
  1031 * this frame drawer. Copy-on-write semantics is used, so this only does a shallow copy. 
       
  1032 */
       
  1033 HbFrameDrawer &HbFrameDrawer::operator=(const HbFrameDrawer &other)
       
  1034 {
       
  1035     if (&other != this) {
       
  1036         d = other.d;
       
  1037     }
       
  1038     return *this;
       
  1039 }
       
  1040 
       
  1041 /*!
       
  1042 * Destroys the frame drawer.
       
  1043 */
       
  1044 HbFrameDrawer::~HbFrameDrawer()
       
  1045 {
       
  1046     delete d;
       
  1047 }
       
  1048 
       
  1049 /*!
       
  1050 * Returns true if the frame drawer has been constructed with the default constructor
       
  1051 * and the frame graphics name has not been set.
       
  1052 * \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.
       
  1053 */
       
  1054 bool HbFrameDrawer::isNull() const
       
  1055 {
       
  1056     return d->frameGraphicsName.isNull();
       
  1057 }
       
  1058 
       
  1059 /*!
       
  1060 * Returns the frame graphics name.
       
  1061 * \sa HbFrameDrawer::setFrameGraphicsName()
       
  1062 */
       
  1063 QString HbFrameDrawer::frameGraphicsName() const
       
  1064 {
       
  1065     return d->frameGraphicsName;
       
  1066 }
       
  1067 
       
  1068 /*!
       
  1069 * Sets the frame graphics name. See the class description for the file name convention for different frame parts.
       
  1070 * \sa HbFrameDrawer::frameGraphicsName()
       
  1071 */
       
  1072 void HbFrameDrawer::setFrameGraphicsName(const QString &frameGraphicsName)
       
  1073 {
       
  1074     // Remove possible file extension
       
  1075     QString nameWithoutExt = frameGraphicsName;
       
  1076     int index = nameWithoutExt.lastIndexOf(QChar('.'));
       
  1077     if (index>0) {
       
  1078         nameWithoutExt.resize(index);
       
  1079     }
       
  1080 
       
  1081     if (d->frameGraphicsName != nameWithoutExt) {
       
  1082         d->frameGraphicsName = nameWithoutExt;
       
  1083         // Frame graphics changed, clear frame icon
       
  1084         d->reset();
       
  1085         // Frame graphics changed, clear default frame mirroring information based on the automatic mirroring list
       
  1086         d->defaultMirroring = HbFrameDrawerPrivate::Unknown;
       
  1087 
       
  1088         // if graphicsItem is set, request redraw
       
  1089         if ( d->graphicsItem ) {
       
  1090             d->graphicsItem->update();
       
  1091         }
       
  1092     }
       
  1093 }
       
  1094 
       
  1095 /*!
       
  1096 * Returns the frame type.
       
  1097 * \sa HbFrameDrawer::setFrameType()
       
  1098 */
       
  1099 HbFrameDrawer::FrameType HbFrameDrawer::frameType() const
       
  1100 {
       
  1101     return d->type;
       
  1102 }
       
  1103 
       
  1104 /*!
       
  1105 * Sets the frame type.
       
  1106 * \sa HbFrameDrawer::frameType()
       
  1107 */
       
  1108 void HbFrameDrawer::setFrameType(HbFrameDrawer::FrameType type)
       
  1109 {
       
  1110     if (d->type != type) {
       
  1111         d->type = type;
       
  1112         // Frame type changed, clear frame icon
       
  1113         d->reset();
       
  1114     }
       
  1115 }
       
  1116 
       
  1117 /*!
       
  1118 * Returns the border width values. If the border widths has not been set by calling setBorderWidths(),
       
  1119 * this method returns zero for all values.
       
  1120 *
       
  1121 * \sa HbFrameDrawer::setBorderWidths()
       
  1122 */
       
  1123 void HbFrameDrawer::borderWidths(qreal &left, qreal &top, qreal &right, qreal &bottom) const
       
  1124 {
       
  1125     left = d->borderWidths[0];
       
  1126     top = d->borderWidths[1];
       
  1127     right = d->borderWidths[2];
       
  1128     bottom = d->borderWidths[3];
       
  1129 }
       
  1130 
       
  1131 /*!
       
  1132 * Sets the frame border widths ("frame thickness") explicitly for the 3 or 9 parts of the frame.
       
  1133 *
       
  1134 * \note If this method is not called, the bounding rectangle of the frame is divided as follows.
       
  1135 *
       
  1136 * Frame type \b ThreePiecesHorizontal:
       
  1137 *
       
  1138 * - Left part width = (default size of the left part graphics scaled to the bounding rectangle).width
       
  1139 * - Right part width = (default size of the right part graphics scaled to the bounding rectangle).width
       
  1140 * - Center part width = remaining width
       
  1141 * 
       
  1142 * Frame type \b ThreePiecesVertical:
       
  1143 *
       
  1144 * - Top part height = (default size of the top part graphics scaled to the bounding rectangle).height
       
  1145 * - Bottom part height = (default size of the bottom part graphics scaled to the bounding rectangle).height
       
  1146 * - Center part height = remaining height
       
  1147 *
       
  1148 * Frame type \b NinePieces:
       
  1149 *
       
  1150 * - Default sizes of the top left and bottom right part graphics are used.
       
  1151 * - Other sizes are calculated from them and the bounding rectangle.
       
  1152 *
       
  1153 * \sa HbFrameDrawer::borderWidths()
       
  1154 */
       
  1155 void HbFrameDrawer::setBorderWidths(const qreal left, const qreal top, const qreal right, const qreal bottom)
       
  1156 {
       
  1157 	d->setBorderApiProtectionFlag(true);
       
  1158     if ( left != d->borderWidths[0] || top != d->borderWidths[1] ||
       
  1159          right != d->borderWidths[2] || bottom != d->borderWidths[3] ) {
       
  1160         // Negative values are converted to zero.
       
  1161         d->borderWidths[0] = qMax((qreal)0.0, left);
       
  1162         d->borderWidths[1] = qMax((qreal)0.0, top);
       
  1163         d->borderWidths[2] = qMax((qreal)0.0, right);
       
  1164         d->borderWidths[3] = qMax((qreal)0.0, bottom);
       
  1165         // borderWidths changed, clear frame icon
       
  1166         d->reset( false );
       
  1167     }
       
  1168 }
       
  1169 
       
  1170 /*!
       
  1171 * This is a convenience method. Equals to:
       
  1172 *
       
  1173 * setBorderWidths( horizontal, vertical, horizontal, vertical );
       
  1174 *
       
  1175 * \sa HbFrameDrawer::borderWidths()
       
  1176 */
       
  1177 void HbFrameDrawer::setBorderWidths(const qreal horizontal, const qreal vertical)
       
  1178 {
       
  1179     setBorderWidths( horizontal, vertical, horizontal, vertical );
       
  1180 }
       
  1181 
       
  1182 /*!
       
  1183 * This is a convenience method. Equals to:
       
  1184 *
       
  1185 * setBorderWidths( width, width, width, width );
       
  1186 *
       
  1187 * \sa HbFrameDrawer::borderWidths()
       
  1188 */
       
  1189 void HbFrameDrawer::setBorderWidth(const qreal width)
       
  1190 {
       
  1191     setBorderWidths( width, width, width, width );
       
  1192 }
       
  1193 
       
  1194 
       
  1195 /*!
       
  1196 * Returns the bounding rectangle of the frame.
       
  1197 * \sa HbFrameDrawer::setRect()
       
  1198 */
       
  1199 QRectF HbFrameDrawer::rect() const
       
  1200 {
       
  1201     return d->rect;
       
  1202 }
       
  1203 
       
  1204 /*!
       
  1205 * Sets the bounding rectangle for the frame.
       
  1206 * \sa HbFrameDrawer::rect()
       
  1207 */
       
  1208 void HbFrameDrawer::setRect(const QRectF &rect)
       
  1209 {
       
  1210     if (rect != d->rect) {
       
  1211         d->rect = rect;
       
  1212         // Rect changed, clear frame icon
       
  1213         d->reset( false );
       
  1214     }
       
  1215 }
       
  1216 
       
  1217 /*!
       
  1218 * Paints the frame with the given \a painter.
       
  1219 */
       
  1220 void HbFrameDrawer::paint(QPainter *painter, const QRectF &rect) const
       
  1221 {
       
  1222     const_cast<HbFrameDrawer*>(this)->setRect( rect );
       
  1223 
       
  1224     if (d->frameGraphicsName.isEmpty() || d->type == HbFrameDrawer::Undefined || d->rect.isEmpty()) {
       
  1225         return;
       
  1226     }
       
  1227 
       
  1228     // Lazy graphics rasterizing is used.
       
  1229     // Rasterize the frame parts now if that has not been done yet.
       
  1230     if (d->icon && (rect.toRect().size() !=  d->prevRect.size())) {
       
  1231         d->reset(); 
       
  1232     } 
       
  1233     d->prepareFrameIcon();
       
  1234     d->prevRect = rect.toRect();
       
  1235     // Paint the frame
       
  1236     d->paint(painter);
       
  1237 }
       
  1238 
       
  1239 /*!
       
  1240 * Returns whether the whole bounding rectangle is always filled by the frame graphics.
       
  1241 * By default, this property is false and in that case, the 3-piece horizontal frame height
       
  1242 * and 3-piece vertical frame width are defined by the default sizes of the frame part graphics.
       
  1243 * If the whole bounding rectangle is not filled, the frame area is centered
       
  1244 * in the bounding rectangle.
       
  1245 *
       
  1246 * \note 9-piece frames always fill the whole bounding rectangle.
       
  1247 *
       
  1248 * \sa HbFrameDrawer::setFillWholeRect()
       
  1249 */
       
  1250 bool HbFrameDrawer::fillWholeRect() const
       
  1251 {
       
  1252     return d->fillWholeRect();
       
  1253 }
       
  1254 
       
  1255 /*!
       
  1256 * Sets the property whether the whole bounding rectangle is always filled by the frame graphics.
       
  1257 * By default, this property is false and in that case, the 3-piece horizontal frame height
       
  1258 * and 3-piece vertical frame width are defined by the default sizes of the frame part graphics.
       
  1259 * If the whole bounding rectangle is not filled, the frame area is centered
       
  1260 * in the bounding rectangle.
       
  1261 *
       
  1262 * \note 9-piece frames always fill the whole bounding rectangle.
       
  1263 *
       
  1264 * \sa HbFrameDrawer::fillWholeRect()
       
  1265 */
       
  1266 void HbFrameDrawer::setFillWholeRect(bool fill)
       
  1267 {
       
  1268     if ( (fill && !d->fillWholeRect()) || (!fill && d->fillWholeRect()) ) {
       
  1269         if ( fill ) {
       
  1270             d->flags |= HbFrameDrawerPrivate::FillWholeRect;
       
  1271         } else {
       
  1272             d->flags &= ~HbFrameDrawerPrivate::FillWholeRect;
       
  1273         }
       
  1274 
       
  1275         // Fill mode changed, clear frame Icon
       
  1276         d->reset( false );
       
  1277     }
       
  1278 }
       
  1279 
       
  1280 /*! Returns the mirroring mode set for the frame drawer.
       
  1281 * \sa HbFrameDrawer::setMirroringMode()
       
  1282 */
       
  1283 HbIcon::MirroringMode HbFrameDrawer::mirroringMode() const
       
  1284 {
       
  1285     return d->mirroring;
       
  1286 }
       
  1287 
       
  1288 /*! Sets the mirroring \a mode for the frame drawer.
       
  1289 * \sa HbFrameDrawer::mirroringMode()
       
  1290 */
       
  1291 void HbFrameDrawer::setMirroringMode(HbIcon::MirroringMode mode)
       
  1292 {
       
  1293     if (mode != d->mirroring) {
       
  1294         d->mirroring = mode;
       
  1295         // Mirroring changed, clear frame Icon
       
  1296         d->reset( false );
       
  1297     }
       
  1298 }
       
  1299 
       
  1300 /*! Returns the filename suffix list.
       
  1301 * See the class level documentation for how frame part filenames are determined
       
  1302 * using the these filename suffixes. If the suffix list has been set explicitly with
       
  1303 * method HbFrameDrawer::setFileNameSuffixList, that list is returned.
       
  1304 * Otherwise, a list of default suffixes (see class level documentation) is returned.
       
  1305 *
       
  1306 * \note If the explicitly given suffix list does not have enough entries for the
       
  1307 * defined frame type, the default suffix list is returned.
       
  1308 *
       
  1309 * \sa HbFrameDrawer::setFileNameSuffixList()
       
  1310 */
       
  1311 QStringList HbFrameDrawer::fileNameSuffixList() const
       
  1312 {
       
  1313     return d->fileNameSuffixList();
       
  1314 }
       
  1315 
       
  1316 /*! Sets the filename suffix list.
       
  1317 * If the frame type is ThreePiecesHorizontal or ThreePiecesVertical, the list must contain three entries.
       
  1318 * If the frame type is NinePieces, the list must contain nine entries.
       
  1319 * The order of the list entries is the following.
       
  1320 *
       
  1321 * Frame type \b ThreePiecesHorizontal:
       
  1322 *
       
  1323 * - [0] left
       
  1324 * - [1] center
       
  1325 * - [2] right
       
  1326 *
       
  1327 * Frame type \b ThreePiecesVertical:
       
  1328 *
       
  1329 * - [0] top
       
  1330 * - [1] center
       
  1331 * - [2] bottom
       
  1332 *
       
  1333 * Frame type \b NinePieces:
       
  1334 *
       
  1335 * - [0] top left
       
  1336 * - [1] top
       
  1337 * - [2] top right
       
  1338 * - [3] left
       
  1339 * - [4] center
       
  1340 * - [5] right
       
  1341 * - [6] bottom left
       
  1342 * - [7] bottom
       
  1343 * - [8] bottom right
       
  1344 *
       
  1345 * Example:
       
  1346 *
       
  1347 * A three piece frame has the following frame part filenames:
       
  1348 * ":/myapp/frame_a.svg", ":/myapp/frame_b.svg", ":/myapp/frame_c.svg".
       
  1349 * The following code sets the frame graphics name and the filename suffixes.
       
  1350 *
       
  1351 * \dontinclude ultimatecodesnippet/ultimatecodesnippet.cpp
       
  1352 * \skip Start of snippet 20
       
  1353 * \until End of snippet 20
       
  1354 *
       
  1355 * \sa HbFrameDrawer::fileNameSuffixList()
       
  1356 */
       
  1357 void HbFrameDrawer::setFileNameSuffixList(const QStringList &list)
       
  1358 {
       
  1359     if (list != d->suffixList) {
       
  1360         d->suffixList = list;
       
  1361         // Frame part filename suffix list changed, clear frame parts count info and generated frame icon.
       
  1362         d->reset();
       
  1363     }
       
  1364 }
       
  1365 
       
  1366 /*! 
       
  1367 * Sets the mask to be applied with the the entire frame icon.
       
  1368 * If the mask is also a frame item, use another frame drawer to draw it.
       
  1369 * Mask should be of the same size as returned by frameSize().
       
  1370 * To unset the mask, set it to a null pixmap.
       
  1371 * 
       
  1372 * \warning Currently this method makes use of pixmap() routine in case of NVG icons. 
       
  1373 * pixmap() slows down the hardware accelerated rendering.
       
  1374 * \sa frameSize(), mask()
       
  1375 */
       
  1376 void HbFrameDrawer::setMask(const QPixmap &mask)
       
  1377 {
       
  1378     d->mask = mask;
       
  1379     d->maskChanged = true;
       
  1380 }
       
  1381 
       
  1382 /*! 
       
  1383 * Sets the mask to be applied with the the entire frame icon.
       
  1384 * If the mask is also a frame item, use another frame drawer to draw it.
       
  1385 * Mask should be of the same size as returned by frameSize().
       
  1386 * To unset the mask, set it to a null bitmap.
       
  1387 *
       
  1388  \warning Currently this method makes use of pixmap() routine in case of NVG icons. 
       
  1389 * pixmap() slows down the hardware accelerated rendering.
       
  1390 *
       
  1391 *\sa frameSize(), mask()
       
  1392 */
       
  1393 void HbFrameDrawer::setMask(const QBitmap &mask)
       
  1394 {
       
  1395     d->mask = mask;
       
  1396     d->maskChanged = true;
       
  1397 }
       
  1398 
       
  1399 /*!
       
  1400 * Returns the mask set on the frame drawer.
       
  1401 * As default, returns a null pixmap.
       
  1402 * \sa setMask()
       
  1403 */
       
  1404 
       
  1405 QPixmap HbFrameDrawer::mask() const
       
  1406 {
       
  1407     return d->mask;
       
  1408 }
       
  1409 
       
  1410 
       
  1411 /*!
       
  1412 * Returns the mask set on the frame drawer.
       
  1413 * As default, returns a null bitmap.
       
  1414 * \sa setMask()
       
  1415 */
       
  1416 QBitmap HbFrameDrawer::maskBitmap() const
       
  1417 {
       
  1418     return d->mask;
       
  1419 }
       
  1420 /*!
       
  1421  * Returns the size of the entire frame icon. 
       
  1422  * Use this method to retrieve the correct size for a mask pixmap that can be set with method setMask().
       
  1423  * If the frame graphics name, bounding rectangle or frame type have not been set, this method returns
       
  1424  * an empty size.
       
  1425  */
       
  1426 QSize HbFrameDrawer::frameSize() const
       
  1427 {
       
  1428     if (d->frameGraphicsName.isEmpty() || d->type == HbFrameDrawer::Undefined || d->rect.isEmpty()) {
       
  1429         return QSize(0, 0);
       
  1430     }
       
  1431 
       
  1432     d->prepareFrameIcon();
       
  1433 
       
  1434     if (d->icon) {
       
  1435         return d->icon->keySize().toSize();
       
  1436     } else if (d->fallbackMaskableIconList.count()) {
       
  1437         QSize sz;
       
  1438         for (int i = 0, ie = d->fallbackMaskableIconList.count(); i != ie; ++i) {
       
  1439             if (d->fallbackMaskableIconList[i]) {
       
  1440                 sz += d->multiPartSizeData.targets[i].size();
       
  1441             }
       
  1442         }
       
  1443         return sz;
       
  1444     }
       
  1445 
       
  1446     return QSize(0, 0);
       
  1447 }
       
  1448 
       
  1449 /*!
       
  1450 * This function should be called when the theme changes. This clears the used frame
       
  1451 * graphic.
       
  1452 */
       
  1453 void HbFrameDrawer::themeChanged()
       
  1454 {
       
  1455     d->reset();
       
  1456 }
       
  1457 
       
  1458 /*!
       
  1459 * Sets the layout direction of the frame drawer.
       
  1460 *
       
  1461 * Valid only when the mirroring mode is HbIcon::LayoutDirection.
       
  1462 */
       
  1463 void HbFrameDrawer::setLayoutDirection( Qt::LayoutDirection direction )
       
  1464 {
       
  1465     d->flags |= HbFrameDrawerPrivate::LayoutDirectionSet;
       
  1466 
       
  1467     if ( d->layoutDirection != direction ) {
       
  1468         d->layoutDirection = direction;
       
  1469         
       
  1470         if ( ( d->mirroring == HbIcon::Default 
       
  1471                && d->defaultMirroring == HbFrameDrawerPrivate::Enabled ) ||
       
  1472             d->mirroring == HbIcon::LayoutDirection) {
       
  1473 
       
  1474             d->reset( false );
       
  1475         }
       
  1476     }
       
  1477 }
       
  1478 
       
  1479 /*!
       
  1480 * Sets the \a item which is needs to be redrawn when the frame drawer
       
  1481 * needs re-paint. 
       
  1482 */
       
  1483 void HbFrameDrawer::setGraphicsItem( QGraphicsItem *item )
       
  1484 {
       
  1485     d->graphicsItem = item;
       
  1486 }
       
  1487 
       
  1488 
       
  1489 // End of File