1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicsdeviceinterface/screendriver/sbit/BMDRAW32PMA.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,785 @@
1.4 +// Copyright (c) 2006-2010 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 "BMDRAW.H"
1.20 +#include <graphics/lookuptable.h>
1.21 +#include <graphics/blendingalgorithms.h>
1.22 +
1.23 +/*
1.24 +Does the same conversion as NonPMA2PMAPixel, but leaves the values in the RB and G uint32 values
1.25 +ready for use in the blending algorithm. Also assumes alphas of 0 or 0xFF have already been
1.26 +stripped out as special cases.
1.27 +*/
1.28 +FORCEINLINE void NonPMA2PMAPixelRBG(TUint32 aPixel, TUint32 &aSrcRB, TUint32 &aSrcG, TUint32 &aMask)
1.29 + {
1.30 + TUint32 alpha=(aPixel >> 24);
1.31 + aMask = 0x0100 - alpha; // for use in PMABlend_fromRBandG
1.32 + TUint32 tap1=alpha+1;
1.33 + aSrcRB = (aPixel & KRBMask) * tap1;
1.34 + aSrcRB >>= 8;
1.35 + aSrcRB &= KRBMask;
1.36 + aSrcG = (aPixel&0xFF000000) | (((aPixel & KGMask)>>8) * tap1) & KAGMask;
1.37 + }
1.38 +
1.39 +/*
1.40 +Uses same algorithm as PMABlend_noChecksInplace, but optimised for use with NonPMA2PMAPixelRBG where
1.41 +source values are pre-split into RB and G components ready for use in blend
1.42 +*/
1.43 +FORCEINLINE void PMABlend_fromRBandG(TUint32& aDest_io, const TUint32 aSrcRB, const TUint32 aSrcG, const TUint8 aMask)
1.44 + {
1.45 + TUint32 dst_ag = (aDest_io & KAGMask) >> 8;
1.46 + aDest_io = aDest_io & KRBMask;
1.47 + aDest_io = (aSrcRB + ((aMask * aDest_io) >> 8)) & KRBMask;
1.48 + aDest_io |= (aSrcG + (aMask * dst_ag)) & KAGMask;
1.49 + }
1.50 +
1.51 +/*
1.52 +Takes a non-PM source colour and an alpha value
1.53 +First pre-multiplies aSrcPixel with aAlpha
1.54 +Then blends it into aDestIo using the same alpha value.
1.55 +*/
1.56 +FORCEINLINE void PMABlend_FromNonPmAndAlpha(TUint32& aDest_io, const TUint32& aSrcPixel, TUint32 aAlpha)
1.57 + {
1.58 + TUint32 tap1=aAlpha+1;
1.59 + TUint32 srcRB = (aSrcPixel & KRBMask) * tap1;
1.60 + srcRB=(srcRB>>8) & KRBMask;
1.61 + TUint32 srcAG = (aSrcPixel & KGMask ) * tap1;
1.62 + srcAG=(srcAG>>8) & KGMask;
1.63 + srcAG|=aAlpha<<24;
1.64 +
1.65 + TUint32 dst_ag = (aDest_io & KAGMask) >> 8;
1.66 + TUint32 dst_rb = aDest_io & KRBMask;
1.67 + const TUint32 mask = 0x0100 - aAlpha;
1.68 + aDest_io = (srcRB + ((mask*dst_rb) >> 8)) & KRBMask;
1.69 + aDest_io |= (srcAG + mask*dst_ag) & KAGMask;
1.70 + }
1.71 +
1.72 +// Same as NonPMA2PMAPixel, but for use where checks for alpha of 0 or 0xFF have already been done
1.73 +FORCEINLINE TUint32 NonPMA2PMAPixelNoCheck(TUint32 aPixel)
1.74 + {
1.75 + TUint32 tap1=(aPixel>>24)+1;
1.76 + TUint32 scaledRB = (aPixel & KRBMask) * tap1;
1.77 + TUint32 scaledG = (aPixel & KGMask ) * tap1;
1.78 + return (aPixel & 0xff000000) | ((scaledRB>>8) & KRBMask) | ((scaledG>>8)& KGMask);
1.79 + }
1.80 +
1.81 +/**
1.82 +Composite mask application
1.83 +where AlphaComposite = AlphaColor * AlphaMask / 255.
1.84 +@param aColor - non-premltiplied color with alpha
1.85 +@param aMask - the mask value. (0 to 255).
1.86 +@return the color with alpha combined from color and mask (combination
1.87 +operator used is scaled multiplication).
1.88 +*/
1.89 +FORCEINLINE TUint32 CompMask(TUint32 aColor, TUint8 aMask)
1.90 + {
1.91 + // if the mask is FF the colour will be fully opaque and can be immediatly returned
1.92 + if (aMask == 0xff)
1.93 + return aColor;
1.94 +
1.95 + TUint32 cAlpha = (aMask+1) * (aColor >> 24);
1.96 + return ((aColor & 0x00ffffff) | ((cAlpha <<16) & 0xff000000));
1.97 + }
1.98 +
1.99 +TInt CDrawThirtyTwoBppBitmapAlphaPM::Construct(TSize aSize)
1.100 + {
1.101 + return Construct(aSize, aSize.iWidth << 2);
1.102 + }
1.103 +
1.104 +TInt CDrawThirtyTwoBppBitmapAlphaPM::Construct(TSize aSize, TInt aStride)
1.105 + {
1.106 + iDispMode = EColor16MAP;
1.107 + return CDrawThirtyTwoBppBitmapCommon::Construct(aSize, aStride);
1.108 + }
1.109 +
1.110 +/**
1.111 +MAlphaBlend::WriteRgbAlphaLine() implementation.
1.112 +Blends the supplied buffer of TRgb format data (ARGB), and the mask, to the destination
1.113 +which is specified by the pixel positions aX, aY and length.
1.114 +@param aX The starting position on the x-axis for the destination pixel.
1.115 +@param aY The starting position on the y-axis for the destination pixel.
1.116 +@param aRgbBuffer The RGB source data buffer. This is assumed to be bit aligned 32 bit non-premultiplied data
1.117 +@param aMaskBuffer The masking data. The mask buffer and the source alpha values are multiplied together to
1.118 + generate the alpha used for blending to the destination.
1.119 +@param aShadowing The shadowing flag. Indicates when and how to apply shadowing.
1.120 +@param aDrawMode The mode for rendering the source image to the destination.
1.121 + Currently supports EWriteAlpha and EPenmode.
1.122 +
1.123 +@see MAlphaBlend::WriteRgbAlphaLine()
1.124 +*/
1.125 +void CDrawThirtyTwoBppBitmapAlphaPM::WriteRgbAlphaLine(TInt aX, TInt aY, TInt aLength,
1.126 + const TUint8* aRgbBuffer,
1.127 + const TUint8* aMaskBuffer,
1.128 + MAlphaBlend::TShadowing aShadowing,
1.129 + CGraphicsContext::TDrawMode aDrawMode)
1.130 + {
1.131 + // precondition for this function is that the aRgbBuffer lies on a word boundary
1.132 + // Assert checks that the pointer is at a word boundary
1.133 + __ASSERT_DEBUG(!(((TUint)aRgbBuffer) & 0x3), Panic(EScreenDriverPanicInvalidPointer));
1.134 +
1.135 + DeOrientate(aX,aY);
1.136 + TUint32* pixelPtr = PixelAddress(aX,aY);
1.137 + const TInt pixelPtrInc = PixelAddressIncrement();
1.138 + const TUint16* normTable = PtrTo16BitNormalisationTable();
1.139 + TRgb tmp;
1.140 + const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
1.141 + // The purpose of this conditional is to remove if statements from within the loop
1.142 + // if shadow mode is not enabled and the UserDispMode is none or EColor16MAP
1.143 + if(!(iShadowMode & (EFade | EShadow)) && (iUserDispMode ==EColor16MAP || iUserDispMode == ENone))
1.144 + {
1.145 + while (aMaskBuffer < maskBufferPtrLimit)
1.146 + {
1.147 + if (*aMaskBuffer)
1.148 + {
1.149 + TUint32 srcData = *((TUint32*)aRgbBuffer);
1.150 + if ((aDrawMode == CGraphicsContext::EDrawModeWriteAlpha) && (*aMaskBuffer == 0xFF))
1.151 + {
1.152 + // Write the source straight through to the target, otherwise
1.153 + // blend. This relies on the fact that EDrawModeWriteAlpha can only
1.154 + // be used with masks that contain only black or white.
1.155 + Convert2PMA(srcData);
1.156 + *pixelPtr = srcData;
1.157 + }
1.158 + else
1.159 + {
1.160 + //blend alpha value in source with the mask value.
1.161 + srcData = CompMask(srcData, *aMaskBuffer);
1.162 + //pre-multiply, inplace.
1.163 + Convert2PMA(srcData);
1.164 + PMAInplaceBlend(*pixelPtr, srcData);
1.165 + }
1.166 + }
1.167 + pixelPtr += pixelPtrInc;
1.168 + aRgbBuffer += 4;
1.169 + aMaskBuffer++;
1.170 + }
1.171 + }
1.172 + else
1.173 + {
1.174 + while (aMaskBuffer < maskBufferPtrLimit)
1.175 + {
1.176 + TUint32 srcColor = *((TUint32*)(aRgbBuffer));
1.177 + if(*aMaskBuffer)
1.178 + {
1.179 + if(aShadowing == MAlphaBlend::EShdwBefore)
1.180 + {
1.181 + // src color in non-premultiplied.
1.182 + Shadow(*(TRgb*)&srcColor);
1.183 + }
1.184 + TUint32 srcData;
1.185 + if ((aDrawMode == CGraphicsContext::EDrawModeWriteAlpha) && (*aMaskBuffer == 0xFF))
1.186 + {
1.187 + Convert2PMA(srcColor);
1.188 + srcData = srcColor;
1.189 + }
1.190 + else
1.191 + {
1.192 + //blend alpha value in source with the mask value.
1.193 + srcData = CompMask(srcColor, *aMaskBuffer);
1.194 + //pre-multiply, inplace.
1.195 + Convert2PMA(srcData);
1.196 + srcData = PMAPixelBlend(*pixelPtr, srcData);
1.197 + }
1.198 +
1.199 + if(aShadowing == MAlphaBlend::EShdwAfter)
1.200 + {
1.201 + // shadow is done in PMA mode.
1.202 + Shadow(srcData);
1.203 + }
1.204 + if(iUserDispMode !=EColor16MAP && iUserDispMode != ENone)
1.205 + {
1.206 + tmp.SetInternal(PMA2NonPMAPixel(srcData, normTable));
1.207 + CDrawThirtyTwoBppBitmapCommon::MapColorToUserDisplayMode(tmp);
1.208 + srcData = tmp.Internal();
1.209 + Convert2PMA(srcData);
1.210 + }
1.211 + *pixelPtr = srcData;
1.212 + }
1.213 + pixelPtr += pixelPtrInc;
1.214 + aRgbBuffer += 4;
1.215 + aMaskBuffer++;
1.216 + }
1.217 + }
1.218 + }
1.219 +
1.220 +/**
1.221 +This assumes that the pen color (aColor) alpha information is to be blended with
1.222 +the alpha provided by the mask buffer.
1.223 +If pen is opaque, the mask is used as transparency information to be used.
1.224 +If pen is semi-transparent, the mask is contructed by calculating the resulting alpha
1.225 +by multiplying the mask with the alpha information of the pen color.
1.226 +@see CFbsDrawDevice::WriteRgbAlphaMulti
1.227 +*/
1.228 +void CDrawThirtyTwoBppBitmapAlphaPM::WriteRgbAlphaMulti(TInt aX,TInt aY,TInt aLength,TRgb aColor,const TUint8* aMaskBuffer)
1.229 + {
1.230 + TUint32 srcAlpha = aColor.Alpha();
1.231 + if (srcAlpha==0 || aLength<=0)
1.232 + return;
1.233 + DeOrientate(aX,aY);
1.234 + TUint32* pixelPtr = PixelAddress(aX,aY);
1.235 + const TInt pixelPtrInc = PixelAddressIncrement();
1.236 + const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
1.237 + if (iShadowMode)
1.238 + CDrawThirtyTwoBppBitmapCommon::Shadow(aColor);
1.239 + // pre-multiply the color.
1.240 + const TUint32 srcColor = aColor.Internal();
1.241 + if (srcAlpha == 255)
1.242 + { // source (pen) is opaque, so we simply blend it using the mask
1.243 + // little trick to make main loop more optimised, having 'pixelPtr += pixelPtrInc' at the top
1.244 + // of the loop makes the compiler generate better code without extra jumps to reach the
1.245 + // 'pixelPtr += pixelPtrInc' line.
1.246 + // We also need to do the FOREVER loop with a break when aMaskBuffer==maskBufferPtrLimit or
1.247 + // else the compiler puts the test at the end and extra jumps are required to reach it.
1.248 + pixelPtr -= pixelPtrInc;
1.249 + FOREVER
1.250 + {
1.251 + pixelPtr += pixelPtrInc;
1.252 + if (aMaskBuffer==maskBufferPtrLimit)
1.253 + break;
1.254 + const TUint maskAlpha=*aMaskBuffer++;
1.255 + if (maskAlpha==0)
1.256 + { // Most pixels in text are blank, so this is the most important route to optimise
1.257 + continue;
1.258 + }
1.259 + else if (maskAlpha==0xFF)
1.260 + { // Second most important are fully opaque pixels
1.261 + *pixelPtr=srcColor;
1.262 + continue;
1.263 + }
1.264 + TUint32 maskColor = NonPMA2PMAPixelNoCheck((srcColor&~0xFF000000) | ((TUint32)maskAlpha << 24));
1.265 + PMAInplaceBlend(*pixelPtr, maskColor);
1.266 + }
1.267 + }
1.268 + else if(srcAlpha > 0)
1.269 + {
1.270 + // pen is semi-transparent, so we must blend using both the mask and pen alpha
1.271 + // pre calculate ffMaskColor optimised for common case where aMaskBuffer contains 0xFF
1.272 + const TUint32 ffMaskColor=NonPMA2PMAPixelNoCheck(srcColor);
1.273 + const TUint32 noAlphaSrcColor=srcColor&0xFFFFFF;
1.274 + while (aMaskBuffer < maskBufferPtrLimit)
1.275 + {
1.276 + const TUint maskAlpha=*aMaskBuffer;
1.277 + if (maskAlpha)
1.278 + {
1.279 + if (maskAlpha==0xFF)
1.280 + PMABlend_noChecksInplace(*pixelPtr, ffMaskColor, srcAlpha);
1.281 + else
1.282 + {
1.283 + TUint32 mixedAlpha = ((maskAlpha+1) * srcAlpha)>>8;
1.284 + PMABlend_FromNonPmAndAlpha(*pixelPtr, noAlphaSrcColor, mixedAlpha);
1.285 + }
1.286 + }
1.287 + pixelPtr += pixelPtrInc;
1.288 + aMaskBuffer++;
1.289 + }
1.290 + }
1.291 + }
1.292 +
1.293 +/**
1.294 +@see CFbsDrawDevice::WriteRgb
1.295 +*/
1.296 +void CDrawThirtyTwoBppBitmapAlphaPM::WriteRgb(TInt aX,TInt aY,TRgb aColor)
1.297 + {
1.298 + TUint32 srcColor = NonPMA2PMAPixel(aColor.Internal());
1.299 + TUint32* pixelPtr = PixelAddress(aX,aY);
1.300 + PMAInplaceBlend(*pixelPtr, srcColor);
1.301 + }
1.302 +
1.303 +/**
1.304 +@see CFbsDrawDevice::WriteBinary
1.305 +*/
1.306 +void CDrawThirtyTwoBppBitmapAlphaPM::WriteBinary(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,TInt aHeight,TRgb aColor)
1.307 + {
1.308 + const TUint32 colorInternal=aColor.Internal();
1.309 + const TUint8 srcAlpha = colorInternal >> 24;
1.310 + if (srcAlpha==0)
1.311 + return;
1.312 + DeOrientate(aX,aY);
1.313 +
1.314 + TInt pixelInc;
1.315 + TInt rowInc;
1.316 +
1.317 + switch(iOrientation)
1.318 + {
1.319 + case EOrientationNormal:
1.320 + {
1.321 + pixelInc = 1;
1.322 + rowInc = iScanLineWords;
1.323 + break;
1.324 + }
1.325 + case EOrientationRotated90:
1.326 + {
1.327 + pixelInc = iScanLineWords;
1.328 + rowInc = -1;
1.329 + break;
1.330 + }
1.331 + case EOrientationRotated180:
1.332 + {
1.333 + pixelInc = -1;
1.334 + rowInc = -iScanLineWords;
1.335 + break;
1.336 + }
1.337 + default: // EOrientationRotated270
1.338 + {
1.339 + pixelInc = -iScanLineWords;
1.340 + rowInc = 1;
1.341 + }
1.342 + }
1.343 +
1.344 + const TUint32* dataLimit = aBuffer + aHeight;
1.345 + const TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
1.346 +
1.347 + TUint32* pixelPtr = PixelAddress(aX,aY);
1.348 + if (srcAlpha==0xFF)
1.349 + {
1.350 + while (aBuffer < dataLimit)
1.351 + {
1.352 + TUint32 dataWord = *aBuffer++;
1.353 + TUint32 dataMask = 1;
1.354 + TUint32* tempPixelPtr = pixelPtr;
1.355 + while (dataMask != dataMaskLimit)
1.356 + {
1.357 + if(dataWord & dataMask)
1.358 + {
1.359 + *tempPixelPtr=colorInternal;
1.360 + }
1.361 +
1.362 + tempPixelPtr += pixelInc;
1.363 + dataMask <<= 1;
1.364 + }
1.365 +
1.366 + pixelPtr += rowInc;
1.367 + }
1.368 + }
1.369 + else
1.370 + {
1.371 + TUint32 src_rb;
1.372 + TUint32 src_g;
1.373 + TUint32 mask;
1.374 + //pre-multiply the src color, before blending.
1.375 + NonPMA2PMAPixelRBG(colorInternal,src_rb,src_g,mask);
1.376 + while (aBuffer < dataLimit)
1.377 + {
1.378 + TUint32 dataWord = *aBuffer++;
1.379 + TUint32 dataMask = 1;
1.380 + TUint32* tempPixelPtr = pixelPtr;
1.381 + while (dataMask != dataMaskLimit)
1.382 + {
1.383 + if(dataWord & dataMask)
1.384 + {
1.385 + PMABlend_fromRBandG(*tempPixelPtr, src_rb, src_g, mask);
1.386 + }
1.387 +
1.388 + tempPixelPtr += pixelInc;
1.389 + dataMask <<= 1;
1.390 + }
1.391 +
1.392 + pixelPtr += rowInc;
1.393 + }
1.394 + }
1.395 + }
1.396 +
1.397 +/**
1.398 +@see CFbsDrawDevice::WriteBinaryLineVertical
1.399 +*/
1.400 +void CDrawThirtyTwoBppBitmapAlphaPM::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aBuffer,TInt aHeight,TRgb aColor,TBool aUp)
1.401 + {
1.402 + const TUint32 colorInternal=aColor.Internal();
1.403 + const TInt sourceAlpha = colorInternal>>24;
1.404 + if (sourceAlpha==0)
1.405 + return;
1.406 +
1.407 + DeOrientate(aX,aY);
1.408 +
1.409 + TInt scanlineWordLength;
1.410 +
1.411 + switch(iOrientation)
1.412 + {
1.413 + case EOrientationNormal:
1.414 + scanlineWordLength = iScanLineWords;
1.415 + break;
1.416 + case EOrientationRotated90:
1.417 + scanlineWordLength = -1;
1.418 + break;
1.419 + case EOrientationRotated180:
1.420 + scanlineWordLength = -iScanLineWords;
1.421 + break;
1.422 + default: // EOrientationRotated270
1.423 + scanlineWordLength = 1;
1.424 + }
1.425 +
1.426 + if (aUp)
1.427 + scanlineWordLength = -scanlineWordLength;
1.428 +
1.429 + TUint32* pixelPtr = PixelAddress(aX,aY);
1.430 + const TUint32* pixelPtrLimit = pixelPtr + (aHeight * scanlineWordLength);
1.431 + TUint32 dataWord = *aBuffer;
1.432 + TUint32 dataMask = 1;
1.433 +
1.434 + if (sourceAlpha==0xFF)
1.435 + {
1.436 + while(pixelPtr != pixelPtrLimit)
1.437 + {
1.438 + if(!dataMask)
1.439 + {
1.440 + dataMask = 1;
1.441 + aBuffer++;
1.442 + dataWord = *aBuffer;
1.443 + }
1.444 +
1.445 + if(dataWord & dataMask)
1.446 + {
1.447 + *pixelPtr = colorInternal;
1.448 + }
1.449 + dataMask <<= 1;
1.450 + pixelPtr += scanlineWordLength;
1.451 + }
1.452 + }
1.453 + else
1.454 + {
1.455 + TUint32 src_rb;
1.456 + TUint32 src_g;
1.457 + TUint32 mask;
1.458 + //pre-multiply the src color, before blending.
1.459 + NonPMA2PMAPixelRBG(colorInternal,src_rb,src_g,mask);
1.460 + while(pixelPtr != pixelPtrLimit)
1.461 + {
1.462 + if(!dataMask)
1.463 + {
1.464 + dataMask = 1;
1.465 + aBuffer++;
1.466 + dataWord = *aBuffer;
1.467 + }
1.468 +
1.469 + if(dataWord & dataMask)
1.470 + {
1.471 + PMABlend_fromRBandG(*pixelPtr, src_rb, src_g, mask);
1.472 + }
1.473 + dataMask <<= 1;
1.474 + pixelPtr += scanlineWordLength;
1.475 + }
1.476 + }
1.477 + }
1.478 +
1.479 +/**
1.480 +@see CFbsDrawDevice::BlendRgbMulti
1.481 +*/
1.482 +void CDrawThirtyTwoBppBitmapAlphaPM::BlendRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
1.483 + {
1.484 + const TInt sourceAlpha = aColor.Alpha();
1.485 + if (sourceAlpha==255)// opaque
1.486 + {
1.487 + WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
1.488 + return;
1.489 + }
1.490 + if (sourceAlpha==0)// transparent
1.491 + return;
1.492 + TUint32* pixelPtr = PixelAddress(aX,aY);
1.493 + TUint32* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineWords);
1.494 + TUint32* pixelPtrLimit = pixelPtr + aLength;
1.495 +
1.496 + TUint32 srcValue = NonPMA2PMAPixel(aColor.Internal());
1.497 + TUint32 src_c = srcValue & KRBMask;
1.498 + TUint32 src_g = (srcValue & KAGMask)>>8;
1.499 + const TUint32 mask = 0x0100 - sourceAlpha;
1.500 + while (pixelPtr < pixelRowPtrLimit)
1.501 + {
1.502 + for (TUint32* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr++)
1.503 + {
1.504 + const TUint32 dst = *tempPixelPtr;
1.505 + TUint32 dst_c = dst & KRBMask;
1.506 + dst_c = (src_c + ((mask * dst_c)>>8)) & KRBMask;
1.507 + const TUint32 dst_ag = (dst & KAGMask)>>8;
1.508 + dst_c |= ((src_g + ((mask * dst_ag)>>8)) & KRBMask)<<8;
1.509 + *tempPixelPtr=dst_c;
1.510 + }
1.511 + pixelPtr += iScanLineWords;
1.512 + pixelPtrLimit += iScanLineWords;
1.513 + }
1.514 + }
1.515 +
1.516 +/**
1.517 +@see CFbsDrawDevice::BlendLine
1.518 +*/
1.519 +void CDrawThirtyTwoBppBitmapAlphaPM::BlendLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
1.520 + {
1.521 + TUint32* pixelPtr = PixelAddress(aX,aY);
1.522 +
1.523 + const TUint32* bufferPtrLimit = aBuffer + aLength;
1.524 + const TInt pixelPtrInc = (iOrientation == EOrientationNormal) ? 1 : PixelAddressIncrement();
1.525 +
1.526 + while (aBuffer < bufferPtrLimit)
1.527 + {
1.528 + PMAInplaceBlend(*pixelPtr, *aBuffer);
1.529 + aBuffer++;
1.530 + pixelPtr += pixelPtrInc;
1.531 + }
1.532 + }
1.533 +/**
1.534 +@see CFbsDrawDevice::ShadowArea
1.535 +*/
1.536 +void CDrawThirtyTwoBppBitmapAlphaPM::ShadowArea(const TRect& aRect)
1.537 + {
1.538 + const TRect rect(DeOrientate(aRect));
1.539 + __ASSERT_DEBUG(rect.iTl.iX>=0 && rect.iBr.iX<=iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
1.540 + __ASSERT_DEBUG(rect.iTl.iY>=0 && rect.iBr.iY<=iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
1.541 +
1.542 + TUint32* pixelPtr = PixelAddress(rect.iTl.iX,rect.iTl.iY);
1.543 + TUint32* pixelRowPtrLimit = pixelPtr + (rect.Height() * iScanLineWords);
1.544 +
1.545 + TUint32* pixelRowPtr = pixelPtr;
1.546 + TUint32* pixelPtrLimit = pixelPtr + rect.Width();
1.547 +
1.548 + if (iShadowMode & EFade)
1.549 + {
1.550 + while (pixelRowPtr < pixelRowPtrLimit)
1.551 + {
1.552 + TUint32* tempPixelPtr = pixelRowPtr;
1.553 +
1.554 + while (tempPixelPtr < pixelPtrLimit)
1.555 + {
1.556 + const TUint32 color = *tempPixelPtr;
1.557 +#if defined(SYMBIAN_USE_FAST_FADING)
1.558 + const TUint32 fast_fade_offset = NonPMA2PMAPixel((color & 0xff000000) | SYMBIAN_USE_FAST_FADING) & 0x00ffffff;
1.559 + *tempPixelPtr++ = (color & 0xff000000) | ((((color & 0x00ffffff) >> 1) & ~0x00808080) + fast_fade_offset);
1.560 +#else
1.561 + const TInt alpha = (color >> 24) + 1;
1.562 + const TUint32 fadeMapOffset = ((alpha * iFadeMapOffset) >> 8) & 0xff;
1.563 + const TUint32 wordFadeMapOffset = ((fadeMapOffset) << 16) | (fadeMapOffset);
1.564 + const TUint32 rb = ((((color & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
1.565 + const TUint32 g = ((((color & 0x0000ff00) * iFadeMapFactor) >> 16) + fadeMapOffset) << 8;
1.566 + *tempPixelPtr++ = (color & 0xff000000) | rb | g;
1.567 +#endif
1.568 + }
1.569 + pixelRowPtr += iScanLineWords;
1.570 + pixelPtrLimit += iScanLineWords;
1.571 + }
1.572 + }
1.573 +
1.574 + if (iShadowMode & EShadow)
1.575 + {
1.576 + pixelRowPtr = pixelPtr;
1.577 + pixelPtrLimit = pixelPtr + rect.Width();
1.578 +
1.579 + while (pixelRowPtr < pixelRowPtrLimit)
1.580 + {
1.581 + TUint32* tempPixelPtr = pixelRowPtr;
1.582 +
1.583 + while (tempPixelPtr < pixelPtrLimit)
1.584 + {
1.585 + const TUint32 color = *tempPixelPtr;
1.586 + const TInt alpha = (color >> 24) + 1;
1.587 + const TInt uLimit = ((0x40) * alpha) >> 8;
1.588 + TInt r = (color >> 16) & 0xff;
1.589 + r = (r > uLimit) ? (r-uLimit) : 0;
1.590 + TInt g = (color >> 8) & 0xff;
1.591 + g = (g > uLimit) ? (g - uLimit) : 0;
1.592 + TInt b = color & 0xff;
1.593 + b = (b > uLimit) ? (b - uLimit) : 0;
1.594 + *tempPixelPtr++ = (color & 0xff000000) | (r << 16) | (g << 8) | b;
1.595 + }
1.596 + pixelRowPtr += iScanLineWords;
1.597 + pixelPtrLimit += iScanLineWords;
1.598 + }
1.599 + }
1.600 + }
1.601 +
1.602 +/**
1.603 +@see CFbsDrawDevice::WriteLine
1.604 +*/
1.605 +void CDrawThirtyTwoBppBitmapAlphaPM::WriteLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer,
1.606 + CGraphicsContext::TDrawMode aDrawMode)
1.607 + {
1.608 + const TPoint originalPoint(aX,aY);
1.609 + DeOrientate(aX,aY);//aX and aY - physical coordinates
1.610 +
1.611 + __ASSERT_DEBUG(aX >= 0,Panic(EScreenDriverPanicOutOfBounds));
1.612 + __ASSERT_DEBUG(aY >= 0,Panic(EScreenDriverPanicOutOfBounds));
1.613 +#if defined(_DEBUG)
1.614 + switch (iOrientation)
1.615 + {
1.616 + case EOrientationNormal:
1.617 + __ASSERT_DEBUG(aX + aLength <= iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
1.618 + break;
1.619 + case EOrientationRotated90:
1.620 + __ASSERT_DEBUG(aY + aLength <= iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
1.621 + break;
1.622 + case EOrientationRotated180:
1.623 + __ASSERT_DEBUG(aX - aLength >= -1,Panic(EScreenDriverPanicOutOfBounds));
1.624 + break;
1.625 + default: // EOrientationRotated270
1.626 + __ASSERT_DEBUG(aY - aLength >= -1,Panic(EScreenDriverPanicOutOfBounds));
1.627 + break;
1.628 + }
1.629 +#endif
1.630 + __ASSERT_DEBUG(aLength > 0,Panic(EScreenDriverPanicZeroLength));
1.631 + __ASSERT_DEBUG(aBuffer,Panic(EScreenDriverPanicNullPointer));
1.632 +
1.633 + MapBufferToUserDisplayMode(aLength,aBuffer);
1.634 + if(iShadowMode)
1.635 + {
1.636 + ShadowBuffer(aLength,aBuffer);
1.637 + }
1.638 + if(aDrawMode&CGraphicsContext::EInvertPen)
1.639 + {
1.640 +#if defined(_DEBUG)
1.641 + // code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
1.642 +// RDebug::Printf("Premultiplied alpha mode invert pen behaviour not defined / implemented");
1.643 +#endif
1.644 + // no-operation
1.645 + }
1.646 + if(aDrawMode&CGraphicsContext::EPenmode)
1.647 + {
1.648 + BlendLine(aX,aY,aLength,aBuffer);
1.649 + return;
1.650 + }
1.651 + if(aDrawMode&CGraphicsContext::EWriteAlpha)
1.652 + {
1.653 + CDrawThirtyTwoBppBitmapCommon::WriteLine(aX,aY,aLength,aBuffer);
1.654 + return;
1.655 + }
1.656 + if(aDrawMode&CGraphicsContext::EInvertScreen)
1.657 + {
1.658 +#if defined(_DEBUG)
1.659 +// RDebug::Printf("Premultiplied alpha mode invert screen behaviour not defined / implemented");
1.660 +#endif
1.661 + return; //no-operation
1.662 + }
1.663 + if(aDrawMode&CGraphicsContext::EXor)
1.664 + {
1.665 +#if defined(_DEBUG)
1.666 + // code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
1.667 +// RDebug::Printf("Premultiplied alpha mode XOR operation not defined / implemented");
1.668 +#endif
1.669 + return; //no-operation
1.670 + }
1.671 +else if(aDrawMode&CGraphicsContext::EAnd)
1.672 + {
1.673 +#if defined(_DEBUG)
1.674 + // code in CFbsBitGc::DoBitBltMasked() does not require logical operator pen modes in premultiplied alpha screen driver for blitting of icons with masks
1.675 +// RDebug::Printf("Premultiplied alpha mode AND operation not defined / implemented");
1.676 +#endif
1.677 + return; //no-operation
1.678 + }
1.679 + else if(aDrawMode&CGraphicsContext::EOr)
1.680 + {
1.681 +#if defined(_DEBUG)
1.682 +// RDebug::Printf("Premultiplied alpha mode OR operation not defined / implemented");
1.683 +#endif
1.684 + return; //no-operation
1.685 + }
1.686 + }
1.687 +
1.688 +TRgb CDrawThirtyTwoBppBitmapAlphaPM::RgbColor(TUint32 aColor) const
1.689 + {
1.690 + return TRgb::_Color16MAP(aColor);
1.691 + }
1.692 +
1.693 +TUint32 CDrawThirtyTwoBppBitmapAlphaPM::Color(const TRgb& aColor)
1.694 + {
1.695 + return aColor._Color16MAP();
1.696 + }
1.697 +
1.698 +TInt CDrawThirtyTwoBppBitmapAlphaPM::WriteRgbOutlineAndShadow(TInt aX, TInt aY, const TInt aLength,
1.699 + TUint32 aOutlinePenColor, TUint32 aShadowColor,
1.700 + TUint32 aFillColor, const TUint8* aDataBuffer)
1.701 + {
1.702 + DeOrientate(aX,aY);
1.703 + TUint32* pixelPtr = PixelAddress(aX,aY);
1.704 + const TInt pixelPtrInc = PixelAddressIncrement();
1.705 + const TUint8* dataBufferPtrLimit = aDataBuffer + aLength;
1.706 + TInt blendedRedColor;
1.707 + TInt blendedGreenColor;
1.708 + TInt blendedBlueColor;
1.709 + TInt blendedAlpha;
1.710 + TUint8 index = 0;
1.711 + TUint32 finalColor;
1.712 +
1.713 + //Get red color. Equivalent to TRgb::Red()
1.714 + const TInt redOutlinePenColor = (aOutlinePenColor & 0xff0000) >> 16;
1.715 + const TInt redShadowColor = (aShadowColor & 0xff0000) >> 16;
1.716 + const TInt redFillColor = (aFillColor & 0xff0000) >> 16;
1.717 +
1.718 + //Get green color. Equivalent to TRgb::Green()
1.719 + const TInt greenOutlinePenColor = (aOutlinePenColor & 0xff00) >> 8;
1.720 + const TInt greenShadowColor = (aShadowColor & 0xff00) >> 8;
1.721 + const TInt greenFillColor = (aFillColor & 0xff00) >> 8;
1.722 +
1.723 + //Get blue color. Equivalent to TRgb::Blue()
1.724 + const TInt blueOutlinePenColor = aOutlinePenColor & 0xff;
1.725 + const TInt blueShadowColor = aShadowColor & 0xff;
1.726 + const TInt blueFillColor = aFillColor & 0xff;
1.727 +
1.728 + //Get alpha color. Equivalent to TRgb::Alpha()
1.729 + const TInt alphaOutlinePenColor = aOutlinePenColor >> 24;
1.730 + const TInt alphaShadowColor = aShadowColor >> 24;
1.731 + const TInt alphaFillColor = aFillColor >> 24;
1.732 +
1.733 + // Calculate PMA values for aFillColor & aOutlinePenColor that we can use for fast blending in the simple cases
1.734 + // Don't pre calculate PMA version of aShadowColor as it is presumed not to be used enough to make this worthwhile
1.735 + const TUint32 pmaFillColor = NonPMA2PMAPixel(aFillColor);
1.736 + const TUint32 pmaOutlineColor = NonPMA2PMAPixel(aOutlinePenColor);
1.737 +
1.738 + while (aDataBuffer < dataBufferPtrLimit)
1.739 + {
1.740 + index = *aDataBuffer++;
1.741 + if (255 == FourColorBlendLookup[index][KBackgroundColorIndex])
1.742 + {
1.743 + //background colour
1.744 + //No drawing required
1.745 + }
1.746 + else if (255 == FourColorBlendLookup[index][KFillColorIndex])
1.747 + {
1.748 + //Use fill colour to draw
1.749 + finalColor = pmaFillColor;
1.750 + PMAInplaceBlend(*pixelPtr, finalColor);
1.751 + }
1.752 + else if (255 == FourColorBlendLookup[index][KOutlineColorIndex])
1.753 + {
1.754 + //Use outline colour to draw
1.755 + finalColor = pmaOutlineColor;
1.756 + PMAInplaceBlend(*pixelPtr, finalColor);
1.757 + }
1.758 + else if (255 == FourColorBlendLookup[index][KShadowColorIndex])
1.759 + {
1.760 + //Use shadow colour to draw
1.761 + finalColor = NonPMA2PMAPixel(aShadowColor);
1.762 + PMAInplaceBlend(*pixelPtr, finalColor);
1.763 + }
1.764 + else
1.765 + {
1.766 + blendedRedColor = (redOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor +
1.767 + redShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
1.768 + redFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
1.769 +
1.770 + blendedGreenColor = (greenOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor +
1.771 + greenShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
1.772 + greenFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
1.773 +
1.774 + blendedBlueColor = (blueOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor +
1.775 + blueShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
1.776 + blueFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
1.777 +
1.778 + blendedAlpha = (alphaOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] +
1.779 + alphaShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
1.780 + alphaFillColor * FourColorBlendLookup[index][KFillColorIndex]) >> 8;
1.781 +
1.782 + finalColor = (blendedAlpha << 24) | (blendedRedColor << 16) | (blendedGreenColor << 8 )| (blendedBlueColor);
1.783 + PMAInplaceBlend(*pixelPtr, finalColor);
1.784 + }
1.785 + pixelPtr += pixelPtrInc;
1.786 + }
1.787 + return KErrNone;
1.788 + }