pictographs/AknPictograph/src/AknPictographDrawer.cpp
changeset 0 05e9090e2422
equal deleted inserted replaced
-1:000000000000 0:05e9090e2422
       
     1 /*
       
     2 * Copyright (c) 2002 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:  Pictograph drawer
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "AknPictographDrawer.h"
       
    22 #include "AknPictographConstants.h"
       
    23 #include "AknPictographRange.h"
       
    24 #include "AknPictographFactory.h"
       
    25 #include "AknPictographAnimator.h"
       
    26 #include "AknPictographPanic.h"
       
    27 #include "AknPictographDrawerFlags.h"
       
    28 
       
    29 #include <gdi.h>
       
    30 #include <fbs.h>
       
    31 #include <eikenv.h>
       
    32 #include <coecntrl.h>
       
    33 
       
    34 // CONSTANTS
       
    35 
       
    36 // ============================ MEMBER FUNCTIONS ===============================
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CAknPictographDrawer::CAknPictographDrawer
       
    40 // C++ default constructor can NOT contain any code, that
       
    41 // might leave.
       
    42 // -----------------------------------------------------------------------------
       
    43 //
       
    44 CAknPictographDrawer::CAknPictographDrawer( 
       
    45     MAknPictographAnimatorCallBack& aCallBack ) :
       
    46         iCallBack( aCallBack ), iDrawingMode(EDrawingModeNormal)
       
    47     {
       
    48     }
       
    49 
       
    50 // -----------------------------------------------------------------------------
       
    51 // CAknPictographDrawer::ConstructL
       
    52 // Symbian 2nd phase constructor can leave.
       
    53 // -----------------------------------------------------------------------------
       
    54 //
       
    55 void CAknPictographDrawer::ConstructL()
       
    56     {
       
    57     iAnimator = static_cast<CAknPictographAnimator*>(
       
    58         CCoeEnv::Static( KUidAknPictographAnimator ) );
       
    59 
       
    60     if ( !iAnimator )
       
    61         {
       
    62         // adds CCoeStatic in CoeEnv
       
    63         iAnimator = CAknPictographAnimator::CreateSingletonL();
       
    64         }
       
    65 
       
    66     iAnimator->AddClientL( *this );
       
    67     }
       
    68 
       
    69 // -----------------------------------------------------------------------------
       
    70 // CAknPictographDrawer::NewL
       
    71 // Two-phased constructor.
       
    72 // -----------------------------------------------------------------------------
       
    73 //
       
    74 CAknPictographDrawer* CAknPictographDrawer::NewL(
       
    75     MAknPictographAnimatorCallBack& aCallBack )
       
    76     {
       
    77     CAknPictographDrawer* self = 
       
    78         new( ELeave ) CAknPictographDrawer( aCallBack );
       
    79     CleanupStack::PushL( self );
       
    80     self->ConstructL();
       
    81     CleanupStack::Pop();
       
    82     return self;
       
    83     }
       
    84 
       
    85 // Destructor
       
    86 CAknPictographDrawer::~CAknPictographDrawer()
       
    87     {
       
    88     // CCoeStatic list is destroyed in Cone before AppUi, so have to check if
       
    89     // it still exist here.
       
    90     if ( CCoeEnv::Static( KUidAknPictographAnimator ) )
       
    91         {
       
    92         StopAnimator();
       
    93         if ( iAnimator->RemoveClient( *this ) == 0 )
       
    94             {
       
    95             // Removes CCoeStatic
       
    96             delete iAnimator;
       
    97             }
       
    98         }
       
    99     }
       
   100 
       
   101 // -----------------------------------------------------------------------------
       
   102 // CAknPictographDrawer::SupportedPictographCodesL
       
   103 // -- API method --
       
   104 // -----------------------------------------------------------------------------
       
   105 //
       
   106 HBufC* CAknPictographDrawer::SupportedPictographCodesL() const
       
   107     {
       
   108     return AknPictographFactory::SupportedPictographCodesL();
       
   109     }
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // CAknPictographDrawer::IsPictograph
       
   113 // -- API method --
       
   114 // -----------------------------------------------------------------------------
       
   115 //
       
   116 TBool CAknPictographDrawer::IsPictograph( TText aCode ) const
       
   117     {
       
   118     return ( aCode >= KPictographRangeStart &&
       
   119              aCode <= KPictographRangeEnd );
       
   120     }
       
   121 
       
   122 // -----------------------------------------------------------------------------
       
   123 // CAknPictographDrawer::ContainsPictographs
       
   124 // -- API method --
       
   125 // -----------------------------------------------------------------------------
       
   126 //
       
   127 TBool CAknPictographDrawer::ContainsPictographs( const TDesC& aText ) const
       
   128     {
       
   129     const TText* text = aText.Ptr();
       
   130     TInt length( aText.Length() );
       
   131 
       
   132     TBool ret( EFalse );
       
   133 
       
   134     for ( TInt i = 0 ; i < length ; i++ )
       
   135         {
       
   136         if ( IsPictograph( text[i] ) )
       
   137             {
       
   138             ret = ETrue;
       
   139             break;
       
   140             }
       
   141         }
       
   142 
       
   143     return ret;
       
   144     }
       
   145 
       
   146 // -----------------------------------------------------------------------------
       
   147 // CAknPictographDrawer::DrawPictograph
       
   148 // -- API method --
       
   149 // -----------------------------------------------------------------------------
       
   150 //
       
   151 void CAknPictographDrawer::DrawPictograph(
       
   152     CBitmapContext& aGc,
       
   153     const TPoint& aTopLeft,
       
   154     TText aCode,
       
   155     TAknPictographHeight aHeight ) const
       
   156     {
       
   157     iFlags &= ~KFlagNullBrushSet;
       
   158 
       
   159     iCurrentHeight = aHeight;
       
   160     TAknPictographData data;
       
   161 
       
   162     TInt ret = FetchPictographData( aCode, data );
       
   163 
       
   164     if ( ret == KErrNone )
       
   165         {
       
   166         DoDrawPictograph( aGc, aTopLeft, data, NULL );
       
   167         }
       
   168     }
       
   169 
       
   170 // -----------------------------------------------------------------------------
       
   171 // CAknPictographDrawer::DrawPictograph
       
   172 // -- API method --
       
   173 // -----------------------------------------------------------------------------
       
   174 //
       
   175 void CAknPictographDrawer::DrawPictograph(
       
   176     CBitmapContext& aGc,
       
   177     const TRect& aRect,
       
   178     TText aCode,
       
   179     TAknPictographHeight aHeight ) const
       
   180     {
       
   181     DrawPictograph(
       
   182         aGc,
       
   183         aRect,
       
   184         aRect,
       
   185         aCode,
       
   186         aHeight );
       
   187     }
       
   188 
       
   189 // -----------------------------------------------------------------------------
       
   190 // CAknPictographDrawer::DrawPictograph
       
   191 // -- API method --
       
   192 // -----------------------------------------------------------------------------
       
   193 //
       
   194 void CAknPictographDrawer::DrawPictograph(
       
   195     CBitmapContext& aGc,
       
   196     const TRect& aRect,
       
   197     const TRect& aClipRect,
       
   198     TText aCode,
       
   199     TAknPictographHeight aHeight ) const
       
   200     {
       
   201     iFlags &= ~KFlagNullBrushSet;
       
   202 
       
   203     iCurrentHeight = aHeight;
       
   204     TAknPictographData data;
       
   205 
       
   206     TInt ret = FetchPictographData( aCode, data );
       
   207 
       
   208     if ( ret == KErrNone )
       
   209         {
       
   210         // Center the pictograph bitmap in the given rect.
       
   211         // Round to the left and down if required.
       
   212 
       
   213         TRect pictoRect( aRect );
       
   214 
       
   215         TInt rectWidth = aRect.Width();
       
   216         TInt rectHeight = aRect.Height();
       
   217 
       
   218         if ( data.iSize.iWidth < rectWidth )
       
   219             {
       
   220             pictoRect.iTl.iX += ( rectWidth - data.iSize.iWidth ) / 2;
       
   221             }
       
   222         if ( data.iSize.iHeight < rectHeight )
       
   223             {
       
   224             // +1 makes rounding down instead of up.
       
   225             pictoRect.iTl.iY += ( rectHeight - data.iSize.iHeight + 1 ) / 2;
       
   226             }
       
   227 
       
   228         pictoRect.iBr.iX = pictoRect.iTl.iX + data.iSize.iWidth;
       
   229         pictoRect.iBr.iY = pictoRect.iTl.iY + data.iSize.iHeight;
       
   230 
       
   231         // Calculate rect that is drawn in the pictograph bitmap,
       
   232         // based on cliprect.
       
   233 
       
   234         TRect intersection = pictoRect;
       
   235         intersection.Intersection( aClipRect );
       
   236 
       
   237         TPoint topLeft = intersection.iTl;
       
   238 
       
   239         // change rect coordinates relative to bitmap's top left
       
   240         intersection.Move( -pictoRect.iTl.iX, -pictoRect.iTl.iY );
       
   241 
       
   242         DoDrawPictograph( aGc, topLeft, data, &intersection );
       
   243         }
       
   244     }
       
   245 
       
   246 // -----------------------------------------------------------------------------
       
   247 // CAknPictographDrawer::DrawText
       
   248 // -- API method --
       
   249 // -----------------------------------------------------------------------------
       
   250 //
       
   251 void CAknPictographDrawer::DrawText(
       
   252     CBitmapContext& aGc,
       
   253     const CFont& aFont,
       
   254     const TDesC& aText,
       
   255     const TPoint& aPosition ) const
       
   256     {
       
   257     aGc.DrawText( aText, aPosition );
       
   258     DrawPictographsInText( aGc, aFont, aText, aPosition );
       
   259     }
       
   260 
       
   261 // -----------------------------------------------------------------------------
       
   262 // CAknPictographDrawer::DrawText
       
   263 // -- API method --
       
   264 // -----------------------------------------------------------------------------
       
   265 //
       
   266 void CAknPictographDrawer::DrawText(
       
   267     CBitmapContext& aGc,
       
   268     const CFont& aFont,
       
   269     const TDesC& aText,
       
   270     const TRect& aBox,
       
   271     TInt aBaselineOffset,
       
   272     CGraphicsContext::TTextAlign aAlignment,
       
   273     TInt aLeftMargin ) const
       
   274     {
       
   275     aGc.DrawText( aText, aBox, aBaselineOffset, aAlignment, aLeftMargin );
       
   276 
       
   277     DrawPictographsInText( 
       
   278         aGc, aFont, aText, aBox, aBaselineOffset, aAlignment, aLeftMargin );
       
   279     }
       
   280 
       
   281 // -----------------------------------------------------------------------------
       
   282 // CAknPictographDrawer::DrawPictographsInText
       
   283 // -- API method --
       
   284 // -----------------------------------------------------------------------------
       
   285 //
       
   286 void CAknPictographDrawer::DrawPictographsInText(
       
   287     CBitmapContext& aGc,
       
   288     const CFont& aFont,
       
   289     const TDesC& aText,
       
   290     const TPoint& aPosition ) const
       
   291     {
       
   292     if ( !ContainsPictographs( aText ) )
       
   293         {
       
   294         return;
       
   295         }
       
   296 
       
   297     DrawPictographs( aGc, aFont, aText, aPosition, NULL );
       
   298     }
       
   299 
       
   300 // -----------------------------------------------------------------------------
       
   301 // CAknPictographDrawer::DrawPictographsInText
       
   302 // -- API method --
       
   303 // -----------------------------------------------------------------------------
       
   304 //
       
   305 void CAknPictographDrawer::DrawPictographsInText(
       
   306     CBitmapContext& aGc,
       
   307     const CFont& aFont,
       
   308     const TDesC& aText,
       
   309     const TRect& aBox,
       
   310     TInt aBaselineOffset,
       
   311     CGraphicsContext::TTextAlign aAlignment,
       
   312     TInt aMargin ) const
       
   313     {
       
   314     if ( !ContainsPictographs( aText ) )
       
   315         {
       
   316         return;
       
   317         }
       
   318 
       
   319     // Work out the text layout.
       
   320     TPoint p( aBox.iTl );
       
   321     p.iY += aBaselineOffset;
       
   322 
       
   323     if ( aAlignment == CGraphicsContext::ELeft )
       
   324         {
       
   325         p.iX += aMargin;
       
   326         }
       
   327     else
       
   328         {
       
   329         // measure the text
       
   330 	    CFont::TMeasureTextInput input;
       
   331 	    input.iFlags |= CFont::TMeasureTextInput::EFVisualOrder;
       
   332 	    TInt textWidth = aFont.MeasureText( aText, &input );
       
   333 
       
   334         if ( aAlignment == CGraphicsContext::ERight )
       
   335             {
       
   336             p.iX = aBox.iBr.iX - aMargin - textWidth;
       
   337             }
       
   338         else if ( aAlignment == CGraphicsContext::ECenter )
       
   339             {
       
   340             p.iX += aBox.Width() / 2 + aMargin - textWidth / 2;
       
   341             }
       
   342         }
       
   343 
       
   344     DrawPictographs( aGc, aFont, aText, p, &aBox );
       
   345     }
       
   346 
       
   347 // -----------------------------------------------------------------------------
       
   348 // CAknPictographDrawer::IsAnimated
       
   349 // -----------------------------------------------------------------------------
       
   350 //
       
   351 TBool CAknPictographDrawer::IsAnimated(
       
   352     TText aCode, TAknPictographHeight aHeight ) const
       
   353     {
       
   354     TAknPictographData data;
       
   355 
       
   356     return AknPictographFactory::AnimatedPictographData(
       
   357         aCode, aHeight, 0, data ) == KErrNone;
       
   358     }
       
   359 
       
   360 // -----------------------------------------------------------------------------
       
   361 // CAknPictographDrawer::SelectPictographHeightForFont
       
   362 // -----------------------------------------------------------------------------
       
   363 //
       
   364 TInt CAknPictographDrawer::SelectPictographHeightForFont(
       
   365             const CFont& aFont,
       
   366             TAknPictographHeight& aHeight ) const
       
   367     {
       
   368     return AknPictographFactory::SelectPictographHeightForFont(aFont,aHeight);
       
   369     }
       
   370 
       
   371 // -----------------------------------------------------------------------------
       
   372 // CAknPictographDrawer::SetPictographDrawingMode
       
   373 // -----------------------------------------------------------------------------
       
   374 //
       
   375 TAknPictographDrawingMode CAknPictographDrawer::SetPictographDrawingMode(
       
   376             TAknPictographDrawingMode aDrawingMode)
       
   377     {
       
   378     TAknPictographDrawingMode currentDrawingMode = iDrawingMode;
       
   379     iDrawingMode = aDrawingMode;
       
   380     return currentDrawingMode;
       
   381     }
       
   382 
       
   383 // -----------------------------------------------------------------------------
       
   384 // CAknPictographDrawer::DrawPictographs
       
   385 // -----------------------------------------------------------------------------
       
   386 //
       
   387 void CAknPictographDrawer::DrawPictographs(
       
   388     CBitmapContext& aGc,
       
   389     const CFont& aFont,
       
   390     const TDesC& aText,
       
   391     const TPoint& aPosition,
       
   392     const TRect* aClipRect ) const
       
   393     {
       
   394 
       
   395     // Choose pictograph height based on font.
       
   396     if( AknPictographFactory::SelectPictographHeightForFont(
       
   397             aFont,
       
   398             iCurrentHeight
       
   399             ) != KErrNone)
       
   400 
       
   401         {
       
   402         return;
       
   403         }
       
   404 
       
   405     TInt topY = aPosition.iY - aFont.AscentInPixels();
       
   406     TInt bottomY = aPosition.iY + aFont.DescentInPixels();
       
   407 
       
   408     const TText* text = aText.Ptr();
       
   409     TInt length( aText.Length() );
       
   410 
       
   411     iFlags &= ~KFlagNullBrushSet;
       
   412     iFlags |= KFlagDrawingMultiplePictographs;
       
   413    
       
   414 
       
   415     // Draw the pictographs in loop.
       
   416     for ( TInt i = 0 ; i < length ; i++ )
       
   417         {
       
   418         if ( IsPictograph( text[i] ) )
       
   419             {
       
   420             TInt x = aPosition.iX;
       
   421             x += aFont.TextWidthInPixels( aText.Left( i ) );
       
   422 
       
   423             TRect rect( x, topY, x + aFont.CharWidthInPixels( text[i] ), bottomY );
       
   424             TRect clipRect = aClipRect ? *aClipRect : rect;
       
   425 
       
   426             DrawPictograph(
       
   427                 aGc, 
       
   428                 rect,
       
   429                 clipRect,
       
   430                 text[i],
       
   431                 iCurrentHeight );
       
   432             }
       
   433         }
       
   434     iFlags &= ~KFlagDrawingMultiplePictographs;
       
   435     }
       
   436 
       
   437 // -----------------------------------------------------------------------------
       
   438 // CAknPictographDrawer::HandleGainingForeground
       
   439 // -----------------------------------------------------------------------------
       
   440 //
       
   441 void CAknPictographDrawer::HandleGainingForeground()
       
   442     {
       
   443     StartAnimatorIfRequired();
       
   444     }
       
   445 
       
   446 // -----------------------------------------------------------------------------
       
   447 // CAknPictographDrawer::HandleLosingForeground
       
   448 // -----------------------------------------------------------------------------
       
   449 //
       
   450 void CAknPictographDrawer::HandleLosingForeground()
       
   451     {
       
   452     StopAnimator();
       
   453     }
       
   454 
       
   455 // -----------------------------------------------------------------------------
       
   456 // CAknPictographDrawer::DoDrawPictograph
       
   457 // -----------------------------------------------------------------------------
       
   458 //
       
   459 void CAknPictographDrawer::DoDrawPictograph( 
       
   460     CBitmapContext& aGc,
       
   461     const TPoint& aTopLeft,
       
   462     const TAknPictographData& aData,
       
   463     TRect* aRect ) const
       
   464     {
       
   465     // First get the index for accessing the correct bitmap
       
   466     // This also validates iCurrentHeight 
       
   467     TUint bitmapIndex;
       
   468     if( AknPictographFactory::GetArrayIndexForHeight(iCurrentHeight,bitmapIndex) != KErrNone )
       
   469         {
       
   470         return;
       
   471         }
       
   472 
       
   473     if ( aData.iAnimated )
       
   474         {
       
   475         // Animated pictographs used
       
   476         iFlags |= KFlagAnimatedPictographs;
       
   477         StartAnimatorIfRequired();
       
   478         }
       
   479 
       
   480     TRect rect = aRect ? *aRect : TRect( aData.iSize );
       
   481 
       
   482     // Move to the correct x-offset in the pictograph collection bitmap
       
   483     rect.Move( aData.iOffset, 0 );
       
   484 
       
   485     RPointerArray<CFbsBitmap>* bitmaps = iAnimator->Bitmaps();
       
   486     RPointerArray<CFbsBitmap>* masks = iAnimator->Masks();
       
   487 
       
   488     CFbsBitmap* bitmap = (*bitmaps)[bitmapIndex];
       
   489     CFbsBitmap* mask = (*masks)[bitmapIndex];
       
   490 
       
   491 
       
   492     if ( EDrawingModeWhite==iDrawingMode && 
       
   493          !(iFlags & KFlagDrawingMultiplePictographs) )
       
   494         {
       
   495         // Note: EDrawingModeWhite is supported only if 
       
   496         // a single pictograph is drawn only per component->Draw() call.
       
   497         // This restriction is needed because aGc.BitBltMasked calls are cached
       
   498         // in client side as a result only the last pictograph will be drawn
       
   499         // in place all other aGc.BitBltMasked calls.
       
   500         bitmap = iAnimator->WhiteBitmap();
       
   501         CFbsBitGc* maskGc = iAnimator->WhiteBitmapMaskGc();
       
   502         maskGc->Clear();
       
   503         maskGc->BitBlt(TPoint(0,0), mask, rect);
       
   504         mask = iAnimator->WhiteBitmapMask();
       
   505         rect.Move( -rect.iTl );
       
   506         }
       
   507     
       
   508     if ( !( iFlags & KFlagNullBrushSet ) )
       
   509         {
       
   510         // To minimize WS buffer consumption, we set null brush
       
   511         // only once per API call.
       
   512         aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
       
   513         iFlags |= KFlagNullBrushSet;
       
   514         }
       
   515 
       
   516     aGc.BitBltMasked(
       
   517         aTopLeft,
       
   518         bitmap,
       
   519         rect,
       
   520         mask,
       
   521         ETrue );
       
   522     }
       
   523 
       
   524 // -----------------------------------------------------------------------------
       
   525 // CAknPictographDrawer::AnimationTick
       
   526 // -----------------------------------------------------------------------------
       
   527 //
       
   528 void CAknPictographDrawer::AnimationTick()
       
   529     {
       
   530     // Clear animated pictographs flag before callback to see whether they are
       
   531     // needed any more or not (the flag will be updated during the callback).
       
   532     iFlags &= ~KFlagAnimatedPictographs;
       
   533 
       
   534     iCallBack.DrawPictographArea();
       
   535 
       
   536     // If no animation was required during the redraw callback,
       
   537     // stop the animator.
       
   538     // It will be started again when a request to draw an animated pictograph
       
   539     // is detected.
       
   540     if ( !( iFlags & KFlagAnimatedPictographs ) )
       
   541         {
       
   542         StopAnimator();
       
   543         }
       
   544     }
       
   545 
       
   546 // -----------------------------------------------------------------------------
       
   547 // CAknPictographDrawer::StartAnimatorIfRequired
       
   548 // -----------------------------------------------------------------------------
       
   549 //
       
   550 void CAknPictographDrawer::StartAnimatorIfRequired() const
       
   551     {
       
   552     TInt bits = iFlags & ( KFlagAnimatedPictographs | KFlagTimerStarted );
       
   553 
       
   554     // Animated pictographs but timer not started?
       
   555     if ( bits == KFlagAnimatedPictographs )
       
   556         {
       
   557         iAnimator->Start();
       
   558         iFlags |= KFlagTimerStarted;
       
   559         }
       
   560     }
       
   561 
       
   562 // -----------------------------------------------------------------------------
       
   563 // CAknPictographDrawer::StopAnimator
       
   564 // -----------------------------------------------------------------------------
       
   565 //
       
   566 void CAknPictographDrawer::StopAnimator() const
       
   567     {
       
   568     if ( iFlags & KFlagTimerStarted )
       
   569         {
       
   570         iAnimator->Stop();
       
   571         iFlags &= ~KFlagTimerStarted;
       
   572         }
       
   573     }
       
   574 
       
   575 // -----------------------------------------------------------------------------
       
   576 // CAknPictographDrawer::FetchPictographData
       
   577 // -----------------------------------------------------------------------------
       
   578 //
       
   579 TInt CAknPictographDrawer::FetchPictographData(
       
   580     TText aCode,
       
   581     TAknPictographData& aData ) const
       
   582     {
       
   583     TInt ret = AknPictographFactory::StaticPictographData(
       
   584         aCode, iCurrentHeight, aData );
       
   585 
       
   586     if ( ret != KErrNone )
       
   587         {
       
   588         ret = AknPictographFactory::AnimatedPictographData(
       
   589             aCode, iCurrentHeight, iAnimator->Counter(), aData );
       
   590         }
       
   591 
       
   592     return ret;
       
   593     }
       
   594 
       
   595 //  End of File