1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/fbs/fontandbitmapserver/sfbs/BitmapCompr.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,348 @@
1.4 +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <e32base.h>
1.20 +#include <bitmap.h>
1.21 +#include "CompressionBookmark.h"
1.22 +#include "BitmapCompr.h"
1.23 +#include "UTILS.H"
1.24 +#include "bitmapconst.h"
1.25 +
1.26 +GLREF_C void Panic(TFbsPanic aPanic);
1.27 +
1.28 +/**
1.29 +The method recalculates aLineScanPos which is used for quick search of the
1.30 +nearest "length" byte before aStartPos.
1.31 +Note: The method should be used only for compressed in RAM bitmaps for which
1.32 +iPile != NULL.
1.33 +@internalComponent
1.34 +@post aLineScanPos might be updated
1.35 +*/
1.36 +GLDEF_C void AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos,
1.37 + const TUint32* aBase,
1.38 + TInt aBitmapWidth,
1.39 + TInt aStartPos,
1.40 + TInt aCompressedDataBytes)
1.41 + {
1.42 + TInt difference = ::Abs(aStartPos - aLineScanPos.iCursorPos);
1.43 + if(difference > aBitmapWidth && aCompressedDataBytes > KCompressionBookMarkThreshold)
1.44 + {
1.45 + const TCompressionBookMark* bookMarkPtr =
1.46 + (const TCompressionBookMark*)((const TUint8*)aBase +
1.47 + (aCompressedDataBytes + 3) / 4 * 4 + 4);
1.48 + if(bookMarkPtr->iSrcDataOffset && bookMarkPtr->IsCheckSumOk())
1.49 + {
1.50 + TInt difference2 = ::Abs(aStartPos - bookMarkPtr->iCursorPos);
1.51 + if(difference2 < difference)
1.52 + {
1.53 + aLineScanPos.iCursorPos = bookMarkPtr->iCursorPos;
1.54 + aLineScanPos.iSrcDataPtr = ((TUint8*)aBase) + bookMarkPtr->iSrcDataOffset;
1.55 + }
1.56 + }
1.57 + }
1.58 + }
1.59 +
1.60 +/**
1.61 +The method gets the first 16 bpp pixel value pointed by aSrcPtr and copies it aCount times
1.62 +to aDestPtr buffer.
1.63 +@internalComponent
1.64 +@pre aCount > 0
1.65 +@param aSrcPtr It points to the source pixel
1.66 +@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
1.67 +@param aCount How many times the pixel value should be copied
1.68 +@return The updated aDestPtr
1.69 +*/
1.70 +template <>
1.71 +TUint8* TScanLineDecompressor<E2bpp, E2bpp>::CopyPixel(TUint8* aDestPtr,
1.72 + const TUint8* aSrcPtr,
1.73 + TInt aCount) const
1.74 + {
1.75 + //We can't access directly the 16 bits data chunk, because it may be located at an odd address and
1.76 + //THUMB build will fail with "KERNEL EXEC-3".
1.77 + TUint8 lsb = *aSrcPtr;
1.78 + TUint8 msb = *(aSrcPtr + 1);
1.79 + TUint16 data = TUint16(lsb | (TUint16(msb) << 8));
1.80 + TUint32 data32 = TUint32(data | (TUint32(data) << 16));
1.81 + if((TUint32(aDestPtr) & 0x2) && aCount)
1.82 + {
1.83 + *(TUint16*)aDestPtr = data;
1.84 + aDestPtr += 2;//+= 2 - the pixel color is coded into 16 bits - 2 bytes
1.85 + aCount--;
1.86 + }
1.87 + while(aCount > 1)
1.88 + {
1.89 + *(TUint32*)aDestPtr = data32;
1.90 + aDestPtr += 4;//+= 4 - the pixel color is coded into 16 bits - 2 x 2 bytes
1.91 + aCount -= 2;
1.92 + }
1.93 + if(aCount)
1.94 + {
1.95 + *(TUint16*)aDestPtr = data;
1.96 + aDestPtr += 2;//+= 2 - the pixel color is coded into 16 bits - 2 bytes
1.97 + }
1.98 + return aDestPtr;
1.99 + }
1.100 +
1.101 +/**
1.102 +The method gets the first 24 bpp pixel value pointed by aSrcPtr and copies it aCount times
1.103 +to aDestPtr buffer.
1.104 +@internalComponent
1.105 +@pre aCount > 0
1.106 +@param aSrcPtr It points to the source pixel
1.107 +@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
1.108 +@param aCount How many times the pixel value should be copied
1.109 +@return The updated aDestPtr
1.110 +*/
1.111 +template <>
1.112 +TUint8* TScanLineDecompressor<E3bpp, E3bpp>::CopyPixel(TUint8* aDestPtr,
1.113 + const TUint8* aSrcPtr,
1.114 + TInt aCount) const
1.115 + {
1.116 + const TUint8 b1 = *aSrcPtr;
1.117 + const TUint8 b2 = *(aSrcPtr + 1);
1.118 + const TUint8 b3 = *(aSrcPtr + 2);
1.119 + while(aCount--)
1.120 + {
1.121 + *aDestPtr++ = b1;
1.122 + *aDestPtr++ = b2;
1.123 + *aDestPtr++ = b3;
1.124 + }
1.125 + return aDestPtr;
1.126 + }
1.127 +
1.128 +/**
1.129 +The method gets the first 32 bpp pixel value pointed by aSrcPtr and copies it aCount times
1.130 +to aDestPtr buffer.
1.131 +@internalComponent
1.132 +@pre aCount > 0
1.133 +@param aSrcPtr It points to the source pixel
1.134 +@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
1.135 +@param aCount How many times the pixel value should be copied
1.136 +@return The updated aDestPtr
1.137 +*/
1.138 +template <>
1.139 +TUint8* TScanLineDecompressor<E4bpp, E4bpp>::CopyPixel(TUint8* aDestPtr,
1.140 + const TUint8* aSrcPtr,
1.141 + TInt aCount) const
1.142 + {
1.143 + __ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestPtr) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
1.144 +
1.145 + const TUint8 b1 = *aSrcPtr;
1.146 + const TUint8 b2 = *(aSrcPtr + 1);
1.147 + const TUint8 b3 = *(aSrcPtr + 2);
1.148 + const TUint8 b4 = *(aSrcPtr + 3);
1.149 +
1.150 + if((reinterpret_cast<TUint32>(aDestPtr) & 0x3)== 0) // the start address is word aligned
1.151 + {
1.152 + const TUint32 pixel = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
1.153 + TUint32* destPtr32 = reinterpret_cast <TUint32*>(aDestPtr);
1.154 + TInt blocksOf16 = ((aCount + 0x0f) >> 4); // number of blocks of upto 16 words to write
1.155 + // the first iteration writes 1 to 15 words
1.156 + switch (aCount & 0x0f)
1.157 + { // note that case statements intentionally cascade
1.158 + case 0:
1.159 + do { // second and subsequent iterations always write 16 words
1.160 + *destPtr32++ = pixel;
1.161 + case 15:
1.162 + *destPtr32++ = pixel;
1.163 + case 14:
1.164 + *destPtr32++ = pixel;
1.165 + case 13:
1.166 + *destPtr32++ = pixel;
1.167 + case 12:
1.168 + *destPtr32++ = pixel;
1.169 + case 11:
1.170 + *destPtr32++ = pixel;
1.171 + case 10:
1.172 + *destPtr32++ = pixel;
1.173 + case 9:
1.174 + *destPtr32++ = pixel;
1.175 + case 8:
1.176 + *destPtr32++ = pixel;
1.177 + case 7:
1.178 + *destPtr32++ = pixel;
1.179 + case 6:
1.180 + *destPtr32++ = pixel;
1.181 + case 5:
1.182 + *destPtr32++ = pixel;
1.183 + case 4:
1.184 + *destPtr32++ = pixel;
1.185 + case 3:
1.186 + *destPtr32++ = pixel;
1.187 + case 2:
1.188 + *destPtr32++ = pixel;
1.189 + case 1:
1.190 + *destPtr32++ = pixel;
1.191 + } while(--blocksOf16 > 0);
1.192 + }
1.193 +
1.194 + return reinterpret_cast <TUint8*>(destPtr32);
1.195 + }
1.196 +
1.197 + while(aCount--)
1.198 + {
1.199 + *aDestPtr++ = b1;
1.200 + *aDestPtr++ = b2;
1.201 + *aDestPtr++ = b3;
1.202 + *aDestPtr++ = b4;
1.203 + }
1.204 + return aDestPtr;
1.205 + }
1.206 +
1.207 +/**
1.208 +The method gets the first 24 bpp pixel value pointed by aSrcPtr and copies it aCount times
1.209 +to aDestPtr 32 bpp buffer.
1.210 +@internalComponent
1.211 +@pre aCount > 0
1.212 +@param aSrcPtr It points to the source pixel
1.213 +@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
1.214 +@param aCount How many times the pixel value should be copied
1.215 +@return The updated aDestPtr
1.216 +*/
1.217 +template <>
1.218 +TUint8* TScanLineDecompressor<E3bpp, E4bpp>::CopyPixel(TUint8* aDestPtr,
1.219 + const TUint8* aSrcPtr,
1.220 + TInt aCount) const
1.221 + {
1.222 + const TUint8 b1 = *aSrcPtr;
1.223 + const TUint8 b2 = *(aSrcPtr + 1);
1.224 + const TUint8 b3 = *(aSrcPtr + 2);
1.225 +
1.226 + if((reinterpret_cast<TUint32>(aDestPtr) & 0x3)== 0) // the start address is word aligned
1.227 + {
1.228 + const TUint32 pixel = 0xFF000000 | (b3 << 16) | (b2 << 8) | b1; //it is more accurate to equalize to 0xff,
1.229 + //as top byte could correspond an alpha channel
1.230 + TUint32* destPtr32 = reinterpret_cast <TUint32*>(aDestPtr);
1.231 + TInt blocksOf16 = ((aCount + 0x0f) >> 4); // number of blocks of upto 16 words to write
1.232 + // the first iteration writes 1 to 15 words
1.233 + switch (aCount & 0x0f)
1.234 + { // note that case statements intentionally cascade
1.235 + case 0:
1.236 + do { // second and subsequent iterations always write 16 words
1.237 + *destPtr32++ = pixel;
1.238 + case 15:
1.239 + *destPtr32++ = pixel;
1.240 + case 14:
1.241 + *destPtr32++ = pixel;
1.242 + case 13:
1.243 + *destPtr32++ = pixel;
1.244 + case 12:
1.245 + *destPtr32++ = pixel;
1.246 + case 11:
1.247 + *destPtr32++ = pixel;
1.248 + case 10:
1.249 + *destPtr32++ = pixel;
1.250 + case 9:
1.251 + *destPtr32++ = pixel;
1.252 + case 8:
1.253 + *destPtr32++ = pixel;
1.254 + case 7:
1.255 + *destPtr32++ = pixel;
1.256 + case 6:
1.257 + *destPtr32++ = pixel;
1.258 + case 5:
1.259 + *destPtr32++ = pixel;
1.260 + case 4:
1.261 + *destPtr32++ = pixel;
1.262 + case 3:
1.263 + *destPtr32++ = pixel;
1.264 + case 2:
1.265 + *destPtr32++ = pixel;
1.266 + case 1:
1.267 + *destPtr32++ = pixel;
1.268 + } while(--blocksOf16 > 0);
1.269 + }
1.270 +
1.271 + return reinterpret_cast <TUint8*>(destPtr32);
1.272 + }
1.273 +
1.274 + while(aCount--)
1.275 + {
1.276 + *aDestPtr++ = b1;
1.277 + *aDestPtr++ = b2;
1.278 + *aDestPtr++ = b3;
1.279 + *aDestPtr++ = 0xff; //it is more accurate to equalize to 0xff, as top byte
1.280 + //could correspond an alpha channel
1.281 + }
1.282 + return aDestPtr;
1.283 + }
1.284 +
1.285 +/**
1.286 +The method gets the 24 bpp pixel value pointed by aSrcPtr and copies it aCount times
1.287 +to aDestPtr 32 bpp buffer.
1.288 +@internalComponent
1.289 +@pre aCount > 0
1.290 +@param aSrcPtr It points to the source pixel
1.291 +@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times
1.292 +@param aCount How many times the pixel value should be copied
1.293 +@return The updated aDestPtr
1.294 +*/
1.295 +template <>
1.296 +TUint8* TScanLineDecompressor<E3bpp, E4bpp>::CopyBlockPixel(TUint8* aDestPtr,
1.297 + const TUint8* aSrcPtr,
1.298 + TInt aCount) const
1.299 + {
1.300 + while(aCount--)
1.301 + {
1.302 + *aDestPtr++ = *aSrcPtr++;
1.303 + *aDestPtr++ = *aSrcPtr++;
1.304 + *aDestPtr++ = *aSrcPtr++;
1.305 + *aDestPtr++ = 0xff; //it is more accurate to equalize to 0xff, as top byte
1.306 + //could correspond an alpha channel
1.307 + }
1.308 + return aDestPtr;
1.309 + }
1.310 +
1.311 +/**
1.312 +The method should never be executed.
1.313 +Introduced to prevent CCover compiler from failing.
1.314 +@internalComponent
1.315 +@return The unchanged aDestPtr
1.316 +*/
1.317 +template <>
1.318 +TUint8* TScanLineDecompressor<E2bpp, E2bpp>::CopyBlockPixel(TUint8* aDestPtr,
1.319 + const TUint8* /*aSrcPtr*/,
1.320 + TInt /*aCount*/) const
1.321 + {
1.322 + return aDestPtr;
1.323 + }
1.324 +
1.325 +/**
1.326 +The method should never be executed.
1.327 +Introduced to prevent CCover compiler from failing.
1.328 +@internalComponent
1.329 +@return The unchanged aDestPtr
1.330 +*/
1.331 +template <>
1.332 +TUint8* TScanLineDecompressor<E3bpp, E3bpp>::CopyBlockPixel(TUint8* aDestPtr,
1.333 + const TUint8* /*aSrcPtr*/,
1.334 + TInt /*aCount*/) const
1.335 + {
1.336 + return aDestPtr;
1.337 + }
1.338 +
1.339 +/**
1.340 +The method should never be executed.
1.341 +Introduced to prevent CCover compiler from failing.
1.342 +@internalComponent
1.343 +@return The unchanged aDestPtr
1.344 +*/
1.345 +template <>
1.346 +TUint8* TScanLineDecompressor<E4bpp, E4bpp>::CopyBlockPixel(TUint8* aDestPtr,
1.347 + const TUint8* /*aSrcPtr*/,
1.348 + TInt /*aCount*/) const
1.349 + {
1.350 + return aDestPtr;
1.351 + }