Update contrib.
1 // Copyright (c) 2004-2010 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.
17 #include <graphics/lookuptable.h>
18 #include <graphics/blendingalgorithms.h>
21 Performs a blend based on the PD method, with 2* 16 bit in one 32 bit operation optimisation.
22 Note that this method assumes both input s are NOT alpha pre multiplied, but the output IS pre multiplied.
23 The mechanism of this method is non-standard and non-intuitive, and is being addressed in 9.3
24 by developing distinct classes for the premultiplied and nonmultiplied cases.
25 The mechanism remains hybrid to maintain compatibility and colour channel overflows caused by rounding
26 overflows have been addressed.
27 PD is basically CDest=CSrc*MulSrc+CDest*MulDest
28 //A second optimisation is that multiplier value must be scaled from 0..255 to 0.0..1.0, this is 1/255 = 0.00392156.
29 A second optimisation is that multiplier value must be scaled from 257..65535 to 0.0..1.0, this is 1/65535 = 0.0000152590.
30 This used to be done by simply adding 1, giving 1..256/256
31 but this allows overflows to occur when the fractional parts are added together.
32 We want to keep adding the fractional parts as that gives a better result.
33 Instead I am now using an approximation of 0.00392151, based on 255*257/256.
34 To describe it imagine a "decimal" colour mode, where the channels count from 0..9, and 10-based operations are "efficient".
35 We need 9 to generate 1.0 or 10/10 meaning "all".
36 If we add 1, then we get 1..10 ==> 0.1 .. 1.0
37 If we multiply by 1.1 then we get 0.0 .. 9.9.
38 And finally add a 0.5 rounding to the result.
39 I do this multiply after the CSrc*MulSrc, while I still have a 16bit intermediate result.
40 It is possible to generate a faster, less accurate result by exhaustively finding
41 the highest value that can be added instead of rb = rb+((rb>>8)&0x00ff00ff)+0x00800080; without causing an overflow.
42 @param aBeneath non-premultiplied color with alpha of the destination
43 @param aSrcColor non-premultiplied color with alpha of the source
44 @param aMaskBuffer mask
45 @return pre multiplied color resulting from the blending operation
47 FORCEINLINE TUint32 OptimizedBlend32A(TUint32 aBeneath,TUint32 aSrcColor,TUint8 aMaskBuffer)
51 if(aMaskBuffer == 0xff) // opaque, so unchanged
53 //Still need to convert source to destination from non-multiplied to pre-multiplied
54 //But this code resolves to a copy. The ARM optimiser prefers shifts over big constants.
55 return (aSrcColor|(aMaskBuffer<<24));
62 const TUint32 srcMult = aMaskBuffer;
63 TUint32 destMult = ((255 - aMaskBuffer) * ((aBeneath >> 24)));
64 //This gives a slightly more accurate result than ((aBeneath >> 24)+1)
65 destMult=destMult+(destMult>>8);
69 TUint32 rb =(((aSrcColor&0x00ff00ff)*srcMult)) + (((aBeneath&0x00ff00ff)*destMult));
70 rb = rb+((rb>>8)&0x00ff00ff);
73 TUint32 ag = (((aSrcColor&0x0000ff00)*srcMult)) + (((aBeneath&0x0000ff00)*destMult));
74 ag>>=8; //Note that if alpha is processed here, this shift must be performed before the multiplies
75 ag = ag+((ag>>8)&0x00ff00ff);
77 TUint32 aa = srcMult+destMult;
78 return (rb&0x00ff00ff) | (ag&0x0000ff00) | (aa << 24);
82 else // completely transparent
89 TInt CDrawThirtyTwoBppBitmapAlpha::Construct(TSize aSize)
91 return Construct(aSize, aSize.iWidth << 2);
94 TInt CDrawThirtyTwoBppBitmapAlpha::Construct(TSize aSize, TInt aStride)
96 iDispMode = EColor16MA;
97 return CDrawThirtyTwoBppBitmapCommon::Construct(aSize, aStride);
100 void CDrawThirtyTwoBppBitmapAlpha::Shadow(TUint32& aColor)
102 TUint32 value = aColor & 0x00ffffff;
103 if (iShadowMode & EFade)
105 #if defined(SYMBIAN_USE_FAST_FADING)
106 value = ((value >> 1) & ~0x00808080) + (SYMBIAN_USE_FAST_FADING);
108 const TInt wordFadeMapOffset = ((iFadeMapOffset & 0xff) << 16) | (iFadeMapOffset & 0xff);
109 const TInt rb = ((((value & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
110 const TInt g = ((((value & 0x0000ff00) * iFadeMapFactor) >> 16) + iFadeMapOffset) << 8;
115 if (iShadowMode & EShadow)
117 const TInt r = (value & 0x00c00000) ? ((value & 0x00ff0000)-0x00400000) : 0;
118 const TInt g = (value & 0x0000c000) ? ((value & 0x0000ff00)-0x00004000) : 0;
119 const TInt b = (value & 0x000000c0) ? ((value & 0x000000ff)-0x00000040) : 0;
122 // alpha is unchanged.
123 aColor = (aColor & 0xff000000) | value;
127 MAlphaBlend::WriteRgbAlphaLine() implementation.
128 @see MAlphaBlend::WriteRgbAlphaLine()
130 void CDrawThirtyTwoBppBitmapAlpha::WriteRgbAlphaLine(TInt aX, TInt aY, TInt aLength,
131 const TUint8* aRgbBuffer,
132 const TUint8* aMaskBuffer,
133 MAlphaBlend::TShadowing aShadowing,
134 CGraphicsContext::TDrawMode /*aDrawMode*/)
136 // precondition for this function is that the aRgbBuffer lies on a word boundary
137 // Assert checks that the pointer is at a word boundary
138 __ASSERT_DEBUG(!(((TUint)aRgbBuffer) & 0x3), Panic(EScreenDriverPanicInvalidPointer));
141 TUint32* pixelPtr = PixelAddress(aX,aY);
142 const TInt pixelPtrInc = PixelAddressIncrement();
143 const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
145 // The purpose of this conditional is to remove if statements from within the loop
146 // if shadow mode is not enabled and the UserDispMode is none or EColor16MA
147 if(!(iShadowMode & (EFade | EShadow)) && (iUserDispMode ==EColor16MA || iUserDispMode == ENone))
149 while (aMaskBuffer < maskBufferPtrLimit)
153 *pixelPtr = OptimizedBlend32A(*pixelPtr, *((TUint32*)(aRgbBuffer)), *aMaskBuffer);
155 pixelPtr += pixelPtrInc;
162 while (aMaskBuffer < maskBufferPtrLimit)
166 TUint32 srcColor = *((TUint32*)(aRgbBuffer));
167 if(aShadowing == MAlphaBlend::EShdwBefore)
172 TUint32 pixelClr = 0x0;
174 pixelClr = OptimizedBlend32A(*pixelPtr, srcColor, *aMaskBuffer);
176 if(aShadowing == MAlphaBlend::EShdwAfter)
181 if(iUserDispMode !=EColor16MA && iUserDispMode != ENone)
183 TInt red = TUint8(pixelClr >> 16);
184 TInt green = TUint8(pixelClr >> 8);
185 TInt blue = TUint8(pixelClr);
186 CDrawBitmap::MapColorToUserDisplayMode(red,green,blue);
187 pixelClr = (pixelClr&0xff000000) | (red << 16) | (green << 8) | blue;
189 *pixelPtr = pixelClr;
191 pixelPtr += pixelPtrInc;
198 void CDrawThirtyTwoBppBitmapAlpha::WriteRgbAlphaMulti(TInt aX,TInt aY,TInt aLength,TRgb aColor,const TUint8* aMaskBuffer)
201 TUint32* pixelPtr = PixelAddress(aX,aY);
202 const TInt pixelPtrInc = PixelAddressIncrement();
203 const TUint8* maskBufferPtrLimit = aMaskBuffer + aLength;
205 TUint32 srcColor = aColor.Internal();
209 const TInt red = (srcColor & 0x00ff0000) >> 16;
210 const TInt green = (srcColor & 0x0000ff00) >> 8;
211 const TInt blue = srcColor & 0x000000ff;
212 const TInt alpha = srcColor >> 24;
216 // the most common case
217 // source is opaque, so we simply blend it using the mask
218 while (aMaskBuffer < maskBufferPtrLimit)
221 *pixelPtr = OptimizedBlend32A(*pixelPtr, srcColor, *aMaskBuffer);
223 pixelPtr += pixelPtrInc;
229 // pen is semi-transparent, so we must blend using both the mask and pen alpha
230 while (aMaskBuffer < maskBufferPtrLimit)
232 TUint8* componentPtr = reinterpret_cast <TUint8*> (pixelPtr);
233 const TUint32 srcAlpha = alpha * aMaskBuffer[0];
234 const TUint32 srcMult = srcAlpha * 255;
235 const TUint32 destMult = (255*255 - srcAlpha) * componentPtr[3];
236 componentPtr[0] = TUint8(((blue * srcMult) + (componentPtr[0] * destMult)) / (255*255*255));
237 componentPtr[1] = TUint8(((green * srcMult) + (componentPtr[1] * destMult)) / (255*255*255));
238 componentPtr[2] = TUint8(((red * srcMult) + (componentPtr[2] * destMult)) / (255*255*255));
239 componentPtr[3] = TUint8((srcMult + destMult) / (255*255));
240 // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
242 pixelPtr += pixelPtrInc;
248 void CDrawThirtyTwoBppBitmapAlpha::WriteRgb(TInt aX,TInt aY,TRgb aColor)
250 const TInt sourceAlpha = aColor.Alpha();
254 TUint32* componentPtr = PixelAddress(aX,aY);
255 *componentPtr=aColor.Internal();
257 else if (sourceAlpha==0)
263 TUint8* componentPtr = reinterpret_cast <TUint8*> (PixelAddress(aX,aY));
264 const TUint32 srcMult = sourceAlpha * 255;
265 const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
266 componentPtr[0] = TUint8(((aColor.Blue() * srcMult) + (componentPtr[0] * destMult)) / (255*255));
267 componentPtr[1] = TUint8(((aColor.Green() * srcMult) + (componentPtr[1] * destMult)) / (255*255));
268 componentPtr[2] = TUint8(((aColor.Red() * srcMult) + (componentPtr[2] * destMult)) / (255*255));
269 componentPtr[3] = TUint8((srcMult + destMult) / 255);
270 // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
274 void CDrawThirtyTwoBppBitmapAlpha::WriteBinary(TInt aX,TInt aY,TUint32* aBuffer,TInt aLength,TInt aHeight,TRgb aColor)
276 const TInt sourceAlpha = aColor.Alpha();
277 if (sourceAlpha==255)
279 CDrawThirtyTwoBppBitmapCommon::WriteBinary(aX,aY,aBuffer,aLength,aHeight,aColor);
292 case EOrientationNormal:
295 rowInc = iScanLineWords;
298 case EOrientationRotated90:
300 pixelInc = iScanLineWords;
304 case EOrientationRotated180:
307 rowInc = -iScanLineWords;
310 default: // EOrientationRotated270
312 pixelInc = -iScanLineWords;
317 const TUint32* dataLimit = aBuffer + aHeight;
318 const TUint32 dataMaskLimit = (aLength < 32) ? 1 << aLength : 0;
320 TUint32* pixelPtr = PixelAddress(aX,aY);
322 const TInt sourceRed = aColor.Red();
323 const TInt sourceGreen = aColor.Green();
324 const TInt sourceBlue = aColor.Blue();
326 while (aBuffer < dataLimit)
328 TUint32 dataWord = *aBuffer++;
329 TUint32 dataMask = 1;
330 TUint32* tempPixelPtr = pixelPtr;
332 while (dataMask != dataMaskLimit)
334 if(dataWord & dataMask)
336 TUint8* componentPtr = reinterpret_cast <TUint8*> (tempPixelPtr);
337 const TUint32 srcMult = sourceAlpha * 255;
338 const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
339 componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
340 componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
341 componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
342 componentPtr[3] = TUint8((srcMult + destMult) / 255);
343 // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
346 tempPixelPtr += pixelInc;
354 void CDrawThirtyTwoBppBitmapAlpha::WriteBinaryLineVertical(TInt aX,TInt aY,TUint32* aBuffer,TInt aHeight,TRgb aColor,TBool aUp)
356 const TInt sourceAlpha = aColor.Alpha();
357 if (sourceAlpha==255)
359 CDrawThirtyTwoBppBitmapCommon::WriteBinaryLineVertical(aX,aY,aBuffer,aHeight,aColor,aUp);
367 TInt scanlineWordLength;
371 case EOrientationNormal:
372 scanlineWordLength = iScanLineWords;
374 case EOrientationRotated90:
375 scanlineWordLength = -1;
377 case EOrientationRotated180:
378 scanlineWordLength = -iScanLineWords;
380 default: // EOrientationRotated270
381 scanlineWordLength = 1;
385 scanlineWordLength = -scanlineWordLength;
387 TUint32* pixelPtr = PixelAddress(aX,aY);
388 const TUint32* pixelPtrLimit = pixelPtr + (aHeight * scanlineWordLength);
389 TUint32 dataWord = *aBuffer;
390 TUint32 dataMask = 1;
392 const TInt sourceRed = aColor.Red();
393 const TInt sourceGreen = aColor.Green();
394 const TInt sourceBlue = aColor.Blue();
396 while(pixelPtr != pixelPtrLimit)
405 if(dataWord & dataMask)
407 TUint8* componentPtr = reinterpret_cast <TUint8*> (pixelPtr);
408 const TUint32 srcMult = sourceAlpha * 255;
409 const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
410 componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
411 componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
412 componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
413 componentPtr[3] = TUint8((srcMult + destMult) / 255);
414 // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
418 pixelPtr += scanlineWordLength;
422 void CDrawThirtyTwoBppBitmapAlpha::MapBufferToUserDisplayMode(TInt aLength,TUint32* aBuffer)
424 const TUint32* bufferLimit = aBuffer + aLength;
427 switch (iUserDispMode)
430 while (aBuffer < bufferLimit)
432 color = TRgb::_Color16MA(*aBuffer);
433 color = TRgb::_Gray2(color._Gray2());
434 *aBuffer++ = color._Color16MA();
438 while (aBuffer < bufferLimit)
440 color = TRgb::_Color16MA(*aBuffer);
441 color = TRgb::_Gray4(color._Gray4());
442 *aBuffer++ = color._Color16MA();
446 while (aBuffer < bufferLimit)
448 color = TRgb::_Color16MA(*aBuffer);
449 color = TRgb::_Gray16(color._Gray16());
450 *aBuffer++ = color._Color16MA();
454 while (aBuffer < bufferLimit)
456 color = TRgb::_Color16MA(*aBuffer);
457 color = TRgb::_Gray256(color._Gray256());
458 *aBuffer++ = color._Color16MA();
462 while (aBuffer < bufferLimit)
464 color = TRgb::_Color16MA(*aBuffer);
465 color = TRgb::Color16(color.Color16());
466 *aBuffer++ = color._Color16MA();
470 while (aBuffer < bufferLimit)
472 color = TRgb::_Color16MA(*aBuffer);
473 color = TRgb::Color256(color.Color256());
474 *aBuffer++ = color._Color16MA();
478 while (aBuffer < bufferLimit)
480 color = TRgb::_Color16MA(*aBuffer);
481 color = TRgb::_Color4K(color._Color4K());
482 *aBuffer++ = color._Color16MA();
486 while (aBuffer < bufferLimit)
488 color = TRgb::_Color16MA(*aBuffer);
489 color = TRgb::_Color64K(color._Color64K());
490 *aBuffer++ = color._Color16MA();
498 void CDrawThirtyTwoBppBitmapAlpha::BlendRgbMulti(TInt aX,TInt aY,TInt aLength,TInt aHeight,TRgb aColor)
500 const TInt sourceAlpha = aColor.Alpha();
501 if (sourceAlpha==255)// opaque
503 WriteRgbMulti(aX,aY,aLength,aHeight,aColor);
506 if (sourceAlpha==0)// transparent
509 TUint32* pixelPtr = PixelAddress(aX,aY);
510 TUint32* pixelRowPtrLimit = pixelPtr + (aHeight * iScanLineWords);
511 TUint32* pixelPtrLimit = pixelPtr + aLength;
513 const TInt sourceRed = aColor.Red();
514 const TInt sourceGreen = aColor.Green();
515 const TInt sourceBlue = aColor.Blue();
516 TUint srcValue = aColor._Color16MA();
517 while (pixelPtr < pixelRowPtrLimit)
519 for (TUint32* tempPixelPtr = pixelPtr; tempPixelPtr < pixelPtrLimit; tempPixelPtr++)
521 // check that the alpha value is not 0xFF
522 if((*tempPixelPtr & 0xFF000000) ^ 0xFF000000)
524 TUint8* componentPtr = reinterpret_cast <TUint8*> (tempPixelPtr);
525 const TUint32 srcMult = sourceAlpha * 255;
526 const TUint32 destMult = (255 - sourceAlpha) * componentPtr[3];
527 componentPtr[0] = TUint8(((sourceBlue * srcMult) + (componentPtr[0] * destMult)) / (255*255));
528 componentPtr[1] = TUint8(((sourceGreen * srcMult) + (componentPtr[1] * destMult)) / (255*255));
529 componentPtr[2] = TUint8(((sourceRed * srcMult) + (componentPtr[2] * destMult)) / (255*255));
530 componentPtr[3] = TUint8((srcMult + destMult) / 255);
534 AlphaBlendPixelToDest(srcValue, (TUint8)sourceAlpha, tempPixelPtr);
537 // ie alpha' = srcAlpha + (1-srcAlpha)*destAlpha
540 pixelPtr += iScanLineWords;
541 pixelPtrLimit += iScanLineWords;
545 void CDrawThirtyTwoBppBitmapAlpha::BlendLine(TInt aX,TInt aY,TInt aLength,TUint32* aBuffer)
547 TUint32* pixelPtr = PixelAddress(aX,aY);
549 const TUint32* bufferPtrLimit = aBuffer + aLength;
550 const TInt pixelPtrInc = (iOrientation == EOrientationNormal) ? 1 : PixelAddressIncrement();
552 while (aBuffer < bufferPtrLimit)
554 *pixelPtr = OptimizedBlend32A(*pixelPtr, *aBuffer, (*aBuffer)>>24);
557 pixelPtr += pixelPtrInc;
561 TRgb CDrawThirtyTwoBppBitmapAlpha::RgbColor(TUint32 aColor) const
563 return TRgb::_Color16MA(aColor);
566 TUint32 CDrawThirtyTwoBppBitmapAlpha::Color(const TRgb& aColor)
568 return aColor._Color16MA();
571 void CDrawThirtyTwoBppBitmapAlpha::ShadowArea(const TRect& aRect)
573 const TRect rect(DeOrientate(aRect));
575 __ASSERT_DEBUG(rect.iTl.iX>=0 && rect.iBr.iX<=iSize.iWidth,Panic(EScreenDriverPanicOutOfBounds));
576 __ASSERT_DEBUG(rect.iTl.iY>=0 && rect.iBr.iY<=iSize.iHeight,Panic(EScreenDriverPanicOutOfBounds));
578 TUint32* pixelPtr = PixelAddress(rect.iTl.iX,rect.iTl.iY);
579 TUint32* pixelRowPtrLimit = pixelPtr + (rect.Height() * iScanLineWords);
581 TUint32* pixelRowPtr = pixelPtr;
582 TUint32* pixelPtrLimit = pixelPtr + rect.Width();
584 if (iShadowMode & EFade)
586 #if !defined(SYMBIAN_USE_FAST_FADING)
587 const TInt wordFadeMapOffset = ((iFadeMapOffset & 0xff) << 16) | (iFadeMapOffset & 0xff);
589 while (pixelRowPtr < pixelRowPtrLimit)
591 TUint32* tempPixelPtr = pixelRowPtr;
593 while (tempPixelPtr < pixelPtrLimit)
595 const TUint32 color = *tempPixelPtr;
596 #if defined(SYMBIAN_USE_FAST_FADING)
597 *tempPixelPtr++ = (color & 0xff000000) | ((((color & 0x00ffffff) >> 1) & ~0x00808080) + (SYMBIAN_USE_FAST_FADING));
599 const TInt rb = ((((color & 0x00ff00ff) * iFadeMapFactor) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
600 const TInt g = ((((color & 0x0000ff00) * iFadeMapFactor) >> 16) + iFadeMapOffset) << 8;
601 *tempPixelPtr++ = (color & 0xff000000) | rb | g;
605 pixelRowPtr += iScanLineWords;
606 pixelPtrLimit += iScanLineWords;
610 if (iShadowMode & EShadow)
612 pixelRowPtr = pixelPtr;
613 pixelPtrLimit = pixelPtr + rect.Width();
615 while (pixelRowPtr < pixelRowPtrLimit)
617 TUint32* tempPixelPtr = pixelRowPtr;
619 while (tempPixelPtr < pixelPtrLimit)
621 const TUint32 color = *tempPixelPtr;
622 const TInt r = (color & 0x00c00000) ? ((color & 0x00ff0000)-0x00400000) : 0;
623 const TInt g = (color & 0x0000c000) ? ((color & 0x0000ff00)-0x00004000) : 0;
624 const TInt b = (color & 0x000000c0) ? ((color & 0x000000ff)-0x00000040) : 0;
625 *tempPixelPtr++ = (color & 0xff000000) | r | g | b;
628 pixelRowPtr += iScanLineWords;
629 pixelPtrLimit += iScanLineWords;
634 TInt CDrawThirtyTwoBppBitmapAlpha::WriteRgbOutlineAndShadow(TInt aX, TInt aY, const TInt aLength,
635 TUint32 aOutlinePenColor, TUint32 aShadowColor,
636 TUint32 aFillColor, const TUint8* aDataBuffer)
639 TUint32* pixelPtr = PixelAddress(aX,aY);
640 const TInt pixelPtrInc = PixelAddressIncrement();
641 const TUint8* dataBufferPtrLimit = aDataBuffer + aLength;
642 TInt blendedRedColor;
643 TInt blendedGreenColor;
644 TInt blendedBlueColor;
648 const TUint16* normTable = PtrTo16BitNormalisationTable();
650 //Get red color. Equivalent to TRgb::Red()
651 const TInt redOutlinePenColor = (aOutlinePenColor & 0xff0000) >> 16;
652 const TInt redShadowColor = (aShadowColor & 0xff0000) >> 16;
653 const TInt redFillColor = (aFillColor & 0xff0000) >> 16;
655 //Get green color. Equivalent to TRgb::Green()
656 const TInt greenOutlinePenColor = (aOutlinePenColor & 0xff00) >> 8;
657 const TInt greenShadowColor = (aShadowColor & 0xff00) >> 8;
658 const TInt greenFillColor = (aFillColor & 0xff00) >> 8;
660 //Get blue color. Equivalent to TRgb::Blue()
661 const TInt blueOutlinePenColor = aOutlinePenColor & 0xff;
662 const TInt blueShadowColor = aShadowColor & 0xff;
663 const TInt blueFillColor = aFillColor & 0xff;
665 //Get alpha color. Equivalent to TRgb::Alpha()
666 const TInt alphaOutlinePenColor = aOutlinePenColor >> 24;
667 const TInt alphaShadowColor = aShadowColor >> 24;
668 const TInt alphaFillColor = aFillColor >> 24;
670 while (aDataBuffer < dataBufferPtrLimit)
672 index = *aDataBuffer++;
673 if(255 == FourColorBlendLookup[index][KBackgroundColorIndex])
676 //No drawing required
678 else if (255 == FourColorBlendLookup[index][KFillColorIndex])
680 //Use fill colour to draw
681 finalColor = OptimizedBlend32A(*pixelPtr, aFillColor, alphaFillColor);
682 *pixelPtr = PMA2NonPMAPixel(finalColor, normTable);
684 else if (255 == FourColorBlendLookup[index][KShadowColorIndex])
686 //Use shadow colour to draw
687 finalColor = OptimizedBlend32A(*pixelPtr, aShadowColor, alphaShadowColor);
688 *pixelPtr = PMA2NonPMAPixel(finalColor, normTable);
690 else if (255 == FourColorBlendLookup[index][KOutlineColorIndex])
692 //Use outline colour to draw
693 finalColor = OptimizedBlend32A(*pixelPtr, aOutlinePenColor, alphaOutlinePenColor);
694 *pixelPtr = PMA2NonPMAPixel(finalColor, normTable);
698 blendedRedColor = (redOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor +
699 redShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
700 redFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
702 blendedGreenColor = (greenOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor +
703 greenShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
704 greenFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
706 blendedBlueColor = (blueOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] * alphaOutlinePenColor +
707 blueShadowColor * FourColorBlendLookup[index][KShadowColorIndex] * alphaShadowColor +
708 blueFillColor * FourColorBlendLookup[index][KFillColorIndex] * alphaFillColor) >> 16;
710 blendedAlpha = (alphaOutlinePenColor * FourColorBlendLookup[index][KOutlineColorIndex] +
711 alphaShadowColor * FourColorBlendLookup[index][KShadowColorIndex] +
712 alphaFillColor * FourColorBlendLookup[index][KFillColorIndex]) >> 8;
714 // The blended colours have been alpha multiplied, hence the resulting colour is 16MAP
715 // Before doing the OptimizedBlend with the destination, note the following
716 // - The source alpha is set as fully opaque so that the blend is just with the mask
717 // - Input parameters for OptimizedBlend are NON-PRE, hence conversion from PRE to NON-PRE beforehand
718 // - output parameter for OptimizedBlend is PRE, hence conversion from PRE to NON-PRE afterwards
719 finalColor = PMA2NonPMAPixel((blendedAlpha << 24) | (blendedRedColor << 16) | (blendedGreenColor << 8) | blendedBlueColor, normTable);
720 finalColor = OptimizedBlend32A(*pixelPtr, finalColor | 0xff000000, blendedAlpha);
721 *pixelPtr = PMA2NonPMAPixel(finalColor, normTable);
723 pixelPtr += pixelPtrInc;