phoneuis/BubbleManager/Src/BMCallObjectUtils.cpp
branchRCL_3
changeset 62 5266b1f337bd
parent 0 5f000ab63145
equal deleted inserted replaced
61:41a7f70b3818 62:5266b1f337bd
       
     1 /*
       
     2 * Copyright (c) 2002-2006 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Utility methods for call object handling.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include    "BMCallObjectUtils.h"
       
    22 #include    "BMLayout2.h"
       
    23 #include    "BMUtils.h"
       
    24 #include    "BMPanic.h"
       
    25 #include    <AknUtils.h>
       
    26 #include    <AknBidiTextUtils.h>
       
    27 #include    <AknLayoutFont.h>
       
    28 
       
    29 // CONSTANTS
       
    30 const TReal KBMCallObjectScaleFactorMax = 1.0;
       
    31 _LIT( KSpaceChar, " " );
       
    32 
       
    33 
       
    34 // ============================ MEMBER FUNCTIONS ===============================
       
    35 
       
    36 // ---------------------------------------------------------------------------
       
    37 // BubbleCallObjectUtils::CreateBitmapL
       
    38 //
       
    39 // ---------------------------------------------------------------------------
       
    40 //    
       
    41 CFbsBitmap* BubbleCallObjectUtils::CreateBitmapL( 
       
    42     const CFbsBitmap* aBitmap, 
       
    43     const TSize& aTargetSize,
       
    44     TDisplayMode aDisplayMode,
       
    45     TTileMode aTileMode )
       
    46     {
       
    47     __ASSERT_ALWAYS( aBitmap, User::Leave( KErrArgument ) );
       
    48     
       
    49     // get scaling factor
       
    50     TReal scalingFactor = ScalingFactor( aBitmap->SizeInPixels(),
       
    51                                          aTargetSize,
       
    52                                          EFillTarget );
       
    53                                                   
       
    54     if ( scalingFactor > 1.0 ) // bitmap scaling not supported
       
    55         {
       
    56         // image smaller than target area is tiled
       
    57         return CreateTiledBitmapL( aBitmap, 
       
    58                                    aTargetSize, 
       
    59                                    aDisplayMode, 
       
    60                                    aTileMode );
       
    61         }
       
    62     else        
       
    63         {
       
    64         // image bigger than target area is clipped
       
    65         return CreateCroppedBitmapL( aBitmap,
       
    66                                      aTargetSize,
       
    67                                      aDisplayMode );    
       
    68         }
       
    69     }
       
    70 
       
    71 // ---------------------------------------------------------------------------
       
    72 // BubbleCallObjectUtils::CreateCroppedBitmapL
       
    73 //
       
    74 // ---------------------------------------------------------------------------
       
    75 //    
       
    76 CFbsBitmap* BubbleCallObjectUtils::CreateCroppedBitmapL( 
       
    77     const CFbsBitmap* aBitmap, 
       
    78     const TSize& aTargetSize,
       
    79     TDisplayMode aDisplayMode )
       
    80     {
       
    81     __ASSERT_ALWAYS( aBitmap, User::Leave( KErrArgument ) );
       
    82     
       
    83     // create bitmap
       
    84     CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
       
    85     CleanupStack::PushL( bitmap );
       
    86     
       
    87     // calculate cropping rectangle   
       
    88     TSize sourceBitmapSize( aBitmap->SizeInPixels() );
       
    89     TRect croppingRect( TPoint(0,0), sourceBitmapSize );
       
    90     
       
    91     TInt xDelta( sourceBitmapSize.iWidth - aTargetSize.iWidth );
       
    92     if ( xDelta < 0 )
       
    93         {
       
    94         // do not crop horizontally
       
    95         xDelta = 0;    
       
    96         }
       
    97     
       
    98     TInt yDelta( sourceBitmapSize.iHeight - aTargetSize.iHeight );
       
    99     if ( yDelta < 0 )
       
   100         {
       
   101         // do not crop vertically
       
   102         yDelta = 0;    
       
   103         }
       
   104         
       
   105     if ( xDelta == 0 && yDelta == 0 )
       
   106         {
       
   107         // cropping not required -> just duplicate
       
   108         User::LeaveIfError( bitmap->Duplicate( aBitmap->Handle() ) );
       
   109         CleanupStack::Pop( bitmap );
       
   110         return bitmap;                            
       
   111         }
       
   112     else
       
   113         {
       
   114         // shrink to cropping area
       
   115         croppingRect.Shrink( xDelta/2, yDelta/2 );        
       
   116         }
       
   117     
       
   118     
       
   119     // create bitmap to target size
       
   120     User::LeaveIfError( bitmap->Create( aTargetSize, 
       
   121                                         aDisplayMode ) );
       
   122     // crop
       
   123     CFbsBitmapDevice* bitmapDev = 
       
   124         CFbsBitmapDevice::NewL( bitmap );
       
   125     CleanupStack::PushL( bitmapDev );
       
   126     CFbsBitGc* bitmapCtx;
       
   127     User::LeaveIfError( bitmapDev->CreateContext( bitmapCtx ) );
       
   128     CleanupStack::PushL( bitmapCtx );                                               
       
   129     TRect targetRect( TPoint(0,0), aTargetSize );
       
   130     bitmapCtx->DrawBitmap( targetRect, aBitmap, croppingRect );    
       
   131     
       
   132     CleanupStack::PopAndDestroy( 2, bitmapDev );
       
   133     CleanupStack::Pop( bitmap );
       
   134     
       
   135     return bitmap;            
       
   136     }
       
   137 
       
   138 // ---------------------------------------------------------------------------
       
   139 // BubbleCallObjectUtils::CreateTiledBitmapL
       
   140 //
       
   141 // ---------------------------------------------------------------------------
       
   142 //    
       
   143 CFbsBitmap* BubbleCallObjectUtils::CreateTiledBitmapL( 
       
   144     const CFbsBitmap* aBitmap, 
       
   145     const TSize& aTargetSize,
       
   146     TDisplayMode aDisplayMode,
       
   147     TTileMode aTileMode )
       
   148     {
       
   149     __ASSERT_ALWAYS( aBitmap, User::Leave( KErrArgument ) );
       
   150     
       
   151     TSize sourceSize = aBitmap->SizeInPixels();
       
   152     TPoint offset(0,0);
       
   153     
       
   154     // calculate offset for brush origin
       
   155     
       
   156     // horizontal offset
       
   157     if ( aTargetSize.iWidth <= sourceSize.iWidth )
       
   158         {
       
   159         // wide image -> center horizontally
       
   160         offset.iX = ( sourceSize.iWidth - aTargetSize.iWidth ) / 2;    
       
   161         }
       
   162     else if ( ( aTileMode == ETileCenterRight ) ||
       
   163               ( aTileMode == ETileTopRight ) )
       
   164         {
       
   165         // begin tiling from right
       
   166         offset.iX = sourceSize.iWidth - ( aTargetSize.iWidth % 
       
   167                                           sourceSize.iWidth );    
       
   168         }
       
   169     
       
   170     // vertical offset
       
   171     if ( aTargetSize.iHeight <= sourceSize.iHeight )
       
   172         {
       
   173         // tall image -> center vertically 
       
   174         offset.iY = ( sourceSize.iHeight - aTargetSize.iHeight ) / 2;    
       
   175         }
       
   176     else if ( ( aTileMode == ETileCenterRight ) ||
       
   177               ( aTileMode == ETileCenterLeft ) )
       
   178         {
       
   179         // middle most tile is centered vertically
       
   180         TInt topMargin = ( aTargetSize.iHeight - sourceSize.iHeight ) / 2;
       
   181         if ( topMargin <= sourceSize.iHeight )
       
   182             {
       
   183             offset.iY = ( sourceSize.iHeight - topMargin );    
       
   184             }
       
   185         else
       
   186             {
       
   187             offset.iY = sourceSize.iHeight - ( topMargin % 
       
   188                                                sourceSize.iHeight );    
       
   189             }            
       
   190         }
       
   191 
       
   192     // create bitmap to target size
       
   193     CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
       
   194     CleanupStack::PushL( bitmap );
       
   195     User::LeaveIfError( bitmap->Create( aTargetSize, 
       
   196                                         aDisplayMode ) );            
       
   197     
       
   198     // create device and graphics context
       
   199     CFbsBitmapDevice* bitmapDev = CFbsBitmapDevice::NewL( bitmap );
       
   200     CleanupStack::PushL( bitmapDev );
       
   201     CFbsBitGc* bitmapCtx;
       
   202     User::LeaveIfError( bitmapDev->CreateContext( bitmapCtx ) );
       
   203     CleanupStack::PushL( bitmapCtx );         
       
   204     
       
   205     // do tiling by using patterned brush
       
   206     CFbsBitmap* pattern = new(ELeave) CFbsBitmap;
       
   207     CleanupStack::PushL( pattern );
       
   208     User::LeaveIfError( pattern->Duplicate( aBitmap->Handle() ) );
       
   209     
       
   210     TRect bitmapRect( TPoint(0,0), aTargetSize );
       
   211     bitmapCtx->SetPenStyle( CGraphicsContext::ENullPen ); 
       
   212     bitmapCtx->SetBrushStyle( CGraphicsContext::EPatternedBrush ); 
       
   213     bitmapCtx->UseBrushPattern( pattern );
       
   214     bitmapCtx->SetBrushOrigin( -offset );
       
   215     bitmapCtx->DrawRect( bitmapRect );
       
   216     bitmapCtx->DiscardBrushPattern();
       
   217     
       
   218     CleanupStack::PopAndDestroy( 3, bitmapDev );
       
   219     CleanupStack::Pop( bitmap ); 
       
   220     
       
   221     return bitmap;       
       
   222     }    
       
   223 
       
   224 // ---------------------------------------------------------------------------
       
   225 // BubbleCallObjectUtils::CreateImageBitmapsFromTextLC
       
   226 //
       
   227 // ---------------------------------------------------------------------------
       
   228 //    
       
   229 void BubbleCallObjectUtils::CreateImageBitmapsFromTextLC(
       
   230     const TDesC& aText,
       
   231     const TRect& aMainPaneRect, 
       
   232     const TSize& aSize,
       
   233     const TRgb&  aTextColor,
       
   234     TUint aAlpha,
       
   235     TDisplayMode aDisplayMode,
       
   236     CFbsBitmap*& aBitmap,
       
   237     CFbsBitmap*& aMask )
       
   238     {
       
   239     // create bitmap
       
   240     aBitmap= new(ELeave) CFbsBitmap;
       
   241     CleanupStack::PushL( aBitmap );
       
   242     User::LeaveIfError( aBitmap->Create( aSize, aDisplayMode ) );
       
   243     
       
   244     // create mask
       
   245     aMask = new(ELeave) CFbsBitmap;
       
   246     CleanupStack::PushL( aMask );
       
   247     User::LeaveIfError( aMask->Create( aSize, EGray256 ) );
       
   248 
       
   249     // create bitmap context
       
   250     CFbsBitmapDevice* bitmapDev = CFbsBitmapDevice::NewL( aBitmap );
       
   251     CleanupStack::PushL( bitmapDev );
       
   252     CFbsBitGc* bitmapGc;
       
   253     User::LeaveIfError( bitmapDev->CreateContext( bitmapGc ) ); 
       
   254     CleanupStack::PushL( bitmapGc );    
       
   255     
       
   256     // create mask context
       
   257     CFbsBitmapDevice* maskDev = CFbsBitmapDevice::NewL( aMask );
       
   258     CleanupStack::PushL( maskDev );
       
   259     CFbsBitGc* maskGc;
       
   260     User::LeaveIfError( maskDev->CreateContext( maskGc ) ); 
       
   261     CleanupStack::PushL( maskGc );
       
   262     
       
   263     // initialize bitmap
       
   264     bitmapGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   265     bitmapGc->SetPenStyle( CGraphicsContext::ENullPen );
       
   266     bitmapGc->SetBrushColor( KRgbWhite );
       
   267     bitmapGc->DrawRect( TRect( aSize ) );
       
   268     bitmapGc->SetPenStyle( CGraphicsContext::ESolidPen );
       
   269     bitmapGc->SetBrushStyle( CGraphicsContext::ENullBrush );
       
   270     // initialize mask
       
   271     maskGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   272     maskGc->SetPenStyle( CGraphicsContext::ENullPen );
       
   273     maskGc->SetBrushColor( KRgbBlack );
       
   274     maskGc->DrawRect( TRect( aSize ) );
       
   275     maskGc->SetPenStyle( CGraphicsContext::ESolidPen );
       
   276     maskGc->SetBrushStyle( CGraphicsContext::ENullBrush );
       
   277     
       
   278     // reserve text buffers
       
   279     TAknLayoutRect textPaneLayout;
       
   280     textPaneLayout.LayoutRect( aMainPaneRect,
       
   281                              BubbleLayout2::call2_cli_visual_text_pane() );
       
   282     TRect textPaneRect = textPaneLayout.Rect();                             
       
   283     
       
   284     TAknLayoutText textLayout;
       
   285     textLayout.LayoutText( textPaneRect, 
       
   286                            BubbleLayout2::call2_main_pane_text( 0 ) );
       
   287     const CFont* font = textLayout.Font();
       
   288     TInt lineWidth = textLayout.TextRect().Size().iWidth;
       
   289     TInt averageFontWidth( font->WidthZeroInPixels() );
       
   290     
       
   291     TInt maxCharsPerLine( lineWidth / averageFontWidth );
       
   292     maxCharsPerLine = maxCharsPerLine * 4; // to secure
       
   293     HBufC* logicalLineBuf = HBufC::NewL( maxCharsPerLine );
       
   294     CleanupStack::PushL( logicalLineBuf );
       
   295     HBufC* visualLineBuf = HBufC::NewL( maxCharsPerLine + 
       
   296                                         KAknBidiExtraSpacePerLine );
       
   297     CleanupStack::PushL( visualLineBuf );
       
   298     TPtr logicalLine( logicalLineBuf->Des() );
       
   299     TPtr visualLine( visualLineBuf->Des() );
       
   300     
       
   301     TRgb alphaColor( aAlpha, aAlpha, aAlpha );
       
   302     TInt currentRow = 0;
       
   303     TInt i = 0;
       
   304     TInt textLength = aText.Length();    
       
   305     const TInt numberOfRows = 
       
   306         BubbleLayout2::call2_cli_visual_text_number_of_rows();
       
   307     
       
   308     // shift gc origin
       
   309     TPoint offset( (aMainPaneRect.Size().iWidth - aSize.iWidth) / 2,
       
   310                    (aMainPaneRect.Size().iHeight - aSize.iHeight) / 2 );
       
   311     bitmapGc->SetOrigin( -offset );
       
   312     maskGc->SetOrigin( -offset );
       
   313     
       
   314     // render text
       
   315     while ( currentRow <= numberOfRows )
       
   316         {
       
   317         TAknLayoutText textLayout;
       
   318         textLayout.LayoutText( textPaneRect,
       
   319             BubbleLayout2::call2_main_pane_text( currentRow ) );
       
   320         
       
   321         TRect textRect = textLayout.TextRect();            
       
   322         if ( ( textRect.iBr.iY < offset.iY ) || 
       
   323              ( textRect.iTl.iY > ( offset.iY + aSize.iHeight ) ) )
       
   324             {
       
   325             // this line is outside the bitmap.
       
   326             currentRow++;
       
   327             continue;                
       
   328             }
       
   329         
       
   330         logicalLine.Zero();
       
   331         TBool clipped( EFalse );
       
   332         do // Find the clipping point
       
   333             {
       
   334             TChar c( aText[i] );
       
   335             if( logicalLine.Length() == maxCharsPerLine )
       
   336                 {
       
   337                 User::Leave( KErrOverflow );
       
   338                 }
       
   339             logicalLine.Append( c );
       
   340             i++;
       
   341             if ( i == textLength )
       
   342                 {
       
   343                 if( logicalLine.Length() == maxCharsPerLine )
       
   344                     {
       
   345                     User::Leave( KErrOverflow );
       
   346                     }
       
   347                 // start over to fill whole pane
       
   348                 i = 0;
       
   349                 logicalLine.Append( KSpaceChar );
       
   350                 }
       
   351             
       
   352             visualLine.Zero();
       
   353             clipped = AknBidiTextUtils::ConvertToVisualAndClip(
       
   354                 logicalLine,
       
   355                 visualLine,
       
   356                 *font,
       
   357                 lineWidth,
       
   358                 lineWidth,
       
   359                 AknBidiTextUtils::EImplicit,
       
   360                 0xFFFF );
       
   361                 
       
   362             } while ( !clipped );
       
   363         
       
   364         // Remove the last character that caused clipping
       
   365         if ( logicalLine.Length() )
       
   366             {
       
   367             logicalLine.SetLength( logicalLine.Length() - 1 );                
       
   368             }
       
   369         
       
   370         AknBidiTextUtils::ConvertToVisualAndClip(
       
   371             logicalLine,
       
   372             visualLine,
       
   373             *font,
       
   374             lineWidth,
       
   375             lineWidth,
       
   376             AknBidiTextUtils::EImplicit,
       
   377             0xFFFF );
       
   378         
       
   379         textLayout.DrawText( *bitmapGc, visualLine, EFalse, aTextColor );
       
   380         textLayout.DrawText( *maskGc, visualLine, EFalse, alphaColor );
       
   381         
       
   382         // clipped -> go back by one        
       
   383         i = i > 0 ? (i - 1) : (textLength-1);                    
       
   384         
       
   385         currentRow++;
       
   386         }
       
   387 
       
   388     CleanupStack::PopAndDestroy(6, bitmapDev);
       
   389     }
       
   390 
       
   391 // ---------------------------------------------------------------------------
       
   392 // BubbleCallObjectUtils::ScalingFactor
       
   393 //
       
   394 // ---------------------------------------------------------------------------
       
   395 //
       
   396 TReal BubbleCallObjectUtils::ScalingFactor( 
       
   397     const TSize& aSourceSize,
       
   398     const TSize& aTargetSize,
       
   399     TScaleMode aScaleMode )
       
   400     {
       
   401     if ( aTargetSize == TSize(0,0) || aSourceSize == TSize(0,0) )
       
   402         {
       
   403         return 0;    
       
   404         }
       
   405     
       
   406     // check aspect ratios
       
   407     TReal targetAspectRatio = (TReal) aTargetSize.iWidth / 
       
   408                               (TReal) aTargetSize.iHeight;
       
   409     TReal sourceAspectRatio = (TReal) aSourceSize.iWidth  / 
       
   410                               (TReal) aSourceSize.iHeight;
       
   411     TReal scaleFactor = 1.0; 
       
   412     
       
   413     
       
   414     if ( sourceAspectRatio == targetAspectRatio )
       
   415         {
       
   416         // aspect ratios are same.
       
   417         return (TReal) aTargetSize.iWidth / (TReal) aSourceSize.iWidth;
       
   418         }
       
   419     else if ( targetAspectRatio > sourceAspectRatio )
       
   420         {
       
   421         // target wide more screen than source.
       
   422         if ( aScaleMode == EFillTarget )
       
   423             {
       
   424             // width defines the scale
       
   425             scaleFactor = (TReal) aTargetSize.iWidth / 
       
   426                           (TReal) aSourceSize.iWidth;    
       
   427             }
       
   428         else // EMaximumFit
       
   429             {
       
   430             // height defines the scale
       
   431             scaleFactor = (TReal) aTargetSize.iHeight / 
       
   432                           (TReal) aSourceSize.iHeight;    
       
   433             }            
       
   434         }
       
   435     else
       
   436         {
       
   437         // video is more wide screen than window.
       
   438         if ( aScaleMode == EFillTarget )
       
   439             {
       
   440             // height defines the scale
       
   441             scaleFactor = (TReal) aTargetSize.iHeight / 
       
   442                           (TReal) aSourceSize.iHeight;    
       
   443             }
       
   444         else // EMaximumFit
       
   445             {
       
   446             // width defines the scale
       
   447             scaleFactor = (TReal) aTargetSize.iWidth / 
       
   448                           (TReal) aSourceSize.iWidth;    
       
   449             }            
       
   450         }
       
   451     
       
   452     return scaleFactor;        
       
   453     }
       
   454 
       
   455 // ---------------------------------------------------------------------------
       
   456 // BubbleCallObjectUtils::GetScaleFactorAndClipRect
       
   457 //
       
   458 // ---------------------------------------------------------------------------
       
   459 //    
       
   460 TBool BubbleCallObjectUtils::GetScaleFactorAndClipRect( 
       
   461     const TSize& aSourceSize,
       
   462     const TSize& aTargetSize,
       
   463     TScaleMode aScaleMode,
       
   464     TReal& aScaleFactor,
       
   465     TRect& aClipRect )
       
   466     {
       
   467     TBool isTinyImage( EFalse );
       
   468     
       
   469     // scaling to fit main pane
       
   470     TReal scaleFactor = BubbleCallObjectUtils::ScalingFactor(
       
   471         aSourceSize,
       
   472         aTargetSize,
       
   473         aScaleMode );
       
   474     
       
   475     // set clipping rect
       
   476     TRect clipRect;
       
   477     
       
   478     if ( aScaleMode == EMaximumFit )
       
   479         {
       
   480         aScaleFactor = scaleFactor > KBMCallObjectScaleFactorMax ?
       
   481                        KBMCallObjectScaleFactorMax : scaleFactor; 
       
   482         aClipRect = TRect( aSourceSize ); // no clip   
       
   483         }
       
   484     else if ( scaleFactor == 0 )
       
   485         {
       
   486         aScaleFactor = scaleFactor;
       
   487         aClipRect = TRect( aSourceSize );    
       
   488         }
       
   489     else if ( scaleFactor > KBMCallObjectScaleFactorMax )
       
   490         {
       
   491         isTinyImage = ETrue;
       
   492         aScaleFactor = KBMCallObjectScaleFactorMax;
       
   493         TInt x_offset = 0;
       
   494         if ( aSourceSize.iWidth > aTargetSize.iWidth )
       
   495             {
       
   496             // center horizontally
       
   497             x_offset =
       
   498                 ( aSourceSize.iWidth - aTargetSize.iWidth ) / 4;
       
   499             }
       
   500         TInt y_offset = 0;
       
   501         if ( aSourceSize.iHeight > aTargetSize.iHeight )
       
   502             {
       
   503             // center vertically
       
   504             y_offset =
       
   505                 ( aSourceSize.iHeight - aTargetSize.iHeight ) / 4;    
       
   506             }
       
   507         
       
   508         aClipRect = TRect( aSourceSize );
       
   509         aClipRect.Shrink( x_offset, y_offset );    
       
   510         }
       
   511     else // 0 < scaleFactor < KBMCallObjectScaleFactorMax
       
   512         {
       
   513         aScaleFactor = scaleFactor;
       
   514         TSize relativeTargetSize;
       
   515         relativeTargetSize.iWidth = aTargetSize.iWidth / scaleFactor;
       
   516         relativeTargetSize.iHeight = aTargetSize.iHeight / scaleFactor;
       
   517         TInt x_offset = ( aSourceSize.iWidth - 
       
   518                           relativeTargetSize.iWidth ) / 2;
       
   519         TInt y_offset = ( aSourceSize.iHeight - 
       
   520                           relativeTargetSize.iHeight ) / 2;
       
   521         aClipRect = TRect( relativeTargetSize );
       
   522         if ( x_offset >= 0 && y_offset >= 0 )
       
   523             {
       
   524             // clip from center of the source image
       
   525             aClipRect.Move( x_offset, y_offset );    
       
   526             }
       
   527         }
       
   528     
       
   529     return isTinyImage;            
       
   530     }
       
   531     
       
   532 //  End of File