javauis/lcdui_akn/lcdgr/src/LcdFbsImage.cpp
branchRCL_3
changeset 14 04becd199f91
equal deleted inserted replaced
13:f5050f1da672 14:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2005 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:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <bitdev.h>
       
    19 #include <bitstd.h>
       
    20 #include <lcdgdrv.h>
       
    21 #include "LcdFbsImage.h"
       
    22 
       
    23 #ifdef LCDGR_ACCELERATED_BITGDI
       
    24 const TUid KJvmExeUid = { 0x102033E6 };
       
    25 #endif
       
    26 
       
    27 /**
       
    28  * Copy bitmap data from (aColorBitmap,aAlphaBitmap) to aFbsImage.
       
    29  */
       
    30 extern void CopyBitmapsL
       
    31 (
       
    32     CLcdGraphicsDriver& /* aDriver */,  // not used yet
       
    33     CLcdFbsImage&       aFbsImage,
       
    34     CFbsBitmap*         aColorBitmap,
       
    35     CFbsBitmap*         aAlphaBitmap,
       
    36     TBool               aInvertMask
       
    37 );
       
    38 
       
    39 /**
       
    40  * Create a CFbsBitmap of size aSize in displaymode aMode
       
    41  */
       
    42 LOCAL_C CFbsBitmap* CreateBitmapL(const TSize& aSize, TDisplayMode aMode);
       
    43 
       
    44 /**
       
    45  * Set alpha channel in EColor16MA mode aBitmap from aAlphaBitmap. If aAlphaBitmap is
       
    46  * in a mode other than EGray256 this procedure will create a temporary bitmap in
       
    47  * EGray256 mode and copy pixels from aAlphaBitmap into that first. It is expected
       
    48  * that aAlphaBitmap would be a binary mask.
       
    49  */
       
    50 LOCAL_C void SetAlphaChannelL(CFbsBitmap* aBitmap, CFbsBitmap* aAlphaBitmap, TBool aInvert);
       
    51 
       
    52 /**
       
    53  * Set the alpha channel in an EColor16MA mode aBitmap from an EGray256 mode
       
    54  * aGray256Bitmap.
       
    55  */
       
    56 LOCAL_C void SetAlphaChannel(CFbsBitmap* aBitmap, CFbsBitmap* aGray256Bitmap, TBool aInvert);
       
    57 
       
    58 /**
       
    59  * Copy alpha information from EColor16MA bitmap aSource, into EGray2 or EGray256
       
    60  * bitmap aTarget.
       
    61  */
       
    62 LOCAL_C void GetAlphaChannelL(CFbsBitmap* aTarget, CFbsBitmap* aSource, TBool aInvert);
       
    63 
       
    64 /**
       
    65  * Copy alpha channel from EColor16MA bitmap into an EGray256 bitmap
       
    66  */
       
    67 LOCAL_C void GetAlphaChannel(CFbsBitmap* aTargetGray256, CFbsBitmap* aSourceColor16MA, TBool aInvert);
       
    68 
       
    69 #ifdef _DEBUG
       
    70 //
       
    71 // debug only - check that EColor16MA aBitmap is fully opaque
       
    72 //
       
    73 LOCAL_C TBool CheckOpaque(CFbsBitmap* aBitmap);
       
    74 #endif
       
    75 
       
    76 
       
    77 /*************************************************************
       
    78  *
       
    79  * CLcdFbsImage potentially public bitmapped image class.
       
    80  *
       
    81  ************************************************************/
       
    82 
       
    83 CLcdFbsImage* CLcdFbsImage::NewL(const TSize& aSize, TDisplayMode aColorMode, TDisplayMode aAlphaMode)
       
    84 {
       
    85     CLcdFbsImage* image = new(ELeave) CLcdFbsImage;
       
    86     CleanupStack::PushL(image);
       
    87     image->iColorBitmap = CreateBitmapL(aSize, aColorMode);
       
    88     if (aAlphaMode)
       
    89     {
       
    90         image->iAlphaBitmap = CreateBitmapL(aSize, aAlphaMode);
       
    91     }
       
    92     CleanupStack::Pop(image);
       
    93     return image;
       
    94 }
       
    95 
       
    96 CLcdFbsImage* CLcdFbsImage::NewL(CFbsBitmap* aColorBitmap, CFbsBitmap* aAlphaBitmap)
       
    97 {
       
    98     CLcdFbsImage* image = new(ELeave) CLcdFbsImage;
       
    99 
       
   100     CleanupStack::PushL(image);
       
   101     image->iColorBitmap = DuplicateBitmapL(aColorBitmap);
       
   102     if (aAlphaBitmap)
       
   103     {
       
   104         image->iAlphaBitmap = DuplicateBitmapL(aAlphaBitmap);
       
   105     }
       
   106     CleanupStack::Pop(image);
       
   107 
       
   108     return image;
       
   109 }
       
   110 
       
   111 CLcdFbsImage::~CLcdFbsImage()
       
   112 {
       
   113     ASSERT(0 == iRefCount);
       
   114     delete iAlphaBitmap;
       
   115     delete iColorBitmap;
       
   116 }
       
   117 
       
   118 TSize CLcdFbsImage::Size() const
       
   119 {
       
   120     return iColorBitmap->SizeInPixels();
       
   121 }
       
   122 
       
   123 void CLcdFbsImage::AddRef()
       
   124 {
       
   125     ++iRefCount;
       
   126 }
       
   127 
       
   128 void CLcdFbsImage::RemoveRef()
       
   129 {
       
   130     --iRefCount;
       
   131     if (iRefCount == 0)
       
   132     {
       
   133         delete this;
       
   134     }
       
   135 }
       
   136 
       
   137 /**
       
   138  *@return the color bitmap
       
   139  */
       
   140 CFbsBitmap* CLcdFbsImage::ColorBitmap() const
       
   141 {
       
   142     return iColorBitmap;
       
   143 }
       
   144 
       
   145 /**
       
   146  *@return the alpha bitmap if any
       
   147  */
       
   148 CFbsBitmap* CLcdFbsImage::AlphaBitmap() const
       
   149 {
       
   150     return iAlphaBitmap;
       
   151 }
       
   152 
       
   153 void CLcdFbsImage::CreateAlphaBitmapL()
       
   154 {
       
   155     if (iAlphaBitmap)
       
   156     {
       
   157         User::Leave(KErrAlreadyExists);
       
   158     }
       
   159 
       
   160     iAlphaBitmap = CreateBitmapL(Size(), EGray256);
       
   161 }
       
   162 
       
   163 /**
       
   164  * Create a bitmap of size aSize in display mode aMode.
       
   165  */
       
   166 LOCAL_C CFbsBitmap* CreateBitmapL(const TSize& aSize, TDisplayMode aMode)
       
   167 {
       
   168     TInt err = KErrNotSupported;
       
   169 
       
   170     CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
       
   171     CleanupStack::PushL(bitmap);
       
   172 
       
   173 #ifdef LCDGR_ACCELERATED_BITGDI
       
   174     //
       
   175     // Attempt to create hardware bitmap which can be used with a
       
   176     // hardware graphics accelerator. Very few if any devices
       
   177     // appear to support RHardwareBitmap so this is very unlikely
       
   178     // to be used.
       
   179     //
       
   180     err = bitmap->CreateHardwareBitmap(aSize, aMode, KJvmExeUid);
       
   181 #endif
       
   182 
       
   183     if (err != KErrNone)
       
   184     {
       
   185         //
       
   186         // Fallback to software only bitmap if hardware unavailable/not supported.
       
   187         //
       
   188         err = bitmap->Create(aSize, aMode);
       
   189     }
       
   190 
       
   191     User::LeaveIfError(err);
       
   192 
       
   193     CleanupStack::Pop(bitmap);
       
   194 
       
   195     return bitmap;
       
   196 }
       
   197 
       
   198 /**
       
   199  * Create a new bitmap in a given mode and copy the data.
       
   200  * Slowish closest match copy. We could use lcd graphics driver for some
       
   201  * of these copies but is good enough for now.
       
   202  */
       
   203 CFbsBitmap* CLcdFbsImage::CopyBitmapL(CFbsBitmap* aBitmap, TDisplayMode aMode, TBool aInvert)
       
   204 {
       
   205     CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
       
   206     CleanupStack::PushL(bitmap);
       
   207     User::LeaveIfError(bitmap->Create(aBitmap->SizeInPixels(), aMode));
       
   208     CopyBitmapL(bitmap, aBitmap, aInvert);
       
   209     CleanupStack::Pop(bitmap);
       
   210     return bitmap;
       
   211 }
       
   212 
       
   213 /**
       
   214  * Copy bitmap content from aSource to aTarget optionally inverting.
       
   215  */
       
   216 void CLcdFbsImage::CopyBitmapL(CFbsBitmap* aTarget, CFbsBitmap* aSource, TBool aInvert)
       
   217 {
       
   218     CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(aTarget);
       
   219     CleanupStack::PushL(device);
       
   220     CFbsBitGc* gc = NULL;
       
   221     User::LeaveIfError(device->CreateContext(gc));
       
   222 
       
   223     // Don't alpha blend (Either copy the alpha component or write opaque pixels)
       
   224     TInt drawMode = CGraphicsContext::EDrawModeWriteAlpha;
       
   225     if (aInvert)
       
   226     {
       
   227         // Invert pixel values - only really makes sense for binary masks
       
   228         // For EColor16MA images the alpha component is not inverted
       
   229         drawMode |= CGraphicsContext::EInvertPen;
       
   230     }
       
   231 
       
   232     gc->SetDrawMode(CGraphicsContext::TDrawMode(drawMode));
       
   233     gc->BitBlt(TPoint(), aSource);
       
   234     delete gc;
       
   235     CleanupStack::PopAndDestroy(device);
       
   236 }
       
   237 
       
   238 /**
       
   239  * Dup the handle. This requires an FBSERV ipc.
       
   240  */
       
   241 CFbsBitmap* CLcdFbsImage::DuplicateBitmapL(CFbsBitmap* aBitmap)
       
   242 {
       
   243     CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
       
   244     CleanupStack::PushL(bitmap);
       
   245     User::LeaveIfError(bitmap->Duplicate(aBitmap->Handle()));
       
   246     CleanupStack::Pop(bitmap);
       
   247     return bitmap;
       
   248 }
       
   249 
       
   250 /**
       
   251  * Copy bitmap data from (aColorBitmap,aAlphaBitmap) to aFbsImage.
       
   252  */
       
   253 extern void CopyBitmapsL
       
   254 (
       
   255     CLcdGraphicsDriver& /* aDriver */,  // not used yet
       
   256     CLcdFbsImage&       aFbsImage,
       
   257     CFbsBitmap*         aColorBitmap,
       
   258     CFbsBitmap*         aAlphaBitmap,
       
   259     TBool               aInvertMask
       
   260 )
       
   261 {
       
   262     //
       
   263     // First copy the the pixel color data.
       
   264     //
       
   265     CLcdFbsImage::CopyBitmapL(aFbsImage.ColorBitmap(), aColorBitmap, EFalse);
       
   266 
       
   267     //
       
   268     // If target colour bitmap contains alpha channel, copy any alpha data
       
   269     // into it.
       
   270     //
       
   271     if (aFbsImage.ColorBitmap()->DisplayMode() == EColor16MA)
       
   272     {
       
   273         ASSERT(NULL == aFbsImage.AlphaBitmap());
       
   274         if (aAlphaBitmap)
       
   275         {
       
   276             SetAlphaChannelL(aFbsImage.ColorBitmap(), aAlphaBitmap, aInvertMask);
       
   277         }
       
   278 #ifdef _DEBUG
       
   279         else
       
   280         {
       
   281             ASSERT(CheckOpaque(aFbsImage.ColorBitmap()));
       
   282         }
       
   283 #endif
       
   284     }
       
   285     else if (aFbsImage.AlphaBitmap())
       
   286     {
       
   287         if (aAlphaBitmap)
       
   288         {
       
   289             CLcdFbsImage::CopyBitmapL(aFbsImage.AlphaBitmap(), aAlphaBitmap, EFalse);
       
   290         }
       
   291         else if (aColorBitmap->DisplayMode() == EColor16MA)
       
   292         {
       
   293             GetAlphaChannelL(aFbsImage.AlphaBitmap(), aColorBitmap, aInvertMask);
       
   294         }
       
   295     }
       
   296 }
       
   297 
       
   298 
       
   299 //
       
   300 // Set the alpha channel in a bitmap in a mode that contains alpha
       
   301 // information from an alpha bitmap.
       
   302 //
       
   303 // Not the cheapest, but this is hopefully an edge case.
       
   304 //
       
   305 // EColor16M,Gray256 is the most likely format, so a dedicated blitter
       
   306 // could help.
       
   307 //
       
   308 LOCAL_C void SetAlphaChannelL(CFbsBitmap* aBitmap, CFbsBitmap* aAlphaBitmap, TBool aInvert)
       
   309 {
       
   310     ASSERT(aBitmap->DisplayMode() == EColor16MA);
       
   311     if (aAlphaBitmap->DisplayMode() != EGray256)
       
   312     {
       
   313         CFbsBitmap* alpha = CLcdFbsImage::CopyBitmapL(aAlphaBitmap, EGray256, EFalse);
       
   314         SetAlphaChannel(aBitmap, alpha, aInvert);
       
   315         delete alpha;
       
   316     }
       
   317     else
       
   318     {
       
   319         SetAlphaChannel(aBitmap, aAlphaBitmap, aInvert);
       
   320     }
       
   321 }
       
   322 
       
   323 //
       
   324 // Set the alpha channel in an EColor16MA bitmap from an EGray256
       
   325 // bitmap.
       
   326 //
       
   327 LOCAL_C void SetAlphaChannel(CFbsBitmap* aBitmap, CFbsBitmap* aGray256Bitmap, TBool aInvert)
       
   328 {
       
   329     ASSERT(aBitmap->DisplayMode()        == EColor16MA);
       
   330     ASSERT(aGray256Bitmap->DisplayMode() == EGray256);
       
   331 
       
   332     TAcceleratedBitmapSpec targetSpec(aBitmap);
       
   333     TAcceleratedBitmapInfo target;
       
   334     TAcceleratedBitmapSpec sourceSpec(aGray256Bitmap);
       
   335     TAcceleratedBitmapInfo source;
       
   336     TBitmapLockCount count;
       
   337 
       
   338     targetSpec.Lock(count);
       
   339     sourceSpec.Lock(count);
       
   340 
       
   341     targetSpec.GetInfo(target);
       
   342     sourceSpec.GetInfo(source);
       
   343 
       
   344     ASSERT(target.iSize == source.iSize);
       
   345 
       
   346     TUint8* tgtAddress   = target.iAddress;
       
   347     TInt    tgtLinePitch = target.iLinePitch;
       
   348     TUint8* srcAddress   = source.iAddress;
       
   349     TInt    srcLinePitch = source.iLinePitch;
       
   350 
       
   351     TUint32 mask = aInvert ? 0xff:0x00;
       
   352     for (TInt h=target.iSize.iHeight; --h>=0;)
       
   353     {
       
   354         TUint8*  src = srcAddress;
       
   355         TUint32* tgt = (TUint32*)tgtAddress;
       
   356         TUint32* end = tgt + target.iSize.iWidth;
       
   357         while (tgt < end)
       
   358         {
       
   359             TUint32 alpha = (*src) ^ mask;
       
   360             TUint32 pixel = *tgt;
       
   361             pixel &= 0x00ffffff;
       
   362             pixel |= (alpha << 24);
       
   363             *tgt = pixel;
       
   364             ++src;
       
   365             ++tgt;
       
   366         }
       
   367         tgtAddress += tgtLinePitch;
       
   368         srcAddress += srcLinePitch;
       
   369     }
       
   370 
       
   371     sourceSpec.Unlock(count);
       
   372     targetSpec.Unlock(count);
       
   373 }
       
   374 
       
   375 
       
   376 //
       
   377 // Copy alpha information from EColor16MA bitmap aSource, into EGray2 or EGray256
       
   378 // bitmap aTarget.
       
   379 //
       
   380 LOCAL_C void GetAlphaChannelL(CFbsBitmap* aTarget, CFbsBitmap* aSource, TBool aInvert)
       
   381 {
       
   382     ASSERT(aTarget->DisplayMode() == EGray2 || aTarget->DisplayMode() == EGray256);
       
   383     if (aTarget->DisplayMode() == EGray2)
       
   384     {
       
   385         TSize size = aSource->SizeInPixels();
       
   386         CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
       
   387         CleanupStack::PushL(bitmap);
       
   388         User::LeaveIfError(bitmap->Create(size, EGray256));
       
   389         GetAlphaChannel(bitmap, aSource, aInvert);
       
   390         CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(aTarget);
       
   391         CleanupStack::PushL(device);
       
   392         CFbsBitGc* context = NULL;
       
   393         User::LeaveIfError(device->CreateContext(context));
       
   394         context->BitBlt(TPoint(), bitmap);
       
   395         delete context;
       
   396         CleanupStack::PopAndDestroy(device);
       
   397         CleanupStack::PopAndDestroy(bitmap);
       
   398     }
       
   399     else
       
   400     {
       
   401         GetAlphaChannel(aTarget, aSource, aInvert);
       
   402     }
       
   403 }
       
   404 
       
   405 //
       
   406 // Copy alpha channel from EColor16MA bitmap into an EGray256 bitmap
       
   407 //
       
   408 LOCAL_C void GetAlphaChannel(CFbsBitmap* aTargetGray256, CFbsBitmap* aSourceColor16MA, TBool aInvert)
       
   409 {
       
   410     ASSERT(aTargetGray256->DisplayMode()   == EGray256);
       
   411     ASSERT(aSourceColor16MA->DisplayMode() == EColor16MA);
       
   412 
       
   413     TAcceleratedBitmapSpec targetSpec(aTargetGray256);
       
   414     TAcceleratedBitmapInfo target;
       
   415     TAcceleratedBitmapSpec sourceSpec(aSourceColor16MA);
       
   416     TAcceleratedBitmapInfo source;
       
   417     TBitmapLockCount count;
       
   418 
       
   419     targetSpec.Lock(count);
       
   420     sourceSpec.Lock(count);
       
   421 
       
   422     targetSpec.GetInfo(target);
       
   423     sourceSpec.GetInfo(source);
       
   424 
       
   425     ASSERT(target.iSize == source.iSize);
       
   426 
       
   427     TUint8* tgtAddress   = target.iAddress;
       
   428     TInt    tgtLinePitch = target.iLinePitch;
       
   429     TUint8* srcAddress   = source.iAddress;
       
   430     TInt    srcLinePitch = source.iLinePitch;
       
   431 
       
   432     TUint32 mask = aInvert ? 0xff:0x00;
       
   433     for (TInt h=target.iSize.iHeight; --h>=0;)
       
   434     {
       
   435         TUint32*  src = (TUint32*)srcAddress;
       
   436         TUint8*   tgt = (TUint8*)tgtAddress;
       
   437         TUint8*   end = tgt + target.iSize.iWidth;
       
   438         while (tgt < end)
       
   439         {
       
   440             *tgt++ = (TUint8)(((*src++)>>24)^mask);
       
   441         }
       
   442         tgtAddress += tgtLinePitch;
       
   443         srcAddress += srcLinePitch;
       
   444     }
       
   445 
       
   446     sourceSpec.Unlock(count);
       
   447     targetSpec.Unlock(count);
       
   448 }
       
   449 
       
   450 #ifdef _DEBUG
       
   451 LOCAL_C TBool CheckOpaque(CFbsBitmap* aBitmap)
       
   452 {
       
   453     ASSERT(aBitmap->DisplayMode() == EColor16MA);
       
   454     TAcceleratedBitmapSpec spec(aBitmap);
       
   455     TAcceleratedBitmapInfo info;
       
   456     TBitmapLockCount count;
       
   457 
       
   458     spec.Lock(count);
       
   459     spec.GetInfo(info);
       
   460 
       
   461     TUint8* address = info.iAddress;
       
   462     TInt    linePitch = info.iLinePitch;
       
   463     TUint32 accum = 0xff000000;
       
   464 
       
   465     for (TInt h=info.iSize.iHeight; --h>=0;)
       
   466     {
       
   467         TUint32* src = (TUint32*)address;
       
   468         TUint32* end = src + info.iSize.iWidth;
       
   469         while (src < end)
       
   470         {
       
   471             accum &= *src++;
       
   472         }
       
   473         address += linePitch;
       
   474     }
       
   475 
       
   476     spec.Unlock(count);
       
   477 
       
   478     return (accum == 0xff000000);
       
   479 }
       
   480 #endif