diff -r 000000000000 -r 5d03bc08d59c fbs/fontandbitmapserver/sfbs/BMPUTIL.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fbs/fontandbitmapserver/sfbs/BMPUTIL.CPP Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,693 @@ +// Copyright (c) 1995-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 +#include +#include "fbsdefs.h" +#include "UTILS.H" + +GLREF_C void Panic(TFbsPanic aPanic); + +/* Macros used in support of EColor16M mode bitmaps in TBitmapUtil. +PTR2UINT, UINT2PTR defined to ease byte pointer arithmatic using +the existing iWordPos word sized pointer. +i MACROS redefine the meaning of members in the class for 16M use. +All in the name of Binary Compatibility - adding 16M support but +without wasting memory or increasing the size of this class's objects. */ +#define PTR2UINT(_ptr) reinterpret_cast(_ptr) +#define UINT2PTR(_expr) reinterpret_cast(_expr) +#define iNUM_WASTE_BYTES iMask +#define iSTART_OF_SCAN_LINE iWordPos +#define iPIXEL_BYTE_OFFSET iPixelShift +#define iPIXEL_ADDRESS UINT2PTR(PTR2UINT(iWordPos)+iPixelShift) + + +/** Constructs a TBitmapUtil object for the specified bitmap. + +@param aBitmap The bitmap on which this TBitmapUtil will operate. */ +EXPORT_C TBitmapUtil::TBitmapUtil(CFbsBitmap* aBitmap): + iFbsBitmap(aBitmap), // Address of bitmap to navigate and modify. + iWordPos(NULL), // Non16M: Address of the word containing the bits + // of the current pixel. + // 16M: Redefined to iSTART_OF_SCAN_LINE - word address + // of the scan line containing the current pixel. + iMinWordPos(NULL), // Member holds the word address of the top left pixel. + iMaxWordPos(NULL), // Member holds address of the word following the last + // word in the last scan line of the bitmap. + iBpp(0), // Number of bits needed for each pixel's data. + iPixelShift(0), // Non16M: Right shift factor to convert pixel index + // to word index into scan line. + // 16M: Redefined to iPIXEL_BYTE_OFFSET - index to first + // byte in pixel from the start of the scan line. + iBitShift(0), // Non16M: Changing index of right shift require to + // move pixel bits into LSB of word. + // 16M: Not used, always 0 + iMask(0), // Non16M: Mask of LSB required to hold + // pixel data eg. 16cols 0x0f + // 16M: Redefined to iNUM_WASTE_BYTES - number of + // padding bytes at end of scan line 0,3,6,9 as 16M + // scanlines are always multiples of 12 bytes. + iScanlineWordLength(0), // Number of 4-byte words in bitmap scan line + iWritten(EFalse) + {} + +/** Sets the current pixel position to the specified position and prepares +the bitmap for access to its pixel data. + +This function must be called before using any of the other functions provided +by this class, otherwise damage to data may occur. It must also be matched +by a subsequent call to End(). + +@pre The bitmap which was passed on class construction has been created and holds + a valid handle. +@param aPosition The position to which the current pixel position should be +set. */ +EXPORT_C void TBitmapUtil::Begin(const TPoint& aPosition) + { + ASSERT(iFbsBitmap); + iFbsBitmap->BeginDataAccess(); + TSize bmpsize(iFbsBitmap->SizeInPixels()); + ASSERT(bmpsize.iWidth > 0 && bmpsize.iHeight > 0); + + iWritten = EFalse; + + TDisplayMode dm=iFbsBitmap->DisplayMode(); + TInt numBytesInScanline = CFbsBitmap::ScanLineLength(bmpsize.iWidth,dm); + switch(dm) + { + case EGray2: + iMask=1; + iPixelShift=5; + iBpp=1; + break; + case EGray4: + iMask=3; + iPixelShift=4; + iBpp=2; + break; + case EGray16: + case EColor16: + iMask=0xf; + iPixelShift=3; + iBpp=4; + break; + case EGray256: + case EColor256: + iMask=0xff; + iPixelShift=2; + iBpp=8; + break; + case EColor4K: + case EColor64K: + iMask=0xffff; + iPixelShift=1; + iBpp=16; + break; + /* Bit twiddling not used in the EColor16M, members redefined for + different use. */ + case EColor16M: + iNUM_WASTE_BYTES = numBytesInScanline-(bmpsize.iWidth*3); + iPIXEL_BYTE_OFFSET=0; + iBpp=24; // Indicates 16M display mode, flag for member functions + // to switch functionality. + break; + case EColor16MU: + case EColor16MA: + case EColor16MAP: + iMask=0xffffffff; + iPixelShift=0; + iBpp=32; + break; + default: //shouldn't reach this point + Panic(EFbsBitmapInvalidMode); + } + + iMinWordPos=(TUint32*)iFbsBitmap->DataAddress(); + iScanlineWordLength = numBytesInScanline / 4; + iMaxWordPos = iMinWordPos + (bmpsize.iHeight * iScanlineWordLength); + + TPoint correct(aPosition); + if(correct.iX<0) correct.iX=0; + if(correct.iY<0) correct.iY=0; + if(correct.iX>=bmpsize.iWidth) correct.iX=bmpsize.iWidth; + if(correct.iY>=bmpsize.iHeight) correct.iY=bmpsize.iHeight; + SetPos(correct); + } + +/** Sets the current pixel position to the specified position and prepares +the bitmap for access to its pixel data. + +This function is deprecated. Use the other overload, Begin(const TPoint&). +@deprecated + +@param aPosition The position to which the current pixel position should be +set. +@param aUtil Not used. +@panic FBCLI 10 The bitmap's display mode is ERgb or ENone. */ +EXPORT_C void TBitmapUtil::Begin(const TPoint& aPosition, const TBitmapUtil& /*aUtil*/) + { + Begin(aPosition); + } + +/** Marks the end of the access to the bitmap data. +This function must be called when finished using all the other functions +provided by this class. + +There must be exactly one call to End() for each previous call to Begin() +for a given TBitmapUtil object. */ +EXPORT_C void TBitmapUtil::End() + { + iFbsBitmap->EndDataAccess(!iWritten); + } + + + +/** Gets the value of the pixel at the current pixel position. + +In normal usage, the value returned will immediately be used as the parameter +to a call to SetPixel(). To remove the overhead of constructing a TRgb, the +function uses a TUint32 rather than a TRgb to hold an RGB value. + +@return The value of the pixel at the current pixel position. */ +EXPORT_C TUint32 TBitmapUtil::GetPixel() const + { + if (iBpp!=24) + // 1,2,4,8,12,16,32-bit pixels + return((*iWordPos>>iBitShift)&iMask); + else + { + // 24-bit pixels + // Due to machine word alignment requirement on ARM, need to copy + // pixel data at iWordPos a byte at a time if address is not aligned + // on a 4 byte boundary i.e. 1st or 2nd least sig. bits set. + if (iPIXEL_BYTE_OFFSET & 0x3) + { + TUint32 pixel = 0; + Mem::Copy(&pixel, iPIXEL_ADDRESS, 3); + return pixel; + } + else + return (*( iPIXEL_ADDRESS )&0x00ffffff); + } + } + +/** Sets the value of the pixel at the current pixel position. + +To remove the overhead of constructing a TRgb, the function uses a TUint32 +rather than a TRgb to hold an RGB value. + +@param aValue The value to which the pixel at the current pixel position is +to be set. */ +EXPORT_C void TBitmapUtil::SetPixel(TUint32 aValue) + { + iWritten = ETrue; + if (iBpp!=24) + { + // 1,2,4,8,12,16,32-bit pixels + *iWordPos&=~(iMask<DisplayMode() == EColor16MU) + { + *iWordPos|= 0xff000000; + } + } + else + { + // 24-bit pixels + // Due to machine word alignment requirement on ARM, need to copy + // pixel data at iWordPos a byte at a time if address is not aligned + // on a 4 byte boundary i.e. 1st or 2nd least sig. bits set. + if (iPIXEL_BYTE_OFFSET & 0x3) + Mem::Copy(iPIXEL_ADDRESS, &aValue, 3); + else + { + *(iPIXEL_ADDRESS) &= ~0xffffff; + *(iPIXEL_ADDRESS) |= (aValue&0x00ffffff); + } + } + } + +/** Sets the value of the pixel at the current pixel position to that returned +by aSource.GetPixel(). + +@param aSource The TBitmapUtil of the source bitmap, whose pixel value is +used to set the pixel at the current pixel position. */ +EXPORT_C void TBitmapUtil::SetPixel(const TBitmapUtil& aSource) + { + SetPixel(aSource.GetPixel()); + } + +/** Sets a new current pixel position. + +@param aPosition The new current pixel position. */ +EXPORT_C void TBitmapUtil::SetPos(const TPoint& aPosition) + { + TSize bmpsize(iFbsBitmap->SizeInPixels()); + TPoint correct(aPosition); + + correct.iX%=bmpsize.iWidth; + correct.iY%=bmpsize.iHeight; + if(correct.iX<0) correct.iX+=bmpsize.iWidth; + if(correct.iY<0) correct.iY+=bmpsize.iHeight; + + iWordPos=iMinWordPos; + iWordPos+=iScanlineWordLength*correct.iY; + if (iBpp!=24) + { + // 1,2,4,8,12,16,32-bit pixels + iWordPos+=correct.iX>>iPixelShift; + iBitShift=(correct.iX*iBpp)%32; + } + else + { + // 24-bit pixels + // iSTART_OF_SCAN_LINE (iWordPos) has correct value at this point + // iBitShift not used in 16M modes + iPIXEL_BYTE_OFFSET = correct.iX*3; // Byte offset in iY scan line to iX pixel + } +} + +/** Decrements the x co-ordinate of the current pixel position. */ +EXPORT_C void TBitmapUtil::DecXPos() + { + if (iBpp!=24) + { + // 1,2,4,8,12,16,32-bit pixels + iBitShift-=iBpp; + if(iBitShift<0) + { + iBitShift+=32; + iWordPos--; + if(iWordPos=32) + { + iBitShift=0; + iWordPos++; + if(iWordPos>=iMaxWordPos) iWordPos=iMinWordPos; + } + } + else + { + // 24-bit pixels + iPIXEL_BYTE_OFFSET += 3; + + // Scanline overflow? + if (iPIXEL_BYTE_OFFSET >= + (iScanlineWordLength*4)-static_cast(iNUM_WASTE_BYTES)) + { + iPIXEL_BYTE_OFFSET = 0; + iSTART_OF_SCAN_LINE += iScanlineWordLength; + + // Bitmap overflow? + if (iSTART_OF_SCAN_LINE >= iMaxWordPos) + iSTART_OF_SCAN_LINE = iMinWordPos; + } + } + } + +/** Increments the y co-ordinate of the current pixel position. */ +EXPORT_C void TBitmapUtil::IncYPos() + { + iWordPos+=iScanlineWordLength; + if(iWordPos>=iMaxWordPos) iWordPos-=iMaxWordPos-iMinWordPos; + } + + + +// +// CDitherColor256 +// + +class TDitherColorError + { +public: + inline TDitherColorError() {}; + inline TDitherColorError(TInt aRed,TInt aGreen,TInt aBlue) : iRed(aRed), iGreen(aGreen), iBlue(aBlue) {} +public: + TInt iRed; + TInt iGreen; + TInt iBlue; + }; + +NONSHARABLE_CLASS(CDitherColor256) : public CBase + { +public: + void ConstructL(TInt aLineWidth,const TColor256Util* aColorUtil = NULL); + void Reset(); + void ConvertLine(TUint8* aDestination,TRgb* aSource); + ~CDitherColor256(); +private: + const TColor256Util* iColorUtil; + TInt iLineWidth; + TDitherColorError* iErrorBuffer; + TInt iErrorBufferLength; + }; + +CDitherColor256::~CDitherColor256() + { + delete[] iErrorBuffer; + } + +void CDitherColor256::ConstructL(TInt aLineWidth,const TColor256Util* aColorUtil) + { + if(iErrorBufferLength<=aLineWidth) + { + delete[] iErrorBuffer; + iErrorBuffer = NULL; + } + + if(!iErrorBuffer) + { + iErrorBuffer = new (ELeave) TDitherColorError[aLineWidth+1]; + iErrorBufferLength = aLineWidth+1; + } + + iLineWidth = aLineWidth; + if(!aColorUtil) + aColorUtil = TColor256Util::Default(); + iColorUtil = aColorUtil; + + Reset(); + } + +void CDitherColor256::Reset() + { + Mem::FillZ(iErrorBuffer,iErrorBufferLength*sizeof(iErrorBuffer[0])); + } + +void CDitherColor256::ConvertLine(TUint8* aDestination,TRgb* aSource) + { + TUint8* dstLimit = aDestination+iLineWidth; + TDitherColorError* errorBuffer = iErrorBuffer; + + TInt r = errorBuffer->iRed; + TInt g = errorBuffer->iGreen; + TInt b = errorBuffer->iBlue; + errorBuffer->iRed = 0; + errorBuffer->iGreen = 0; + errorBuffer->iBlue = 0; + + while(aDestinationRed(); + if(r>255) + value = 255; + else if(r>0) + value = r; + + g += aSource->Green(); + if(g>255) + value |= 255<<8; + else if(g>0) + value |= g<<8; + + b += aSource->Blue(); + if(b>255) + value |= 255<<16; + else if(b>0) + value |= b<<16; + + aSource++; + + value = iColorUtil->Color256(TRgb(value)); + *(aDestination) = (TUint8)value; + value = iColorUtil->Color256(value).Value(); + + r -= value&0xFF; + g -= (value>>8)&0xFF; + b -= (value>>16)&0xFF; + } + + { + TInt x = r>>2; + r = (r>>1)-(r>>3); + errorBuffer->iRed += r; + r += errorBuffer[1].iRed; + errorBuffer[1].iRed = x; + + x = g>>2; + g = (g>>1)-(g>>3); + errorBuffer->iGreen += g; + g += errorBuffer[1].iGreen; + errorBuffer[1].iGreen = x; + + x = b>>2; + b = (b>>1)-(b>>3); + errorBuffer->iBlue += b; + b += errorBuffer[1].iBlue; + errorBuffer[1].iBlue = x; + + errorBuffer++; + } + + aDestination++; + } + } + +// +// CFbsColor256BitmapUtil +// + +inline CFbsColor256BitmapUtil::CFbsColor256BitmapUtil() + { } + +/** Allocates and constructs a new 256 colour bitmap utility object, optionally +specifying a palette. + +@param aPalette The palette of colours to use for the destination 256 colour +bitmap. If there are more than 256 colours in the palette, only the first +256 are used. May be NULL, in which case the system default 256 colour palette +is used. +@return The newly constructed object. */ +EXPORT_C CFbsColor256BitmapUtil* CFbsColor256BitmapUtil::NewL(const CPalette* aPalette) + { + CFbsColor256BitmapUtil* self = new (ELeave) CFbsColor256BitmapUtil; + CleanupStack::PushL(self); + if(aPalette) + { + self->iColor256Util = new (ELeave) TColor256Util; + self->iColor256Util->Construct(*aPalette); + } + // coverity[leave_without_push : FALSE] + // class member variables should not be pushed onto the cleanupstack + self->iDither = new (ELeave) CDitherColor256; + CleanupStack::Pop(); + return self; + } + +CFbsColor256BitmapUtil::~CFbsColor256BitmapUtil() + { + delete iColor256Util; + delete iDither; + } + +/** Copies the contents of a source bitmap to a destination 256 colour bitmap. +Both bitmaps must be the same size and the destination bitmap's display mode +must be EColor256. + +@param aColor256Destination The destination to copy the bitmap to. Its display +mode must be EColor256. +@param aSource The source bitmap to copy from. Its display mode can be EColor16M, +EColor64K, EColor4K or EColor256. +@param aDither Specify EFloydSteinberg for Floyd-Steinberg dithering. By default, +no dithering. +@return KErrNone, if successful; otherwise, another of the system-wide error +codes. KErrNotSupported is returned if aSource's display mode is not one of +the values listed. +@panic EFbsColor256UtilError Either aColor256Destination's display mode is +not EColor256, or the two bitmaps are not the same size. */ +EXPORT_C TInt CFbsColor256BitmapUtil::CopyBitmap(CFbsBitmap* aColor256Destination,CFbsBitmap* aSource,TDither aDither) + { + aSource->BeginDataAccess(); + aColor256Destination->BeginDataAccess(); + const TDisplayMode sourceMode = aSource->DisplayMode(); + + TSize size(aSource->SizeInPixels()); + TInt width = size.iWidth; + TInt height = size.iHeight; + + // Check we are being askes to copy a bitmap to a color256 bitmap of the same size + if( aColor256Destination->DisplayMode()!=EColor256 || aColor256Destination->SizeInPixels()!=size ) + Panic(EFbsColor256UtilError); + + if( sourceMode!=EColor256 && sourceMode!=EColor4K && sourceMode!=EColor64K && + sourceMode!=EColor16M && sourceMode!=EColor16MU && sourceMode!=EColor16MA && sourceMode!=EColor16MAP) + { + aSource->EndDataAccess(ETrue); + aColor256Destination->EndDataAccess(ETrue); + return KErrNotSupported; + } + + // get a TColor256Utils to use + const TColor256Util* colorUtil = iColor256Util; + if(!colorUtil) + colorUtil = TColor256Util::Default(); + + if(aDither==EFloydSteinberg) + { + TRAPD(err,iDither->ConstructL(width,colorUtil)); + if(err!=KErrNone) + { + aSource->EndDataAccess(ETrue); + aColor256Destination->EndDataAccess(ETrue); + return err; + } + } + + TRgb* pixelBuffer = new TRgb[width]; + if(!pixelBuffer) + { + aSource->EndDataAccess(ETrue); + aColor256Destination->EndDataAccess(ETrue); + return KErrNoMemory; + } + + TUint8* src = (TUint8*)aSource->DataAddress(); + TInt srcPitch = aSource->ScanLineLength(width,sourceMode); + TUint8* dst = (TUint8*)aColor256Destination->DataAddress(); + TInt dstPitch = aColor256Destination->ScanLineLength(width,EColor256); + + while(height--) + { + TInt i(0); + switch(sourceMode) + { + case EColor256: + for(i=0; i (src); + TInt32* dataLimit = data+width; + i = 0; + while(data (src); + TInt32* dataLimit = data+width; + i = 0; + while(data (src); + TInt32* dataLimit = data+width; + while(dataConvertLine(dst,pixelBuffer); + else + colorUtil->Color256(dst,pixelBuffer,width); + dst += dstPitch; + src += srcPitch; + } + + aSource->EndDataAccess(ETrue); + aColor256Destination->EndDataAccess(EFalse); + + delete[] pixelBuffer; + return KErrNone; + } + +/** + +Required to ensure BC between NGage and 7.0S platforms. +Function is exported at ordinal corresponding to where NGage platform +has extended this library and must not be moved. */ +EXPORT_C void DummyReserved1() + { + User::Panic(_L("Dummy Function"), 0); + } + +