graphicsresourceservices/graphicsresource/src/sgutils.cpp
author jakl.martin@cell-telecom.com
Mon, 06 Dec 2010 18:07:30 +0100
branchNewGraphicsArchitecture
changeset 218 99b3451c560e
parent 0 5d03bc08d59c
permissions -rw-r--r--
Fix for Bug 3890

// Copyright (c) 2008-2009 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 "sgutils.h"


// Helper function used to transfer a scanline in 64K to the various formats of the destination.
LOCAL_C void TransferScanLine64K(TUint8* aDest, const TUint16* aSrc, TUidPixelFormat aPixelFormatDest, TInt aPixelLength)
	{
	switch (aPixelFormatDest)
		{
	case EUidPixelFormatRGB_565:
		{
		Mem::Copy(aDest, aSrc, aPixelLength << 1);
		break;
		}
	case EUidPixelFormatARGB_8888_PRE:
		{
		TUint32* dest = reinterpret_cast<TUint32*>(aDest);
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*dest++ = TRgb::Color64K(*aSrc++).Color16MAP();
			}
		break;
		}
	case EUidPixelFormatARGB_8888:
		{
		TUint32* dest = reinterpret_cast<TUint32*>(aDest);
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*dest++ = TRgb::Color64K(*aSrc++).Color16MA();
			}
		break;
		}
	case EUidPixelFormatXRGB_8888:
		{
		TUint32* dest = reinterpret_cast<TUint32*>(aDest);
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*dest++ = (TRgb::Color64K(*aSrc++).Color16MU() | 0xff000000);
			}
		break;
		}
	case EUidPixelFormatRGB_888:
		{
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			TInt col = TRgb::Color64K(*aSrc++).Color16M();
			*aDest++ = col;
			*aDest++ = col >> 8;
			*aDest++ = col >> 16;
			}
		break;
		}
	case EUidPixelFormatXRGB_4444:
		{
		TUint16* dest = reinterpret_cast<TUint16*>(aDest);
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*dest++ = TRgb::Color64K(*aSrc++).Color4K();
			}
		break;
		}
	case EUidPixelFormatP_8:
		{
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest++ = TRgb::Color64K(*aSrc++).Color256();
			}
		break;
		}
	case EUidPixelFormatL_8:
		{
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest++ = TRgb::Color64K(*aSrc++).Gray256();
			}
		break;
		}
	case EUidPixelFormatL_4:
		{
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest = 0;
			for (TInt index = 0; (index < 8) && (aSrc < srcEnd); index+= 4)
				{
				TInt col = TRgb::Color64K(*aSrc++).Gray16();
				col <<= index;
				*aDest |= col;
				}
			aDest++;
			}
		break;
		}
	case EUidPixelFormatP_4:
		{
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest = 0;
			for (TInt index = 0; (index < 8) && (aSrc < srcEnd); index+= 4)
				{
				TInt col = TRgb::Color64K(*aSrc++).Color16();
				col <<= index;
				*aDest |= col;
				}
			aDest++;
			}
		break;
		}
	case EUidPixelFormatL_2:
		{
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest = 0;
			for (TInt index = 0; (index < 8) && (aSrc < srcEnd); index+= 2)
				{
				TInt col = TRgb::Color64K(*aSrc++).Gray4();
				col <<= index;
				*aDest |= col;
				}
			aDest++;
			}
		break;
		}
	case EUidPixelFormatL_1:
		{
		const TUint16* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest = 0;
			for (TInt index = 0; (index < 8) && (aSrc < srcEnd); index++)
				{
				TInt col = TRgb::Color64K(*aSrc++).Gray2();
				col <<= index;
				*aDest |= col;
				}
			aDest++;
			}
		break;
		}
	default:
		break;
		}
	}

// Helper function used to transfer a scanline in 16MAP to the various formats of the destination.
LOCAL_C void TransferScanLine16MAP(TUint8* aDest, const TUint32* aSrc, TUidPixelFormat aPixelFormatDest, TInt aPixelLength)
	{
	switch (aPixelFormatDest)
		{
	case EUidPixelFormatARGB_8888_PRE:
		{
		Mem::Copy(aDest, aSrc, aPixelLength << 2);
		break;
		}
	case EUidPixelFormatARGB_8888:
		{
		TUint32* dest = reinterpret_cast<TUint32*>(aDest);
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*dest++ = TRgb::Color16MAP(*aSrc++).Color16MA();
			}
		break;
		}
	case EUidPixelFormatXRGB_8888:
		{
		TUint32* dest = reinterpret_cast<TUint32*>(aDest);
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*dest++ = (TRgb::Color16MAP(*aSrc++).Color16MU() | 0xff000000);
			}
		break;
		}
	case EUidPixelFormatRGB_888:
		{
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			TInt col = TRgb::Color16MAP(*aSrc++).Color16M();
			*aDest++ = col;
			*aDest++ = col >> 8;
			*aDest++ = col >> 16;
			}
		break;
		}
	case EUidPixelFormatRGB_565:
		{
		TUint16* dest = reinterpret_cast<TUint16*>(aDest);
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*dest++ = TRgb::Color16MAP(*aSrc++).Color64K();
			}
		break;
		}
	case EUidPixelFormatXRGB_4444:
		{
		TUint16* dest = reinterpret_cast<TUint16*>(aDest);
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*dest++ = TRgb::Color16MAP(*aSrc++).Color4K();
			}
		break;
		}
	case EUidPixelFormatP_8:
		{
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest++ = TRgb::Color16MAP(*aSrc++).Color256();
			}
		break;
		}
	case EUidPixelFormatL_8:
		{
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest++ = TRgb::Color16MAP(*aSrc++).Gray256();
			}
		break;
		}
	case EUidPixelFormatL_4:
		{
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest = 0;
			for (TInt index = 0; (index < 8) && (aSrc < srcEnd); index+= 4)
				{
				TInt col = TRgb::Color16MAP(*aSrc++).Gray16();
				col <<= index;
				*aDest |= col;
				}
			aDest++;
			}
		break;
		}
	case EUidPixelFormatP_4:
		{
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest = 0;
			for (TInt index = 0; (index < 8) && (aSrc < srcEnd); index+= 4)
				{
				TInt col = TRgb::Color16MAP(*aSrc++).Color16();
				col <<= index;
				*aDest |= col;
				}
			aDest++;
			}
		break;
		}
	case EUidPixelFormatL_2:
		{
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest = 0;
			for (TInt index = 0; (index < 8) && (aSrc < srcEnd); index+= 2)
				{
				TInt col = TRgb::Color16MAP(*aSrc++).Gray4();
				col <<= index;
				*aDest |= col;
				}
			aDest++;
			}
		break;
		}
	case EUidPixelFormatL_1:
		{
		const TUint32* srcEnd = aSrc + aPixelLength;
		while (aSrc < srcEnd)
			{
			*aDest = 0;
			for (TInt index = 0; (index < 8) && (aSrc < srcEnd); index++)
				{
				TInt col = TRgb::Color16MAP(*aSrc++).Gray2();
				col <<= index;
				*aDest |= col;
				}
			aDest++;
			}
		}
	default:
		break;
		}
	}

// Helper function used to copy a buffer in 64K to the various formats of the destination.
LOCAL_C TInt TransferPixels64K(TAny* aDataAddressDest, TInt aDataStrideDest, TUidPixelFormat aPixelFormatDest,
                               const TUint16* aDataAddressSrc, TInt aDataStrideSrc, const TRect& aRectSource)
	{
	TInt err = KErrNone;
	const TInt width = aRectSource.Width();
	const TUint16* dataAddressSrc = PtrAdd(aDataAddressSrc + aRectSource.iTl.iX, aRectSource.iTl.iY * aDataStrideSrc);
	const TUint16* dataAddressSrcEnd = PtrAdd(dataAddressSrc, aDataStrideSrc * aRectSource.Height());

	switch (aPixelFormatDest)
		{
	case EUidPixelFormatRGB_565:
		{
		TUint8* dataAddressDest = static_cast<TUint8*>(aDataAddressDest);
		const TInt dataLength = width << 1;
		while (dataAddressSrcEnd > dataAddressSrc)
			{
			Mem::Copy(dataAddressDest, dataAddressSrc, dataLength);
			dataAddressSrc = PtrAdd(dataAddressSrc, aDataStrideSrc);
			dataAddressDest += aDataStrideDest;
			}
		break;
		}
	case EUidPixelFormatARGB_8888_PRE:
	case EUidPixelFormatARGB_8888:
	case EUidPixelFormatXRGB_8888:
	case EUidPixelFormatXRGB_4444:
	case EUidPixelFormatL_1:
	case EUidPixelFormatL_2:
	case EUidPixelFormatL_4:
	case EUidPixelFormatL_8:
	case EUidPixelFormatP_4:
	case EUidPixelFormatP_8:
	case EUidPixelFormatRGB_888:
		{
		TUint8* dataAddressDest = static_cast<TUint8*>(aDataAddressDest);
		while (dataAddressSrcEnd > dataAddressSrc)
			{
			TransferScanLine64K(dataAddressDest, dataAddressSrc, aPixelFormatDest, width);
			dataAddressSrc = PtrAdd(dataAddressSrc, aDataStrideSrc);
			dataAddressDest += aDataStrideDest;
			}
		break;
		}
	default:
		err = KErrNotSupported;
		break;
		}
	return err;
	}

// Helper function used to copy a buffer in 16MAP to the various formats of the destination.
LOCAL_C TInt TransferPixels16MAP(TAny* aDataAddressDest, TInt aDataStrideDest, TUidPixelFormat aPixelFormatDest,
                                 const TUint32* aDataAddressSrc, TInt aDataStrideSrc, const TRect& aRectSource)
	{
	TInt err = KErrNone;
	const TInt width = aRectSource.Width();
	const TUint32* dataAddressSrc = PtrAdd(aDataAddressSrc + aRectSource.iTl.iX, aRectSource.iTl.iY * aDataStrideSrc);
	const TUint32* dataAddressSrcEnd = PtrAdd(dataAddressSrc, aRectSource.Height() * aDataStrideSrc);

	switch (aPixelFormatDest)
		{
	case EUidPixelFormatARGB_8888_PRE:
			{
			TUint8* dataAddressDest = static_cast<TUint8*>(aDataAddressDest);
			const TInt dataLength = width << 2;
			while (dataAddressSrcEnd > dataAddressSrc)
				{
				Mem::Copy(dataAddressDest, dataAddressSrc, dataLength);
				dataAddressSrc = PtrAdd(dataAddressSrc, aDataStrideSrc);
				dataAddressDest += aDataStrideDest;
				}
			break;
			}
	case EUidPixelFormatXRGB_8888:
	case EUidPixelFormatARGB_8888:
	case EUidPixelFormatRGB_565:
	case EUidPixelFormatXRGB_4444:
	case EUidPixelFormatL_1:
	case EUidPixelFormatL_2:
	case EUidPixelFormatL_4:
	case EUidPixelFormatL_8:
	case EUidPixelFormatP_4:
	case EUidPixelFormatP_8:
	case EUidPixelFormatRGB_888:
		{
		TUint8* dataAddressDest = static_cast<TUint8*> (aDataAddressDest);
		while (dataAddressSrcEnd > dataAddressSrc)
			{
			TransferScanLine16MAP(dataAddressDest, dataAddressSrc, aPixelFormatDest, width);
			dataAddressSrc = PtrAdd(dataAddressSrc, aDataStrideSrc);
			dataAddressDest += aDataStrideDest;
			}
		break;
		}
	default:
		err = KErrNotSupported;
		break;
		}
	return err;
	}


/**
@publishedPartner
@prototype
@deprecated

Convert from display mode to pixel format.

@param aDisplayMode Display mode to convert.

@return Pixel format corresponding to aDisplayMode, or EUidPixelFormatUnknown if aDisplayMode does not match any existing pixel format.
*/
EXPORT_C TUidPixelFormat SgUtils::DisplayModeToPixelFormat(TDisplayMode aDisplayMode)
	{
	switch (aDisplayMode)
		{
	case EGray2:
		return EUidPixelFormatL_1;
	case EGray4:
		return EUidPixelFormatL_2;
	case EGray16:
		return EUidPixelFormatL_4;
	case EGray256:
		return EUidPixelFormatL_8;
	case EColor16:
		return EUidPixelFormatP_4;
	case EColor256:
		return EUidPixelFormatP_8;
	case EColor4K:
		return EUidPixelFormatXRGB_4444;
	case EColor64K:
		return EUidPixelFormatRGB_565;
	case EColor16M:
		return EUidPixelFormatRGB_888;
	case EColor16MU:
		return EUidPixelFormatXRGB_8888;
	case ERgb:
	case EColor16MA:
		return EUidPixelFormatARGB_8888;
	case EColor16MAP:
		return EUidPixelFormatARGB_8888_PRE;
	default:
		break;
		}
	return EUidPixelFormatUnknown;
	}


/**
@publishedPartner
@prototype
@deprecated

Convert from pixel format to display mode.

@param aPixelFormat Pixel format to convert.

@return Display mode corresponding to aPixelFormat, or ENone if aPixelFormat does not match any existing display mode.
*/
EXPORT_C TDisplayMode SgUtils::PixelFormatToDisplayMode(TUidPixelFormat aPixelFormat)
	{
	switch (aPixelFormat)
		{
	case EUidPixelFormatL_1:
		return EGray2;
	case EUidPixelFormatL_2:
		return EGray4;
	case EUidPixelFormatL_4:
		return EGray16;
	case EUidPixelFormatL_8:
		return EGray256;
	case EUidPixelFormatP_4:
		return EColor16;
	case EUidPixelFormatP_8:
		return EColor256;
	case EUidPixelFormatXRGB_4444:
		return EColor4K;
	case EUidPixelFormatRGB_565:
		return EColor64K;
	case EUidPixelFormatRGB_888:
		return EColor16M;
	case EUidPixelFormatXRGB_8888:
		return EColor16MU;
	case EUidPixelFormatARGB_8888:
		return EColor16MA;
	case EUidPixelFormatARGB_8888_PRE:
		return EColor16MAP;
	default:
		break;
		}
	return ENone;
	}


/**
@publishedPartner
@prototype
@deprecated

Calculates the minimum number of bytes between rows of data in a bi-dimensional pixel buffer.
The returned value is not guaranteed to be aligned onto any boundary.

@param aWidth Width in pixels of the buffer.
@param aPixelFormat Pixel format of the buffer.
@return The minimum number of bytes between rows of data in a buffer with the given width and pixel format,
        or KErrNotSupported if aPixelFormat is not recognized.
*/
EXPORT_C TInt SgUtils::MinDataStride(TInt aWidth, TUidPixelFormat aPixelFormat)
	{
	switch (aPixelFormat)
		{
	case EUidPixelFormatXRGB_8888:
	case EUidPixelFormatBGRX_8888:
	case EUidPixelFormatXBGR_8888:
	case EUidPixelFormatBGRA_8888:
	case EUidPixelFormatARGB_8888:
	case EUidPixelFormatABGR_8888:
	case EUidPixelFormatARGB_8888_PRE:
	case EUidPixelFormatABGR_8888_PRE:
	case EUidPixelFormatBGRA_8888_PRE:
	case EUidPixelFormatARGB_2101010:
	case EUidPixelFormatABGR_2101010:
		return aWidth << 2;
	case EUidPixelFormatBGR_888:
	case EUidPixelFormatRGB_888:
		return aWidth * 3;
	case EUidPixelFormatRGB_565:
	case EUidPixelFormatBGR_565:
	case EUidPixelFormatARGB_1555:
	case EUidPixelFormatXRGB_1555:
	case EUidPixelFormatARGB_4444:
	case EUidPixelFormatARGB_8332:
	case EUidPixelFormatBGRX_5551:
	case EUidPixelFormatBGRA_5551:
	case EUidPixelFormatBGRA_4444:
	case EUidPixelFormatBGRX_4444:
	case EUidPixelFormatAP_88:
	case EUidPixelFormatXRGB_4444:
	case EUidPixelFormatXBGR_4444:
		return aWidth << 1;
	case EUidPixelFormatRGB_332:
	case EUidPixelFormatA_8:
	case EUidPixelFormatBGR_332:
	case EUidPixelFormatP_8:
	case EUidPixelFormatL_8:
		return aWidth;
	case EUidPixelFormatP_4:
	case EUidPixelFormatL_4:
		return (aWidth + 1) >> 1;
	case EUidPixelFormatP_2:
	case EUidPixelFormatL_2:
		return (aWidth + 3) >> 2;
	case EUidPixelFormatP_1:
	case EUidPixelFormatL_1:
		return (aWidth + 7) >> 3;
	default:
		return KErrNotSupported;
		}
	}


/**
@publishedPartner
@prototype
@deprecated

Transfer data from one bi-dimensional pixel buffer to another bi-dimensional pixel buffer with a different pixel format.
The pixel format conversion may involve some data loss. This function currently supports the following pixel formats.
	- For the source: EUidPixelFormatRGB_565, EUidPixelFormatARGB_8888_PRE.
	- For the destination: EUidPixelFormatARGB_8888_PRE, EUidPixelFormatARGB_8888, EUidPixelFormatXRGB_8888, EUidPixelFormatRGB_888,
	  EUidPixelFormatRGB_565, EUidPixelFormatXRGB_4444, EUidPixelFormatP_8, EUidPixelFormatL_8, EUidPixelFormatL_4, EUidPixelFormatP_4,
	  EUidPixelFormatL_2, EUidPixelFormatL_1.

@param aDataAddressDest The base address of the destination pixel buffer.
@param aDataStrideDest The number of bytes between rows of data in the destination pixel buffer.
@param aPixelFormatDest Pixel format of the destination buffer.
@param aDataAddressSrc The base address of the source pixel buffer.
@param aDataStrideSrc The number of bytes between rows of data in the source pixel buffer.
@param aPixelFormatSrc Pixel format of the source buffer.
@param aRectSource Rectangle of the source pixel buffer which will be transferred to the destination pixel buffer.

@return KErrNone if successful.
@return KErrArgument If arguments do not lie within expected range.
@return KErrNotSupported If source or destination format is not supported.
*/
EXPORT_C TInt SgUtils::TransferPixels(TAny* aDataAddressDest, TInt aDataStrideDest, TUidPixelFormat aPixelFormatDest,
                                      const TAny* aDataAddressSrc, TInt aDataStrideSrc, TUidPixelFormat aPixelFormatSrc,
                                      const TRect& aRectSource)
	{
	if (aRectSource.IsEmpty() || !aDataAddressDest || !aDataAddressSrc || (aDataStrideDest <= 0) || (aDataStrideSrc <= 0)
		|| (SgUtils::MinDataStride(aRectSource.iBr.iX, aPixelFormatSrc) > aDataStrideSrc)
		|| (SgUtils::MinDataStride(aRectSource.Width(), aPixelFormatDest) > aDataStrideDest))
		{
		return KErrArgument;
		}

	TInt err = KErrNotSupported;
	switch (aPixelFormatSrc)
		{
	case EUidPixelFormatRGB_565:
		{
		err = TransferPixels64K(aDataAddressDest, aDataStrideDest, aPixelFormatDest,
		                        static_cast<const TUint16*>(aDataAddressSrc), aDataStrideSrc, aRectSource);
		break;
		}
	case EUidPixelFormatARGB_8888_PRE:
		{
		err = TransferPixels16MAP(aDataAddressDest, aDataStrideDest, aPixelFormatDest,
		                          static_cast<const TUint32*>(aDataAddressSrc), aDataStrideSrc, aRectSource);
		break;
		}
	default:
		break;
		}
	return err;
	}