diff -r 000000000000 -r bde4ae8d615e os/graphics/fbs/fontandbitmapserver/sfbs/BITBMPEX.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/fbs/fontandbitmapserver/sfbs/BITBMPEX.CPP Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,1479 @@ +// Copyright (c) 1997-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 +#include +#include "UTILS.H" +#include +#include +//#include "12to16.h" // lookup table for 12->16 bpp conversion + +#ifdef __ARMCC__ +#pragma arm +#pragma O3 +#pragma Otime +#endif + +GLREF_C void Panic(TFbsPanic aPanic); + +#define COLOR_VALUE(ScanLinePtr, XPos) (*((ScanLinePtr) + ((XPos) >> 5)) & ( 1 << ((XPos) & 0x1F))) + + +void CBitwiseBitmap::GetScanLineGray2(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,(TInt)((aBuf.MaxLength()) << 3)); + aBuf.SetLength((aLength + 7) >> 3); + + TUint8* ptr = (TUint8*)aBuf.Ptr(); + + TUint8 mask = 1; + TInt x = aPixel.iX; + *ptr=0; + + if (aDither) + { + TBool oddx = aDitherOffset.iX & 1; + TBool oddy = aDitherOffset.iY & 1; + + for(TInt count = 0;count < aLength;count++) + { + if (!mask) + { + mask = 1; + ptr++; + *ptr = 0; + } + if (HashTo1bpp(GetGrayPixelEx(x,aScanlinePtr),oddx,oddy)) + *ptr |= mask; + mask <<= 1; + oddx ^= 1; + x++; + } + } + else + { + for(TInt count = 0;count < aLength;count++) + { + if (!mask) + { + mask = 1; + ptr++; + *ptr = 0; + } + if (GetGrayPixelEx(x,aScanlinePtr) > 127) + *ptr |= mask; + mask <<= 1; + x++; + } + } + } + +void CBitwiseBitmap::GetScanLineGray4(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,(TInt)((aBuf.MaxLength())<<2)); + aBuf.SetLength((aLength + 3) >> 2); + + TUint8* ptr=(TUint8*)aBuf.Ptr(); + + TInt x = aPixel.iX; + if (iSettings.CurrentDisplayMode() == EGray16 && aDither) + { + *ptr=0; + TInt shift = 0; + TUint8 col = 0; + const TInt hasharray[4]={0,3,2,1}; + TInt index = (aDitherOffset.iX&1)+((aDitherOffset.iY&1)<<1); + for(TInt count=0;count> 4); + TInt value=col/5; + col%=5; + if (col>2) col--; + if (hasharray[index]> 2); + while (ptr < ptrLimit) + { + TUint8 pixelGrayShade = TUint8(GetGrayPixelEx(x++,aScanlinePtr) >> 6); + pixelGrayShade |= TUint8((GetGrayPixelEx(x++,aScanlinePtr) >> 4) & 0x0c); + pixelGrayShade |= TUint8((GetGrayPixelEx(x++,aScanlinePtr) >> 2) & 0x30); + pixelGrayShade |= TUint8(GetGrayPixelEx(x++,aScanlinePtr) & 0xc0); + *ptr++ = pixelGrayShade; + } + } + } + +void CBitwiseBitmap::GetScanLineGray16(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength=Min(aLength,(TInt)(aBuf.MaxLength()<<1)); + aBuf.SetLength((aLength + 1) >> 1); + + TUint8* ptr = (TUint8*)aBuf.Ptr(); + TUint8* ptrLimit = ptr + aBuf.Length(); + TInt x = aPixel.iX; + + if(iHeader.iBitsPerPixel == 1) + { + while (ptr < ptrLimit) + { + TUint8 pixelGrayShade = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0x0F : 0); + x++; + pixelGrayShade |= TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xF0 : 0); + x++; + *ptr++ = pixelGrayShade; + } + } + else + { + while (ptr < ptrLimit) + { + TUint8 pixelGrayShade = TUint8(GetGrayPixelEx(x++,aScanlinePtr) >> 4); + pixelGrayShade |= GetGrayPixelEx(x++,aScanlinePtr) & 0xf0; + *ptr++ = pixelGrayShade; + } + } + } + +void CBitwiseBitmap::GetScanLineGray256(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,aBuf.MaxLength()); + aBuf.SetLength(aLength); + + TUint8* ptr = (TUint8*)aBuf.Ptr(); + TUint8* ptrLimit = ptr + aLength; + TInt xCoord = aPixel.iX; + + if(iHeader.iBitsPerPixel == 1) + { + while (ptr < ptrLimit) + { + *ptr++ = TUint8(COLOR_VALUE(aScanlinePtr, xCoord) ? 0xFF : 0); + xCoord++; + } + } + else + { + while (ptr < ptrLimit) + *ptr++ = GetGrayPixelEx(xCoord++,aScanlinePtr); + } + } + +void CBitwiseBitmap::GetScanLineColor16(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength=Min(aLength,(TInt)(aBuf.MaxLength()<<1)); + aBuf.SetLength((aLength + 1) >> 1); + + TUint8* ptr = (TUint8*)aBuf.Ptr(); + TUint8* ptrLimit = ptr + aBuf.Length(); + TInt x = aPixel.iX; + + if(iHeader.iBitsPerPixel == 1) + { + while (ptr < ptrLimit) + { + TUint8 pixelGrayShade = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0x0F : 0); + x++; + pixelGrayShade |= TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xF0 : 0); + x++; + *ptr++ = pixelGrayShade; + } + } + else + { + while (ptr < ptrLimit) + { + TUint8 pixelGrayShade = TUint8(GetRgbPixelEx(x++,aScanlinePtr).Color16()); + pixelGrayShade |= GetRgbPixelEx(x++,aScanlinePtr).Color16() << 4; + *ptr++ = pixelGrayShade; + } + } + } + +void CBitwiseBitmap::GetScanLineColor256(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,aBuf.MaxLength()); + aBuf.SetLength(aLength); + + TUint8* ptr = (TUint8*)aBuf.Ptr(); + TUint8* ptrLimit = ptr + aLength; + TInt xCoord = aPixel.iX; + + if(iHeader.iBitsPerPixel == 1) + { + while (ptr < ptrLimit) + { + *ptr++ = TUint8(COLOR_VALUE(aScanlinePtr, xCoord) ? 0xFF : 0); + xCoord++; + } + } + else + { + while (ptr < ptrLimit) + *ptr++ = TUint8(GetRgbPixelEx(xCoord++,aScanlinePtr).Color256()); + } + } + +void CBitwiseBitmap::GetScanLineColor4K(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,aBuf.MaxLength() >> 1); + aBuf.SetLength(aLength << 1); + + TUint16* ptr = (TUint16*)aBuf.Ptr(); + const TUint16* ptrLimit = ptr + aLength; + TInt x = aPixel.iX; + + if(iHeader.iBitsPerPixel == 1) + { + while (ptr < ptrLimit) + { + *ptr++ = TUint16(COLOR_VALUE(aScanlinePtr, x) ? 0x0FFF : 0); + x++; + } + } + else + { + while (ptr < ptrLimit) + *ptr++ = TUint16(GetRgbPixelEx(x++,aScanlinePtr)._Color4K()); + } + } + +void CBitwiseBitmap::GetScanLineColor64K(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,aBuf.MaxLength() >> 1); + aBuf.SetLength(aLength << 1); + + TUint16* ptr = (TUint16*)aBuf.Ptr(); + TUint16* ptrLimit = ptr + aLength; + TInt x = aPixel.iX; + + if(iHeader.iBitsPerPixel == 1) + { + while (ptr < ptrLimit) + { + *ptr++ = TUint16(COLOR_VALUE(aScanlinePtr, x) ? 0xFFFF : 0); + x++; + } + } + else if(iHeader.iBitsPerPixel == 12) + { +/* + // use lookup table for 12->16 conversion + TUint16* pixel4K = ((TUint16*) aScanlinePtr) + x; + while(ptr < ptrLimit) + { + // this takes the 12 bit value, this is a number between 0 and 4095, + // and looks up its corrosponding 16 bit value in the lookup table. + // the colour should be identical, and but just in a different format + // see below for an explaination of 12 & 16 bit colour values + *ptr++ = K12to16LUT[*pixel4K++]; + } +*/ +/* This code uses logic rather than a lookup table + to convert from 12->16 bpp and can be used instead of the above code + if the 8k the lookup table uses becomes an issue + + 12 bit colour + ------------- + The 12 bit colour format uses 4 bits for the red, green and blue values. + The colour is stored as a word with the most significant 4 bits having a + value of zero. + i.e. 0000RRRR GGGGBBBB where R,G & B represent single bits in the word. + + The code below labeled 'conversion of 4k colour...' changes the colour from + 16 bit to 32 bit where each colour nibble in the 16 bit version is changed + to a byte in the 32 bit version e.g. + 0000RRRR GGGGBBBB -> 00000000 RRRRRRRR GGGGGGGG BBBBBBBB + + + 16 bit colour + ------------- + The 16 bit colour format uses all 16 bits to represent the required colour. + There are two possible 16 bit formats 5-5-5 and 5-6-5. + Symbian uses the 5-6-5 format, with this all 16 bits are used to make the colour + giving a possible value between 0..65535. The RGB components are divided up + as follows RRRR RGGG GGGB BBBB i.e. 5 bits for red and blue, and 6 for green. + + The code below labeled 'conversion to 64k' converts the colour from a 16 bit + 0000 RRRR GGGG BBBB -> RRRR RGGG GGGB BBBB format. +*/ + register TUint16* pixel4K = ((TUint16*) aScanlinePtr) + x; + while (ptr < ptrLimit) + { + // conversion of 4k colour from 16 to 32 bits + // this changes from a 16 to 32 bit value while keeping colour unchanged + register TUint16 pixelVal = *pixel4K++; + register TUint32 value32 = ((pixelVal & 0x0f00) >> 8) | + ((pixelVal & 0x00f0) << 4) | + ((pixelVal & 0x000f) << 16); + value32 |= (value32 << 4); + // conversion to 64k (RRRR RGGG GGGB BBBB) + // this will make the change from (16 bit) 4-4-4 bpp to 5-6-5 bpp format + register TUint32 color64K = ((value32 & 0x000000f8) << 8) | + ((value32 & 0x0000fc00) >> 5) | + ((value32 & 0x00f80000) >> 19); + // store new colour value + *ptr++ = static_cast (color64K); + } + } + else + { + while (ptr < ptrLimit) + *ptr++ = TUint16(GetRgbPixelEx(x++,aScanlinePtr)._Color64K()); + } + } + +void CBitwiseBitmap::GetScanLineColor16M(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,aBuf.MaxLength() / 3); + aBuf.SetLength(aLength * 3); + + TUint8* ptr = (TUint8*)aBuf.Ptr(); + TUint8* ptrLimit = ptr + (aLength * 3); + TInt x = aPixel.iX; + + if(iHeader.iBitsPerPixel == 1) + { + while (ptr < ptrLimit) + { + const TUint8 color = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xFF : 0); + *ptr++ = color; + *ptr++ = color; + *ptr++ = color; + x++; + } + } + else + { + GetRgbPixelExMany16M(aPixel.iX,aScanlinePtr,ptr,aLength); + } + } + +void CBitwiseBitmap::GetScanLineColor16MU(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,aBuf.MaxLength() >> 2); + aBuf.SetLength(aLength << 2); + + TUint32* ptr = (TUint32*)aBuf.Ptr(); + + GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength); + } + +void CBitwiseBitmap::GetScanLineColor16MA(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,aBuf.MaxLength() >> 2); + aBuf.SetLength(aLength << 2); + + TUint32* ptr = (TUint32*)aBuf.Ptr(); + GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength); + } + +/** +Get the scanline data into the destination buffer in the EColor16MAP format. +@param aDestBuf - destination buffer +@param aPixel - the start position of the scanline. +@param aLength - scanline length, as word length +@param aScanlinePtr - scanline pointer +*/ +void CBitwiseBitmap::GetScanLineColor16MAP(TDes8& aDestBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength, aDestBuf.MaxLength() >> 2); + aDestBuf.SetLength(aLength << 2); + TUint32* ptr = (TUint32*)aDestBuf.Ptr(); + GetRgbPixelExMany16MAP(aPixel.iX,aScanlinePtr,ptr,aLength); + } + + +void CBitwiseBitmap::GetScanLineColorRgb(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const + { + aLength = Min(aLength,aBuf.MaxLength() / sizeof(TRgb)); + aBuf.SetLength(aLength * sizeof(TRgb)); + + TUint32* ptr = (TUint32*)aBuf.Ptr(); + GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength); + } + +void CBitwiseBitmap::GetScanLineExBits(TDes8& aBuf,TInt aX,TInt aLength,TUint32* aScanlinePtr) const + { + TInt bitshift = 1; + TInt pixelsPerWord = 8; + TInt roundingmask = ~0x7; + TInt logbpp = 2; + TInt roundupfactor = 1; + const TDisplayMode displayMode = iSettings.CurrentDisplayMode(); + + switch(displayMode) + { + case EGray16: + case EColor16: + break; // set by default + case EGray4: + { + bitshift = 2; + pixelsPerWord = 16; + roundingmask = ~0xf; + logbpp = 1; + roundupfactor = 3; + break; + } + case EGray2: + { + bitshift = 3; + pixelsPerWord = 32; + roundingmask = ~0x1f; + logbpp = 0; + roundupfactor = 7; + break; + } + default: + Panic(EFbsBitmapInvalidMode); + } + + aLength = Min(aLength,aBuf.MaxLength() << bitshift); + aBuf.SetLength((aLength + roundupfactor) >> bitshift); + + TUint32* ptr = (TUint32*)aBuf.Ptr(); // guaranteed to be word aligned by the calling function + TInt startlong = aX & roundingmask; + TInt finishlong = (aX + aLength + pixelsPerWord - 1) & roundingmask; + bitshift += 2; // Convert pixels per byte shift to pixels per word shift + TUint32* wordptr = aScanlinePtr + (startlong >> bitshift); + TInt wordLength = (finishlong - startlong) >> bitshift; + TUint32* wordptrLimit = wordptr + wordLength; + + const TInt destinationWords = Min(aBuf.MaxLength() >> 2,wordLength); + TUint32* ptrlimit = ptr + destinationWords; + + TInt offset = (aX - startlong) << logbpp; + + if (offset) + { + TInt offsetextra = 32-offset; + TUint32 data = *wordptr++; + data >>= offset; + + while (ptr < ptrlimit - 1) + { + TUint32 tmp = *wordptr++; + data |= tmp << offsetextra; + *ptr++ = data; + data = tmp >> offset; + } + + if (wordptr < wordptrLimit) + *ptr = data | (*wordptr << offsetextra); + else + *ptr = data; + } + else + { + while (ptr < ptrlimit) + *ptr++ = *wordptr++; + + // if the buffer isn't a whole number of words long, + // we need to copy the remaining bytes + const TInt bytesRemaining = aBuf.Length() - (destinationWords * sizeof(TUint32)); + if (bytesRemaining > 0) + Mem::Copy(ptr,wordptr,bytesRemaining); + + } + } + +void CBitwiseBitmap::GetScanLineExBytes(TDes8& aBuf,TInt aX,TInt aLength,TUint32* aScanlinePtr) const + { + TInt numberOfBytesToCopy = 0; + TUint8* ptr = (TUint8*)aScanlinePtr; + TDisplayMode displayMode = iSettings.CurrentDisplayMode(); + switch(displayMode) + { + case EGray256: + case EColor256: + { + aLength = Min(aLength,aBuf.MaxLength()); + numberOfBytesToCopy = aLength; + ptr += aX; + break; + } + case EColor4K: + case EColor64K: + { + aLength = Min(aLength,aBuf.MaxLength() / 2); + numberOfBytesToCopy = aLength * 2; + ptr += (aX << 1); + break; + } + case EColor16M: + { + aLength = Min(aLength,aBuf.MaxLength() / 3); + numberOfBytesToCopy = aLength * 3; + ptr += (aX * 3); + break; + } + case EColor16MU: + case EColor16MA: + case EColor16MAP: + { + aLength = Min(aLength,aBuf.MaxLength() / 4); + numberOfBytesToCopy = aLength * 4; + ptr += (aX * 4); + break; + } + default: + Panic(EFbsBitmapInvalidMode); + } + + aBuf.SetLength(numberOfBytesToCopy); + + Mem::Copy((TAny*)aBuf.Ptr(),ptr,numberOfBytesToCopy); + } + +void CBitwiseBitmap::DoStretchScanLine(TDes8& aBuf,TInt x,TInt y,TInt aClipStrchX, + TInt aClipStrchLen,TInt aStretchLength,TInt aOrgX,TInt aOrgLen, + const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase, + TLineScanningPosition& aLineScanningPosition) const + { + TInt lastValue = 0; + TUint32* bufptr=(TUint32*)((TInt)(&aBuf[0]+3)&~3); + TUint32* buflimit=bufptr; + TUint32* slptr=NULL; + TPoint pixel(aOrgX,y); + const TDisplayMode displayMode = iSettings.CurrentDisplayMode(); + GetScanLinePtr(slptr, aOrgLen, pixel,aBase, aLineScanningPosition); + if (!slptr) + { + WhiteFill((TUint8*)aBuf.Ptr(),aBuf.MaxLength(),displayMode); + return; + } + + TInt lastcoord=-1; + TLinearDDA stretchmap; + TPoint coordmap(aOrgX,0); + stretchmap.Construct(coordmap,coordmap+TPoint(aOrgLen,aStretchLength),TLinearDDA::ELeft); + coordmap.iY=aClipStrchX; + if (aClipStrchX>0) stretchmap.JumpToYCoord(coordmap.iX,coordmap.iY); + else stretchmap.SingleStep(coordmap); + switch(aDispMode) + { + case EGray4: + { + aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<4)); + aBuf.SetLength((aClipStrchLen+3)>>2); + buflimit+=(aBuf.Length()+3)>>2; + if (displayMode == EGray16) + { + TInt index=((aDitherOffset.iY&1)<<1)+((aDitherOffset.iX+x)&1); + while(bufptrlastcoord) + { + lastValue=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index); + lastcoord=coordmap.iX; + } + *bufptr|=(lastValue<lastcoord) + { + lastValue = GetGrayPixelEx(coordmap.iX,slptr) >> 6; + lastcoord = coordmap.iX; + } + *bufptr |= (lastValue << shift); + shift += 2; + if (stretchmap.SingleStep(coordmap)) break; + } + bufptr++; + } + } + break; + } + case EGray16: + { + aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<3)); + aBuf.SetLength((aClipStrchLen+1)>>1); + buflimit+=(aBuf.Length()+3)>>2; + while(bufptrlastcoord) + { + lastValue = GetGrayPixelEx(coordmap.iX,slptr) >> 4; + lastcoord=coordmap.iX; + } + *bufptr |= lastValue << shift; + shift+=4; + if (stretchmap.SingleStep(coordmap)) break; + } + bufptr++; + } + break; + } + case EColor16: + { + aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<3)); + aBuf.SetLength((aClipStrchLen+1)>>1); + buflimit+=(aBuf.Length()+3)>>2; + while(bufptrlastcoord) + { + lastValue = GetRgbPixelEx(coordmap.iX,slptr).Color16(); + lastcoord = coordmap.iX; + } + *bufptr |= lastValue << shift; + shift+=4; + if (stretchmap.SingleStep(coordmap)) break; + } + bufptr++; + } + break; + } + case EGray256: + { + aClipStrchLen = Min(aClipStrchLen,(TInt)(aBuf.MaxLength() & ~3)); + aBuf.SetLength(aClipStrchLen); + buflimit += (aBuf.Length() + 3) >> 2; + + while (bufptr < buflimit) + { + TInt shift=0; + *bufptr=0; + while(shift<32) + { + if (coordmap.iX>lastcoord) + { + lastValue = GetGrayPixelEx(coordmap.iX,slptr); + lastcoord=coordmap.iX; + } + *bufptr |= lastValue << shift; + shift += 8; + if (stretchmap.SingleStep(coordmap)) + break; + } + bufptr++; + } + break; + } + case EColor256: + { + aClipStrchLen = Min(aClipStrchLen,(TInt)(aBuf.MaxLength() & ~3)); + aBuf.SetLength(aClipStrchLen); + buflimit += (aBuf.Length() + 3) >> 2; + + while (bufptr < buflimit) + { + TInt shift=0; + *bufptr=0; + while(shift<32) + { + if (coordmap.iX>lastcoord) + { + lastValue = TUint8(GetRgbPixelEx(coordmap.iX,slptr).Color256()); + lastcoord = coordmap.iX; + } + *bufptr |= lastValue << shift; + shift += 8; + if (stretchmap.SingleStep(coordmap)) + break; + } + bufptr++; + } + break; + } + case EColor4K: + { + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1); + aBuf.SetLength(aClipStrchLen << 1); + buflimit += (aBuf.Length() + 3) >> 2; + + while (bufptr < buflimit) + { + if (coordmap.iX>lastcoord) + { + lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color4K(); + lastcoord=coordmap.iX; + } + *bufptr = lastValue; + if (stretchmap.SingleStep(coordmap)) + break; + if (coordmap.iX>lastcoord) + { + lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color4K(); + lastcoord=coordmap.iX; + } + *bufptr |= lastValue << 16; + if (stretchmap.SingleStep(coordmap)) + break; + bufptr++; + } + break; + } + case EColor64K: + { + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1); + aBuf.SetLength(aClipStrchLen << 1); + buflimit += (aBuf.Length() + 3) >> 2; + + while (bufptr < buflimit) + { + if (coordmap.iX>lastcoord) + { + lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color64K(); + lastcoord=coordmap.iX; + } + *bufptr = lastValue; + if (stretchmap.SingleStep(coordmap)) + break; + if (coordmap.iX>lastcoord) + { + lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color64K(); + lastcoord=coordmap.iX; + } + *bufptr |= lastValue << 16; + if (stretchmap.SingleStep(coordmap)) + break; + bufptr++; + } + break; + } + case EColor16M: // Destination Mode + { + // Optimisation: Both of conditions on 32bpp and 24bpp were added to avoid to use + // GetRgbPixelEx() for each pixel + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / 3); + aBuf.SetLength(aClipStrchLen * 3); + TUint8* ptr = (TUint8*)bufptr; + TUint8* ptrLimit = ptr + aBuf.Length(); + + if (iHeader.iBitsPerPixel == 32) // 32bpp source image => color + { + TInt lastColor = 0; + if(displayMode == EColor16MAP) + { + const TUint16* normTable = PtrTo16BitNormalisationTable(); + while (ptr < ptrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable); + lastcoord = coordmap.iX; + } + *ptr++ = TUint8(lastColor); + *ptr++ = TUint8(lastColor >> 8); + *ptr++ = TUint8(lastColor >> 16); + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else{ + while (ptr < ptrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = *(slptr + coordmap.iX); + lastcoord = coordmap.iX; + } + *ptr++ = TUint8(lastColor); + *ptr++ = TUint8(lastColor >> 8); + *ptr++ = TUint8(lastColor >> 16); + if (stretchmap.SingleStep(coordmap)) + break; + } + } + } + else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color + { + TInt lastColor = 0; + while (ptr < ptrLimit) + { + if (coordmap.iX > lastcoord) + { + TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3; + lastColor = TUint8(*scanLineBytePointer); + scanLineBytePointer++; + lastColor |= TUint8(*scanLineBytePointer) << 8; + scanLineBytePointer++; + lastColor |= TUint8(*scanLineBytePointer) << 16; + lastcoord = coordmap.iX; + } + *ptr++ = TUint8(lastColor); + *ptr++ = TUint8(lastColor >> 8); + *ptr++ = TUint8(lastColor >> 16); + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else + { + TRgb lastColor; + while (ptr < ptrLimit) + { + if (coordmap.iX>lastcoord) + { + lastColor = GetRgbPixelEx(coordmap.iX,slptr); + lastcoord=coordmap.iX; + } + TInt color16M = lastColor._Color16M(); + *ptr++ = TUint8(color16M); + *ptr++ = TUint8(color16M >> 8); + *ptr++ = TUint8(color16M >> 16); + if (stretchmap.SingleStep(coordmap)) + break; + } + } + break; + } + case ERgb: + { + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / sizeof(TRgb)); + aBuf.SetLength(aClipStrchLen * sizeof(TRgb)); + TRgb* pixelPtr = (TRgb*)bufptr; + TRgb* pixelPtrLimit = pixelPtr + aClipStrchLen; + TRgb lastColor; + + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = GetRgbPixelEx(coordmap.iX,slptr); + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor; + if (stretchmap.SingleStep(coordmap)) + break; + } + break; + } + case EColor16MU: // Destination Mode + { + // Optimisation: The condition 32bpp was added to avoid to use + //GetRgbPixelEx() for each pixel (construction of a TRgb object each time) + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2); + aBuf.SetLength(aClipStrchLen << 2); + TInt32* pixelPtr = (TInt32*)bufptr; + TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen; + + if (iHeader.iBitsPerPixel == 32) //32bpp source image => color + { + TInt lastColor = 0; + if(displayMode == EColor16MAP) + { + const TUint16* normTable = PtrTo16BitNormalisationTable(); + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable); + lastcoord = coordmap.iX; + } + *pixelPtr++ = (lastColor | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else{ + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = *(slptr + coordmap.iX); + lastcoord = coordmap.iX; + } + *pixelPtr++ = (lastColor | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order + if (stretchmap.SingleStep(coordmap)) + break; + } + } + } + + else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color + { + TInt lastColor = 0; + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3; + lastColor = TUint8(*scanLineBytePointer); + scanLineBytePointer++; + lastColor |= TUint8(*scanLineBytePointer) << 8; + scanLineBytePointer++; + lastColor |= TUint8(*scanLineBytePointer) << 16; + lastcoord = coordmap.iX; + } + *pixelPtr++ = (lastColor | 0xff000000); + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color + { + TInt lastColor = 0; + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + TUint rawColor = *(((TUint16*)slptr) + coordmap.iX); + TInt red = (rawColor & 0xF800)>>8; + red += red>>5; + TInt green = (rawColor & 0x07E0)>>3; + green += green>>6; + TInt blue = (rawColor & 0x001F)<<3; + blue += blue>>5; + lastColor = 0xff000000 | (red << 16) | (green << 8) | blue; + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor; + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else + { + TRgb lastColor; + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = GetRgbPixelEx(coordmap.iX,slptr); + lastcoord = coordmap.iX; + } + *pixelPtr++ = (lastColor._Color16MU() | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order + if (stretchmap.SingleStep(coordmap)) + break; + } + } + break; + } + case EColor16MA: + { + // Optimisation: The condition 32bpp was added to avoid to use + // GetRgbPixelEx() for each pixel (construction of a TRgb object each time) + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2); + aBuf.SetLength(aClipStrchLen << 2); + TInt32* pixelPtr = (TInt32*)bufptr; + TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen; + const TUint16* normTable = PtrTo16BitNormalisationTable(); + if (iHeader.iBitsPerPixel == 32) //32bpp source image => color + { + TInt lastColor = 0; + if(displayMode == EColor16MAP) + { + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable); + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else + { + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = *(slptr + coordmap.iX); + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor; + if (stretchmap.SingleStep(coordmap)) + break; + } + } + } + else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color + { + TInt lastColor = 0; + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3; + lastColor = TUint8(*scanLineBytePointer); + scanLineBytePointer++; + lastColor |= TUint8(*scanLineBytePointer) << 8; + scanLineBytePointer++; + lastColor |= TUint8(*scanLineBytePointer) << 16; + lastcoord = coordmap.iX; + } + *pixelPtr++ = (lastColor | 0xff000000); + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color + { + TInt lastColor = 0; + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + TUint rawColor = *(((TUint16*)slptr) + coordmap.iX); + TInt red = (rawColor & 0xF800)>>8; + red += red>>5; + TInt green = (rawColor & 0x07E0)>>3; + green += green>>6; + TInt blue = (rawColor & 0x001F)<<3; + blue += blue>>5; + lastColor = 0xff000000 | (red << 16) | (green << 8) | blue; + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor; + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else + { + TRgb lastColor; + + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = GetRgbPixelEx(coordmap.iX,slptr); + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor._Color16MA();//BGRA (Blue/Green/Red) as little endian byte order + if (stretchmap.SingleStep(coordmap)) + break; + } + } + break; + } + case EColor16MAP: + { //if alpha is not available, assign 255 as alpha (opaque). + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2); + aBuf.SetLength(aClipStrchLen << 2); + TInt32* pixelPtr = (TInt32*)bufptr; + TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen; + if (iHeader.iBitsPerPixel == 32) //32bpp source image => color + { + TInt lastColor = 0; + //pre-multiply if alpha IS available. + if(displayMode == EColor16MA) + { + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = NonPMA2PMAPixel(*(slptr + coordmap.iX)); + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else if(displayMode == EColor16MU) + { + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + //do not want to convert to non pma, since keep transparency + //e.g. alpha 0.5, red 0.5. Want to keep red as 0.5 since it + //is not fully red. For 16MA convert to 1, and keep 0.5 alpha + lastColor = (*(slptr + coordmap.iX))|0xff000000; + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else + { + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = *(slptr + coordmap.iX); + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor; + if (stretchmap.SingleStep(coordmap)) + break; + } + } + } + else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color + { + TInt lastColor = 0; + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3; + lastColor = TUint8(*scanLineBytePointer); + scanLineBytePointer++; + lastColor |= TUint8(*scanLineBytePointer) << 8; + scanLineBytePointer++; + lastColor |= TUint8(*scanLineBytePointer) << 16; + lastcoord = coordmap.iX; + } + *pixelPtr++ = (lastColor | 0xff000000); + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color + { + TInt lastColor = 0; + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + TUint rawColor = *(((TUint16*)slptr) + coordmap.iX); + TInt red = (rawColor & 0xF800)>>8; + red += red>>5; + TInt green = (rawColor & 0x07E0)>>3; + green += green>>6; + TInt blue = (rawColor & 0x001F)<<3; + blue += blue>>5; + lastColor = 0xff000000 | (red << 16) | (green << 8) | blue; + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor; + if (stretchmap.SingleStep(coordmap)) + break; + } + } + else + { + TRgb lastColor; + + while (pixelPtr < pixelPtrLimit) + { + if (coordmap.iX > lastcoord) + { + lastColor = GetRgbPixelEx(coordmap.iX,slptr); + lastcoord = coordmap.iX; + } + *pixelPtr++ = lastColor._Color16MA();//BGRA (Blue/Green/Red) as little endian byte order + if (stretchmap.SingleStep(coordmap)) + break; + } + } + break; + } + case EGray2: + { + TBool oddx=(aDitherOffset.iX&1); + TBool oddy=(aDitherOffset.iY&1); + aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<5)); + aBuf.SetLength((aClipStrchLen+7)>>3); + buflimit+=(aBuf.Length()+3)>>2; + while(bufptr lastcoord) + { + lastValue = GetGrayPixelEx(coordmap.iX,slptr); + lastcoord = coordmap.iX; + } + if (HashTo1bpp(lastValue,oddx,oddy)) + *bufptr|=mask; + mask<<=1; + oddx^=1; + if (stretchmap.SingleStep(coordmap)) break; + } + bufptr++; + } + break; + } + default: + Panic(EFbsBitmapInvalidMode); + } + } + +void CBitwiseBitmap::DoCompressScanLine(TDes8& aBuf,TInt x,TInt y,TInt aClipStrchX,TInt aClipStrchLen,TInt aStretchLength,TInt aOrgX,TInt aOrgLen,const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase,TLineScanningPosition& aLineScanningPosition) const + { + TInt first=0,second=0,third=0,fourth=0,fifth=0,sixth=0,seventh=0,eighth=0; + TUint8* bufptr=&aBuf[0]; + TUint8* buflimit=bufptr; + TUint32* slptr=NULL; + TPoint pixel(aOrgX,y); + TDisplayMode displayMode = iSettings.CurrentDisplayMode(); + GetScanLinePtr(slptr,aOrgLen,pixel,aBase, aLineScanningPosition); + if (!slptr) + { + WhiteFill((TUint8*)aBuf.Ptr(),aBuf.MaxLength(),displayMode); + return; + } + TLinearDDA stretchmap; + TPoint coordmap(aOrgX,0); + stretchmap.Construct(coordmap,coordmap+TPoint(aOrgLen,aStretchLength),TLinearDDA::ELeft); + coordmap.iY=aClipStrchX; + if (aClipStrchX>0) stretchmap.JumpToYCoord(coordmap.iX,coordmap.iY); + else stretchmap.NextStep(coordmap); + switch(aDispMode) + { + case EGray4: + { + aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<2)); + aBuf.SetLength((aClipStrchLen+3)>>2); + TInt index=((aDitherOffset.iY&1)<<1)+((aDitherOffset.iX+x)&1); + buflimit+=aBuf.Length(); + if (displayMode==EGray16) + { + while(bufptr>6; + stretchmap.NextStep(coordmap); + second=GetGrayPixelEx(coordmap.iX,slptr)>>6; + stretchmap.NextStep(coordmap); + third=GetGrayPixelEx(coordmap.iX,slptr)>>6; + stretchmap.NextStep(coordmap); + fourth=GetGrayPixelEx(coordmap.iX,slptr)>>6; + *bufptr++=TUint8(first|(second<<2)|(third<<4)|(fourth<<6)); + stretchmap.NextStep(coordmap); + } + } + break; + } + case EGray16: + { + aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<1)); + aBuf.SetLength((aClipStrchLen+1)>>1); + buflimit+=aBuf.Length(); + while(bufptr> 4; + stretchmap.NextStep(coordmap); + first |= GetGrayPixelEx(coordmap.iX,slptr) & 0xf0; + *bufptr++ = TUint8(first); + stretchmap.NextStep(coordmap); + } + break; + } + case EColor16: + { + aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<1)); + aBuf.SetLength((aClipStrchLen+1)>>1); + buflimit+=aBuf.Length(); + while(bufptr> 1); + aBuf.SetLength(aClipStrchLen << 1); + buflimit += aBuf.Length(); + + while(bufptr < buflimit) + { + *((TUint16*)bufptr) = TUint16(GetRgbPixelEx(coordmap.iX,slptr)._Color4K()); + bufptr += 2; + stretchmap.NextStep(coordmap); + } + break; + } + case EColor64K: + { + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1); + aBuf.SetLength(aClipStrchLen << 1); + buflimit += aBuf.Length(); + + while(bufptr < buflimit) + { + *((TUint16*)bufptr) = TUint16(GetRgbPixelEx(coordmap.iX,slptr)._Color64K()); + bufptr += 2; + stretchmap.NextStep(coordmap); + } + break; + } + case EColor16M: + { + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / 3); + aBuf.SetLength(aClipStrchLen * 3); + buflimit += aBuf.Length(); + + while(bufptr> 8); + *bufptr++ = TUint8(color16M >> 16); + stretchmap.NextStep(coordmap); + } + break; + } + case ERgb: + case EColor16MU: + case EColor16MA: + case EColor16MAP: + { + aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2); + aBuf.SetLength(aClipStrchLen << 2); + TUint32* pixelPtr = (TUint32*)bufptr; + TUint32* pixelPtrLimit = pixelPtr + aClipStrchLen; + if (aDispMode == EColor16MAP && displayMode == EColor16MA) + while(pixelPtr < pixelPtrLimit) + { + *pixelPtr++ = NonPMA2PMAPixel(*(slptr + coordmap.iX)); + stretchmap.NextStep(coordmap); + } + else if (aDispMode == EColor16MAP && displayMode == EColor16MAP) + while(pixelPtr < pixelPtrLimit) + { + *pixelPtr++ = *(slptr + coordmap.iX); + stretchmap.NextStep(coordmap); + } + else if (aDispMode == EColor16MU) + while(pixelPtr < pixelPtrLimit) + { + *pixelPtr++ = GetRgbPixelEx(coordmap.iX, slptr).Internal(); + stretchmap.NextStep(coordmap); + } + else + while(pixelPtr < pixelPtrLimit) + { + *pixelPtr++ = GetRgbPixelEx(coordmap.iX, slptr).Internal(); + stretchmap.NextStep(coordmap); + } + break; + } + case EGray2: + { + TBool oddx=(aDitherOffset.iX&1); + TBool oddy=(aDitherOffset.iY&1); + aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<3)); + aBuf.SetLength((aClipStrchLen+7)>>3); + buflimit+=aBuf.Length(); + while(bufptr