sl@0: // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: /** sl@0: sl@0: The created class instance doesn't take the ownership on aBase parameter. sl@0: @internalComponent sl@0: @pre aBase != NULL sl@0: @param aBase Points to the beginning of compressed bitmap data sl@0: @param aComprDataBytes Total amount of compressed bitmap bytes sl@0: @param aCanAdjustLineScanPos If not EFalse - scanline position can be adjusted calling sl@0: AdjustLineScanningPosition function. sl@0: @see AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos, const TUint32* aBase, TInt aBitmapWidth, TInt aStartPos, TInt aCompressedDataBytes); sl@0: */ sl@0: template sl@0: TScanLineDecompressor::TScanLineDecompressor(const TUint32* aBase, sl@0: TInt aComprDataBytes, sl@0: TBool aCanAdjustLineScanPos) : sl@0: iBase(aBase), sl@0: iComprDataBytes(aComprDataBytes), sl@0: iCanAdjustLineScanPos(aCanAdjustLineScanPos) sl@0: { sl@0: } sl@0: sl@0: /** sl@0: The method calculates the start byte position (as a index) in decompressed bitmap data . sl@0: @internalComponent sl@0: @param aPixel The decompression starts from this pixel sl@0: @param aByteWidth Scanline width in bytes sl@0: @return Calculated start position. sl@0: */ sl@0: template sl@0: TInt TScanLineDecompressor::CalcStartPos(const TPoint& aPixel, TInt aByteWidth) const sl@0: { sl@0: return aPixel.iY * aByteWidth + aPixel.iX * BPP; sl@0: } sl@0: sl@0: /** sl@0: The method calculates the start byte position (as a index) in decompressed bitmap data . sl@0: @internalComponent sl@0: @param aPixel The decompression starts from this pixel sl@0: @param aByteWidth Scanline width in bytes sl@0: @return Calculated start position. sl@0: */ sl@0: template sl@0: TInt TScanLineDecompressor::CalcDestStartPos(const TPoint& aPixel, TInt aByteWidth) const sl@0: { sl@0: return aPixel.iY * aByteWidth + aPixel.iX * BPP_DEST; sl@0: } sl@0: sl@0: /** sl@0: The method calculates the end byte position (as a index) in decompressed bitmap data . sl@0: @internalComponent sl@0: @param aLength Length in pixels of bitmap data we want to decompress. sl@0: @param aPixel The decompression starts from this pixel sl@0: @param aByteWidth Scanline width in bytes sl@0: @return Calculated end position. sl@0: */ sl@0: template sl@0: TInt TScanLineDecompressor::CalcEndPos(TInt aLength, const TPoint& aPixel, sl@0: TInt aByteWidth) const sl@0: { sl@0: return aPixel.iY * aByteWidth + (aPixel.iX + aLength) * BPP_DEST; sl@0: } sl@0: sl@0: /** sl@0: The method calculates a pointer to a place in aDestBuffer where the sl@0: copying of decompressed bitmap data starts. sl@0: @internalComponent sl@0: @param aDestBuffer Points to the start of the destination buffer. sl@0: @param aPixel The decompression starts from this pixel sl@0: @return A pointer to a place in aDestBuffer where the sl@0: copying of decompressed bitmap data starts. sl@0: */ sl@0: template sl@0: TUint8* TScanLineDecompressor::CalcDestPtr(const TUint8* aDestBuffer, sl@0: const TPoint& aPixel) const sl@0: { sl@0: return const_cast (aDestBuffer + aPixel.iX * BPP_DEST); sl@0: } sl@0: sl@0: /** sl@0: The method calculates a pointer to a place in aDestBuffer where the copying sl@0: of the decompressed data stops. sl@0: @internalComponent sl@0: @param aDestPtr A pointer to a place in aDestBuffer where the sl@0: copying of decompressed bitmap data starts - CalcDestPtr() return value. sl@0: @param aPixel The decompression starts from this pixel sl@0: @param aByteWidth Scanline width in bytes sl@0: @param aLength Length in pixels of bitmap data we want to decompress. sl@0: @param aStartPos CalcStartPos() method return value. sl@0: @return A pointer to a place in aDestBuffer where the sl@0: copying of decompressed bitmap data stops. sl@0: @see CalcDestPtr sl@0: @see CalcStartPos sl@0: */ sl@0: template sl@0: TUint8* TScanLineDecompressor::CalcDestPtrLimit(const TUint8* aDestPtr, sl@0: const TPoint& aPixel, TInt aByteWidth, sl@0: TInt aLength, TInt aStartPos) const sl@0: { sl@0: return const_cast (aDestPtr + CalcEndPos(aLength, aPixel, aByteWidth) - aStartPos); sl@0: } sl@0: sl@0: /** sl@0: The method performs a quick find of the correct start position. sl@0: It uses the fact that aLineScanPos parameter should be recalculated after each positioning sl@0: in the compresed bitmap data and might be used in the next call of decompression methods. sl@0: @internalComponent sl@0: @param aLineScanPos Saved information about the last used position in the compressed data sl@0: @param aByteWidth Scanline width in bytes sl@0: @param aStartPos CalcStartPos() method return value. sl@0: @return A pointer to a position in compressed bitmap data, where the decompression sl@0: starts from sl@0: @see CalcStartPos sl@0: */ sl@0: template sl@0: TUint8* TScanLineDecompressor::AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos, sl@0: TInt aByteWidth, sl@0: TInt aStartPos) const sl@0: { sl@0: TUint8* srcPtr = NULL; sl@0: // Fast find the correct position to start sl@0: if(iCanAdjustLineScanPos) sl@0: { sl@0: ::AdjustLineScanningPosition(aLineScanPos, iBase, aByteWidth, aStartPos, iComprDataBytes); sl@0: } sl@0: srcPtr = aLineScanPos.iSrcDataPtr; sl@0: //Unfortunatelly we can't move fast srcPtr if aLineScanPos.iCursorPos > aStartPos, sl@0: //because we have 1 byte for the compressed data length and the data itself after the "length" sl@0: //byte. With this information we can move srcPtr forward, not backward. sl@0: if(aLineScanPos.iCursorPos > aStartPos) sl@0: { sl@0: srcPtr = (TUint8*)iBase; sl@0: aLineScanPos.iCursorPos = 0; sl@0: } sl@0: TInt count = TInt8(*srcPtr);//pixels count sl@0: TInt length = (count < 0 ? -count : count + 1) * BPP;//length in bytes sl@0: //If count < 0 - we have a sequence of abs(count) pixels - abs(count) * BPP bytes sl@0: //If count >= 0 - we have (count + 1) pixels with the same color - (count + 1) * BPP bytes sl@0: while((aLineScanPos.iCursorPos + length) <= aStartPos) sl@0: { sl@0: srcPtr += count < 0 ? length + 1 : (BPP + 1);//(BPP + 1) - bytes for the pixel + 1 byte for the length sl@0: aLineScanPos.iCursorPos += length; sl@0: count = TInt8(*srcPtr); sl@0: length = (count < 0 ? -count : count + 1) * BPP; sl@0: } sl@0: //After executing of the previous "if" operator and "while" loop, srcPtr points to sl@0: //the nearest "length" byte before the start position in compressed bitmap data. sl@0: return srcPtr; sl@0: } sl@0: sl@0: /** sl@0: This overloaded "()" operator used for decompression of bitmap scan lines. sl@0: @internalComponent sl@0: @param aDestBuffer Points to the destination buffer. After the call it fill be filled sl@0: with the decomperssed data. sl@0: @param aPixel The decompression starts from this pixel sl@0: @param aLineScanPos Saved information about the last used position in the compressed data sl@0: @param aByteWidth Scanline width in bytes sl@0: @param aLength Length of requested decompressed data - in pixels sl@0: */ sl@0: template sl@0: void TScanLineDecompressor::operator()(TUint8* aDestBuffer, const TPoint& aPixel, sl@0: TLineScanningPosition& aLineScanPos, sl@0: TInt aByteWidth, TInt aDestByteWidth, TInt aLength) const sl@0: { sl@0: TInt startPos = CalcStartPos(aPixel, aByteWidth); sl@0: TInt destStartPos = CalcDestStartPos(aPixel, aDestByteWidth); sl@0: TUint8* destPtr = CalcDestPtr(aDestBuffer, aPixel); sl@0: const TUint8* destPtrLimit = CalcDestPtrLimit(destPtr, aPixel, aDestByteWidth, aLength, destStartPos); sl@0: //Fast find the correct position to start sl@0: TUint8* srcPtr = AdjustLineScanningPosition(aLineScanPos, aByteWidth, startPos); sl@0: //Decompress each slot of compressed data which has the following format: sl@0: // ...|"length byte"| "pixel value(s)" |... sl@0: while(destPtr < destPtrLimit) sl@0: { sl@0: TInt pixelsInTheSlot = TInt8(*srcPtr++); sl@0: TInt availDestSpaceInBytes = destPtrLimit - destPtr; sl@0: TInt skipBytes = startPos - aLineScanPos.iCursorPos; sl@0: if(pixelsInTheSlot < 0) sl@0: {//a sequence of abs(pixelsInTheSlot) pixels with different color values sl@0: TInt bytesInTheSlot = -pixelsInTheSlot * BPP; sl@0: TUint8* start_pos = srcPtr; sl@0: TInt bytesToCopy = bytesInTheSlot; sl@0: if(skipBytes > 0) //Skip the pixels before the start possition sl@0: { sl@0: bytesToCopy -= skipBytes; sl@0: start_pos += skipBytes; sl@0: } sl@0: if(BPP == BPP_DEST) sl@0: { sl@0: destPtr = Mem::Copy(destPtr, start_pos, ::Min(bytesToCopy, availDestSpaceInBytes)); sl@0: } sl@0: else sl@0: { sl@0: destPtr = CopyBlockPixel(destPtr, start_pos, ::Min(bytesToCopy / BPP, availDestSpaceInBytes / BPP_DEST)); sl@0: } sl@0: //Move to the next "length" byte only if everything, sl@0: //controlled by the current "length" byte, is copied sl@0: if((bytesToCopy / BPP) <= (availDestSpaceInBytes / BPP_DEST)) sl@0: { sl@0: srcPtr += bytesInTheSlot; sl@0: aLineScanPos.iCursorPos += bytesInTheSlot; sl@0: } sl@0: else sl@0: { sl@0: srcPtr--; sl@0: } sl@0: } sl@0: else//the "else" part of - if(pixelsInTheSlot < 0) sl@0: {//(pixelsInTheSlot + 1) pixels with the same color sl@0: TInt pixelsToCopy = pixelsInTheSlot + 1; sl@0: TInt bytesInTheSlot = pixelsToCopy * BPP; sl@0: if(skipBytes > 0) //Skip the pixels before the start possition sl@0: { sl@0: pixelsToCopy -= skipBytes / BPP; sl@0: } sl@0: destPtr = CopyPixel(destPtr, srcPtr, ::Min(pixelsToCopy, availDestSpaceInBytes / BPP_DEST)); sl@0: //Move to the next "length" byte only if everything, sl@0: //controlled by the current "length" byte, is copied sl@0: if((pixelsToCopy * BPP) <= availDestSpaceInBytes) sl@0: { sl@0: srcPtr += BPP;// += BPP - we have (count + 1) pixels with the same color - only BPP bytes are used. sl@0: aLineScanPos.iCursorPos += bytesInTheSlot; sl@0: } sl@0: else sl@0: { sl@0: srcPtr--; sl@0: } sl@0: }//end of - if(pixelsCnt < 0) sl@0: }//end of - while(destPtr < destPtrLimit) sl@0: aLineScanPos.iSrcDataPtr = srcPtr;//update aLineScanPos.iSrcDataPtr - it will be used sl@0: //when the method is called again. sl@0: } sl@0: sl@0: