javauis/lcdui_akn/lcdgd/src/lcdbitblt.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 27 Apr 2010 16:30:29 +0300
branchRCL_3
changeset 14 04becd199f91
permissions -rw-r--r--
Revision: v2.1.22 Kit: 201017

/*
* 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 <graphicsaccelerator.h>
#include <gdi.h>
#include "lcdgdrvif.h"
#include "lcdgdrvutil.h"
#include "lcdtransform.h"
#include "lcdbitblt.h"

LOCAL_C INLINE TInt PixelPitch(const TAcceleratedBitmapInfo* aBitmap)
{
    switch (aBitmap->iDisplayMode)
    {
    case EColor64K:
    case EColor4K:
        return 2;
    case EColorARGB8888:
    case EColor16MU:
        return 4;
    case EGray256:
        return 1;
    }

    // Any other display mode is either invalid, or has a fractional number of
    // bytes per pixel, and cannot be handled by this routine.
    ASSERT(EFalse);
    return 0;   // Pacify the compiler
}

extern void GenericBlit
(
    const TAcceleratedBitmapInfo*   aDstColorBitmap,
    const TRect&                    aDstRect,       // must be clipped to destination
    const TAcceleratedBitmapInfo*   aSrcColorBitmap,
    const TLcdTransform&            aTransform,     // includes anchor
    TBlitLineFunction               aBlitLineFn     // function to call on each line
)
{
    ASSERT(aDstColorBitmap != NULL);
    ASSERT(aSrcColorBitmap != NULL);

    TPoint srcPoint = aTransform(aDstRect.iTl);

    TInt dudx = aTransform.iDuDx;
    TInt dudy = aTransform.iDuDy;
    TInt dvdx = aTransform.iDvDx;
    TInt dvdy = aTransform.iDvDy;

    //
    // For each bitmap, calculate the starting address and byte offsets to the
    // next address for one line down and one pixel right.
    //
    const TInt dstLinePitch = aDstColorBitmap->iLinePitch;
    const TInt dstPixelPitch = PixelPitch(aDstColorBitmap);
    TUint8* dstAddress = aDstColorBitmap->iAddress;
    dstAddress += aDstRect.iTl.iY * dstLinePitch + aDstRect.iTl.iX * dstPixelPitch;

    const TInt colorLinePitch = aSrcColorBitmap->iLinePitch;
    const TInt colorPixelPitch = PixelPitch(aSrcColorBitmap);
    TUint8* colorAddress = aSrcColorBitmap->iAddress;
    colorAddress += srcPoint.iY * colorLinePitch + srcPoint.iX * colorPixelPitch;

    // For the source bitmap, also calculate the pitch to the next address for
    // one line down and one pixel right in the destination bitmap.
    const TInt colorDstLinePitch = colorLinePitch * dvdy + colorPixelPitch * dudy;
    const TInt colorDstPixelPitch = colorLinePitch * dvdx + colorPixelPitch * dudx;

    //
    // Iterate over destination pixels.
    //
    const TInt width = aDstRect.Width();
    TInt h = aDstRect.Height();
    while (h-- > 0)
    {
        (*aBlitLineFn)(dstAddress, width, colorAddress, colorDstPixelPitch);
        dstAddress += dstLinePitch;
        colorAddress += colorDstLinePitch;
    }
}


extern void GenericMaskBlit
(
    const TAcceleratedBitmapInfo*   aDstColorBitmap,
    const TRect&                    aDstRect,       // must be clipped to destination
    const TAcceleratedBitmapInfo*   aSrcColorBitmap,
    const TLcdTransform&            aTransform,     // includes anchor
    const TAcceleratedBitmapInfo*   aAlphaBitmap,   // source or destination alpha
    TBool                           aIsSrcAlpha,    // ETrue if alpha is source
    TMaskBlitLineFunction           aBlitLineFn     // function to call on each line
)
{
    ASSERT(aDstColorBitmap != NULL);
    ASSERT(aSrcColorBitmap != NULL);
    ASSERT(aAlphaBitmap != NULL);

    TPoint srcPoint = aTransform(aDstRect.iTl);

    TInt dudx = aTransform.iDuDx;
    TInt dudy = aTransform.iDuDy;
    TInt dvdx = aTransform.iDvDx;
    TInt dvdy = aTransform.iDvDy;

    //
    // For each bitmap, calculate the starting address and byte offsets to the
    // next address for one line down and one pixel right.
    //
    const TInt dstLinePitch = aDstColorBitmap->iLinePitch;
    const TInt dstPixelPitch = PixelPitch(aDstColorBitmap);
    TUint8* dstAddress = aDstColorBitmap->iAddress;
    dstAddress += aDstRect.iTl.iY * dstLinePitch + aDstRect.iTl.iX * dstPixelPitch;

    const TInt colorLinePitch = aSrcColorBitmap->iLinePitch;
    const TInt colorPixelPitch = PixelPitch(aSrcColorBitmap);
    TUint8* colorAddress = aSrcColorBitmap->iAddress;
    colorAddress += srcPoint.iY * colorLinePitch + srcPoint.iX * colorPixelPitch;

    const TInt alphaLinePitch = aAlphaBitmap->iLinePitch;
    const TInt alphaPixelPitch = PixelPitch(aAlphaBitmap);
    TUint8* alphaAddress = aAlphaBitmap->iAddress;

    // Choose the start according to whether alpha/mask is source or destination
    TPoint alphaTl(aIsSrcAlpha ? srcPoint : aDstRect.iTl);
    alphaAddress += alphaTl.iY * alphaLinePitch + alphaTl.iX * alphaPixelPitch;

    // For the source and alpha bitmaps, also calculate the pitch to the next
    // address for one line down and one pixel right in the destination bitmap.
    const TInt colorDstLinePitch = colorLinePitch * dvdy + colorPixelPitch * dudy;
    const TInt colorDstPixelPitch = colorLinePitch * dvdx + colorPixelPitch * dudx;

    TInt alphaDstLinePitch;
    TInt alphaDstPixelPitch;
    if (aIsSrcAlpha)
    {
        alphaDstLinePitch = alphaLinePitch * dvdy + alphaPixelPitch * dudy;
        alphaDstPixelPitch = alphaLinePitch * dvdx + alphaPixelPitch * dudx;
    }
    else
    {
        alphaDstLinePitch = alphaLinePitch;
        alphaDstPixelPitch = alphaPixelPitch;
    }

    //
    // Iterate over destination pixels.
    //
    const TInt width = aDstRect.Width();
    TInt h = aDstRect.Height();
    while (h-- > 0)
    {
        (*aBlitLineFn)(dstAddress, width, colorAddress, colorDstPixelPitch,
                       alphaAddress, alphaDstPixelPitch);
        dstAddress += dstLinePitch;
        colorAddress += colorDstLinePitch;
        alphaAddress += alphaDstLinePitch;
    }
}


extern void BitBltOneBpp
(
    const TAcceleratedBitmapInfo*   aDstColorBitmap,
    const TAcceleratedBitmapInfo*   /*aDstAlphaBitmap*/,
    const TRect&                    aDstRect,
    const TAcceleratedBitmapInfo*   aSrcColorBitmap,
    const TAcceleratedBitmapInfo*   /*aSrcAlphaBitmap*/,
    const TLcdTransform&            aTransform
)
{
    TPoint srcPoint = aTransform(aDstRect.iTl);

    TInt dudx = aTransform.iDuDx;
    TInt dudy = aTransform.iDuDy;
    TInt dvdx = aTransform.iDvDx;
    TInt dvdy = aTransform.iDvDy;
    TInt u0   = srcPoint.iX;
    TInt v0   = srcPoint.iY;
    TInt u    = u0;
    TInt v    = v0;

    TUint8* dstAddress = aDstColorBitmap->iAddress;
    TUint8* srcAddress = aSrcColorBitmap->iAddress;
    TInt dstLinePitch  = aDstColorBitmap->iLinePitch;
    TInt srcLinePitch  = aSrcColorBitmap->iLinePitch;

    TInt height = aDstRect.Height();
    TInt width  = aDstRect.Width();

    const TInt x0 = aDstRect.iTl.iX;
    const TInt x3 = aDstRect.iBr.iX;
    const TInt x2 = Max(x0, aDstRect.iBr.iX & ~7);
    const TInt x1 = Min(x3,(aDstRect.iTl.iX + 7) & ~7);

    for (; height>0; --height)
    {
        TUint8 accum;
        TInt x;

        u = u0;
        v = v0;

        x = x0;
        if (x < x1)
        {
            //
            // Left edge.
            //
            accum = dstAddress[x0>>3];
            for (; x<x1; x++)
            {
                TUint8 mb = 1<<(x&0x7);
                TUint8 sb = *(srcAddress + srcLinePitch*v + (u>>3));

                if (sb & (1<<(u&7)))
                {
                    accum |= mb;
                }
                else
                {
                    accum &= ~mb;
                }

                u += dudx;
                v += dvdx;
            }
            dstAddress[x0>>3] = accum;
        }

        //
        // Middle section.
        //
        for (; x<x2; x+=8)
        {
            ASSERT((x & 7) == 0);   // must be byte aligned
            accum = 0;
            for (TInt j=0; j<8; j++)
            {
                TUint8 sb = *(srcAddress + srcLinePitch*v + (u>>3));
                if (sb & (1<<(u&7)))
                {
                    accum |= (1<<j);
                }
                u += dudx;
                v += dvdx;
            }
            dstAddress[x>>3] = accum;
        }

        //
        // Right edge
        //
        if (x < x3)
        {
            accum = dstAddress[x>>3];
            for (; x<=x3; x++)
            {
                TUint8 mb = 1<<(x&0x7);
                TUint8 sb = *(srcAddress + srcLinePitch*v + (u>>3));

                if (sb & (1<<(u&7)))
                {
                    accum |= mb;
                }
                else
                {
                    accum &= ~mb;
                }

                u += dudx;
                v += dvdx;
            }
            dstAddress[x>>3] = accum;
        }
        u0 += dudy;
        v0 += dvdy;
        dstAddress += dstLinePitch;
    }
}


LOCAL_C void BlitLineEightBppSimple
(
    TUint8* aDstAddress,
    TInt    aWidth,
    TUint8* aColorAddress,
    TInt    aColorPixelPitch
)
{
    ASSERT(aColorPixelPitch == sizeof(TUint8));
    UNUSED(aColorPixelPitch);   // ASSERT is the only use otherwise.

    Mem::Copy(aDstAddress, aColorAddress, aWidth);
}


extern void BitBltEightBppSimple
(
    const TAcceleratedBitmapInfo*   aDstColorBitmap,
    const TAcceleratedBitmapInfo*   /*aDstAlphaBitmap*/,
    const TRect&                    aDstRect,
    const TAcceleratedBitmapInfo*   aSrcColorBitmap,
    const TAcceleratedBitmapInfo*   /*aSrcAlphaBitmap*/,
    const TLcdTransform&            aTransform
)
{
    GenericBlit(aDstColorBitmap, aDstRect, aSrcColorBitmap, aTransform,
                BlitLineEightBppSimple);
}


LOCAL_C void BlitLineEightBpp
(
    TUint8* aDstAddress,
    TInt    aWidth,
    TUint8* aColorAddress,
    TInt    aColorPixelPitch
)
{
    TUint8* dst = aDstAddress;
    TUint8* end = dst + aWidth;

    TUint8* colorAddr = aColorAddress;
    while (dst < end)
    {
        *dst++ = *colorAddr;
        colorAddr += aColorPixelPitch;
    }
}


extern void BitBltEightBpp
(
    const TAcceleratedBitmapInfo*   aDstColorBitmap,
    const TAcceleratedBitmapInfo*   /*aDstAlphaBitmap*/,
    const TRect&                    aDstRect,
    const TAcceleratedBitmapInfo*   aSrcColorBitmap,
    const TAcceleratedBitmapInfo*   /*aSrcAlphaBitmap*/,
    const TLcdTransform&            aTransform
)
{
    GenericBlit(aDstColorBitmap, aDstRect, aSrcColorBitmap, aTransform,
                BlitLineEightBpp);
}