javauis/lcdui_akn/lcdgd/src/collision.cpp
branchRCL_3
changeset 19 04becd199f91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdgd/src/collision.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,503 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <fbs.h>
+#include "lcdtransform.h"
+#include "collision.h"
+
+/**
+Return ETrue if the mask pixel is fully opaque.
+*/
+TBool IsOpaque(TDisplayMode aDisplayMode, TUint8* aAddress, TInt aLinePitch , TInt aX, TInt aY)
+{
+    switch (aDisplayMode)
+    {
+        // binary transparent
+    case EGray2:
+    {
+        TUint8 m1 = *(aAddress + aY*aLinePitch + (aX>>3));
+        TUint8 srcMask1 = m1 >> (aX&0x7);
+        return srcMask1 & 0x1;
+    }
+
+    // alpha transparent
+    case EGray256:
+    {
+        TUint8 srcMask2 = *(TUint8*)(aAddress + aY*aLinePitch + aX*sizeof(TUint8));
+        // semi-transparent is treated as transparent.
+        return srcMask2 == 0xff;
+    }
+
+    // mask matched
+    case EColor64K:
+    {
+        TUint16 srcMask3 = *(TUint16*)(aAddress + aY*aLinePitch + aX*sizeof(TUint16));
+        return srcMask3 == 0xffff;
+    }
+    case EColor4K:
+    {
+        TUint16 srcMask4 = *(TUint16*)(aAddress + aY*aLinePitch + aX*sizeof(TUint16));
+        return srcMask4 == 0xfff;
+    }
+    case EColor16MU:
+    {
+        TUint32 srcMask5  = *(TUint32*)(aAddress + aY*aLinePitch + aX*sizeof(TUint32));
+        return srcMask5 == 0xffffff;
+    }
+
+    default:
+    {
+        __ASSERT_DEBUG(EFalse, User::Invariant());
+    }
+    }
+    return EFalse;
+}
+
+TBool GenericDetectCollision
+(
+    const TAcceleratedBitmapInfo*   aBitmap1,
+    const TAcceleratedBitmapInfo*   aBitmap2,
+    const TRect&                    aRect1,
+    const TRect&                    aRect2,
+    const TLcdTransform&            aTransform1,
+    const TLcdTransform&            aTransform2
+)
+{
+
+    // if only one mask, just need to check if it has any opaque pixels
+    if (aBitmap1 == NULL)
+    {
+        return ::HasOpaquePixel(aBitmap2, aRect2);
+    }
+    if (aBitmap2 == NULL)
+    {
+        return ::HasOpaquePixel(aBitmap1, aRect1);
+    }
+
+    TLcdTransform transform = aTransform1 * aTransform2.Inverse();
+    TRect rect = aRect2;
+
+    TInt x1 = rect.iTl.iX;
+    TInt x2 = rect.iBr.iX-1;    // inclusive!
+    TInt y  = rect.iTl.iY;
+    TInt h  = rect.Height();
+
+    TPoint srcPoint = transform(rect.iTl);
+    TInt dudx = transform.iDuDx;
+    TInt dudy = transform.iDuDy;
+    TInt dvdx = transform.iDvDx;
+    TInt dvdy = transform.iDvDy;
+    TInt u0   = srcPoint.iX;
+    TInt v0   = srcPoint.iY;
+    TInt u    = u0;
+    TInt v    = v0;
+
+    const TInt linePitch1   = aBitmap1->iLinePitch;
+    const TInt linePitch2   = aBitmap2->iLinePitch;
+    TUint8* address1        = aBitmap1->iAddress;
+    TUint8* address2        = aBitmap2->iAddress;
+
+    for (; h>0; --h)
+    {
+        u=u0;
+        v=v0;
+
+        for (TInt x=x1; x<=x2; x++)
+        {
+            TBool o1 = IsOpaque(aBitmap2->iDisplayMode, address2, linePitch2, x, y);
+            TBool o2 = IsOpaque(aBitmap1->iDisplayMode, address1, linePitch1, u, v);
+
+            if (o1 && o2)
+            {
+                return ETrue;
+            }
+
+            u+=dudx;
+            v+=dvdx;
+        }
+
+        u0+=dudy;
+        v0+=dvdy;
+        y++;
+    }
+
+    return EFalse;
+}
+
+
+TBool DetectCollisionGray2Gray2
+(
+    const TAcceleratedBitmapInfo*   aGray2Bitmap1,
+    const TAcceleratedBitmapInfo*   aGray2Bitmap2,
+    const TRect&                    aRect1,
+    const TRect&                    aRect2,
+    const TLcdTransform&            aTransform1,
+    const TLcdTransform&            aTransform2
+)
+{
+
+    // if only one mask, just need to check if it has any opaque pixels
+    if (aGray2Bitmap1 == NULL)
+    {
+        return ::HasOpaquePixelGray2(aGray2Bitmap2, aRect2);
+    }
+    if (aGray2Bitmap2 == NULL)
+    {
+        return ::HasOpaquePixelGray2(aGray2Bitmap1, aRect1);
+    }
+
+    ASSERT(aGray2Bitmap1->iDisplayMode == EGray2);
+    ASSERT(aGray2Bitmap2->iDisplayMode == EGray2);
+
+    TLcdTransform transform = aTransform1 * aTransform2.Inverse();
+    TRect rect = aRect2;
+
+    TInt x1 = rect.iTl.iX;
+    TInt x2 = rect.iBr.iX-1;    // inclusive!
+    TInt y  = rect.iTl.iY;
+    TInt h  = rect.Height();
+
+    TPoint srcPoint = transform(rect.iTl);
+    TInt dudx = transform.iDuDx;
+    TInt dudy = transform.iDuDy;
+    TInt dvdx = transform.iDvDx;
+    TInt dvdy = transform.iDvDy;
+    TInt u0   = srcPoint.iX;
+    TInt v0   = srcPoint.iY;
+    TInt u    = u0;
+    TInt v    = v0;
+
+    const TInt linePitch1   = aGray2Bitmap1->iLinePitch;
+    const TInt linePitch2   = aGray2Bitmap2->iLinePitch;
+    TUint8* address1        = aGray2Bitmap1->iAddress;
+    TUint8* address2        = aGray2Bitmap2->iAddress;
+
+    address2 += y*linePitch2;
+    for (; h>0; --h)
+    {
+        u=u0;
+        v=v0;
+
+        for (TInt x=x1; x<=x2; x++)
+        {
+            TUint8 m2 = address2[(x>>3)];
+            TUint8 p2 = m2 >> (x&0x7);
+
+            if (p2&0x1)
+            {
+                TUint8 m1 = *(address1 + v*linePitch1 + (u>>3));
+                TUint8 p1 = m1 >> (u&0x7);
+
+                if (p1&0x1)
+                {
+                    return ETrue;
+                }
+            }
+
+            u+=dudx;
+            v+=dvdx;
+        }
+
+        u0+=dudy;
+        v0+=dvdy;
+
+        address2 += linePitch2;
+    }
+
+    return EFalse;
+}
+
+TBool DetectCollisionGray256Gray256
+(
+    const TAcceleratedBitmapInfo*   aGray256Bitmap1,
+    const TAcceleratedBitmapInfo*   aGray256Bitmap2,
+    const TRect&                    aRect1,
+    const TRect&                    aRect2,
+    const TLcdTransform&            aTransform1,
+    const TLcdTransform&            aTransform2
+)
+{
+    // if only one mask, just need to check if it has any opaque pixels
+    if (aGray256Bitmap1 == NULL)
+    {
+        return ::HasOpaquePixelGray256(aGray256Bitmap2, aRect2);
+    }
+    if (aGray256Bitmap2 == NULL)
+    {
+        return ::HasOpaquePixelGray256(aGray256Bitmap1, aRect1);
+    }
+
+    ASSERT(aGray256Bitmap1->iDisplayMode == EGray256);
+    ASSERT(aGray256Bitmap2->iDisplayMode == EGray256);
+
+    TLcdTransform transform = aTransform1 * aTransform2.Inverse();
+    TRect rect = aRect2;
+
+    const TInt x = rect.iTl.iX;
+    const TInt y = rect.iTl.iY;
+    const TInt w = rect.Width();
+    TInt h = rect.Height();
+
+    TPoint srcPoint = transform(rect.iTl);
+    TInt dudx = transform.iDuDx;
+    TInt dudy = transform.iDuDy;
+    TInt dvdx = transform.iDvDx;
+    TInt dvdy = transform.iDvDy;
+    TInt u0   = srcPoint.iX;
+    TInt v0   = srcPoint.iY;
+
+
+    const TInt linePitch1   = aGray256Bitmap1->iLinePitch;
+    const TInt linePitch2   = aGray256Bitmap2->iLinePitch;
+    TUint8* address1        = aGray256Bitmap1->iAddress;
+    TUint8* address2        = aGray256Bitmap2->iAddress;
+
+    address2 += y*linePitch2 + x*sizeof(TUint8);
+    for (; h>0; --h)
+    {
+        TInt u = u0;
+        TInt v = v0;
+
+        TUint8* ptr2 = address2;
+        const TUint8* end = ptr2 + w;
+
+        while (ptr2 < end)
+        {
+            TUint8 m2 = *ptr2++;
+            if (m2 == 255)
+            {
+                TUint8 m1 = *(TUint8*)(address1 + v*linePitch1 + u*sizeof(TUint8));
+                if (m1 == 255)
+                {
+                    return ETrue;
+                }
+            }
+
+            u+=dudx;
+            v+=dvdx;
+        }
+
+        u0+=dudy;
+        v0+=dvdy;
+        address2 += linePitch2;
+    }
+
+    return EFalse;
+}
+
+TBool DetectCollisionGray2Gray256
+(
+    const TAcceleratedBitmapInfo*   aGray2Bitmap,
+    const TAcceleratedBitmapInfo*   aGray256Bitmap,
+    const TRect&                    aRect1,
+    const TRect&                    aRect2,
+    const TLcdTransform&            aTransform1,
+    const TLcdTransform&            aTransform2
+)
+{
+    // if only one mask, just need to check if it has any opaque pixels
+    if (aGray2Bitmap == NULL)
+    {
+        return ::HasOpaquePixelGray256(aGray256Bitmap, aRect2);
+    }
+    if (aGray256Bitmap == NULL)
+    {
+        return ::HasOpaquePixelGray2(aGray2Bitmap, aRect1);
+    }
+
+    ASSERT(aGray2Bitmap->iDisplayMode == EGray2);
+    ASSERT(aGray256Bitmap->iDisplayMode == EGray256);
+
+    TLcdTransform transform = aTransform1 * aTransform2.Inverse();
+    TRect rect = aRect2;
+
+    const TInt x = rect.iTl.iX;
+    const TInt y = rect.iTl.iY;
+    const TInt w = rect.Width();
+    TInt h = rect.Height();
+
+    TPoint srcPoint = transform(rect.iTl);
+    TInt dudx = transform.iDuDx;
+    TInt dudy = transform.iDuDy;
+    TInt dvdx = transform.iDvDx;
+    TInt dvdy = transform.iDvDy;
+    TInt u0   = srcPoint.iX;
+    TInt v0   = srcPoint.iY;
+
+    const TInt linePitch1   = aGray2Bitmap->iLinePitch;
+    const TInt linePitch2   = aGray256Bitmap->iLinePitch;
+    TUint8* address1        = aGray2Bitmap->iAddress;
+    TUint8* address2        = aGray256Bitmap->iAddress;
+
+    address2 += y*linePitch2 + x*sizeof(TUint8);
+    for (; h>0; --h)
+    {
+        TInt u = u0;
+        TInt v = v0;
+
+        TUint8* ptr2 = address2;
+        const TUint8* end = ptr2 + w;
+        while (ptr2 < end)
+        {
+            TUint8 m2 = *ptr2++;
+
+            if (m2 == 255)
+            {
+                TUint8 m1 = *(address1 + v*linePitch1 + (u>>3));
+                TUint8 p1 = m1 >> (u&0x7);
+
+                if (p1&0x1)
+                {
+                    return ETrue;
+                }
+            }
+
+            u+=dudx;
+            v+=dvdx;
+        }
+
+        u0+=dudy;
+        v0+=dvdy;
+        address2 += linePitch2;
+    }
+
+    return EFalse;
+}
+
+TBool DetectCollisionGray256Gray2
+(
+    const TAcceleratedBitmapInfo*   aGray256Bitmap,
+    const TAcceleratedBitmapInfo*   aGray2Bitmap,
+    const TRect&                    aRect1,
+    const TRect&                    aRect2,
+    const TLcdTransform&            aTransform1,
+    const TLcdTransform&            aTransform2
+)
+{
+    return DetectCollisionGray2Gray256
+           (
+               aGray2Bitmap,
+               aGray256Bitmap,
+               aRect2,
+               aRect1,
+               aTransform2,
+               aTransform1
+           );
+}
+
+TBool HasOpaquePixel
+(
+    const TAcceleratedBitmapInfo*   aBitmap,
+    const TRect&                    aRect
+)
+{
+    const TInt linePitch    = aBitmap->iLinePitch;
+    TUint8* address         = aBitmap->iAddress;
+
+    TInt x1 = aRect.iTl.iX;
+    TInt x2 = aRect.iBr.iX-1;   // inclusive!
+    TInt y  = aRect.iTl.iY;
+    TInt h  = aRect.Height();
+
+    for (; h>0; --h)
+    {
+        for (TInt x=x1; x<=x2; x++)
+        {
+            if (IsOpaque(aBitmap->iDisplayMode, address, linePitch, x, y))
+            {
+                return ETrue;
+            }
+        }
+        y++;
+    }
+
+    return EFalse;
+}
+
+TBool HasOpaquePixelGray2
+(
+    const TAcceleratedBitmapInfo*   aGray2Bitmap,
+    const TRect&                    aRect
+)
+{
+    ASSERT(aGray2Bitmap->iDisplayMode == EGray2);
+
+    const TInt linePitch    = aGray2Bitmap->iLinePitch;
+    TUint8* address         = aGray2Bitmap->iAddress;
+
+    const TInt x1   = aRect.iTl.iX;
+    const TInt x2   = aRect.iBr.iX-1;   // inclusive!
+    const TInt y    = aRect.iTl.iY;
+    TInt h  = aRect.Height();
+
+    address += y*linePitch;
+    for (; h>0; --h)
+    {
+        for (TInt x=x1; x<=x2; x++)
+        {
+            TUint8 m = address[(x>>3)];
+            TUint8 p = m >> (x&0x7);
+
+            if (p&0x1)
+            {
+                return ETrue;
+            }
+        }
+        address += linePitch;
+    }
+
+    return EFalse;
+}
+
+TBool HasOpaquePixelGray256
+(
+    const TAcceleratedBitmapInfo*   aGray256Bitmap,
+    const TRect&                    aRect
+)
+{
+    ASSERT(aGray256Bitmap->iDisplayMode == EGray256);
+
+    const TInt linePitch = aGray256Bitmap->iLinePitch;
+    TUint8* address      = aGray256Bitmap->iAddress;
+
+    const TInt x = aRect.iTl.iX;
+    const TInt y = aRect.iTl.iY;
+    const TInt w = aRect.Width();
+    TInt h = aRect.Height();
+
+    address += y*linePitch + x*sizeof(TUint8);
+    for (; h>0; --h)
+    {
+        TUint8* ptr = address;
+        const TUint8* end = ptr + w;
+
+        while (ptr < end)
+        {
+            // semi-transparent is treated as transparent.
+            TUint8 m = *ptr++;
+            if (m == 255)
+            {
+                return ETrue;
+            }
+        }
+        address += linePitch;
+    }
+
+    return EFalse;
+}
+