Update contrib.
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 #include <graphics/blendingalgorithms.h>
22 #include <graphics/lookuptable.h>
23 //#include "12to16.h" // lookup table for 12->16 bpp conversion
31 GLREF_C void Panic(TFbsPanic aPanic);
33 #define COLOR_VALUE(ScanLinePtr, XPos) (*((ScanLinePtr) + ((XPos) >> 5)) & ( 1 << ((XPos) & 0x1F)))
36 void CBitwiseBitmap::GetScanLineGray2(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TUint32* aScanlinePtr) const
38 aLength = Min(aLength,(TInt)((aBuf.MaxLength()) << 3));
39 aBuf.SetLength((aLength + 7) >> 3);
41 TUint8* ptr = (TUint8*)aBuf.Ptr();
49 TBool oddx = aDitherOffset.iX & 1;
50 TBool oddy = aDitherOffset.iY & 1;
52 for(TInt count = 0;count < aLength;count++)
60 if (HashTo1bpp(GetGrayPixelEx(x,aScanlinePtr),oddx,oddy))
69 for(TInt count = 0;count < aLength;count++)
77 if (GetGrayPixelEx(x,aScanlinePtr) > 127)
85 void CBitwiseBitmap::GetScanLineGray4(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TBool aDither,const TPoint& aDitherOffset,TUint32* aScanlinePtr) const
87 aLength = Min(aLength,(TInt)((aBuf.MaxLength())<<2));
88 aBuf.SetLength((aLength + 3) >> 2);
90 TUint8* ptr=(TUint8*)aBuf.Ptr();
93 if (iSettings.CurrentDisplayMode() == EGray16 && aDither)
98 const TInt hasharray[4]={0,3,2,1};
99 TInt index = (aDitherOffset.iX&1)+((aDitherOffset.iY&1)<<1);
100 for(TInt count=0;count<aLength;count++,shift+=2)
108 col = TUint8(GetGrayPixelEx(x+count,aScanlinePtr) >> 4);
112 if (hasharray[index]<TInt(col))
121 TUint8* ptrLimit = ptr + ((aLength + 3) >> 2);
122 while (ptr < ptrLimit)
124 TUint8 pixelGrayShade = TUint8(GetGrayPixelEx(x++,aScanlinePtr) >> 6);
125 pixelGrayShade |= TUint8((GetGrayPixelEx(x++,aScanlinePtr) >> 4) & 0x0c);
126 pixelGrayShade |= TUint8((GetGrayPixelEx(x++,aScanlinePtr) >> 2) & 0x30);
127 pixelGrayShade |= TUint8(GetGrayPixelEx(x++,aScanlinePtr) & 0xc0);
128 *ptr++ = pixelGrayShade;
133 void CBitwiseBitmap::GetScanLineGray16(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
135 aLength=Min(aLength,(TInt)(aBuf.MaxLength()<<1));
136 aBuf.SetLength((aLength + 1) >> 1);
138 TUint8* ptr = (TUint8*)aBuf.Ptr();
139 TUint8* ptrLimit = ptr + aBuf.Length();
142 if(iHeader.iBitsPerPixel == 1)
144 while (ptr < ptrLimit)
146 TUint8 pixelGrayShade = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0x0F : 0);
148 pixelGrayShade |= TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xF0 : 0);
150 *ptr++ = pixelGrayShade;
155 while (ptr < ptrLimit)
157 TUint8 pixelGrayShade = TUint8(GetGrayPixelEx(x++,aScanlinePtr) >> 4);
158 pixelGrayShade |= GetGrayPixelEx(x++,aScanlinePtr) & 0xf0;
159 *ptr++ = pixelGrayShade;
164 void CBitwiseBitmap::GetScanLineGray256(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
166 aLength = Min(aLength,aBuf.MaxLength());
167 aBuf.SetLength(aLength);
169 TUint8* ptr = (TUint8*)aBuf.Ptr();
170 TUint8* ptrLimit = ptr + aLength;
171 TInt xCoord = aPixel.iX;
173 if(iHeader.iBitsPerPixel == 1)
175 while (ptr < ptrLimit)
177 *ptr++ = TUint8(COLOR_VALUE(aScanlinePtr, xCoord) ? 0xFF : 0);
183 while (ptr < ptrLimit)
184 *ptr++ = GetGrayPixelEx(xCoord++,aScanlinePtr);
188 void CBitwiseBitmap::GetScanLineColor16(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
190 aLength=Min(aLength,(TInt)(aBuf.MaxLength()<<1));
191 aBuf.SetLength((aLength + 1) >> 1);
193 TUint8* ptr = (TUint8*)aBuf.Ptr();
194 TUint8* ptrLimit = ptr + aBuf.Length();
197 if(iHeader.iBitsPerPixel == 1)
199 while (ptr < ptrLimit)
201 TUint8 pixelGrayShade = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0x0F : 0);
203 pixelGrayShade |= TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xF0 : 0);
205 *ptr++ = pixelGrayShade;
210 while (ptr < ptrLimit)
212 TUint8 pixelGrayShade = TUint8(GetRgbPixelEx(x++,aScanlinePtr).Color16());
213 pixelGrayShade |= GetRgbPixelEx(x++,aScanlinePtr).Color16() << 4;
214 *ptr++ = pixelGrayShade;
219 void CBitwiseBitmap::GetScanLineColor256(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
221 aLength = Min(aLength,aBuf.MaxLength());
222 aBuf.SetLength(aLength);
224 TUint8* ptr = (TUint8*)aBuf.Ptr();
225 TUint8* ptrLimit = ptr + aLength;
226 TInt xCoord = aPixel.iX;
228 if(iHeader.iBitsPerPixel == 1)
230 while (ptr < ptrLimit)
232 *ptr++ = TUint8(COLOR_VALUE(aScanlinePtr, xCoord) ? 0xFF : 0);
238 while (ptr < ptrLimit)
239 *ptr++ = TUint8(GetRgbPixelEx(xCoord++,aScanlinePtr).Color256());
243 void CBitwiseBitmap::GetScanLineColor4K(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
245 aLength = Min(aLength,aBuf.MaxLength() >> 1);
246 aBuf.SetLength(aLength << 1);
248 TUint16* ptr = (TUint16*)aBuf.Ptr();
249 const TUint16* ptrLimit = ptr + aLength;
252 if(iHeader.iBitsPerPixel == 1)
254 while (ptr < ptrLimit)
256 *ptr++ = TUint16(COLOR_VALUE(aScanlinePtr, x) ? 0x0FFF : 0);
262 while (ptr < ptrLimit)
263 *ptr++ = TUint16(GetRgbPixelEx(x++,aScanlinePtr)._Color4K());
267 void CBitwiseBitmap::GetScanLineColor64K(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
269 aLength = Min(aLength,aBuf.MaxLength() >> 1);
270 aBuf.SetLength(aLength << 1);
272 TUint16* ptr = (TUint16*)aBuf.Ptr();
273 TUint16* ptrLimit = ptr + aLength;
276 if(iHeader.iBitsPerPixel == 1)
278 while (ptr < ptrLimit)
280 *ptr++ = TUint16(COLOR_VALUE(aScanlinePtr, x) ? 0xFFFF : 0);
284 else if(iHeader.iBitsPerPixel == 12)
287 // use lookup table for 12->16 conversion
288 TUint16* pixel4K = ((TUint16*) aScanlinePtr) + x;
289 while(ptr < ptrLimit)
291 // this takes the 12 bit value, this is a number between 0 and 4095,
292 // and looks up its corrosponding 16 bit value in the lookup table.
293 // the colour should be identical, and but just in a different format
294 // see below for an explaination of 12 & 16 bit colour values
295 *ptr++ = K12to16LUT[*pixel4K++];
298 /* This code uses logic rather than a lookup table
299 to convert from 12->16 bpp and can be used instead of the above code
300 if the 8k the lookup table uses becomes an issue
304 The 12 bit colour format uses 4 bits for the red, green and blue values.
305 The colour is stored as a word with the most significant 4 bits having a
307 i.e. 0000RRRR GGGGBBBB where R,G & B represent single bits in the word.
309 The code below labeled 'conversion of 4k colour...' changes the colour from
310 16 bit to 32 bit where each colour nibble in the 16 bit version is changed
311 to a byte in the 32 bit version e.g.
312 0000RRRR GGGGBBBB -> 00000000 RRRRRRRR GGGGGGGG BBBBBBBB
317 The 16 bit colour format uses all 16 bits to represent the required colour.
318 There are two possible 16 bit formats 5-5-5 and 5-6-5.
319 Symbian uses the 5-6-5 format, with this all 16 bits are used to make the colour
320 giving a possible value between 0..65535. The RGB components are divided up
321 as follows RRRR RGGG GGGB BBBB i.e. 5 bits for red and blue, and 6 for green.
323 The code below labeled 'conversion to 64k' converts the colour from a 16 bit
324 0000 RRRR GGGG BBBB -> RRRR RGGG GGGB BBBB format.
326 register TUint16* pixel4K = ((TUint16*) aScanlinePtr) + x;
327 while (ptr < ptrLimit)
329 // conversion of 4k colour from 16 to 32 bits
330 // this changes from a 16 to 32 bit value while keeping colour unchanged
331 register TUint16 pixelVal = *pixel4K++;
332 register TUint32 value32 = ((pixelVal & 0x0f00) >> 8) |
333 ((pixelVal & 0x00f0) << 4) |
334 ((pixelVal & 0x000f) << 16);
335 value32 |= (value32 << 4);
336 // conversion to 64k (RRRR RGGG GGGB BBBB)
337 // this will make the change from (16 bit) 4-4-4 bpp to 5-6-5 bpp format
338 register TUint32 color64K = ((value32 & 0x000000f8) << 8) |
339 ((value32 & 0x0000fc00) >> 5) |
340 ((value32 & 0x00f80000) >> 19);
341 // store new colour value
342 *ptr++ = static_cast <TUint16> (color64K);
347 while (ptr < ptrLimit)
348 *ptr++ = TUint16(GetRgbPixelEx(x++,aScanlinePtr)._Color64K());
352 void CBitwiseBitmap::GetScanLineColor16M(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
354 aLength = Min(aLength,aBuf.MaxLength() / 3);
355 aBuf.SetLength(aLength * 3);
357 TUint8* ptr = (TUint8*)aBuf.Ptr();
358 TUint8* ptrLimit = ptr + (aLength * 3);
361 if(iHeader.iBitsPerPixel == 1)
363 while (ptr < ptrLimit)
365 const TUint8 color = TUint8(COLOR_VALUE(aScanlinePtr, x) ? 0xFF : 0);
374 GetRgbPixelExMany16M(aPixel.iX,aScanlinePtr,ptr,aLength);
378 void CBitwiseBitmap::GetScanLineColor16MU(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
380 aLength = Min(aLength,aBuf.MaxLength() >> 2);
381 aBuf.SetLength(aLength << 2);
383 TUint32* ptr = (TUint32*)aBuf.Ptr();
385 GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength);
388 void CBitwiseBitmap::GetScanLineColor16MA(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
390 aLength = Min(aLength,aBuf.MaxLength() >> 2);
391 aBuf.SetLength(aLength << 2);
393 TUint32* ptr = (TUint32*)aBuf.Ptr();
394 GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength);
398 Get the scanline data into the destination buffer in the EColor16MAP format.
399 @param aDestBuf - destination buffer
400 @param aPixel - the start position of the scanline.
401 @param aLength - scanline length, as word length
402 @param aScanlinePtr - scanline pointer
404 void CBitwiseBitmap::GetScanLineColor16MAP(TDes8& aDestBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
406 aLength = Min(aLength, aDestBuf.MaxLength() >> 2);
407 aDestBuf.SetLength(aLength << 2);
408 TUint32* ptr = (TUint32*)aDestBuf.Ptr();
409 GetRgbPixelExMany16MAP(aPixel.iX,aScanlinePtr,ptr,aLength);
413 void CBitwiseBitmap::GetScanLineColorRgb(TDes8& aBuf,const TPoint& aPixel,TInt aLength,TUint32* aScanlinePtr) const
415 aLength = Min(aLength,aBuf.MaxLength() / sizeof(TRgb));
416 aBuf.SetLength(aLength * sizeof(TRgb));
418 TUint32* ptr = (TUint32*)aBuf.Ptr();
419 GetRgbPixelExMany(aPixel.iX,aScanlinePtr,ptr,aLength);
422 void CBitwiseBitmap::GetScanLineExBits(TDes8& aBuf,TInt aX,TInt aLength,TUint32* aScanlinePtr) const
425 TInt pixelsPerWord = 8;
426 TInt roundingmask = ~0x7;
428 TInt roundupfactor = 1;
429 const TDisplayMode displayMode = iSettings.CurrentDisplayMode();
435 break; // set by default
449 roundingmask = ~0x1f;
455 Panic(EFbsBitmapInvalidMode);
458 aLength = Min(aLength,aBuf.MaxLength() << bitshift);
459 aBuf.SetLength((aLength + roundupfactor) >> bitshift);
461 TUint32* ptr = (TUint32*)aBuf.Ptr(); // guaranteed to be word aligned by the calling function
462 TInt startlong = aX & roundingmask;
463 TInt finishlong = (aX + aLength + pixelsPerWord - 1) & roundingmask;
464 bitshift += 2; // Convert pixels per byte shift to pixels per word shift
465 TUint32* wordptr = aScanlinePtr + (startlong >> bitshift);
466 TInt wordLength = (finishlong - startlong) >> bitshift;
467 TUint32* wordptrLimit = wordptr + wordLength;
469 const TInt destinationWords = Min(aBuf.MaxLength() >> 2,wordLength);
470 TUint32* ptrlimit = ptr + destinationWords;
472 TInt offset = (aX - startlong) << logbpp;
476 TInt offsetextra = 32-offset;
477 TUint32 data = *wordptr++;
480 while (ptr < ptrlimit - 1)
482 TUint32 tmp = *wordptr++;
483 data |= tmp << offsetextra;
485 data = tmp >> offset;
488 if (wordptr < wordptrLimit)
489 *ptr = data | (*wordptr << offsetextra);
495 while (ptr < ptrlimit)
498 // if the buffer isn't a whole number of words long,
499 // we need to copy the remaining bytes
500 const TInt bytesRemaining = aBuf.Length() - (destinationWords * sizeof(TUint32));
501 if (bytesRemaining > 0)
502 Mem::Copy(ptr,wordptr,bytesRemaining);
507 void CBitwiseBitmap::GetScanLineExBytes(TDes8& aBuf,TInt aX,TInt aLength,TUint32* aScanlinePtr) const
509 TInt numberOfBytesToCopy = 0;
510 TUint8* ptr = (TUint8*)aScanlinePtr;
511 TDisplayMode displayMode = iSettings.CurrentDisplayMode();
517 aLength = Min(aLength,aBuf.MaxLength());
518 numberOfBytesToCopy = aLength;
525 aLength = Min(aLength,aBuf.MaxLength() / 2);
526 numberOfBytesToCopy = aLength * 2;
532 aLength = Min(aLength,aBuf.MaxLength() / 3);
533 numberOfBytesToCopy = aLength * 3;
541 aLength = Min(aLength,aBuf.MaxLength() / 4);
542 numberOfBytesToCopy = aLength * 4;
547 Panic(EFbsBitmapInvalidMode);
550 aBuf.SetLength(numberOfBytesToCopy);
552 Mem::Copy((TAny*)aBuf.Ptr(),ptr,numberOfBytesToCopy);
555 void CBitwiseBitmap::DoStretchScanLine(TDes8& aBuf,TInt x,TInt y,TInt aClipStrchX,
556 TInt aClipStrchLen,TInt aStretchLength,TInt aOrgX,TInt aOrgLen,
557 const TPoint& aDitherOffset,TDisplayMode aDispMode,TUint32* aBase,
558 TLineScanningPosition& aLineScanningPosition) const
561 TUint32* bufptr=(TUint32*)((TInt)(&aBuf[0]+3)&~3);
562 TUint32* buflimit=bufptr;
564 TPoint pixel(aOrgX,y);
565 const TDisplayMode displayMode = iSettings.CurrentDisplayMode();
566 GetScanLinePtr(slptr, aOrgLen, pixel,aBase, aLineScanningPosition);
569 WhiteFill((TUint8*)aBuf.Ptr(),aBuf.MaxLength(),displayMode);
574 TLinearDDA stretchmap;
575 TPoint coordmap(aOrgX,0);
576 stretchmap.Construct(coordmap,coordmap+TPoint(aOrgLen,aStretchLength),TLinearDDA::ELeft);
577 coordmap.iY=aClipStrchX;
578 if (aClipStrchX>0) stretchmap.JumpToYCoord(coordmap.iX,coordmap.iY);
579 else stretchmap.SingleStep(coordmap);
584 aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<4));
585 aBuf.SetLength((aClipStrchLen+3)>>2);
586 buflimit+=(aBuf.Length()+3)>>2;
587 if (displayMode == EGray16)
589 TInt index=((aDitherOffset.iY&1)<<1)+((aDitherOffset.iX+x)&1);
590 while(bufptr<buflimit)
596 if (coordmap.iX>lastcoord)
598 lastValue=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
599 lastcoord=coordmap.iX;
601 *bufptr|=(lastValue<<shift);
604 if (stretchmap.SingleStep(coordmap)) break;
611 while (bufptr < buflimit)
617 if (coordmap.iX>lastcoord)
619 lastValue = GetGrayPixelEx(coordmap.iX,slptr) >> 6;
620 lastcoord = coordmap.iX;
622 *bufptr |= (lastValue << shift);
624 if (stretchmap.SingleStep(coordmap)) break;
633 aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<3));
634 aBuf.SetLength((aClipStrchLen+1)>>1);
635 buflimit+=(aBuf.Length()+3)>>2;
636 while(bufptr<buflimit)
642 if (coordmap.iX>lastcoord)
644 lastValue = GetGrayPixelEx(coordmap.iX,slptr) >> 4;
645 lastcoord=coordmap.iX;
647 *bufptr |= lastValue << shift;
649 if (stretchmap.SingleStep(coordmap)) break;
657 aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<3));
658 aBuf.SetLength((aClipStrchLen+1)>>1);
659 buflimit+=(aBuf.Length()+3)>>2;
660 while(bufptr<buflimit)
666 if (coordmap.iX>lastcoord)
668 lastValue = GetRgbPixelEx(coordmap.iX,slptr).Color16();
669 lastcoord = coordmap.iX;
671 *bufptr |= lastValue << shift;
673 if (stretchmap.SingleStep(coordmap)) break;
681 aClipStrchLen = Min(aClipStrchLen,(TInt)(aBuf.MaxLength() & ~3));
682 aBuf.SetLength(aClipStrchLen);
683 buflimit += (aBuf.Length() + 3) >> 2;
685 while (bufptr < buflimit)
691 if (coordmap.iX>lastcoord)
693 lastValue = GetGrayPixelEx(coordmap.iX,slptr);
694 lastcoord=coordmap.iX;
696 *bufptr |= lastValue << shift;
698 if (stretchmap.SingleStep(coordmap))
707 aClipStrchLen = Min(aClipStrchLen,(TInt)(aBuf.MaxLength() & ~3));
708 aBuf.SetLength(aClipStrchLen);
709 buflimit += (aBuf.Length() + 3) >> 2;
711 while (bufptr < buflimit)
717 if (coordmap.iX>lastcoord)
719 lastValue = TUint8(GetRgbPixelEx(coordmap.iX,slptr).Color256());
720 lastcoord = coordmap.iX;
722 *bufptr |= lastValue << shift;
724 if (stretchmap.SingleStep(coordmap))
733 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1);
734 aBuf.SetLength(aClipStrchLen << 1);
735 buflimit += (aBuf.Length() + 3) >> 2;
737 while (bufptr < buflimit)
739 if (coordmap.iX>lastcoord)
741 lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color4K();
742 lastcoord=coordmap.iX;
745 if (stretchmap.SingleStep(coordmap))
747 if (coordmap.iX>lastcoord)
749 lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color4K();
750 lastcoord=coordmap.iX;
752 *bufptr |= lastValue << 16;
753 if (stretchmap.SingleStep(coordmap))
761 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1);
762 aBuf.SetLength(aClipStrchLen << 1);
763 buflimit += (aBuf.Length() + 3) >> 2;
765 while (bufptr < buflimit)
767 if (coordmap.iX>lastcoord)
769 lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color64K();
770 lastcoord=coordmap.iX;
773 if (stretchmap.SingleStep(coordmap))
775 if (coordmap.iX>lastcoord)
777 lastValue = GetRgbPixelEx(coordmap.iX,slptr)._Color64K();
778 lastcoord=coordmap.iX;
780 *bufptr |= lastValue << 16;
781 if (stretchmap.SingleStep(coordmap))
787 case EColor16M: // Destination Mode
789 // Optimisation: Both of conditions on 32bpp and 24bpp were added to avoid to use
790 // GetRgbPixelEx() for each pixel
791 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / 3);
792 aBuf.SetLength(aClipStrchLen * 3);
793 TUint8* ptr = (TUint8*)bufptr;
794 TUint8* ptrLimit = ptr + aBuf.Length();
796 if (iHeader.iBitsPerPixel == 32) // 32bpp source image => color
799 if(displayMode == EColor16MAP)
801 const TUint16* normTable = PtrTo16BitNormalisationTable();
802 while (ptr < ptrLimit)
804 if (coordmap.iX > lastcoord)
806 lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable);
807 lastcoord = coordmap.iX;
809 *ptr++ = TUint8(lastColor);
810 *ptr++ = TUint8(lastColor >> 8);
811 *ptr++ = TUint8(lastColor >> 16);
812 if (stretchmap.SingleStep(coordmap))
817 while (ptr < ptrLimit)
819 if (coordmap.iX > lastcoord)
821 lastColor = *(slptr + coordmap.iX);
822 lastcoord = coordmap.iX;
824 *ptr++ = TUint8(lastColor);
825 *ptr++ = TUint8(lastColor >> 8);
826 *ptr++ = TUint8(lastColor >> 16);
827 if (stretchmap.SingleStep(coordmap))
832 else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color
835 while (ptr < ptrLimit)
837 if (coordmap.iX > lastcoord)
839 TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3;
840 lastColor = TUint8(*scanLineBytePointer);
841 scanLineBytePointer++;
842 lastColor |= TUint8(*scanLineBytePointer) << 8;
843 scanLineBytePointer++;
844 lastColor |= TUint8(*scanLineBytePointer) << 16;
845 lastcoord = coordmap.iX;
847 *ptr++ = TUint8(lastColor);
848 *ptr++ = TUint8(lastColor >> 8);
849 *ptr++ = TUint8(lastColor >> 16);
850 if (stretchmap.SingleStep(coordmap))
857 while (ptr < ptrLimit)
859 if (coordmap.iX>lastcoord)
861 lastColor = GetRgbPixelEx(coordmap.iX,slptr);
862 lastcoord=coordmap.iX;
864 TInt color16M = lastColor._Color16M();
865 *ptr++ = TUint8(color16M);
866 *ptr++ = TUint8(color16M >> 8);
867 *ptr++ = TUint8(color16M >> 16);
868 if (stretchmap.SingleStep(coordmap))
876 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / sizeof(TRgb));
877 aBuf.SetLength(aClipStrchLen * sizeof(TRgb));
878 TRgb* pixelPtr = (TRgb*)bufptr;
879 TRgb* pixelPtrLimit = pixelPtr + aClipStrchLen;
882 while (pixelPtr < pixelPtrLimit)
884 if (coordmap.iX > lastcoord)
886 lastColor = GetRgbPixelEx(coordmap.iX,slptr);
887 lastcoord = coordmap.iX;
889 *pixelPtr++ = lastColor;
890 if (stretchmap.SingleStep(coordmap))
895 case EColor16MU: // Destination Mode
897 // Optimisation: The condition 32bpp was added to avoid to use
898 //GetRgbPixelEx() for each pixel (construction of a TRgb object each time)
899 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2);
900 aBuf.SetLength(aClipStrchLen << 2);
901 TInt32* pixelPtr = (TInt32*)bufptr;
902 TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen;
904 if (iHeader.iBitsPerPixel == 32) //32bpp source image => color
907 if(displayMode == EColor16MAP)
909 const TUint16* normTable = PtrTo16BitNormalisationTable();
910 while (pixelPtr < pixelPtrLimit)
912 if (coordmap.iX > lastcoord)
914 lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable);
915 lastcoord = coordmap.iX;
917 *pixelPtr++ = (lastColor | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order
918 if (stretchmap.SingleStep(coordmap))
923 while (pixelPtr < pixelPtrLimit)
925 if (coordmap.iX > lastcoord)
927 lastColor = *(slptr + coordmap.iX);
928 lastcoord = coordmap.iX;
930 *pixelPtr++ = (lastColor | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order
931 if (stretchmap.SingleStep(coordmap))
937 else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color
940 while (pixelPtr < pixelPtrLimit)
942 if (coordmap.iX > lastcoord)
944 TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3;
945 lastColor = TUint8(*scanLineBytePointer);
946 scanLineBytePointer++;
947 lastColor |= TUint8(*scanLineBytePointer) << 8;
948 scanLineBytePointer++;
949 lastColor |= TUint8(*scanLineBytePointer) << 16;
950 lastcoord = coordmap.iX;
952 *pixelPtr++ = (lastColor | 0xff000000);
953 if (stretchmap.SingleStep(coordmap))
957 else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color
960 while (pixelPtr < pixelPtrLimit)
962 if (coordmap.iX > lastcoord)
964 TUint rawColor = *(((TUint16*)slptr) + coordmap.iX);
965 TInt red = (rawColor & 0xF800)>>8;
967 TInt green = (rawColor & 0x07E0)>>3;
969 TInt blue = (rawColor & 0x001F)<<3;
971 lastColor = 0xff000000 | (red << 16) | (green << 8) | blue;
972 lastcoord = coordmap.iX;
974 *pixelPtr++ = lastColor;
975 if (stretchmap.SingleStep(coordmap))
982 while (pixelPtr < pixelPtrLimit)
984 if (coordmap.iX > lastcoord)
986 lastColor = GetRgbPixelEx(coordmap.iX,slptr);
987 lastcoord = coordmap.iX;
989 *pixelPtr++ = (lastColor._Color16MU() | 0xff000000);//BGR0 (Blue/Green/Red) as little endian byte order
990 if (stretchmap.SingleStep(coordmap))
998 // Optimisation: The condition 32bpp was added to avoid to use
999 // GetRgbPixelEx() for each pixel (construction of a TRgb object each time)
1000 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2);
1001 aBuf.SetLength(aClipStrchLen << 2);
1002 TInt32* pixelPtr = (TInt32*)bufptr;
1003 TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen;
1004 const TUint16* normTable = PtrTo16BitNormalisationTable();
1005 if (iHeader.iBitsPerPixel == 32) //32bpp source image => color
1008 if(displayMode == EColor16MAP)
1010 while (pixelPtr < pixelPtrLimit)
1012 if (coordmap.iX > lastcoord)
1014 lastColor = PMA2NonPMAPixel(*(slptr + coordmap.iX), normTable);
1015 lastcoord = coordmap.iX;
1017 *pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order
1018 if (stretchmap.SingleStep(coordmap))
1024 while (pixelPtr < pixelPtrLimit)
1026 if (coordmap.iX > lastcoord)
1028 lastColor = *(slptr + coordmap.iX);
1029 lastcoord = coordmap.iX;
1031 *pixelPtr++ = lastColor;
1032 if (stretchmap.SingleStep(coordmap))
1037 else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color
1040 while (pixelPtr < pixelPtrLimit)
1042 if (coordmap.iX > lastcoord)
1044 TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3;
1045 lastColor = TUint8(*scanLineBytePointer);
1046 scanLineBytePointer++;
1047 lastColor |= TUint8(*scanLineBytePointer) << 8;
1048 scanLineBytePointer++;
1049 lastColor |= TUint8(*scanLineBytePointer) << 16;
1050 lastcoord = coordmap.iX;
1052 *pixelPtr++ = (lastColor | 0xff000000);
1053 if (stretchmap.SingleStep(coordmap))
1057 else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color
1060 while (pixelPtr < pixelPtrLimit)
1062 if (coordmap.iX > lastcoord)
1064 TUint rawColor = *(((TUint16*)slptr) + coordmap.iX);
1065 TInt red = (rawColor & 0xF800)>>8;
1067 TInt green = (rawColor & 0x07E0)>>3;
1069 TInt blue = (rawColor & 0x001F)<<3;
1071 lastColor = 0xff000000 | (red << 16) | (green << 8) | blue;
1072 lastcoord = coordmap.iX;
1074 *pixelPtr++ = lastColor;
1075 if (stretchmap.SingleStep(coordmap))
1083 while (pixelPtr < pixelPtrLimit)
1085 if (coordmap.iX > lastcoord)
1087 lastColor = GetRgbPixelEx(coordmap.iX,slptr);
1088 lastcoord = coordmap.iX;
1090 *pixelPtr++ = lastColor._Color16MA();//BGRA (Blue/Green/Red) as little endian byte order
1091 if (stretchmap.SingleStep(coordmap))
1098 { //if alpha is not available, assign 255 as alpha (opaque).
1099 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2);
1100 aBuf.SetLength(aClipStrchLen << 2);
1101 TInt32* pixelPtr = (TInt32*)bufptr;
1102 TInt32* pixelPtrLimit = pixelPtr + aClipStrchLen;
1103 if (iHeader.iBitsPerPixel == 32) //32bpp source image => color
1106 //pre-multiply if alpha IS available.
1107 if(displayMode == EColor16MA)
1109 while (pixelPtr < pixelPtrLimit)
1111 if (coordmap.iX > lastcoord)
1113 lastColor = NonPMA2PMAPixel(*(slptr + coordmap.iX));
1114 lastcoord = coordmap.iX;
1116 *pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order
1117 if (stretchmap.SingleStep(coordmap))
1121 else if(displayMode == EColor16MU)
1123 while (pixelPtr < pixelPtrLimit)
1125 if (coordmap.iX > lastcoord)
1127 //do not want to convert to non pma, since keep transparency
1128 //e.g. alpha 0.5, red 0.5. Want to keep red as 0.5 since it
1129 //is not fully red. For 16MA convert to 1, and keep 0.5 alpha
1130 lastColor = (*(slptr + coordmap.iX))|0xff000000;
1131 lastcoord = coordmap.iX;
1133 *pixelPtr++ = lastColor;//BGRA (Blue/Green/Red) as little endian byte order
1134 if (stretchmap.SingleStep(coordmap))
1140 while (pixelPtr < pixelPtrLimit)
1142 if (coordmap.iX > lastcoord)
1144 lastColor = *(slptr + coordmap.iX);
1145 lastcoord = coordmap.iX;
1147 *pixelPtr++ = lastColor;
1148 if (stretchmap.SingleStep(coordmap))
1153 else if (iHeader.iBitsPerPixel == 24) //24bpp source image => color
1156 while (pixelPtr < pixelPtrLimit)
1158 if (coordmap.iX > lastcoord)
1160 TUint8* scanLineBytePointer = (TUint8*)slptr + coordmap.iX*3;
1161 lastColor = TUint8(*scanLineBytePointer);
1162 scanLineBytePointer++;
1163 lastColor |= TUint8(*scanLineBytePointer) << 8;
1164 scanLineBytePointer++;
1165 lastColor |= TUint8(*scanLineBytePointer) << 16;
1166 lastcoord = coordmap.iX;
1168 *pixelPtr++ = (lastColor | 0xff000000);
1169 if (stretchmap.SingleStep(coordmap))
1173 else if (iHeader.iBitsPerPixel == 16) //16bpp source image => color
1176 while (pixelPtr < pixelPtrLimit)
1178 if (coordmap.iX > lastcoord)
1180 TUint rawColor = *(((TUint16*)slptr) + coordmap.iX);
1181 TInt red = (rawColor & 0xF800)>>8;
1183 TInt green = (rawColor & 0x07E0)>>3;
1185 TInt blue = (rawColor & 0x001F)<<3;
1187 lastColor = 0xff000000 | (red << 16) | (green << 8) | blue;
1188 lastcoord = coordmap.iX;
1190 *pixelPtr++ = lastColor;
1191 if (stretchmap.SingleStep(coordmap))
1199 while (pixelPtr < pixelPtrLimit)
1201 if (coordmap.iX > lastcoord)
1203 lastColor = GetRgbPixelEx(coordmap.iX,slptr);
1204 lastcoord = coordmap.iX;
1206 *pixelPtr++ = lastColor._Color16MA();//BGRA (Blue/Green/Red) as little endian byte order
1207 if (stretchmap.SingleStep(coordmap))
1215 TBool oddx=(aDitherOffset.iX&1);
1216 TBool oddy=(aDitherOffset.iY&1);
1217 aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength()>>2)<<5));
1218 aBuf.SetLength((aClipStrchLen+7)>>3);
1219 buflimit+=(aBuf.Length()+3)>>2;
1220 while(bufptr<buflimit)
1226 if (coordmap.iX > lastcoord)
1228 lastValue = GetGrayPixelEx(coordmap.iX,slptr);
1229 lastcoord = coordmap.iX;
1231 if (HashTo1bpp(lastValue,oddx,oddy))
1235 if (stretchmap.SingleStep(coordmap)) break;
1242 Panic(EFbsBitmapInvalidMode);
1246 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
1248 TInt first=0,second=0,third=0,fourth=0,fifth=0,sixth=0,seventh=0,eighth=0;
1249 TUint8* bufptr=&aBuf[0];
1250 TUint8* buflimit=bufptr;
1251 TUint32* slptr=NULL;
1252 TPoint pixel(aOrgX,y);
1253 TDisplayMode displayMode = iSettings.CurrentDisplayMode();
1254 GetScanLinePtr(slptr,aOrgLen,pixel,aBase, aLineScanningPosition);
1257 WhiteFill((TUint8*)aBuf.Ptr(),aBuf.MaxLength(),displayMode);
1260 TLinearDDA stretchmap;
1261 TPoint coordmap(aOrgX,0);
1262 stretchmap.Construct(coordmap,coordmap+TPoint(aOrgLen,aStretchLength),TLinearDDA::ELeft);
1263 coordmap.iY=aClipStrchX;
1264 if (aClipStrchX>0) stretchmap.JumpToYCoord(coordmap.iX,coordmap.iY);
1265 else stretchmap.NextStep(coordmap);
1270 aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<2));
1271 aBuf.SetLength((aClipStrchLen+3)>>2);
1272 TInt index=((aDitherOffset.iY&1)<<1)+((aDitherOffset.iX+x)&1);
1273 buflimit+=aBuf.Length();
1274 if (displayMode==EGray16)
1276 while(bufptr<buflimit)
1278 first=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
1280 stretchmap.NextStep(coordmap);
1281 second=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
1283 stretchmap.NextStep(coordmap);
1284 third=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
1286 stretchmap.NextStep(coordmap);
1287 fourth=HashTo2bpp(GetGrayPixelEx(coordmap.iX,slptr),index);
1289 *bufptr++=TUint8(first|(second<<2)|(third<<4)|(fourth<<6));
1290 stretchmap.NextStep(coordmap);
1295 while(bufptr<buflimit)
1297 first=GetGrayPixelEx(coordmap.iX,slptr)>>6;
1298 stretchmap.NextStep(coordmap);
1299 second=GetGrayPixelEx(coordmap.iX,slptr)>>6;
1300 stretchmap.NextStep(coordmap);
1301 third=GetGrayPixelEx(coordmap.iX,slptr)>>6;
1302 stretchmap.NextStep(coordmap);
1303 fourth=GetGrayPixelEx(coordmap.iX,slptr)>>6;
1304 *bufptr++=TUint8(first|(second<<2)|(third<<4)|(fourth<<6));
1305 stretchmap.NextStep(coordmap);
1312 aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<1));
1313 aBuf.SetLength((aClipStrchLen+1)>>1);
1314 buflimit+=aBuf.Length();
1315 while(bufptr<buflimit)
1317 first = GetGrayPixelEx(coordmap.iX,slptr) >> 4;
1318 stretchmap.NextStep(coordmap);
1319 first |= GetGrayPixelEx(coordmap.iX,slptr) & 0xf0;
1320 *bufptr++ = TUint8(first);
1321 stretchmap.NextStep(coordmap);
1327 aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<1));
1328 aBuf.SetLength((aClipStrchLen+1)>>1);
1329 buflimit+=aBuf.Length();
1330 while(bufptr<buflimit)
1332 first = GetRgbPixelEx(coordmap.iX,slptr).Color16();
1333 stretchmap.NextStep(coordmap);
1334 first |= GetRgbPixelEx(coordmap.iX,slptr).Color16() << 4;
1335 *bufptr++ = TUint8(first);
1336 stretchmap.NextStep(coordmap);
1342 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength());
1343 aBuf.SetLength(aClipStrchLen);
1344 buflimit += aBuf.Length();
1346 while(bufptr < buflimit)
1348 *bufptr++ = GetGrayPixelEx(coordmap.iX,slptr);
1349 stretchmap.NextStep(coordmap);
1355 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength());
1356 aBuf.SetLength(aClipStrchLen);
1357 buflimit += aBuf.Length();
1359 while(bufptr < buflimit)
1361 *bufptr++ = TUint8(GetRgbPixelEx(coordmap.iX,slptr).Color256());
1362 stretchmap.NextStep(coordmap);
1368 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1);
1369 aBuf.SetLength(aClipStrchLen << 1);
1370 buflimit += aBuf.Length();
1372 while(bufptr < buflimit)
1374 *((TUint16*)bufptr) = TUint16(GetRgbPixelEx(coordmap.iX,slptr)._Color4K());
1376 stretchmap.NextStep(coordmap);
1382 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 1);
1383 aBuf.SetLength(aClipStrchLen << 1);
1384 buflimit += aBuf.Length();
1386 while(bufptr < buflimit)
1388 *((TUint16*)bufptr) = TUint16(GetRgbPixelEx(coordmap.iX,slptr)._Color64K());
1390 stretchmap.NextStep(coordmap);
1396 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() / 3);
1397 aBuf.SetLength(aClipStrchLen * 3);
1398 buflimit += aBuf.Length();
1400 while(bufptr<buflimit)
1402 TInt color16M = GetRgbPixelEx(coordmap.iX,slptr)._Color16M();
1403 *bufptr++ = TUint8(color16M);
1404 *bufptr++ = TUint8(color16M >> 8);
1405 *bufptr++ = TUint8(color16M >> 16);
1406 stretchmap.NextStep(coordmap);
1415 aClipStrchLen = Min(aClipStrchLen,aBuf.MaxLength() >> 2);
1416 aBuf.SetLength(aClipStrchLen << 2);
1417 TUint32* pixelPtr = (TUint32*)bufptr;
1418 TUint32* pixelPtrLimit = pixelPtr + aClipStrchLen;
1419 if (aDispMode == EColor16MAP && displayMode == EColor16MA)
1420 while(pixelPtr < pixelPtrLimit)
1422 *pixelPtr++ = NonPMA2PMAPixel(*(slptr + coordmap.iX));
1423 stretchmap.NextStep(coordmap);
1425 else if (aDispMode == EColor16MAP && displayMode == EColor16MAP)
1426 while(pixelPtr < pixelPtrLimit)
1428 *pixelPtr++ = *(slptr + coordmap.iX);
1429 stretchmap.NextStep(coordmap);
1431 else if (aDispMode == EColor16MU)
1432 while(pixelPtr < pixelPtrLimit)
1434 *pixelPtr++ = GetRgbPixelEx(coordmap.iX, slptr).Internal();
1435 stretchmap.NextStep(coordmap);
1438 while(pixelPtr < pixelPtrLimit)
1440 *pixelPtr++ = GetRgbPixelEx(coordmap.iX, slptr).Internal();
1441 stretchmap.NextStep(coordmap);
1447 TBool oddx=(aDitherOffset.iX&1);
1448 TBool oddy=(aDitherOffset.iY&1);
1449 aClipStrchLen=Min(aClipStrchLen,(TInt)((aBuf.MaxLength())<<3));
1450 aBuf.SetLength((aClipStrchLen+7)>>3);
1451 buflimit+=aBuf.Length();
1452 while(bufptr<buflimit)
1454 first=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
1455 stretchmap.NextStep(coordmap);
1456 second=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
1457 stretchmap.NextStep(coordmap);
1458 third=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
1459 stretchmap.NextStep(coordmap);
1460 fourth=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
1461 stretchmap.NextStep(coordmap);
1462 fifth=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
1463 stretchmap.NextStep(coordmap);
1464 sixth=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
1465 stretchmap.NextStep(coordmap);
1466 seventh=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
1467 stretchmap.NextStep(coordmap);
1468 eighth=HashTo1bpp(GetGrayPixelEx(coordmap.iX,slptr),oddx,oddy);
1469 *bufptr++=TUint8(first|(second<<1)|(third<<2)|(fourth<<3)|
1470 (fifth<<4)|(sixth<<5)|(seventh<<6)|(eighth<<7));
1471 stretchmap.NextStep(coordmap);
1477 Panic(EFbsBitmapInvalidMode);