EXPORT_C TBool AknsDrawUtils::DrawFramePart( MAknsSkinInstance* aInstance,
    CWindowGc& aGc, const TRect& aRect, const TAknsItemID& aFrameID,
    const TAknsFrameElementIndex aFrameElement )
    {
    if( !aInstance )
        {
        return EFalse;
        }

    CAknsImageTableItemData* data = static_cast<CAknsImageTableItemData*>(
        aInstance->GetCachedItemData( aFrameID, EAknsITImageTable ) );
    if( data && (data->NumberOfImages()==EAknsFrameElementsN) )
        {
        aGc.SetPenStyle(CGraphicsContext::ENullPen);
        aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);

        TBool retVal = CheckAndDrawCachedImage( aInstance, aGc, aRect,
            data->ImageIID( aFrameElement ), KAknsDrawParamDefault );

        aGc.SetPenStyle(CGraphicsContext::ESolidPen);
        aGc.SetBrushStyle(CGraphicsContext::ENullBrush);

        return retVal;
        }

    return EFalse;
    }
// -----------------------------------------------------------------------------
// CTestSDKSkins::TestITIDSetImagesL
// -----------------------------------------------------------------------------
TInt CTestSDKSkins::TestITIDSetImagesL( CStifItemParser& /*aItem*/ )
    {
    CAknsImageTableItemData* itemData = CAknsImageTableItemData::NewL();
    CleanupStack::PushL( itemData );
    STIF_ASSERT_NOT_NULL( itemData );

    TAknsItemID itemID;
    itemData->SetImagesL( 1, &itemID );
    
    CleanupStack::PopAndDestroy( itemData );
    
    return KErrNone;
    
    }
// -----------------------------------------------------------------------------
// AknsUtils::SelectBestAppIconBitmapL
// -----------------------------------------------------------------------------
//
TAknsItemID AknsUtils::SelectBestAppIconBitmapL(
    const TSize& aSize,
    MAknsSkinInstance* aSkin,
    const TAknsItemID& aAppIconIID )
    {
    TAknsItemID iid;
    iid.Set( KAknsIIDNone );
    TInt i;

    CAknsImageTableItemData* iconData = static_cast<CAknsImageTableItemData*>(
        aSkin->CreateUncachedItemDataL( aAppIconIID, EAknsITImageTable ) );
    if( !iconData )
        {
        User::Leave( KErrNotFound );
        }

    CleanupStack::PushL( iconData );

    TInt numberOfIcons = iconData->NumberOfImages();
    RArray<TSize> sizeArray;
    for( i=0; i<numberOfIcons; i++ )
        {
        TBool defOwned = EFalse;
        CAknsImageItemDef* def =
            static_cast<CAknsImageItemDef*>(
            static_cast<CAknsAppSkinInstance*>(aSkin)->LookupDef(
            defOwned, iconData->ImageIID(i), EAknsITImage ) );

        TBool appendError = EFalse;

        if( def && def->Attributes() )
            {
            TSize imageSize = def->Attributes()->iSize;
            if( sizeArray.Append( imageSize ) != KErrNone )
                {
                appendError = ETrue;
                }
            }
        else
            {
            appendError = ETrue;
            }

        if( defOwned )
            {
            delete def;
            def = NULL;
            }

        if( appendError )
            {
            sizeArray.Reset();
            User::Leave( KErrGeneral );
            }
        }

    CleanupStack::Pop( iconData );

    // First check for zero size (SVG) or the exact match
    TInt indexFound = -1;
    for( i=0; i<numberOfIcons; i++ )
        {
        if( (sizeArray[i].iWidth==aSize.iWidth) &&
            (sizeArray[i].iHeight==aSize.iHeight) )
            {
            AKNS_TRACE_INFO2("AknsUtils::SBAIB Found (exact) MBM appicon for %x %x", aAppIconIID.iMinor, aAppIconIID.iMajor );
            indexFound = i;
            // Do not break, (0,0) might still be there
            }
        else if( (sizeArray[i].iWidth==0) &&
            (sizeArray[i].iHeight==0) )
            {
            AKNS_TRACE_INFO2("AknsUtils::SBAIB Using SVG appicon for %x %x", aAppIconIID.iMinor, aAppIconIID.iMajor );
            indexFound = i;
            break;
            }
        }

    if( indexFound>-1 )
        {
        iid.Set( iconData->ImageIID( indexFound ) );
        sizeArray.Reset();
        delete iconData;
        return iid;
        }

    // Then the largest of smaller or (in terms of one dimension) equal icons
    TInt bestDSum = 0;
    TInt dSum;
    for( i=0; i<numberOfIcons; i++ )
        {
        if( (sizeArray[i].iWidth<=aSize.iWidth) &&
            (sizeArray[i].iHeight<=aSize.iHeight) )
            {
            dSum = sizeArray[i].iWidth + sizeArray[i].iHeight;
            if( dSum > bestDSum )
                {
                indexFound = i;
                bestDSum = dSum;
                }
            }
        }

    if( indexFound>-1 )
        {
        iid.Set( iconData->ImageIID( indexFound ) );
        sizeArray.Reset();
        delete iconData;
        return iid;
        }

    // Finally, the smallest absolute difference
    bestDSum = KMaxTInt;
    for( i=0; i<numberOfIcons; i++ )
        {
        dSum = ( sizeArray[i].iWidth * sizeArray[i].iHeight ) -
            (aSize.iWidth*aSize.iHeight);
        if( dSum < 0 )
            {
            dSum = 0-dSum;
            }
        if( dSum < bestDSum )
            {
            indexFound = i;
            bestDSum = dSum;
            }
        }

    if( indexFound>-1 )
        {
        iid.Set( iconData->ImageIID( indexFound ) );
        }

    sizeArray.Reset();
    delete iconData;

    if( indexFound<0 )
        {
        User::Leave( KErrNotFound );
        }

    return iid;
    }
// -----------------------------------------------------------------------------
// CheckAndDrawFrame
//
// -----------------------------------------------------------------------------
//
static TBool CheckAndDrawFrame( MAknsSkinInstance* aInstance,
    CBitmapContext& aGc, const TRect& aOuterRect, const TRect& aInnerRect,
    const TAknsItemID& aFrameID, const TAknsItemID& aCenterID,
    const TInt aDrawParam )
    {
    if( !aInstance )
        {
        return EFalse;
        }
    
    if( !(aDrawParam & KAknsDrawParamPrepareOnly) )
        {
        // Prepare before drawing
        CheckAndDrawFrame( aInstance, aGc, aOuterRect, aInnerRect,
            aFrameID, aCenterID, aDrawParam|KAknsDrawParamPrepareOnly );
        }

    CAknsImageItemData* rawData = static_cast<CAknsImageItemData*>(
        aInstance->GetCachedItemData( aFrameID, EAknsITImage ) );
    if( !rawData )
        {
        return EFalse;
        }

    if (!(aDrawParam & KAknsDrawParamPrepareOnly))
        {
        aGc.SetPenStyle(CGraphicsContext::ENullPen);
        aGc.SetBrushStyle(CGraphicsContext::ENullBrush);
        }

    TBool retVal = EFalse;

    if( AknsUtils::IsDerivedType( EAknsITImageTable, rawData->Type() ) )
        {
        CAknsImageTableItemData* data =
            static_cast<CAknsImageTableItemData*>(rawData);
        if( data->NumberOfImages() != EAknsFrameElementsN )
            {
            return EFalse;
            }

        // Corners
        retVal |= CheckAndDrawCachedImage( aInstance, aGc,
            TRect( aOuterRect.iTl, aInnerRect.iTl ),
            data->ImageIID( EAknsFrameIndexTl ), aDrawParam );
        retVal |= CheckAndDrawCachedImage( aInstance, aGc,
            TRect( aInnerRect.iBr.iX, aOuterRect.iTl.iY,
            aOuterRect.iBr.iX, aInnerRect.iTl.iY ),
            data->ImageIID( EAknsFrameIndexTr ), aDrawParam );
        retVal |= CheckAndDrawCachedImage( aInstance, aGc,
            TRect( aOuterRect.iTl.iX, aInnerRect.iBr.iY,
            aInnerRect.iTl.iX, aOuterRect.iBr.iY ),
            data->ImageIID( EAknsFrameIndexBl ), aDrawParam );
        retVal |= CheckAndDrawCachedImage( aInstance, aGc,
            TRect( aInnerRect.iBr, aOuterRect.iBr ),
            data->ImageIID( EAknsFrameIndexBr ), aDrawParam );

        // Sides
        TRect sideRect( aInnerRect.iTl.iX, aOuterRect.iTl.iY,
            aInnerRect.iBr.iX, aInnerRect.iTl.iY );
        retVal |= CheckAndDrawCachedImage( aInstance, aGc, sideRect,
            data->ImageIID( EAknsFrameIndexT ), aDrawParam );
        sideRect.SetRect( aInnerRect.iTl.iX, aInnerRect.iBr.iY,
            aInnerRect.iBr.iX, aOuterRect.iBr.iY );
        retVal |= CheckAndDrawCachedImage( aInstance, aGc, sideRect,
            data->ImageIID( EAknsFrameIndexB ), aDrawParam );
        sideRect.SetRect( aOuterRect.iTl.iX, aInnerRect.iTl.iY,
            aInnerRect.iTl.iX, aInnerRect.iBr.iY );
        retVal |= CheckAndDrawCachedImage( aInstance, aGc, sideRect,
            data->ImageIID( EAknsFrameIndexL ), aDrawParam );
        sideRect.SetRect( aInnerRect.iBr.iX, aInnerRect.iTl.iY,
            aOuterRect.iBr.iX, aInnerRect.iBr.iY );
        retVal |= CheckAndDrawCachedImage( aInstance, aGc, sideRect,
            data->ImageIID( EAknsFrameIndexR ), aDrawParam );

        // Center
        //lint --e{961} Valid logic
        if( aCenterID == KAknsIIDDefault )
            {
            retVal |= CheckAndDrawCachedImage( aInstance, aGc, aInnerRect,
                data->ImageIID( EAknsFrameIndexCenter ), aDrawParam );
            }
        else if( aCenterID != KAknsIIDNone )
            {
            retVal |= CheckAndDrawCachedImage( aInstance, aGc, aInnerRect,
                aCenterID, aDrawParam );
            }
        }
    else if( AknsUtils::IsDerivedType( EAknsITBitmap, rawData->Type() ) )
        {
        // Center only
        retVal |= CheckAndDrawCachedImage( aInstance, aGc, aOuterRect,
            aFrameID, aDrawParam );
        }

    if (!(aDrawParam & KAknsDrawParamPrepareOnly))
        {
        aGc.SetPenStyle(CGraphicsContext::ESolidPen); //lint !e961 Intentional
        aGc.SetBrushStyle(CGraphicsContext::ENullBrush);
        }
    return retVal;
    }